diff --git a/src/main/scala/coreplex/RocketCoreplex.scala b/src/main/scala/coreplex/RocketCoreplex.scala index fc6546d5..7cf9b155 100644 --- a/src/main/scala/coreplex/RocketCoreplex.scala +++ b/src/main/scala/coreplex/RocketCoreplex.scala @@ -57,8 +57,7 @@ case class TileSlavePortParams( case class RocketCrossingParams( crossingType: CoreplexClockCrossing = SynchronousCrossing(), master: TileMasterPortParams = TileMasterPortParams(), - slave: TileSlavePortParams = TileSlavePortParams(), - boundaryBuffers: Boolean = false) { + slave: TileSlavePortParams = TileSlavePortParams()) { def knownRatio: Option[Int] = crossingType match { case RationalCrossing(_) => Some(2) case _ => None @@ -92,8 +91,7 @@ trait HasRocketTiles extends HasTiles // in the global Parameters about the specific tile being built now val wrapper = LazyModule(new RocketTileWrapper( params = tp, - crossing = crossing.crossingType, - boundaryBuffers = crossing.boundaryBuffers + crossing = crossing.crossingType )(p.alterPartial { case TileKey => tp case BuildRoCC => tp.rocc diff --git a/src/main/scala/tile/RocketTile.scala b/src/main/scala/tile/RocketTile.scala index c253ba33..fbb0bf9c 100644 --- a/src/main/scala/tile/RocketTile.scala +++ b/src/main/scala/tile/RocketTile.scala @@ -22,7 +22,9 @@ case class RocketTileParams( trace: Boolean = false, hcfOnUncorrectable: Boolean = false, name: Option[String] = Some("tile"), - hartid: Int = 0) extends TileParams { + hartid: Int = 0, + boundaryBuffers: Boolean = false // if synthesized with hierarchical PnR, cut feed-throughs? + ) extends TileParams { require(icache.isDefined) require(dcache.isDefined) } @@ -189,23 +191,38 @@ class RocketTileWrapperBundle[+L <: RocketTileWrapper](_outer: L) extends BaseTi class RocketTileWrapper( params: RocketTileParams, - val crossing: CoreplexClockCrossing, - val boundaryBuffers: Boolean = false) + val crossing: CoreplexClockCrossing) (implicit p: Parameters) extends BaseTile(params) with HasCrossing { val rocket = LazyModule(new RocketTile(params)) + // The buffers needed to cut feed-through paths are microarchitecture specific, so belong here val masterBuffer = LazyModule(new TLBuffer(BufferParams.none, BufferParams.flow, BufferParams.none, BufferParams.flow, BufferParams(1))) - val masterNode: TLOutwardNode = if (boundaryBuffers) { - masterBuffer.node :=* rocket.masterNode - masterBuffer.node - } else { rocket.masterNode } + val masterNode: TLOutwardNode = crossing match { + case _: AsynchronousCrossing => rocket.masterNode + case SynchronousCrossing(b) => + require (!params.boundaryBuffers || (b.depth >= 1 && !b.flow && !b.pipe), "Buffer misconfiguration creates feed-through paths") + rocket.masterNode + case RationalCrossing(dir) => + require (dir != SlowToFast, "Misconfiguration? Core slower than fabric") + if (params.boundaryBuffers) { + masterBuffer.node :=* rocket.masterNode + } else { + rocket.masterNode + } + } val slaveBuffer = LazyModule(new TLBuffer(BufferParams.flow, BufferParams.none, BufferParams.none, BufferParams.none, BufferParams.none)) - val slaveNode: TLInwardNode = DisableMonitors { implicit p => if (boundaryBuffers) { - rocket.slaveNode :*= slaveBuffer.node - slaveBuffer.node - } else { rocket.slaveNode } } + val slaveNode: TLInwardNode = crossing match { + case _: SynchronousCrossing => rocket.slaveNode // requirement already checked + case _: AsynchronousCrossing => rocket.slaveNode + case _: RationalCrossing => + if (params.boundaryBuffers) { + DisableMonitors { implicit p => rocket.slaveNode :*= slaveBuffer.node } + } else { + rocket.slaveNode + } + } val intXbar = LazyModule(new IntXbar) rocket.intNode := intXbar.intnode