coreplex: RocketTileWrapper now HasCrossingHelper
This commit is contained in:
committed by
Wesley W. Terpstra
parent
9fe35382ea
commit
b48ab985d0
@ -18,6 +18,7 @@ case class TileMasterPortParams(
|
||||
addBuffers: Int = 0,
|
||||
blockerCtrlAddr: Option[BigInt] = None,
|
||||
cork: Option[Boolean] = None) {
|
||||
|
||||
def adapt(coreplex: HasPeripheryBus)
|
||||
(masterNode: TLOutwardNode)
|
||||
(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
@ -29,16 +30,15 @@ case class TileMasterPortParams(
|
||||
val tile_master_fixer = LazyModule(new TLFIFOFixer(TLFIFOFixer.allUncacheable))
|
||||
val tile_master_buffer = LazyModule(new TLBufferChain(addBuffers))
|
||||
|
||||
tile_master_blocker.foreach { _.controlNode := coreplex.pbus.toVariableWidthSlaves }
|
||||
val node: Option[TLNode] = TLNodeChain(List(
|
||||
Some(tile_master_buffer.node),
|
||||
Some(tile_master_fixer.node),
|
||||
tile_master_blocker.map(_.node),
|
||||
tile_master_cork.map(_.node)).flatten)
|
||||
|
||||
val node: Option[TLNode] = SourceCardinality { implicit p =>
|
||||
TLNodeChain(List(
|
||||
Some(tile_master_buffer.node),
|
||||
Some(tile_master_fixer.node),
|
||||
tile_master_blocker.map(_.node),
|
||||
tile_master_cork.map(_.node)).flatten)
|
||||
}
|
||||
tile_master_blocker.foreach { _.controlNode := coreplex.pbus.toVariableWidthSlaves }
|
||||
node.foreach { _ :=* masterNode }
|
||||
|
||||
node.getOrElse(masterNode)
|
||||
}
|
||||
}
|
||||
@ -46,6 +46,7 @@ case class TileMasterPortParams(
|
||||
case class TileSlavePortParams(
|
||||
addBuffers: Int = 0,
|
||||
blockerCtrlAddr: Option[BigInt] = None) {
|
||||
|
||||
def adapt(coreplex: HasPeripheryBus)
|
||||
(masterNode: TLOutwardNode)
|
||||
(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
@ -55,14 +56,13 @@ case class TileSlavePortParams(
|
||||
.map(bp => LazyModule(new BasicBusBlocker(bp)))
|
||||
val tile_slave_buffer = LazyModule(new TLBufferChain(addBuffers))
|
||||
|
||||
tile_slave_blocker.foreach { _.controlNode := coreplex.pbus.toVariableWidthSlaves }
|
||||
val node: Option[TLNode] = TLNodeChain(List(
|
||||
Some(tile_slave_buffer.node),
|
||||
tile_slave_blocker.map(_.node)).flatten)
|
||||
|
||||
val node: Option[TLNode] = SinkCardinality { implicit p =>
|
||||
TLNodeChain(List(
|
||||
Some(tile_slave_buffer.node),
|
||||
tile_slave_blocker.map(_.node)).flatten)
|
||||
}
|
||||
tile_slave_blocker.foreach { _.controlNode := coreplex.pbus.toVariableWidthSlaves }
|
||||
node.foreach { _ :*= masterNode }
|
||||
|
||||
node.getOrElse(masterNode)
|
||||
}
|
||||
}
|
||||
@ -70,7 +70,8 @@ case class TileSlavePortParams(
|
||||
case class RocketCrossingParams(
|
||||
crossingType: CoreplexClockCrossing = SynchronousCrossing(),
|
||||
master: TileMasterPortParams = TileMasterPortParams(),
|
||||
slave: TileSlavePortParams = TileSlavePortParams()) {
|
||||
slave: TileSlavePortParams = TileSlavePortParams(),
|
||||
boundaryBuffers: Boolean = false) {
|
||||
def knownRatio: Option[Int] = crossingType match {
|
||||
case RationalCrossing(_) => Some(2)
|
||||
case _ => None
|
||||
@ -95,67 +96,72 @@ trait HasRocketTiles extends HasTiles
|
||||
case NumRocketTiles => crossingParams
|
||||
case _ => throw new Exception("RocketCrossingKey.size must == 1 or == RocketTilesKey.size")
|
||||
}
|
||||
private val crossingTuples = localIntNodes.zip(tileParams).zip(crossings)
|
||||
|
||||
// Make a wrapper for each tile that will wire it to coreplex devices and crossbars,
|
||||
// according to the specified type of clock crossing.
|
||||
private val crossingTuples = localIntNodes.zip(tileParams).zip(crossings)
|
||||
val tiles: Seq[BaseTile] = crossingTuples.map { case ((lip, tp), crossing) =>
|
||||
val pWithExtra = p.alterPartial {
|
||||
case TileKey => tp
|
||||
case BuildRoCC => tp.rocc
|
||||
case SharedMemoryTLEdge => sharedMemoryTLEdge
|
||||
case RocketCrossingKey => List(crossing)
|
||||
}
|
||||
// For legacy reasons, it is convenient to store some state
|
||||
// in the global Parameters about the specific tile being built now
|
||||
val wrapper = LazyModule(new RocketTileWrapper(
|
||||
params = tp,
|
||||
crossing = crossing.crossingType,
|
||||
boundaryBuffers = crossing.boundaryBuffers
|
||||
)(p.alterPartial {
|
||||
case TileKey => tp
|
||||
case BuildRoCC => tp.rocc
|
||||
case SharedMemoryTLEdge => sharedMemoryTLEdge
|
||||
case RocketCrossingKey => List(crossing)
|
||||
})
|
||||
).suggestName(tp.name)
|
||||
|
||||
val wrapper = crossing.crossingType match {
|
||||
case SynchronousCrossing(params) => {
|
||||
val wrapper = LazyModule(new SyncRocketTile(tp)(pWithExtra))
|
||||
sbus.fromSyncTiles(params, crossing.master.adapt(this) _, tp.name) :=* wrapper.masterNode
|
||||
FlipRendering { implicit p => wrapper.slaveNode:*= pbus.toSyncSlaves(crossing.slave.adapt(this) _, tp.name) }
|
||||
wrapper
|
||||
}
|
||||
case AsynchronousCrossing(depth, sync) => {
|
||||
val wrapper = LazyModule(new AsyncRocketTile(tp)(pWithExtra))
|
||||
sbus.fromAsyncTiles(depth, sync, crossing.master.adapt(this) _, tp.name) :=* wrapper.masterNode
|
||||
FlipRendering { implicit p => wrapper.slaveNode :*= pbus.toAsyncSlaves(sync, crossing.slave.adapt(this) _, tp.name) }
|
||||
wrapper
|
||||
}
|
||||
case RationalCrossing(direction) => {
|
||||
val wrapper = LazyModule(new RationalRocketTile(tp)(pWithExtra))
|
||||
sbus.fromRationalTiles(direction, crossing.master.adapt(this) _, tp.name) :=* wrapper.masterNode
|
||||
FlipRendering { implicit p => wrapper.slaveNode :*= pbus.toRationalSlaves(crossing.slave.adapt(this) _, tp.name) }
|
||||
wrapper
|
||||
}
|
||||
}
|
||||
tp.name.foreach(wrapper.suggestName) // Try to stabilize this name for downstream tools
|
||||
// Connect the master ports of the tile to the system bus
|
||||
sbus.fromTile(
|
||||
adapt = {x: TLOutwardNode => wrapper.cross(x) } andThen
|
||||
crossing.master.adapt(this) _,
|
||||
from = wrapper.masterNode,
|
||||
name = tp.name)
|
||||
|
||||
// Local Interrupts must be synchronized to the core clock
|
||||
// before being passed into this module.
|
||||
// This allows faster latency for interrupts which are already synchronized.
|
||||
// The CLINT and PLIC outputs interrupts that are synchronous to the periphery clock,
|
||||
// so may or may not need to be synchronized depending on the Tile's crossing type.
|
||||
// Debug interrupt is definitely asynchronous in all cases.
|
||||
val asyncIntXbar = LazyModule(new IntXbar)
|
||||
asyncIntXbar.suggestName("asyncIntXbar")
|
||||
asyncIntXbar.intnode := debug.intnode // debug
|
||||
wrapper.asyncIntNode := asyncIntXbar.intnode
|
||||
// Connect the slave ports of the tile to the periphery bus
|
||||
pbus.toTile(
|
||||
adapt = {x: TLOutwardNode => wrapper.cross(x) } compose
|
||||
crossing.slave.adapt(this) _,
|
||||
to = wrapper.slaveNode,
|
||||
name = tp.name)
|
||||
|
||||
val periphIntXbar = LazyModule(new IntXbar)
|
||||
periphIntXbar.suggestName("periphIntXbar")
|
||||
periphIntXbar.intnode := clint.intnode // msip+mtip
|
||||
periphIntXbar.intnode := plic.intnode // meip
|
||||
// Handle all the different types of interrupts crossing to or from the tile:
|
||||
// 1. Debug interrupt is definitely asynchronous in all cases.
|
||||
// 2. The CLINT and PLIC output interrupts are synchronous to the periphery clock,
|
||||
// so might need to be synchronized depending on the Tile's crossing type.
|
||||
// 3. Local Interrupts are required to already be synchronous to the tile clock.
|
||||
// 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.
|
||||
// NOTE: The order of calls to := matters! They must match how interrupts
|
||||
// are decoded from rocket.intNode inside the tile.
|
||||
|
||||
val asyncIntXbar = LazyModule(new IntXbar).suggestName(tp.name.map(_ + "AsyncIntXbar"))
|
||||
asyncIntXbar.intnode := debug.intnode // debug
|
||||
wrapper.intXbar.intnode := wrapper.cross( // 1. always crosses
|
||||
name = tp.name.map(_ + "AsyncIntXbar"),
|
||||
overrideCrossing = Some(AsynchronousCrossing(8,3))
|
||||
)(x = asyncIntXbar.intnode)
|
||||
|
||||
val periphIntXbar = LazyModule(new IntXbar).suggestName(tp.name.map(_ + "PeriphIntXbar"))
|
||||
periphIntXbar.intnode := clint.intnode // msip+mtip
|
||||
periphIntXbar.intnode := plic.intnode // meip
|
||||
if (tp.core.useVM) periphIntXbar.intnode := plic.intnode // seip
|
||||
wrapper.periphIntNode := periphIntXbar.intnode
|
||||
wrapper.intXbar.intnode := wrapper.cross( // 2. conditionally crosses
|
||||
name = tp.name.map(_ + "PeriphIntXbar")
|
||||
)(x = periphIntXbar.intnode)
|
||||
|
||||
val coreIntXbar = LazyModule(new IntXbar)
|
||||
coreIntXbar.suggestName("coreIntXbar")
|
||||
lip.foreach { coreIntXbar.intnode := _ } // lip
|
||||
wrapper.coreIntNode := coreIntXbar.intnode
|
||||
val coreIntXbar = LazyModule(new IntXbar).suggestName(tp.name.map(_ + "CoreIntXbar"))
|
||||
lip.foreach { coreIntXbar.intnode := _ } // lip
|
||||
wrapper.intXbar.intnode := coreIntXbar.intnode // 3. never crosses
|
||||
|
||||
wrapper.intOutputNode.foreach { case int =>
|
||||
val rocketIntXing = LazyModule(new IntXing(wrapper.outputInterruptXingLatency))
|
||||
FlipRendering { implicit p => rocketIntXing.intnode := int }
|
||||
plic.intnode := rocketIntXing.intnode
|
||||
wrapper.rocket.intOutputNode.foreach { i => // 4. conditionally crosses
|
||||
plic.intnode := FlipRendering { implicit p =>
|
||||
wrapper.cross(name = tp.name.map(_ + "PeriphIntOutput"))(x = i)
|
||||
}
|
||||
}
|
||||
|
||||
wrapper
|
||||
|
Reference in New Issue
Block a user