Skip to content

Commit

Permalink
Genericize interrupts
Browse files Browse the repository at this point in the history
  • Loading branch information
jerryz123 committed Sep 26, 2023
1 parent bfda1c9 commit f853681
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 47 deletions.
2 changes: 1 addition & 1 deletion src/main/scala/groundtest/Tile.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ abstract class GroundTestTile(
with SourcesExternalNotifications
{
val cpuDevice: SimpleDevice = new SimpleDevice("groundtest", Nil)
val intOutwardNode: IntOutwardNode = IntIdentityNode()
val intOutwardNode = Seq(None)
val slaveNode: TLInwardNode = TLIdentityNode()
val statusNode = BundleBridgeSource(() => new GroundTestStatus)

Expand Down
10 changes: 5 additions & 5 deletions src/main/scala/subsystem/Element.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ abstract class BaseElement (val crossing: ClockCrossingType)(implicit p: Paramet
def module: BaseElementModuleImp[BaseElement]
def masterNode: TLOutwardNode
def slaveNode: TLInwardNode
def intInwardNode: IntInwardNode // Interrupts to the core from external devices
def intOutwardNode: IntOutwardNode // Interrupts from tile-internal devices (e.g. BEU)
def haltNode: IntOutwardNode // Unrecoverable error has occurred; suggest reset
def ceaseNode: IntOutwardNode // Tile has ceased to retire instructions
def wfiNode: IntOutwardNode // Tile is waiting for an interrupt
def intInwardNode: Seq[IntInwardNode] // Interrupts to the core from external devices
def intOutwardNode: Seq[Option[IntOutwardNode]] // Interrupts from tile-internal devices (e.g. BEU)
def haltNode: Seq[IntOutwardNode] // Unrecoverable error has occurred; suggest reset
def ceaseNode: Seq[IntOutwardNode] // Tile has ceased to retire instructions
def wfiNode: Seq[IntOutwardNode] // Tile is waiting for an interrupt

protected val tlOtherMastersNode = TLIdentityNode()
protected val tlMasterXbar = LazyModule(new TLXbar)
Expand Down
8 changes: 4 additions & 4 deletions src/main/scala/subsystem/ElementPRCIDomain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ abstract class ElementPRCIDomain[T <: BaseElement](
val traceNodes: Seq[BundleBridgeIdentityNode[TraceBundle]]
/** Node to broadcast standardized instruction trace while surpressing it during (async) reset. */
val traceCoreNodes: Seq[BundleBridgeIdentityNode[TraceCoreInterface]]
require(element.traceNodes.size == traceNodes.size)
require(element.traceCoreNodes.size == traceCoreNodes.size)

/** Function to handle all trace crossings when tile is instantiated inside domains */
def crossTracesOut(): Unit = this {
require(element.traceNodes.size == traceNodes.size)
require(element.traceCoreNodes.size == traceCoreNodes.size)
for (i <- 0 until traceNodes.size) {
val traceNexusNode = BundleBridgeBlockDuringReset[TraceBundle](
resetCrossingType = crossingParams.resetCrossingType)
Expand All @@ -72,9 +72,9 @@ abstract class ElementPRCIDomain[T <: BaseElement](
}

/** External code looking to connect and clock-cross the interrupts driven into this tile can call this. */
def crossIntIn(crossingType: ClockCrossingType): IntInwardNode = {
def crossIntIn(crossingType: ClockCrossingType, tileNode: IntInwardNode): IntInwardNode = {
// Unlike the other crossing helpers, here nothing is is blocked during reset because we know these are inputs and assume that tile reset is longer than uncore reset
val intInClockXing = this.crossIn(element.intInwardNode)
val intInClockXing = this.crossIn(tileNode)
intInClockXing(crossingType)
}

Expand Down
18 changes: 17 additions & 1 deletion src/main/scala/subsystem/HasElements.scala
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ trait InstantiatesElements { this: LazyModule with Attachable =>
}

/** HasTiles instantiates and also connects a Config-urable sequence of tiles of any type to subsystem interconnect resources. */
trait HasElements extends HasCoreMonitorBundles with DefaultTileContextType
trait HasElements extends HasCoreMonitorBundles with DefaultElementContextType
{ this: LazyModule with Attachable =>
implicit val p: Parameters

Expand Down Expand Up @@ -117,3 +117,19 @@ trait HasElementsRootModuleImp extends LazyModuleImp {
}
val nmi = outer.totalTiles.zip(outer.tileNMIIONodes).zipWithIndex.map { case ((tile, n), i) => tile.tileParams.core.useNMI.option(n.makeIO(s"nmi_$i")) }
}

/** Most tile types require only these traits in order for their standardized connect functions to apply.
*
* BaseTiles subtypes with different needs can extend this trait to provide themselves with
* additional external connection points.
*/
trait DefaultElementContextType
extends Attachable
with HasTileInterruptSources
with HasTileNotificationSinks
with HasTileInputConstants
{ this: LazyModule with Attachable =>
val clintNode: Option[IntOutwardNode]
val plicNode: Option[IntNode]
val debugNode: Option[IntSyncOutwardNode]
}
38 changes: 11 additions & 27 deletions src/main/scala/subsystem/HasTiles.scala
Original file line number Diff line number Diff line change
Expand Up @@ -158,22 +158,6 @@ trait HasTileNotificationSinks { this: LazyModule =>
tileCeaseSinkNode := tileCeaseXbarNode
}

/** Most tile types require only these traits in order for their standardized connect functions to apply.
*
* BaseTiles subtypes with different needs can extend this trait to provide themselves with
* additional external connection points.
*/
trait DefaultTileContextType
extends Attachable
with HasTileInterruptSources
with HasTileNotificationSinks
with HasTileInputConstants
{ this: LazyModule with Attachable =>
val clintNode: Option[IntOutwardNode]
val plicNode: Option[IntNode]
val debugNode: Option[IntSyncOutwardNode]
}

/** Standardized interface by which parameterized tiles can be attached to contexts containing interconnect resources.
*
* Sub-classes of this trait can optionally override the individual connect functions in order to specialize
Expand All @@ -182,7 +166,7 @@ trait DefaultTileContextType
*/
trait CanAttachTile {
type TileType <: BaseTile
type TileContextType <: DefaultTileContextType
type TileContextType <: DefaultElementContextType
def tileParams: InstantiableTileParams[TileType]
def crossingParams: ElementCrossingParamsLike

Expand Down Expand Up @@ -233,7 +217,7 @@ trait CanAttachTile {
// we stub out missing interrupts with constant sources here.

// 1. Debug interrupt is definitely asynchronous in all cases.
domain.element.intInwardNode :=
domain.element.intInwardNode(0) :=
context.debugNode
.map { node => domain { IntSyncAsyncCrossingSink(3) } := node }
.getOrElse { NullIntSource() }
Expand All @@ -242,16 +226,16 @@ trait CanAttachTile {
// so might need to be synchronized depending on the Tile's crossing type.

// From CLINT: "msip" and "mtip"
domain.crossIntIn(crossingParams.crossingType) :=
domain.crossIntIn(crossingParams.crossingType, domain.element.intInwardNode(0)) :=
context.clintNode.getOrElse { NullIntSource(sources = CLINTConsts.ints) }

// From PLIC: "meip"
domain.crossIntIn(crossingParams.crossingType) :=
domain.crossIntIn(crossingParams.crossingType, domain.element.intInwardNode(0)) :=
context.plicNode.getOrElse { context.meipNode.get }

// From PLIC: "seip" (only if supervisor mode is enabled)
if (domain.element.tileParams.core.hasSupervisorMode) {
domain.crossIntIn(crossingParams.crossingType) :=
domain.crossIntIn(crossingParams.crossingType, domain.element.intInwardNode(0)) :=
context.plicNode.getOrElse { context.seipNode.get }
}

Expand All @@ -261,9 +245,9 @@ trait CanAttachTile {
// 4. Interrupts coming out of the tile are sent to the PLIC,
// so might need to be synchronized depending on the Tile's crossing type.
context.plicNode.foreach { node =>
FlipRendering { implicit p =>
node :*= domain.crossIntOut(crossingParams.crossingType, domain.element.intOutwardNode)
}
FlipRendering { implicit p => domain.element.intOutwardNode(0).foreach { out =>
node :*= domain.crossIntOut(crossingParams.crossingType, out)
}}
}

// 5. Connect NMI inputs to the tile. These inputs are synchronous to the respective core_clock.
Expand All @@ -273,9 +257,9 @@ trait CanAttachTile {
/** Notifications of tile status are connected to be broadcast without needing to be clock-crossed. */
def connectOutputNotifications(domain: TilePRCIDomain[TileType], context: TileContextType): Unit = {
implicit val p = context.p
context.tileHaltXbarNode :=* domain.crossIntOut(NoCrossing, domain.element.haltNode)
context.tileWFIXbarNode :=* domain.crossIntOut(NoCrossing, domain.element.wfiNode)
context.tileCeaseXbarNode :=* domain.crossIntOut(NoCrossing, domain.element.ceaseNode)
context.tileHaltXbarNode :=* domain.crossIntOut(NoCrossing, domain.element.haltNode(0))
context.tileWFIXbarNode :=* domain.crossIntOut(NoCrossing, domain.element.wfiNode(0))
context.tileCeaseXbarNode :=* domain.crossIntOut(NoCrossing, domain.element.ceaseNode(0))
// TODO should context be forced to have a trace sink connected here?
// for now this just ensures domain.trace[Core]Node has been crossed without connecting it externally
domain.crossTracesOut()
Expand Down
14 changes: 7 additions & 7 deletions src/main/scala/tile/Interrupts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class TileInterrupts(implicit p: Parameters) extends CoreBundle()(p) {
// Use diplomatic interrupts to external interrupts from the subsystem into the tile
trait SinksExternalInterrupts { this: BaseTile =>

val intInwardNode = intXbar.intnode :=* IntIdentityNode()(ValName("int_local"))
val intInwardNode = Seq(intXbar.intnode :=* IntIdentityNode()(ValName("int_local")))
protected val intSinkNode = IntSinkNode(IntSinkPortSimple())
intSinkNode := intXbar.intnode

Expand Down Expand Up @@ -85,10 +85,10 @@ trait SinksExternalInterrupts { this: BaseTile =>

trait SourcesExternalNotifications { this: BaseTile =>
// Report unrecoverable error conditions
val haltNode = IntSourceNode(IntSourcePortSimple())
val haltNode = Seq(IntSourceNode(IntSourcePortSimple()))

def reportHalt(could_halt: Option[Bool]): Unit = {
val (halt_and_catch_fire, _) = haltNode.out(0)
val (halt_and_catch_fire, _) = haltNode(0).out(0)
halt_and_catch_fire(0) := could_halt.map(RegEnable(true.B, false.B, _)).getOrElse(false.B)
}

Expand All @@ -97,7 +97,7 @@ trait SourcesExternalNotifications { this: BaseTile =>
}

// Report when the tile has ceased to retire instructions
val ceaseNode = IntSourceNode(IntSourcePortSimple())
val ceaseNode = Seq(IntSourceNode(IntSourcePortSimple()))

def reportCease(could_cease: Option[Bool], quiescenceCycles: Int = 8): Unit = {
def waitForQuiescence(cease: Bool): Bool = {
Expand All @@ -108,7 +108,7 @@ trait SourcesExternalNotifications { this: BaseTile =>
when (cease && !saturated) { count := count + 1.U }
saturated
}
val (cease, _) = ceaseNode.out(0)
val (cease, _) = ceaseNode(0).out(0)
cease(0) := could_cease.map{ c =>
val cease = (waitForQuiescence(c))
// Test-Only Code --
Expand All @@ -119,10 +119,10 @@ trait SourcesExternalNotifications { this: BaseTile =>
}

// Report when the tile is waiting for an interrupt
val wfiNode = IntSourceNode(IntSourcePortSimple())
val wfiNode = Seq(IntSourceNode(IntSourcePortSimple()))

def reportWFI(could_wfi: Option[Bool]): Unit = {
val (wfi, _) = wfiNode.out(0)
val (wfi, _) = wfiNode(0).out(0)
wfi(0) := could_wfi.map(RegNext(_, init=false.B)).getOrElse(false.B)
}
}
4 changes: 2 additions & 2 deletions src/main/scala/tile/RocketTile.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class RocketTile private(
def this(params: RocketTileParams, crossing: ElementCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters) =
this(params, crossing.crossingType, lookup, p)

val intOutwardNode = IntIdentityNode()
val intOutwardNode = Seq(rocketParams.beuAddr map { _ => IntIdentityNode() })
val slaveNode = TLIdentityNode()
val masterNode = visibilityNode

Expand All @@ -63,7 +63,7 @@ class RocketTile private(

val bus_error_unit = rocketParams.beuAddr map { a =>
val beu = LazyModule(new BusErrorUnit(new L1BusErrors, BusErrorUnitParams(a)))
intOutwardNode := beu.intNode
intOutwardNode(0).get := beu.intNode
connectTLSlave(beu.node, xBytes)
beu
}
Expand Down

0 comments on commit f853681

Please sign in to comment.