From e30906589f949b3db75475ee69840150511bc132 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 25 Oct 2017 14:45:44 -0700 Subject: [PATCH] coreplex: refactor crossings to use node pattern --- src/main/scala/coreplex/CrossingWrapper.scala | 178 +++++++++++------- src/main/scala/coreplex/RocketCoreplex.scala | 17 +- src/main/scala/interrupts/package.scala | 1 + src/main/scala/tile/RocketTile.scala | 2 +- 4 files changed, 115 insertions(+), 83 deletions(-) diff --git a/src/main/scala/coreplex/CrossingWrapper.scala b/src/main/scala/coreplex/CrossingWrapper.scala index e0b888be..0f956f74 100644 --- a/src/main/scala/coreplex/CrossingWrapper.scala +++ b/src/main/scala/coreplex/CrossingWrapper.scala @@ -15,80 +15,116 @@ case class SynchronousCrossing(params: BufferParams = BufferParams.default) exte case class RationalCrossing(direction: RationalDirection = FastToSlow) extends CoreplexClockCrossing case class AsynchronousCrossing(depth: Int, sync: Int = 3) extends CoreplexClockCrossing -trait HasCrossingHelper extends LazyScope +trait HasCrossingMethods extends LazyScope +{ + this: LazyModule => + + // TileLink + + def crossTLSyncInOut(out: Boolean)(params: BufferParams = BufferParams.default)(implicit p: Parameters): TLNode = { + this { LazyModule(new TLBuffer(params)).node } + } + + def crossTLAsyncInOut(out: Boolean)(depth: Int = 8, sync: Int = 3)(implicit p: Parameters): TLNode = { + def sourceGen = LazyModule(new TLAsyncCrossingSource(sync)) + def sinkGen = LazyModule(new TLAsyncCrossingSink(depth, sync)) + val source = if (out) this { sourceGen } else sourceGen + val sink = if (out) sinkGen else this { sinkGen } + sink.node :=? source.node + NodeHandle(source.node, sink.node) + } + + def crossTLRationalInOut(out: Boolean)(direction: RationalDirection)(implicit p: Parameters): TLNode = { + def sourceGen = LazyModule(new TLRationalCrossingSource) + def sinkGen = LazyModule(new TLRationalCrossingSink(if (out) direction else direction.flip)) + val source = if (out) this { sourceGen } else sourceGen + val sink = if (out) sinkGen else this { sinkGen } + sink.node :=? source.node + NodeHandle(source.node, sink.node) + } + + def crossTLSyncIn (params: BufferParams = BufferParams.default)(implicit p: Parameters): TLNode = crossTLSyncInOut(false)(params) + def crossTLSyncOut(params: BufferParams = BufferParams.default)(implicit p: Parameters): TLNode = crossTLSyncInOut(true )(params) + def crossTLAsyncIn (depth: Int = 8, sync: Int = 3)(implicit p: Parameters): TLNode = crossTLAsyncInOut(false)(depth, sync) + def crossTLAsyncOut(depth: Int = 8, sync: Int = 3)(implicit p: Parameters): TLNode = crossTLAsyncInOut(true )(depth, sync) + def crossTLRationalIn (direction: RationalDirection)(implicit p: Parameters): TLNode = crossTLRationalInOut(false)(direction) + def crossTLRationalOut(direction: RationalDirection)(implicit p: Parameters): TLNode = crossTLRationalInOut(true )(direction) + + def crossTLIn(arg: CoreplexClockCrossing)(implicit p: Parameters): TLNode = arg match { + case x: SynchronousCrossing => crossTLSyncIn(x.params) + case x: AsynchronousCrossing => crossTLAsyncIn(x.depth, x.sync) + case x: RationalCrossing => crossTLRationalIn(x.direction) + } + + def crossTLOut(arg: CoreplexClockCrossing)(implicit p: Parameters): TLNode = arg match { + case x: SynchronousCrossing => crossTLSyncOut(x.params) + case x: AsynchronousCrossing => crossTLAsyncOut(x.depth, x.sync) + case x: RationalCrossing => crossTLRationalOut(x.direction) + } + + // Interrupts + + def crossIntSyncInOut(out: Boolean)(alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = { + def sourceGen = LazyModule(new IntSyncCrossingSource(alreadyRegistered)) + def sinkGen = LazyModule(new IntSyncCrossingSink(0)) + val source = if (out) this { sourceGen } else sourceGen + val sink = if (out) sinkGen else this { sinkGen } + sink.node :=? source.node + NodeHandle(source.node, sink.node) + } + + def crossIntAsyncInOut(out: Boolean)(sync: Int = 3, alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = { + def sourceGen = LazyModule(new IntSyncCrossingSource(alreadyRegistered)) + def sinkGen = LazyModule(new IntSyncCrossingSink(sync)) + val source = if (out) this { sourceGen } else sourceGen + val sink = if (out) sinkGen else this { sinkGen } + sink.node :=? source.node + NodeHandle(source.node, sink.node) + } + + def crossIntRationalInOut(out: Boolean)(alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = { + def sourceGen = LazyModule(new IntSyncCrossingSource(alreadyRegistered)) + def sinkGen = LazyModule(new IntSyncCrossingSink(1)) + val source = if (out) this { sourceGen } else sourceGen + val sink = if (out) sinkGen else this { sinkGen } + sink.node :=? source.node + NodeHandle(source.node, sink.node) + } + + def crossIntSyncIn (alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = crossIntSyncInOut(false)(alreadyRegistered) + def crossIntSyncOut(alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = crossIntSyncInOut(true )(alreadyRegistered) + def crossIntAsyncIn (sync: Int = 3, alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = crossIntAsyncInOut(false)(sync, alreadyRegistered) + def crossIntAsyncOut(sync: Int = 3, alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = crossIntAsyncInOut(true )(sync, alreadyRegistered) + def crossIntRationalIn (alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = crossIntRationalInOut(false)(alreadyRegistered) + def crossIntRationalOut(alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = crossIntRationalInOut(true )(alreadyRegistered) + + def crossIntIn(arg: CoreplexClockCrossing, alreadyRegistered: Boolean)(implicit p: Parameters): IntNode = arg match { + case x: SynchronousCrossing => crossIntSyncIn(alreadyRegistered) + case x: AsynchronousCrossing => crossIntAsyncIn(x.sync, alreadyRegistered) + case x: RationalCrossing => crossIntRationalIn(alreadyRegistered) + } + + def crossIntOut(arg: CoreplexClockCrossing, alreadyRegistered: Boolean)(implicit p: Parameters): IntNode = arg match { + case x: SynchronousCrossing => crossIntSyncOut(alreadyRegistered) + case x: AsynchronousCrossing => crossIntAsyncOut(x.sync, alreadyRegistered) + case x: RationalCrossing => crossIntRationalOut(alreadyRegistered) + } + + def crossIntIn (arg: CoreplexClockCrossing)(implicit p: Parameters): IntNode = crossIntIn (arg, false) + def crossIntOut(arg: CoreplexClockCrossing)(implicit p: Parameters): IntNode = crossIntOut(arg, false) +} + +trait HasCrossing extends HasCrossingMethods { this: LazyModule => val crossing: CoreplexClockCrossing - def cross(x: TLCrossableNode): TLOutwardNode = { - val out = x.node.parentsOut.exists(_ eq this) // is the crossing exiting the wrapper? - crossing match { - case SynchronousCrossing(params) => { - this { TLBuffer(params)(x.node) } - } - case RationalCrossing(direction) => { - def sourceGen = LazyModule(new TLRationalCrossingSource) - def sinkGen = LazyModule(new TLRationalCrossingSink(direction)) - val source = if (out) this { sourceGen } else sourceGen - val sink = if (out) sinkGen else this { sinkGen } - source.node :=? x.node - sink.node :=? source.node - sink.node - } - case AsynchronousCrossing(depth, sync) => { - def sourceGen = LazyModule(new TLAsyncCrossingSource(sync)) - def sinkGen = LazyModule(new TLAsyncCrossingSink(depth, sync)) - val source = if (out) this { sourceGen } else sourceGen - val sink = if (out) sinkGen else this { sinkGen } - source.node :=? x.node - sink.node :=? source.node - sink.node - } - } - } - - def cross( - name: Option[String] = None, - alreadyRegistered: Boolean = false, - overrideCrossing: Option[CoreplexClockCrossing] = None) - (x: IntCrossableNode): IntOutwardNode = { - val out = x.node.parentsOut.exists(_ eq this) // is the crossing exiting the wrapper? - overrideCrossing.getOrElse(crossing) match { - case SynchronousCrossing(_) => { - def sourceGen = LazyModule(new IntSyncCrossingSource(alreadyRegistered)) - def sinkGen = LazyModule(new IntSyncCrossingSink(0)) - val source = if (out) this { sourceGen } else sourceGen - val sink = if (out) sinkGen else this { sinkGen } - name.map(_ + "SyncSource").foreach(source.suggestName) - name.map(_ + "SyncSink").foreach(sink.suggestName) - source.node :=? x.node - sink.node :=? source.node - sink.node - } - case RationalCrossing(_) => { - def sourceGen = LazyModule(new IntSyncCrossingSource(alreadyRegistered)) - def sinkGen = LazyModule(new IntSyncCrossingSink(1)) - val source = if (out) this { sourceGen } else sourceGen - val sink = if (out) sinkGen else this { sinkGen } - name.map(_ + "SyncSource").foreach(source.suggestName) - name.map(_ + "SyncSink").foreach(sink.suggestName) - source.node :=? x.node - sink.node :=? source.node - sink.node - } - case AsynchronousCrossing(_, sync) => { - def sourceGen = LazyModule(new IntSyncCrossingSource(alreadyRegistered)) - def sinkGen = LazyModule(new IntSyncCrossingSink(sync)) - val source = if (out) this { sourceGen } else sourceGen - val sink = if (out) sinkGen else this { sinkGen } - name.map(_ + "SyncSource").foreach(source.suggestName) - name.map(_ + "SyncSink").foreach(sink.suggestName) - source.node :=? x.node - sink.node :=? source.node - sink.node - } - } - } + def crossTLIn (implicit p: Parameters): TLNode = crossTLIn (crossing) + def crossTLOut (implicit p: Parameters): TLNode = crossTLOut (crossing) + def crossIntIn (implicit p: Parameters): IntNode = crossIntIn (crossing) + def crossIntOut(implicit p: Parameters): IntNode = crossIntOut(crossing) + def crossIntIn (alreadyRegistered: Boolean)(implicit p: Parameters): IntNode = crossIntIn (crossing, alreadyRegistered) + def crossIntOut(alreadyRegistered: Boolean)(implicit p: Parameters): IntNode = crossIntOut(crossing, alreadyRegistered) } -class CrossingWrapper(val crossing: CoreplexClockCrossing)(implicit p: Parameters) extends SimpleLazyModule with HasCrossingHelper +class CrossingWrapper(val crossing: CoreplexClockCrossing)(implicit p: Parameters) extends SimpleLazyModule with HasCrossing diff --git a/src/main/scala/coreplex/RocketCoreplex.scala b/src/main/scala/coreplex/RocketCoreplex.scala index 943edc73..667dfb72 100644 --- a/src/main/scala/coreplex/RocketCoreplex.scala +++ b/src/main/scala/coreplex/RocketCoreplex.scala @@ -49,7 +49,7 @@ case class TileSlavePortParams( .map(bp => LazyModule(new BasicBusBlocker(bp))) tile_slave_blocker.foreach { _.controlNode := coreplex.pbus.toVariableWidthSlaves } - (TLBuffer.chain(addBuffers) ++ tile_slave_blocker.map(_.node)) + (Seq() ++ tile_slave_blocker.map(_.node) ++ TLBuffer.chain(addBuffers)) .foldLeft(slaveNode)(_ :*= _) } } @@ -103,10 +103,10 @@ trait HasRocketTiles extends HasTiles ).suggestName(tp.name) // Connect the master ports of the tile to the system bus - sbus.fromTile(tp.name) { implicit p => crossing.master.adapt(this)(wrapper.cross(wrapper.masterNode)) } + sbus.fromTile(tp.name) { implicit p => crossing.master.adapt(this)(wrapper.crossTLOut :=* wrapper.masterNode) } // Connect the slave ports of the tile to the periphery bus - pbus.toTile(tp.name) { implicit p => crossing.slave.adapt(this)(wrapper.slaveNode) } // !!! wrapper.cross + pbus.toTile(tp.name) { implicit p => crossing.slave.adapt(this)(wrapper.slaveNode :*= wrapper.crossTLIn) } // Handle all the different types of interrupts crossing to or from the tile: // 1. Debug interrupt is definitely asynchronous in all cases. @@ -120,18 +120,13 @@ trait HasRocketTiles extends HasTiles 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) + wrapper.intXbar.intnode := wrapper.crossIntAsyncIn() := asyncIntXbar.intnode // 1. always crosses 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.intXbar.intnode := wrapper.cross( // 2. conditionally crosses - name = tp.name.map(_ + "PeriphIntXbar") - )(x = periphIntXbar.intnode) + wrapper.intXbar.intnode := wrapper.crossIntIn := periphIntXbar.intnode // 2. conditionally crosses val coreIntXbar = LazyModule(new IntXbar).suggestName(tp.name.map(_ + "CoreIntXbar")) lip.foreach { coreIntXbar.intnode := _ } // lip @@ -139,7 +134,7 @@ trait HasRocketTiles extends HasTiles wrapper.rocket.intOutputNode.foreach { i => // 4. conditionally crosses plic.intnode := FlipRendering { implicit p => - wrapper.cross(name = tp.name.map(_ + "PeriphIntOutput"))(x = i) + wrapper.crossIntIn := i } } diff --git a/src/main/scala/interrupts/package.scala b/src/main/scala/interrupts/package.scala index 9b2bef75..91b089db 100644 --- a/src/main/scala/interrupts/package.scala +++ b/src/main/scala/interrupts/package.scala @@ -9,6 +9,7 @@ package object interrupts { type IntInwardNode = InwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, Vec[Bool]] type IntOutwardNode = OutwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, Vec[Bool]] + type IntNode = NodeHandle[IntSourcePortParameters, IntSinkPortParameters, Vec[Bool], IntSourcePortParameters, IntSinkPortParameters, Vec[Bool]] type IntSyncInwardNode = InwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, SyncInterrupts] type IntSyncOutwardNode = OutwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, SyncInterrupts] } diff --git a/src/main/scala/tile/RocketTile.scala b/src/main/scala/tile/RocketTile.scala index 7791c2d9..c253ba33 100644 --- a/src/main/scala/tile/RocketTile.scala +++ b/src/main/scala/tile/RocketTile.scala @@ -191,7 +191,7 @@ class RocketTileWrapper( params: RocketTileParams, val crossing: CoreplexClockCrossing, val boundaryBuffers: Boolean = false) - (implicit p: Parameters) extends BaseTile(params) with HasCrossingHelper { + (implicit p: Parameters) extends BaseTile(params) with HasCrossing { val rocket = LazyModule(new RocketTile(params))