coreplex: refactor crossings to use node pattern
This commit is contained in:
		| @@ -15,80 +15,116 @@ case class SynchronousCrossing(params: BufferParams = BufferParams.default) exte | |||||||
| case class RationalCrossing(direction: RationalDirection = FastToSlow) extends CoreplexClockCrossing | case class RationalCrossing(direction: RationalDirection = FastToSlow) extends CoreplexClockCrossing | ||||||
| case class AsynchronousCrossing(depth: Int, sync: Int = 3) extends CoreplexClockCrossing | case class AsynchronousCrossing(depth: Int, sync: Int = 3) extends CoreplexClockCrossing | ||||||
|  |  | ||||||
| trait HasCrossingHelper extends LazyScope | trait HasCrossingMethods extends LazyScope | ||||||
| { | { | ||||||
|   this: LazyModule => |   this: LazyModule => | ||||||
|   val crossing: CoreplexClockCrossing |  | ||||||
|  |  | ||||||
|   def cross(x: TLCrossableNode): TLOutwardNode = { |   // TileLink | ||||||
|     val out = x.node.parentsOut.exists(_ eq this) // is the crossing exiting the wrapper? |  | ||||||
|     crossing match { |   def crossTLSyncInOut(out: Boolean)(params: BufferParams = BufferParams.default)(implicit p: Parameters): TLNode = { | ||||||
|       case SynchronousCrossing(params) => { |     this { LazyModule(new TLBuffer(params)).node } | ||||||
|         this { TLBuffer(params)(x.node) } |  | ||||||
|   } |   } | ||||||
|       case RationalCrossing(direction) => { |  | ||||||
|         def sourceGen = LazyModule(new TLRationalCrossingSource) |   def crossTLAsyncInOut(out: Boolean)(depth: Int = 8, sync: Int = 3)(implicit p: Parameters): TLNode = { | ||||||
|         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 sourceGen = LazyModule(new TLAsyncCrossingSource(sync)) | ||||||
|     def sinkGen = LazyModule(new TLAsyncCrossingSink(depth, sync)) |     def sinkGen = LazyModule(new TLAsyncCrossingSink(depth, sync)) | ||||||
|     val source = if (out) this { sourceGen } else sourceGen |     val source = if (out) this { sourceGen } else sourceGen | ||||||
|     val sink = if (out) sinkGen else this { sinkGen } |     val sink = if (out) sinkGen else this { sinkGen } | ||||||
|         source.node :=? x.node |  | ||||||
|     sink.node :=? source.node |     sink.node :=? source.node | ||||||
|         sink.node |     NodeHandle(source.node, sink.node) | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   def cross( |   def crossTLRationalInOut(out: Boolean)(direction: RationalDirection)(implicit p: Parameters): TLNode = { | ||||||
|       name: Option[String] = None, |     def sourceGen = LazyModule(new TLRationalCrossingSource) | ||||||
|       alreadyRegistered: Boolean = false, |     def sinkGen = LazyModule(new TLRationalCrossingSink(if (out) direction else direction.flip)) | ||||||
|       overrideCrossing: Option[CoreplexClockCrossing] = None) |     val source = if (out) this { sourceGen } else sourceGen | ||||||
|       (x: IntCrossableNode): IntOutwardNode = { |     val sink = if (out) sinkGen else this { sinkGen } | ||||||
|     val out = x.node.parentsOut.exists(_ eq this) // is the crossing exiting the wrapper? |     sink.node :=? source.node | ||||||
|     overrideCrossing.getOrElse(crossing) match { |     NodeHandle(source.node, sink.node) | ||||||
|       case SynchronousCrossing(_) => { |   } | ||||||
|  |  | ||||||
|  |   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 sourceGen = LazyModule(new IntSyncCrossingSource(alreadyRegistered)) | ||||||
|     def sinkGen = LazyModule(new IntSyncCrossingSink(0)) |     def sinkGen = LazyModule(new IntSyncCrossingSink(0)) | ||||||
|     val source = if (out) this { sourceGen } else sourceGen |     val source = if (out) this { sourceGen } else sourceGen | ||||||
|     val sink = if (out) sinkGen else this { sinkGen } |     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 :=? source.node | ||||||
|         sink.node |     NodeHandle(source.node, sink.node) | ||||||
|   } |   } | ||||||
|       case RationalCrossing(_) => { |  | ||||||
|         def sourceGen = LazyModule(new IntSyncCrossingSource(alreadyRegistered)) |   def crossIntAsyncInOut(out: Boolean)(sync: Int = 3, alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = { | ||||||
|         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 sourceGen = LazyModule(new IntSyncCrossingSource(alreadyRegistered)) | ||||||
|     def sinkGen = LazyModule(new IntSyncCrossingSink(sync)) |     def sinkGen = LazyModule(new IntSyncCrossingSink(sync)) | ||||||
|     val source = if (out) this { sourceGen } else sourceGen |     val source = if (out) this { sourceGen } else sourceGen | ||||||
|     val sink = if (out) sinkGen else this { sinkGen } |     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 :=? source.node | ||||||
|         sink.node |     NodeHandle(source.node, sink.node) | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
| class CrossingWrapper(val crossing: CoreplexClockCrossing)(implicit p: Parameters) extends SimpleLazyModule with HasCrossingHelper |   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 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 HasCrossing | ||||||
|   | |||||||
| @@ -49,7 +49,7 @@ case class TileSlavePortParams( | |||||||
|         .map(bp => LazyModule(new BasicBusBlocker(bp))) |         .map(bp => LazyModule(new BasicBusBlocker(bp))) | ||||||
|  |  | ||||||
|     tile_slave_blocker.foreach { _.controlNode := coreplex.pbus.toVariableWidthSlaves } |     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)(_ :*= _) |     .foldLeft(slaveNode)(_ :*= _) | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -103,10 +103,10 @@ trait HasRocketTiles extends HasTiles | |||||||
|     ).suggestName(tp.name) |     ).suggestName(tp.name) | ||||||
|  |  | ||||||
|     // Connect the master ports of the tile to the system bus |     // 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 |     // 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: |     // Handle all the different types of interrupts crossing to or from the tile: | ||||||
|     // 1. Debug interrupt is definitely asynchronous in all cases. |     // 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")) |     val asyncIntXbar  = LazyModule(new IntXbar).suggestName(tp.name.map(_ + "AsyncIntXbar")) | ||||||
|     asyncIntXbar.intnode  := debug.intnode                   // debug |     asyncIntXbar.intnode  := debug.intnode                   // debug | ||||||
|     wrapper.intXbar.intnode := wrapper.cross(                // 1. always crosses |     wrapper.intXbar.intnode := wrapper.crossIntAsyncIn() := asyncIntXbar.intnode // 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")) |     val periphIntXbar = LazyModule(new IntXbar).suggestName(tp.name.map(_ + "PeriphIntXbar")) | ||||||
|     periphIntXbar.intnode := clint.intnode                   // msip+mtip |     periphIntXbar.intnode := clint.intnode                   // msip+mtip | ||||||
|     periphIntXbar.intnode := plic.intnode                    // meip |     periphIntXbar.intnode := plic.intnode                    // meip | ||||||
|     if (tp.core.useVM) periphIntXbar.intnode := plic.intnode // seip |     if (tp.core.useVM) periphIntXbar.intnode := plic.intnode // seip | ||||||
|     wrapper.intXbar.intnode := wrapper.cross(                // 2. conditionally crosses |     wrapper.intXbar.intnode := wrapper.crossIntIn := periphIntXbar.intnode // 2. conditionally crosses | ||||||
|       name = tp.name.map(_ + "PeriphIntXbar") |  | ||||||
|     )(x = periphIntXbar.intnode) |  | ||||||
|  |  | ||||||
|     val coreIntXbar = LazyModule(new IntXbar).suggestName(tp.name.map(_ + "CoreIntXbar")) |     val coreIntXbar = LazyModule(new IntXbar).suggestName(tp.name.map(_ + "CoreIntXbar")) | ||||||
|     lip.foreach { coreIntXbar.intnode := _ }                 // lip |     lip.foreach { coreIntXbar.intnode := _ }                 // lip | ||||||
| @@ -139,7 +134,7 @@ trait HasRocketTiles extends HasTiles | |||||||
|  |  | ||||||
|     wrapper.rocket.intOutputNode.foreach { i =>              // 4. conditionally crosses |     wrapper.rocket.intOutputNode.foreach { i =>              // 4. conditionally crosses | ||||||
|       plic.intnode := FlipRendering { implicit p => |       plic.intnode := FlipRendering { implicit p => | ||||||
|         wrapper.cross(name = tp.name.map(_ + "PeriphIntOutput"))(x = i) |         wrapper.crossIntIn := i | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ package object interrupts | |||||||
| { | { | ||||||
|   type IntInwardNode = InwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, Vec[Bool]] |   type IntInwardNode = InwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, Vec[Bool]] | ||||||
|   type IntOutwardNode = OutwardNodeHandle[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 IntSyncInwardNode = InwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, SyncInterrupts] | ||||||
|   type IntSyncOutwardNode = OutwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, SyncInterrupts] |   type IntSyncOutwardNode = OutwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, SyncInterrupts] | ||||||
| } | } | ||||||
|   | |||||||
| @@ -191,7 +191,7 @@ class RocketTileWrapper( | |||||||
|     params: RocketTileParams, |     params: RocketTileParams, | ||||||
|     val crossing: CoreplexClockCrossing, |     val crossing: CoreplexClockCrossing, | ||||||
|     val boundaryBuffers: Boolean = false) |     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)) |   val rocket = LazyModule(new RocketTile(params)) | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user