diff --git a/macros/src/main/scala/ValName.scala b/macros/src/main/scala/ValName.scala index 962073b3..de82717d 100644 --- a/macros/src/main/scala/ValName.scala +++ b/macros/src/main/scala/ValName.scala @@ -15,7 +15,7 @@ object ValNameImpl def allOwners(s: c.Symbol): Seq[c.Symbol] = if (s == `NoSymbol`) Nil else s +: allOwners(s.owner) val terms = allOwners(c.internal.enclosingOwner).filter(_.isTerm).map(_.asTerm) - terms.filter(_.isVal).map(_.name.toString).find(_(0) != '$').map { s => + terms.filter(t => t.isVal || t.isLazy).map(_.name.toString).find(_(0) != '$').map { s => val trim = s.replaceAll("\\s", "") c.Expr[ValNameImpl] { q"_root_.freechips.rocketchip.macros.ValNameImpl(${trim})" } }.getOrElse(c.abort(c.enclosingPosition, "Not a valid application.")) diff --git a/src/main/scala/amba/ahb/Nodes.scala b/src/main/scala/amba/ahb/Nodes.scala index c104f9d9..95727ecc 100644 --- a/src/main/scala/amba/ahb/Nodes.scala +++ b/src/main/scala/amba/ahb/Nodes.scala @@ -24,10 +24,8 @@ case class AHBMasterNode(portParams: Seq[AHBMasterPortParameters])(implicit valN case class AHBSlaveNode(portParams: Seq[AHBSlavePortParameters])(implicit valName: ValName) extends SinkNode(AHBImp)(portParams) case class AHBNexusNode( masterFn: Seq[AHBMasterPortParameters] => AHBMasterPortParameters, - slaveFn: Seq[AHBSlavePortParameters] => AHBSlavePortParameters, - numMasterPorts: Range.Inclusive = 1 to 999, - numSlavePorts: Range.Inclusive = 1 to 999)( + slaveFn: Seq[AHBSlavePortParameters] => AHBSlavePortParameters)( implicit valName: ValName) - extends NexusNode(AHBImp)(masterFn, slaveFn, numMasterPorts, numSlavePorts) + extends NexusNode(AHBImp)(masterFn, slaveFn) case class AHBIdentityNode()(implicit valName: ValName) extends IdentityNode(AHBImp)() diff --git a/src/main/scala/amba/ahb/ToTL.scala b/src/main/scala/amba/ahb/ToTL.scala index 4b0484ba..c3a97633 100644 --- a/src/main/scala/amba/ahb/ToTL.scala +++ b/src/main/scala/amba/ahb/ToTL.scala @@ -138,5 +138,9 @@ class AHBToTL()(implicit p: Parameters) extends LazyModule object AHBToTL { - def apply()(implicit p: Parameters) = LazyModule(new AHBToTL).node + def apply()(implicit p: Parameters) = + { + val ahb2tl = LazyModule(new AHBToTL) + ahb2tl.node + } } diff --git a/src/main/scala/amba/ahb/Xbar.scala b/src/main/scala/amba/ahb/Xbar.scala index 5298a441..2d52b611 100644 --- a/src/main/scala/amba/ahb/Xbar.scala +++ b/src/main/scala/amba/ahb/Xbar.scala @@ -10,37 +10,40 @@ import scala.math.{min,max} class AHBFanout()(implicit p: Parameters) extends LazyModule { val node = AHBNexusNode( - numSlavePorts = 1 to 1, - numMasterPorts = 1 to 32, masterFn = { case Seq(m) => m }, slaveFn = { seq => seq(0).copy(slaves = seq.flatMap(_.slaves)) }) lazy val module = new LazyModuleImp(this) { - // Require consistent bus widths - val (io_out, edgesOut) = node.out.unzip - val port0 = edgesOut(0).slave - edgesOut.foreach { edge => - val port = edge.slave - require (port.beatBytes == port0.beatBytes, - s"${port.slaves.map(_.name)} ${port.beatBytes} vs ${port0.slaves.map(_.name)} ${port0.beatBytes}") + if (node.edges.in.size >= 1) { + require (node.edges.in.size == 1, "AHBFanout does not support multiple masters") + require (node.edges.out.size > 0, "AHBFanout requires at least one slave") + + // Require consistent bus widths + val (io_out, edgesOut) = node.out.unzip + val port0 = edgesOut(0).slave + edgesOut.foreach { edge => + val port = edge.slave + require (port.beatBytes == port0.beatBytes, + s"${port.slaves.map(_.name)} ${port.beatBytes} vs ${port0.slaves.map(_.name)} ${port0.beatBytes}") + } + + val port_addrs = edgesOut.map(_.slave.slaves.map(_.address).flatten) + val routingMask = AddressDecoder(port_addrs) + val route_addrs = port_addrs.map(_.map(_.widen(~routingMask)).distinct) + + val (in, _) = node.in(0) + val a_sel = Vec(route_addrs.map(seq => seq.map(_.contains(in.haddr)).reduce(_ || _))) + val d_sel = Reg(a_sel) + + when (in.hready) { d_sel := a_sel } + (a_sel zip io_out) foreach { case (sel, out) => + out := in + out.hsel := in.hsel && sel + } + + in.hreadyout := !Mux1H(d_sel, io_out.map(!_.hreadyout)) + in.hresp := Mux1H(d_sel, io_out.map(_.hresp)) + in.hrdata := Mux1H(d_sel, io_out.map(_.hrdata)) } - - val port_addrs = edgesOut.map(_.slave.slaves.map(_.address).flatten) - val routingMask = AddressDecoder(port_addrs) - val route_addrs = port_addrs.map(_.map(_.widen(~routingMask)).distinct) - - val (in, _) = node.in(0) - val a_sel = Vec(route_addrs.map(seq => seq.map(_.contains(in.haddr)).reduce(_ || _))) - val d_sel = Reg(a_sel) - - when (in.hready) { d_sel := a_sel } - (a_sel zip io_out) foreach { case (sel, out) => - out := in - out.hsel := in.hsel && sel - } - - in.hreadyout := !Mux1H(d_sel, io_out.map(!_.hreadyout)) - in.hresp := Mux1H(d_sel, io_out.map(_.hresp)) - in.hrdata := Mux1H(d_sel, io_out.map(_.hrdata)) } } diff --git a/src/main/scala/amba/ahb/package.scala b/src/main/scala/amba/ahb/package.scala index f7c080ee..f8e3576d 100644 --- a/src/main/scala/amba/ahb/package.scala +++ b/src/main/scala/amba/ahb/package.scala @@ -7,7 +7,7 @@ import freechips.rocketchip.diplomacy._ package object ahb { - type AHBOutwardNode = OutwardNodeHandle[AHBMasterPortParameters, AHBSlavePortParameters, AHBBundle] - type AHBInwardNode = InwardNodeHandle[AHBMasterPortParameters, AHBSlavePortParameters, AHBBundle] - type AHBNode = SimpleNodeHandle[AHBMasterPortParameters, AHBSlavePortParameters, AHBBundle] + type AHBOutwardNode = OutwardNodeHandle[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBBundle] + type AHBInwardNode = InwardNodeHandle[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBBundle] + type AHBNode = SimpleNodeHandle[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBBundle] } diff --git a/src/main/scala/amba/apb/Nodes.scala b/src/main/scala/amba/apb/Nodes.scala index 47e67dbc..cc09a9d9 100644 --- a/src/main/scala/amba/apb/Nodes.scala +++ b/src/main/scala/amba/apb/Nodes.scala @@ -23,10 +23,8 @@ case class APBMasterNode(portParams: Seq[APBMasterPortParameters])(implicit valN case class APBSlaveNode(portParams: Seq[APBSlavePortParameters])(implicit valName: ValName) extends SinkNode(APBImp)(portParams) case class APBNexusNode( masterFn: Seq[APBMasterPortParameters] => APBMasterPortParameters, - slaveFn: Seq[APBSlavePortParameters] => APBSlavePortParameters, - numMasterPorts: Range.Inclusive = 1 to 1, - numSlavePorts: Range.Inclusive = 1 to 1)( + slaveFn: Seq[APBSlavePortParameters] => APBSlavePortParameters)( implicit valName: ValName) - extends NexusNode(APBImp)(masterFn, slaveFn, numMasterPorts, numSlavePorts) + extends NexusNode(APBImp)(masterFn, slaveFn) case class APBIdentityNode()(implicit valName: ValName) extends IdentityNode(APBImp)() diff --git a/src/main/scala/amba/apb/Xbar.scala b/src/main/scala/amba/apb/Xbar.scala index c72e6547..b4a5bf9b 100644 --- a/src/main/scala/amba/apb/Xbar.scala +++ b/src/main/scala/amba/apb/Xbar.scala @@ -10,36 +10,39 @@ import scala.math.{min,max} class APBFanout()(implicit p: Parameters) extends LazyModule { val node = APBNexusNode( - numSlavePorts = 1 to 1, - numMasterPorts = 1 to 32, masterFn = { case Seq(m) => m }, slaveFn = { seq => seq(0).copy(slaves = seq.flatMap(_.slaves)) }) lazy val module = new LazyModuleImp(this) { - val (in, _) = node.in(0) + if (node.edges.in.size >= 1) { + require (node.edges.in.size == 1, "APBFanout does not support multiple masters") + require (node.edges.out.size > 0, "APBFanout requires at least one slave") - // Require consistent bus widths - val (io_out, edgesOut) = node.out.unzip - val port0 = edgesOut(0).slave - edgesOut.foreach { edge => - val port = edge.slave - require (port.beatBytes == port0.beatBytes, - s"${port.slaves.map(_.name)} ${port.beatBytes} vs ${port0.slaves.map(_.name)} ${port0.beatBytes}") + val (in, _) = node.in(0) + + // Require consistent bus widths + val (io_out, edgesOut) = node.out.unzip + val port0 = edgesOut(0).slave + edgesOut.foreach { edge => + val port = edge.slave + require (port.beatBytes == port0.beatBytes, + s"${port.slaves.map(_.name)} ${port.beatBytes} vs ${port0.slaves.map(_.name)} ${port0.beatBytes}") + } + + val port_addrs = edgesOut.map(_.slave.slaves.map(_.address).flatten) + val routingMask = AddressDecoder(port_addrs) + val route_addrs = port_addrs.map(_.map(_.widen(~routingMask)).distinct) + + val sel = Vec(route_addrs.map(seq => seq.map(_.contains(in.paddr)).reduce(_ || _))) + (sel zip io_out) foreach { case (sel, out) => + out := in + out.psel := sel && in.psel + out.penable := sel && in.penable + } + + in.pready := !Mux1H(sel, io_out.map(!_.pready)) + in.pslverr := Mux1H(sel, io_out.map(_.pslverr)) + in.prdata := Mux1H(sel, io_out.map(_.prdata)) } - - val port_addrs = edgesOut.map(_.slave.slaves.map(_.address).flatten) - val routingMask = AddressDecoder(port_addrs) - val route_addrs = port_addrs.map(_.map(_.widen(~routingMask)).distinct) - - val sel = Vec(route_addrs.map(seq => seq.map(_.contains(in.paddr)).reduce(_ || _))) - (sel zip io_out) foreach { case (sel, out) => - out := in - out.psel := sel && in.psel - out.penable := sel && in.penable - } - - in.pready := !Mux1H(sel, io_out.map(!_.pready)) - in.pslverr := Mux1H(sel, io_out.map(_.pslverr)) - in.prdata := Mux1H(sel, io_out.map(_.prdata)) } } diff --git a/src/main/scala/amba/apb/package.scala b/src/main/scala/amba/apb/package.scala index 7a1a5432..5ab9bce0 100644 --- a/src/main/scala/amba/apb/package.scala +++ b/src/main/scala/amba/apb/package.scala @@ -7,7 +7,7 @@ import freechips.rocketchip.diplomacy._ package object apb { - type APBOutwardNode = OutwardNodeHandle[APBMasterPortParameters, APBSlavePortParameters, APBBundle] - type APBInwardNode = InwardNodeHandle[APBMasterPortParameters, APBSlavePortParameters, APBBundle] - type APBNode = SimpleNodeHandle[APBMasterPortParameters, APBSlavePortParameters, APBBundle] + type APBOutwardNode = OutwardNodeHandle[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBBundle] + type APBInwardNode = InwardNodeHandle[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBBundle] + type APBNode = SimpleNodeHandle[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBBundle] } diff --git a/src/main/scala/amba/axi4/AsyncCrossing.scala b/src/main/scala/amba/axi4/AsyncCrossing.scala index 0eb9daf3..3110ef23 100644 --- a/src/main/scala/amba/axi4/AsyncCrossing.scala +++ b/src/main/scala/amba/axi4/AsyncCrossing.scala @@ -43,12 +43,18 @@ class AXI4AsyncCrossingSink(depth: Int = 8, sync: Int = 3)(implicit p: Parameter object AXI4AsyncCrossingSource { - def apply(sync: Int = 3)(implicit p: Parameters) = LazyModule(new AXI4AsyncCrossingSource(sync)).node + def apply(sync: Int = 3)(implicit p: Parameters) = { + val axi4asource = LazyModule(new AXI4AsyncCrossingSource(sync)) + axi4asource.node + } } object AXI4AsyncCrossingSink { - def apply(depth: Int = 8, sync: Int = 3)(implicit p: Parameters) = LazyModule(new AXI4AsyncCrossingSink(depth, sync)).node + def apply(depth: Int = 8, sync: Int = 3)(implicit p: Parameters) = { + val axi4asink = LazyModule(new AXI4AsyncCrossingSink(depth, sync)) + axi4asink.node + } } @deprecated("AXI4AsyncCrossing is fragile. Use AXI4AsyncCrossingSource and AXI4AsyncCrossingSink", "rocket-chip 1.2") @@ -99,5 +105,6 @@ class AXI4RAMAsyncCrossing(txns: Int)(implicit p: Parameters) extends LazyModule } class AXI4RAMAsyncCrossingTest(txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { - io.finished := Module(LazyModule(new AXI4RAMAsyncCrossing(txns)).module).io.finished + val dut = Module(LazyModule(new AXI4RAMAsyncCrossing(txns)).module) + io.finished := dut.io.finished } diff --git a/src/main/scala/amba/axi4/Buffer.scala b/src/main/scala/amba/axi4/Buffer.scala index af51b6dd..1bd186d0 100644 --- a/src/main/scala/amba/axi4/Buffer.scala +++ b/src/main/scala/amba/axi4/Buffer.scala @@ -53,5 +53,9 @@ object AXI4Buffer w: BufferParams, b: BufferParams, ar: BufferParams, - r: BufferParams)(implicit p: Parameters): AXI4Node = LazyModule(new AXI4Buffer(aw, w, b, ar, r)).node + r: BufferParams)(implicit p: Parameters): AXI4Node = + { + val axi4buf = LazyModule(new AXI4Buffer(aw, w, b, ar, r)) + axi4buf.node + } } diff --git a/src/main/scala/amba/axi4/Deinterleaver.scala b/src/main/scala/amba/axi4/Deinterleaver.scala index bdc9db39..1dc7862f 100644 --- a/src/main/scala/amba/axi4/Deinterleaver.scala +++ b/src/main/scala/amba/axi4/Deinterleaver.scala @@ -99,5 +99,9 @@ class AXI4Deinterleaver(maxReadBytes: Int)(implicit p: Parameters) extends LazyM object AXI4Deinterleaver { - def apply(maxReadBytes: Int)(implicit p: Parameters): AXI4Node = LazyModule(new AXI4Deinterleaver(maxReadBytes)).node + def apply(maxReadBytes: Int)(implicit p: Parameters): AXI4Node = + { + val axi4deint = LazyModule(new AXI4Deinterleaver(maxReadBytes)) + axi4deint.node + } } diff --git a/src/main/scala/amba/axi4/Delayer.scala b/src/main/scala/amba/axi4/Delayer.scala index 2ca6d1b2..cc7013f0 100644 --- a/src/main/scala/amba/axi4/Delayer.scala +++ b/src/main/scala/amba/axi4/Delayer.scala @@ -79,5 +79,9 @@ class AXI4Delayer(q: Double)(implicit p: Parameters) extends LazyModule object AXI4Delayer { - def apply(q: Double)(implicit p: Parameters): AXI4Node = LazyModule(new AXI4Delayer(q)).node + def apply(q: Double)(implicit p: Parameters): AXI4Node = + { + val axi4delay = LazyModule(new AXI4Delayer(q)) + axi4delay.node + } } diff --git a/src/main/scala/amba/axi4/Filter.scala b/src/main/scala/amba/axi4/Filter.scala index 99a2e9ca..7eee69aa 100644 --- a/src/main/scala/amba/axi4/Filter.scala +++ b/src/main/scala/amba/axi4/Filter.scala @@ -58,5 +58,9 @@ object AXI4Filter def apply( Sfilter: AXI4SlaveParameters => Option[AXI4SlaveParameters] = AXI4Filter.Sidentity, Mfilter: AXI4MasterParameters => Option[AXI4MasterParameters] = AXI4Filter.Midentity - )(implicit p: Parameters): AXI4Node = LazyModule(new AXI4Filter(Sfilter, Mfilter)).node + )(implicit p: Parameters): AXI4Node = + { + val axi4filt = LazyModule(new AXI4Filter(Sfilter, Mfilter)) + axi4filt.node + } } diff --git a/src/main/scala/amba/axi4/Fragmenter.scala b/src/main/scala/amba/axi4/Fragmenter.scala index b1897f84..cfffcd33 100644 --- a/src/main/scala/amba/axi4/Fragmenter.scala +++ b/src/main/scala/amba/axi4/Fragmenter.scala @@ -199,5 +199,9 @@ class AXI4Fragmenter()(implicit p: Parameters) extends LazyModule object AXI4Fragmenter { - def apply()(implicit p: Parameters): AXI4Node = LazyModule(new AXI4Fragmenter).node + def apply()(implicit p: Parameters): AXI4Node = + { + val axi4frag = LazyModule(new AXI4Fragmenter) + axi4frag.node + } } diff --git a/src/main/scala/amba/axi4/IdIndexer.scala b/src/main/scala/amba/axi4/IdIndexer.scala index d83bf185..d9ef1323 100644 --- a/src/main/scala/amba/axi4/IdIndexer.scala +++ b/src/main/scala/amba/axi4/IdIndexer.scala @@ -75,5 +75,9 @@ class AXI4IdIndexer(idBits: Int)(implicit p: Parameters) extends LazyModule object AXI4IdIndexer { - def apply(idBits: Int)(implicit p: Parameters): AXI4Node = LazyModule(new AXI4IdIndexer(idBits)).node + def apply(idBits: Int)(implicit p: Parameters): AXI4Node = + { + val axi4index = LazyModule(new AXI4IdIndexer(idBits)) + axi4index.node + } } diff --git a/src/main/scala/amba/axi4/Nodes.scala b/src/main/scala/amba/axi4/Nodes.scala index 172feff2..e4815046 100644 --- a/src/main/scala/amba/axi4/Nodes.scala +++ b/src/main/scala/amba/axi4/Nodes.scala @@ -23,17 +23,14 @@ case class AXI4MasterNode(portParams: Seq[AXI4MasterPortParameters])(implicit va case class AXI4SlaveNode(portParams: Seq[AXI4SlavePortParameters])(implicit valName: ValName) extends SinkNode(AXI4Imp)(portParams) case class AXI4NexusNode( masterFn: Seq[AXI4MasterPortParameters] => AXI4MasterPortParameters, - slaveFn: Seq[AXI4SlavePortParameters] => AXI4SlavePortParameters, - numMasterPorts: Range.Inclusive = 1 to 999, - numSlavePorts: Range.Inclusive = 1 to 999)( + slaveFn: Seq[AXI4SlavePortParameters] => AXI4SlavePortParameters)( implicit valName: ValName) - extends NexusNode(AXI4Imp)(masterFn, slaveFn, numMasterPorts, numSlavePorts) + extends NexusNode(AXI4Imp)(masterFn, slaveFn) case class AXI4AdapterNode( masterFn: AXI4MasterPortParameters => AXI4MasterPortParameters = { m => m }, - slaveFn: AXI4SlavePortParameters => AXI4SlavePortParameters = { s => s }, - numPorts: Range.Inclusive = 0 to 999)( + slaveFn: AXI4SlavePortParameters => AXI4SlavePortParameters = { s => s })( implicit valName: ValName) - extends AdapterNode(AXI4Imp)(masterFn, slaveFn, numPorts) + extends AdapterNode(AXI4Imp)(masterFn, slaveFn) case class AXI4IdentityNode()(implicit valName: ValName) extends IdentityNode(AXI4Imp)() object AXI4AsyncImp extends SimpleNodeImp[AXI4AsyncMasterPortParameters, AXI4AsyncSlavePortParameters, AXI4AsyncEdgeParameters, AXI4AsyncBundle] diff --git a/src/main/scala/amba/axi4/SRAM.scala b/src/main/scala/amba/axi4/SRAM.scala index 26e5a318..bf9108bb 100644 --- a/src/main/scala/amba/axi4/SRAM.scala +++ b/src/main/scala/amba/axi4/SRAM.scala @@ -99,5 +99,9 @@ object AXI4RAM beatBytes: Int = 4, devName: Option[String] = None, errors: Seq[AddressSet] = Nil) - (implicit p: Parameters) = LazyModule(new AXI4RAM(address, executable, beatBytes, devName, errors)).node + (implicit p: Parameters) = + { + val axi4ram = LazyModule(new AXI4RAM(address, executable, beatBytes, devName, errors)) + axi4ram.node + } } diff --git a/src/main/scala/amba/axi4/ToTL.scala b/src/main/scala/amba/axi4/ToTL.scala index 207a0353..4e27e4bf 100644 --- a/src/main/scala/amba/axi4/ToTL.scala +++ b/src/main/scala/amba/axi4/ToTL.scala @@ -160,5 +160,9 @@ class AXI4BundleRError(params: AXI4BundleParameters) extends AXI4BundleBase(para object AXI4ToTL { - def apply()(implicit p: Parameters) = LazyModule(new AXI4ToTL).node + def apply()(implicit p: Parameters) = + { + val axi42tl = LazyModule(new AXI4ToTL) + axi42tl.node + } } diff --git a/src/main/scala/amba/axi4/UserYanker.scala b/src/main/scala/amba/axi4/UserYanker.scala index f4c91808..c8bdf40f 100644 --- a/src/main/scala/amba/axi4/UserYanker.scala +++ b/src/main/scala/amba/axi4/UserYanker.scala @@ -91,5 +91,9 @@ class AXI4UserYanker(capMaxFlight: Option[Int] = None)(implicit p: Parameters) e object AXI4UserYanker { - def apply(capMaxFlight: Option[Int] = None)(implicit p: Parameters): AXI4Node = LazyModule(new AXI4UserYanker(capMaxFlight)).node + def apply(capMaxFlight: Option[Int] = None)(implicit p: Parameters): AXI4Node = + { + val axi4yank = LazyModule(new AXI4UserYanker(capMaxFlight)) + axi4yank.node + } } diff --git a/src/main/scala/amba/axi4/Xbar.scala b/src/main/scala/amba/axi4/Xbar.scala index eab6d3b9..ad5c0349 100644 --- a/src/main/scala/amba/axi4/Xbar.scala +++ b/src/main/scala/amba/axi4/Xbar.scala @@ -18,8 +18,6 @@ class AXI4Xbar( require (awQueueDepth >= 1) val node = AXI4NexusNode( - numMasterPorts = 1 to 999, - numSlavePorts = 1 to 999, masterFn = { seq => seq(0).copy( userBits = seq.map(_.userBits).max, @@ -56,14 +54,14 @@ class AXI4Xbar( val awIn = Seq.fill(io_in .size) { Module(new Queue(UInt(width = io_out.size), awQueueDepth, flow = true)) } val awOut = Seq.fill(io_out.size) { Module(new Queue(UInt(width = io_in .size), awQueueDepth, flow = true)) } - val requestARIO = Vec(io_in.map { i => Vec(outputPorts.map { o => o(i.ar.bits.addr) }) }) - val requestAWIO = Vec(io_in.map { i => Vec(outputPorts.map { o => o(i.aw.bits.addr) }) }) - val requestROI = Vec(io_out.map { o => Vec(inputIdRanges.map { i => i.contains(o.r.bits.id) }) }) - val requestBOI = Vec(io_out.map { o => Vec(inputIdRanges.map { i => i.contains(o.b.bits.id) }) }) + val requestARIO = io_in.map { i => Vec(outputPorts.map { o => o(i.ar.bits.addr) }) } + val requestAWIO = io_in.map { i => Vec(outputPorts.map { o => o(i.aw.bits.addr) }) } + val requestROI = io_out.map { o => inputIdRanges.map { i => i.contains(o.r.bits.id) } } + val requestBOI = io_out.map { o => inputIdRanges.map { i => i.contains(o.b.bits.id) } } // W follows the path dictated by the AW Q for (i <- 0 until io_in.size) { awIn(i).io.enq.bits := requestAWIO(i).asUInt } - val requestWIO = Vec(awIn.map { q => if (io_out.size > 1) Vec(q.io.deq.bits.toBools) else Vec.fill(1){Bool(true)} }) + val requestWIO = awIn.map { q => if (io_out.size > 1) q.io.deq.bits.toBools else Seq(Bool(true)) } // We need an intermediate size of bundle with the widest possible identifiers val wide_bundle = AXI4BundleParameters.union(io_in.map(_.params) ++ io_out.map(_.params)) @@ -207,7 +205,11 @@ object AXI4Xbar def apply( arbitrationPolicy: TLArbiter.Policy = TLArbiter.roundRobin, maxFlightPerId: Int = 7, - awQueueDepth: Int = 2)(implicit p: Parameters) = LazyModule(new AXI4Xbar(arbitrationPolicy, maxFlightPerId, awQueueDepth)).node + awQueueDepth: Int = 2)(implicit p: Parameters) = + { + val axi4xbar = LazyModule(new AXI4Xbar(arbitrationPolicy, maxFlightPerId, awQueueDepth)) + axi4xbar.node + } def mapInputIds(ports: Seq[AXI4MasterPortParameters]) = TLXbar.assignRanges(ports.map(_.endId)).map(_.get) diff --git a/src/main/scala/amba/axi4/package.scala b/src/main/scala/amba/axi4/package.scala index 661c6650..8ac107f8 100644 --- a/src/main/scala/amba/axi4/package.scala +++ b/src/main/scala/amba/axi4/package.scala @@ -7,7 +7,7 @@ import freechips.rocketchip.diplomacy._ package object axi4 { - type AXI4Node = SimpleNodeHandle[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4Bundle] - type AXI4OutwardNode = OutwardNodeHandle[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4Bundle] - type AXI4InwardNode = InwardNodeHandle[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4Bundle] + type AXI4Node = SimpleNodeHandle[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4Bundle] + type AXI4OutwardNode = OutwardNodeHandle[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4Bundle] + type AXI4InwardNode = InwardNodeHandle[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4Bundle] } diff --git a/src/main/scala/coreplex/CrossingWrapper.scala b/src/main/scala/coreplex/CrossingWrapper.scala index ec638ebb..b8955b75 100644 --- a/src/main/scala/coreplex/CrossingWrapper.scala +++ b/src/main/scala/coreplex/CrossingWrapper.scala @@ -51,20 +51,20 @@ trait HasCrossingMethods extends LazyModule with LazyScope } 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 } + lazy val asource = LazyModule(new TLAsyncCrossingSource(sync)) + lazy val asink = LazyModule(new TLAsyncCrossingSink(depth, sync)) + val source = if (out) this { asource } else asource + val sink = if (out) asink else this { asink } sink.node :=? source.node checks = CrossingCheck(out, source.node, sink.node) :: checks 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 } + lazy val rsource = LazyModule(new TLRationalCrossingSource) + lazy val rsink = LazyModule(new TLRationalCrossingSink(if (out) direction else direction.flip)) + val source = if (out) this { rsource } else rsource + val sink = if (out) rsink else this { rsink } sink.node :=? source.node checks = CrossingCheck(out, source.node, sink.node) :: checks NodeHandle(source.node, sink.node) @@ -98,10 +98,10 @@ trait HasCrossingMethods extends LazyModule with LazyScope } def crossAXI4AsyncInOut(out: Boolean)(depth: Int = 8, sync: Int = 3)(implicit p: Parameters): AXI4Node = { - def sourceGen = LazyModule(new AXI4AsyncCrossingSource(sync)) - def sinkGen = LazyModule(new AXI4AsyncCrossingSink(depth, sync)) - val source = if (out) this { sourceGen } else sourceGen - val sink = if (out) sinkGen else this { sinkGen } + lazy val axi4asource = LazyModule(new AXI4AsyncCrossingSource(sync)) + lazy val axi4asink = LazyModule(new AXI4AsyncCrossingSink(depth, sync)) + val source = if (out) this { axi4asource } else axi4asource + val sink = if (out) axi4asink else this { axi4asink } sink.node :=? source.node checks = CrossingCheck(out, source.node, sink.node) :: checks NodeHandle(source.node, sink.node) @@ -127,30 +127,30 @@ trait HasCrossingMethods extends LazyModule with LazyScope // 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 } + lazy val intssource = LazyModule(new IntSyncCrossingSource(alreadyRegistered)) + lazy val intssink = LazyModule(new IntSyncCrossingSink(0)) + val source = if (out) this { intssource } else intssource + val sink = if (out) intssink else this { intssink } sink.node :=? source.node checks = CrossingCheck(out, source.node, sink.node) :: checks 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 } + lazy val intasource = LazyModule(new IntSyncCrossingSource(alreadyRegistered)) + lazy val intasink = LazyModule(new IntSyncCrossingSink(sync)) + val source = if (out) this { intasource } else intasource + val sink = if (out) intasink else this { intasink } sink.node :=? source.node checks = CrossingCheck(out, source.node, sink.node) :: checks 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 } + lazy val intrsource = LazyModule(new IntSyncCrossingSource(alreadyRegistered)) + lazy val intrsink = LazyModule(new IntSyncCrossingSink(1)) + val source = if (out) this { intrsource } else intrsource + val sink = if (out) intrsink else this { intrsink } sink.node :=? source.node checks = CrossingCheck(out, source.node, sink.node) :: checks NodeHandle(source.node, sink.node) diff --git a/src/main/scala/coreplex/FrontBus.scala b/src/main/scala/coreplex/FrontBus.scala index ce3e95f9..dc325701 100644 --- a/src/main/scala/coreplex/FrontBus.scala +++ b/src/main/scala/coreplex/FrontBus.scala @@ -38,7 +38,7 @@ class FrontBus(params: FrontBusParams)(implicit p: Parameters) extends TLBusWrap def fromCoherentChip: TLInwardNode = inwardNode - def toSystemBus : TLOutwardNode = outwardBufNode + def toSystemBus : TLOutwardNode = TLBuffer(params.slaveBuffering) :=* xbar.node } @@ -51,5 +51,5 @@ trait HasFrontBus extends HasSystemBus { val fbus = LazyModule(new FrontBus(frontbusParams)) - FlipRendering { implicit p => sbus.fromFrontBus := fbus.toSystemBus } + FlipRendering { implicit p => sbus.fromFrontBus :=* fbus.toSystemBus } } diff --git a/src/main/scala/coreplex/PeripheryBus.scala b/src/main/scala/coreplex/PeripheryBus.scala index 9faee504..66af8ef4 100644 --- a/src/main/scala/coreplex/PeripheryBus.scala +++ b/src/main/scala/coreplex/PeripheryBus.scala @@ -33,7 +33,7 @@ class PeripheryBus(params: PeripheryBusParams)(implicit p: Parameters) extends T val fromSystemBus: TLInwardNode = { val atomics = LazyModule(new TLAtomicAutomata(arithmetic = params.arithmetic)) - inwardBufNode := atomics.node + xbar.node :*= TLBuffer(params.masterBuffering) :*= atomics.node } def toTile(name: Option[String] = None)(gen: Parameters => TLInwardNode) { @@ -59,5 +59,5 @@ trait HasPeripheryBus extends HasSystemBus { val pbus = LazyModule(new PeripheryBus(pbusParams)) // The peripheryBus hangs off of systemBus; here we convert TL-UH -> TL-UL - pbus.fromSystemBus := sbus.toPeripheryBus() + pbus.fromSystemBus :*= sbus.toPeripheryBus() } diff --git a/src/main/scala/coreplex/SystemBus.scala b/src/main/scala/coreplex/SystemBus.scala index 875a8eb0..7bce33da 100644 --- a/src/main/scala/coreplex/SystemBus.scala +++ b/src/main/scala/coreplex/SystemBus.scala @@ -39,7 +39,7 @@ class SystemBus(params: SystemBusParams)(implicit p: Parameters) extends TLBusWr def toSplitSlaves: TLOutwardNode = outwardSplitNode def toPeripheryBus(addBuffers: Int = 0): TLOutwardNode = { - TLBuffer.chain(addBuffers).foldRight(pbus_fixer.node:TLOutwardNode)(_ := _) + TLBuffer.chain(addBuffers).foldRight(pbus_fixer.node:TLOutwardNode)(_ :*= _) } val toMemoryBus: TLOutwardNode = outwardNode diff --git a/src/main/scala/devices/debug/Debug.scala b/src/main/scala/devices/debug/Debug.scala index a0da5a04..9167a715 100644 --- a/src/main/scala/devices/debug/Debug.scala +++ b/src/main/scala/devices/debug/Debug.scala @@ -279,11 +279,9 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod import DMI_RegAddrs._ val intnode = IntNexusNode( - numSourcePorts = 1 to 1024, - numSinkPorts = 0 to 0, sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(1, Seq(Resource(device, "int"))))) }, - sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) } - ) + sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }, + outputRequiresInput = false) val dmiNode = TLRegisterNode ( address = AddressSet.misaligned(DMI_DMCONTROL << 2, 4), @@ -293,6 +291,7 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod ) lazy val module = new LazyModuleImp(this) { + require (intnode.edges.in.size == 0, "Debug Module does not accept interrupts") val nComponents = intnode.out.size diff --git a/src/main/scala/devices/tilelink/BusBypass.scala b/src/main/scala/devices/tilelink/BusBypass.scala index 03989899..4433d535 100644 --- a/src/main/scala/devices/tilelink/BusBypass.scala +++ b/src/main/scala/devices/tilelink/BusBypass.scala @@ -37,14 +37,21 @@ class TLBusBypass(beatBytes: Int)(implicit p: Parameters) extends TLBusBypassBas } } +class TLBypassNode(implicit valName: ValName) extends TLCustomNode +{ + def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { + require (iStars == 0 && oStars == 0, "TLBypass node does not support :=* or :*=") + require (iKnown == 1, "TLBypass node expects exactly one input") + require (oKnown == 2, "TLBypass node expects exactly one output") + (0, 0) + } + def mapParamsD(n: Int, p: Seq[TLClientPortParameters]): Seq[TLClientPortParameters] = { p ++ p } + def mapParamsU(n: Int, p: Seq[TLManagerPortParameters]): Seq[TLManagerPortParameters] = { p.tail } +} + class TLBusBypassBar(implicit p: Parameters) extends LazyModule { - // The client only sees the second slave port - val node = TLNexusNode( - numClientPorts = 2 to 2 , - numManagerPorts = 1 to 1, - clientFn = { seq => seq(0) }, - managerFn = { seq => seq(1) }) + val node = new TLBypassNode() lazy val module = new LazyModuleImp(this) { val io = IO(new Bundle { diff --git a/src/main/scala/devices/tilelink/Clint.scala b/src/main/scala/devices/tilelink/Clint.scala index 9cc83030..94a75fee 100644 --- a/src/main/scala/devices/tilelink/Clint.scala +++ b/src/main/scala/devices/tilelink/Clint.scala @@ -48,12 +48,13 @@ class CoreplexLocalInterrupter(params: ClintParams)(implicit p: Parameters) exte beatBytes = p(XLen)/8) val intnode = IntNexusNode( - numSourcePorts = 0 to 1024, - numSinkPorts = 0 to 0, - sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(ints, Seq(Resource(device, "int"))))) }, - sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }) + sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(ints, Seq(Resource(device, "int"))))) }, + sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }, + outputRequiresInput = false) lazy val module = new LazyModuleImp(this) { + require (intnode.edges.in.size == 0, "CLINT only produces interrupts; it does not accept them") + val io = IO(new Bundle { val rtcTick = Bool(INPUT) }) diff --git a/src/main/scala/devices/tilelink/Plic.scala b/src/main/scala/devices/tilelink/Plic.scala index a6ede5b7..ee915e1d 100644 --- a/src/main/scala/devices/tilelink/Plic.scala +++ b/src/main/scala/devices/tilelink/Plic.scala @@ -86,10 +86,10 @@ class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule concurrency = 1) // limiting concurrency handles RAW hazards on claim registers val intnode = IntNexusNode( - numSourcePorts = 0 to 1024, - numSinkPorts = 0 to 1024, - sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(1, Seq(Resource(device, "int"))))) }, - sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }) + sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(1, Seq(Resource(device, "int"))))) }, + sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }, + outputRequiresInput = false, + inputRequiresOutput = false) /* Negotiated sizes */ def nDevices: Int = intnode.edges.in.map(_.source.num).sum diff --git a/src/main/scala/devices/tilelink/TestRAM.scala b/src/main/scala/devices/tilelink/TestRAM.scala index 0bd6eb6d..f73d702c 100644 --- a/src/main/scala/devices/tilelink/TestRAM.scala +++ b/src/main/scala/devices/tilelink/TestRAM.scala @@ -75,5 +75,6 @@ class TLRAMZeroDelay(ramBeatBytes: Int, txns: Int)(implicit p: Parameters) exten } class TLRAMZeroDelayTest(ramBeatBytes: Int, txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { - io.finished := Module(LazyModule(new TLRAMZeroDelay(ramBeatBytes, txns)).module).io.finished + val dut = Module(LazyModule(new TLRAMZeroDelay(ramBeatBytes, txns)).module) + io.finished := dut.io.finished } diff --git a/src/main/scala/diplomacy/Clone.scala b/src/main/scala/diplomacy/Clone.scala new file mode 100644 index 00000000..0eeb1b81 --- /dev/null +++ b/src/main/scala/diplomacy/Clone.scala @@ -0,0 +1,21 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.diplomacy + +import Chisel._ +import chisel3.shim.CloneModule + +final class CloneLazyModule private (val base: LazyModule) +{ + // Pay special attention to the .iParams and .oParams of the node, which + // indicate the parameters a stand-in master must supply. + def clone[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](node: NodeHandle[DI, UI, EI, BI, DO, UO, EO, BO])(implicit valName: ValName) = + new MixedTestNode(node, this) + + protected[diplomacy] lazy val io = CloneModule(base.module) +} + +object CloneLazyModule +{ + def apply(base: LazyModule) = new CloneLazyModule(base) +} diff --git a/src/main/scala/diplomacy/CloneModule.scala b/src/main/scala/diplomacy/CloneModule.scala new file mode 100644 index 00000000..42f7a3ab --- /dev/null +++ b/src/main/scala/diplomacy/CloneModule.scala @@ -0,0 +1,58 @@ +// See LICENSE.SiFive for license details. + +// !!! HACK TO WORK-AROUND MISSING CHISEL FEATURE +// !!! We need to be inside the chisel3 package to access Builder + +package chisel3.shim + +import Chisel._ +import chisel3.experimental.{RawModule, MultiIOModule, BaseModule} +import chisel3.internal.Builder +import chisel3.core.UserModule +import chisel3.internal.firrtl.{Command, DefInstance} +import scala.collection.immutable.ListMap +import scala.collection.mutable.ArrayBuffer + +class ClonePorts protected[shim](elts: Data*) extends Record +{ + val elements = ListMap(elts.map(d => d.instanceName -> d.chiselCloneType): _*) + def apply(field: String) = elements(field) + override def cloneType = (new ClonePorts(elts: _*)).asInstanceOf[this.type] +} + +private class CloneModule private (model: RawModule) extends BlackBox +{ + import CloneModule._ + override def desiredName = model.name + val io = IO(new ClonePorts(model.getPorts.map(_.id): _*)) +} + +object CloneModule +{ + def apply(model: BaseModule): ClonePorts = { + // Create the 'BlackBox' stand-in + val mod = Module(new CloneModule(model.asInstanceOf[RawModule])) + // Rewrite the instance definition to be the original module + // (this is needed because the original module gets clobbered by DCE + constant prop) + val method = classOf[UserModule].getDeclaredMethod("_commands") + method.setAccessible(true) + val commands = method.invoke(Builder.forcedUserModule).asInstanceOf[ArrayBuffer[Command]] + val victimIdx = commands.lastIndexWhere { + case DefInstance(_, kill, _) => mod eq kill + case _ => false + } + val victim = commands(victimIdx).asInstanceOf[DefInstance] + val standin = new DefInstance(victim.sourceInfo, model, victim.ports) { + override def name = victim.name + } + commands.update(victimIdx, standin) + // Wire it up + model match { + case _: MultiIOModule => + mod.io("clock") := Module.clock + mod.io("reset") := Module.reset + case _: RawModule => // Do nothing + } + mod.io + } +} diff --git a/src/main/scala/diplomacy/LazyModule.scala b/src/main/scala/diplomacy/LazyModule.scala index 48243e61..fe0955e8 100644 --- a/src/main/scala/diplomacy/LazyModule.scala +++ b/src/main/scala/diplomacy/LazyModule.scala @@ -36,7 +36,8 @@ abstract class LazyModule()(implicit val p: Parameters) getClass.getMethods.filter { m => m.getParameterTypes.isEmpty && !java.lang.reflect.Modifier.isStatic(m.getModifiers) && - m.getName != "children" + m.getName != "children" && + m.getName != "getChildren" }.flatMap { m => if (classOf[LazyModule].isAssignableFrom(m.getReturnType)) { val obj = m.invoke(this) @@ -126,6 +127,8 @@ abstract class LazyModule()(implicit val p: Parameters) iterfunc(this) children.foreach( _.nodeIterator(iterfunc) ) } + + def getChildren = children } object LazyModule @@ -162,7 +165,9 @@ sealed trait LazyModuleImpLike extends BaseModule protected[diplomacy] def instantiate() = { val childDangles = wrapper.children.reverse.flatMap { c => implicit val sourceInfo = c.info - Module(c.module).dangles + val mod = Module(c.module) + mod.finishInstantiate() + mod.dangles } wrapper.instantiate() val nodeDangles = wrapper.nodes.reverse.flatMap(_.instantiate()) @@ -181,6 +186,10 @@ sealed trait LazyModuleImpLike extends BaseModule } (auto, dangles) } + + protected[diplomacy] def finishInstantiate() { + wrapper.nodes.reverse.foreach { _.finishInstantiate() } + } } class LazyModuleImp(val wrapper: LazyModule) extends MultiIOModule with LazyModuleImpLike { diff --git a/src/main/scala/diplomacy/Nodes.scala b/src/main/scala/diplomacy/Nodes.scala index 7c4b0eb8..b5ea1b4a 100644 --- a/src/main/scala/diplomacy/Nodes.scala +++ b/src/main/scala/diplomacy/Nodes.scala @@ -93,6 +93,7 @@ abstract class BaseNode(implicit val valName: ValName) val serial = BaseNode.serial BaseNode.serial = BaseNode.serial + 1 protected[diplomacy] def instantiate(): Seq[Dangle] + protected[diplomacy] def finishInstantiate(): Unit def name = lazyModule.name + "." + valName.name def omitGraphML = outputs.isEmpty && inputs.isEmpty @@ -122,50 +123,53 @@ object BaseNode trait NoHandle case object NoHandleObject extends NoHandle -trait NodeHandle[DI, UI, BI <: Data, DO, UO, BO <: Data] - extends InwardNodeHandle[DI, UI, BI] with OutwardNodeHandle[DO, UO, BO] +trait NodeHandle[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data] + extends InwardNodeHandle[DI, UI, EI, BI] with OutwardNodeHandle[DO, UO, EO, BO] { // connecting two full nodes => full node - override def := [DX, UX, BX <: Data](h: NodeHandle[DX, UX, BX, DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NodeHandle[DX, UX, BX, DO, UO, BO] = { bind(h, BIND_ONCE); NodeHandle(h, this) } - override def :*= [DX, UX, BX <: Data](h: NodeHandle[DX, UX, BX, DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NodeHandle[DX, UX, BX, DO, UO, BO] = { bind(h, BIND_STAR); NodeHandle(h, this) } - override def :=* [DX, UX, BX <: Data](h: NodeHandle[DX, UX, BX, DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NodeHandle[DX, UX, BX, DO, UO, BO] = { bind(h, BIND_QUERY); NodeHandle(h, this) } - override def :=? [DX, UX, BX <: Data](h: NodeHandle[DX, UX, BX, DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NodeHandle[DX, UX, BX, DO, UO, BO] = { bind(h, p(CardinalityInferenceDirectionKey)); NodeHandle(h, this) } + override def := [DX, UX, EX, BX <: Data, EY](h: NodeHandle[DX, UX, EX, BX, DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NodeHandle[DX, UX, EX, BX, DO, UO, EO, BO] = { bind(h, BIND_ONCE); NodeHandle(h, this) } + override def :*= [DX, UX, EX, BX <: Data, EY](h: NodeHandle[DX, UX, EX, BX, DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NodeHandle[DX, UX, EX, BX, DO, UO, EO, BO] = { bind(h, BIND_STAR); NodeHandle(h, this) } + override def :=* [DX, UX, EX, BX <: Data, EY](h: NodeHandle[DX, UX, EX, BX, DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NodeHandle[DX, UX, EX, BX, DO, UO, EO, BO] = { bind(h, BIND_QUERY); NodeHandle(h, this) } + override def :=? [DX, UX, EX, BX <: Data, EY](h: NodeHandle[DX, UX, EX, BX, DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NodeHandle[DX, UX, EX, BX, DO, UO, EO, BO] = { bind(h, p(CardinalityInferenceDirectionKey)); NodeHandle(h, this) } // connecting a full node with an output => an output - override def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): OutwardNodeHandle[DO, UO, BO] = { bind(h, BIND_ONCE); this } - override def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): OutwardNodeHandle[DO, UO, BO] = { bind(h, BIND_STAR); this } - override def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): OutwardNodeHandle[DO, UO, BO] = { bind(h, BIND_QUERY); this } - override def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): OutwardNodeHandle[DO, UO, BO] = { bind(h, p(CardinalityInferenceDirectionKey)); this } + override def := [EY](h: OutwardNodeHandle[DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): OutwardNodeHandle[DO, UO, EO, BO] = { bind(h, BIND_ONCE); this } + override def :*= [EY](h: OutwardNodeHandle[DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): OutwardNodeHandle[DO, UO, EO, BO] = { bind(h, BIND_STAR); this } + override def :=* [EY](h: OutwardNodeHandle[DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): OutwardNodeHandle[DO, UO, EO, BO] = { bind(h, BIND_QUERY); this } + override def :=? [EY](h: OutwardNodeHandle[DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): OutwardNodeHandle[DO, UO, EO, BO] = { bind(h, p(CardinalityInferenceDirectionKey)); this } } object NodeHandle { - def apply[DI, UI, BI <: Data, DO, UO, BO <: Data](i: InwardNodeHandle[DI, UI, BI], o: OutwardNodeHandle[DO, UO, BO]) = NodeHandlePair(i, o) + def apply[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](i: InwardNodeHandle[DI, UI, EI, BI], o: OutwardNodeHandle[DO, UO, EO, BO]) = new NodeHandlePair(i, o) } -case class NodeHandlePair[DI, UI, BI <: Data, DO, UO, BO <: Data] - (inwardHandle: InwardNodeHandle[DI, UI, BI], outwardHandle: OutwardNodeHandle[DO, UO, BO]) - extends NodeHandle[DI, UI, BI, DO, UO, BO] +class NodeHandlePair[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data] + (inwardHandle: InwardNodeHandle[DI, UI, EI, BI], outwardHandle: OutwardNodeHandle[DO, UO, EO, BO]) + extends NodeHandle[DI, UI, EI, BI, DO, UO, EO, BO] { val inward = inwardHandle.inward val outward = outwardHandle.outward + def inner = inwardHandle.inner + def outer = outwardHandle.outer } -trait InwardNodeHandle[DI, UI, BI <: Data] extends NoHandle +trait InwardNodeHandle[DI, UI, EI, BI <: Data] extends NoHandle { def inward: InwardNode[DI, UI, BI] - def parentsIn: Seq[LazyModule] = inward.parents - def bind(h: OutwardNodeHandle[DI, UI, BI], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo): Unit = inward.bind(h.outward, binding) + def inner: InwardNodeImp[DI, UI, EI, BI] + + protected def bind[EY](h: OutwardNodeHandle[DI, UI, EY, BI], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo): Unit = inward.bind(h.outward, binding) // connecting an input node with a full nodes => an input node - def := [DX, UX, BX <: Data](h: NodeHandle[DX, UX, BX, DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): InwardNodeHandle[DX, UX, BX] = { bind(h, BIND_ONCE); h } - def :*= [DX, UX, BX <: Data](h: NodeHandle[DX, UX, BX, DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): InwardNodeHandle[DX, UX, BX] = { bind(h, BIND_STAR); h } - def :=* [DX, UX, BX <: Data](h: NodeHandle[DX, UX, BX, DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): InwardNodeHandle[DX, UX, BX] = { bind(h, BIND_QUERY); h } - def :=? [DX, UX, BX <: Data](h: NodeHandle[DX, UX, BX, DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): InwardNodeHandle[DX, UX, BX] = { bind(h, p(CardinalityInferenceDirectionKey)); h } + def := [DX, UX, EX, BX <: Data, EY](h: NodeHandle[DX, UX, EX, BX, DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): InwardNodeHandle[DX, UX, EX, BX] = { bind(h, BIND_ONCE); h } + def :*= [DX, UX, EX, BX <: Data, EY](h: NodeHandle[DX, UX, EX, BX, DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): InwardNodeHandle[DX, UX, EX, BX] = { bind(h, BIND_STAR); h } + def :=* [DX, UX, EX, BX <: Data, EY](h: NodeHandle[DX, UX, EX, BX, DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): InwardNodeHandle[DX, UX, EX, BX] = { bind(h, BIND_QUERY); h } + def :=? [DX, UX, EX, BX <: Data, EY](h: NodeHandle[DX, UX, EX, BX, DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): InwardNodeHandle[DX, UX, EX, BX] = { bind(h, p(CardinalityInferenceDirectionKey)); h } // connecting input node with output node => no node - def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NoHandle = { bind(h, BIND_ONCE); NoHandleObject } - def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NoHandle = { bind(h, BIND_STAR); NoHandleObject } - def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NoHandle = { bind(h, BIND_QUERY); NoHandleObject } - def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NoHandle = { bind(h, p(CardinalityInferenceDirectionKey)); NoHandleObject } + def := [EY](h: OutwardNodeHandle[DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NoHandle = { bind(h, BIND_ONCE); NoHandleObject } + def :*= [EY](h: OutwardNodeHandle[DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NoHandle = { bind(h, BIND_STAR); NoHandleObject } + def :=* [EY](h: OutwardNodeHandle[DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NoHandle = { bind(h, BIND_QUERY); NoHandleObject } + def :=? [EY](h: OutwardNodeHandle[DI, UI, EY, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NoHandle = { bind(h, p(CardinalityInferenceDirectionKey)); NoHandleObject } } sealed trait NodeBinding @@ -182,22 +186,14 @@ object NodeBinding } } -trait InwardNode[DI, UI, BI <: Data] extends BaseNode with InwardNodeHandle[DI, UI, BI] +trait InwardNode[DI, UI, BI <: Data] extends BaseNode { - val inward = this - - protected[diplomacy] val numPI: Range.Inclusive - require (!numPI.isEmpty, s"No number of inputs would be acceptable to ${name}${lazyModule.line}") - require (numPI.start >= 0, s"${name} accepts a negative number of inputs${lazyModule.line}") - private val accPI = ListBuffer[(Int, OutwardNode[DI, UI, BI], NodeBinding, Parameters, SourceInfo)]() private var iRealized = false protected[diplomacy] def iPushed = accPI.size protected[diplomacy] def iPush(index: Int, node: OutwardNode[DI, UI, BI], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo) { val info = sourceLine(sourceInfo, " at ", "") - val noIs = numPI.size == 1 && numPI.contains(0) - require (!noIs, s"${name}${lazyModule.line} was incorrectly connected as a sink" + info) require (!iRealized, s"${name}${lazyModule.line} was incorrectly connected as a sink after its .module was used" + info) accPI += ((index, node, binding, p, sourceInfo)) } @@ -206,33 +202,26 @@ trait InwardNode[DI, UI, BI <: Data] extends BaseNode with InwardNodeHandle[DI, protected[diplomacy] val iStar: Int protected[diplomacy] val iPortMapping: Seq[(Int, Int)] - protected[diplomacy] val iParams: Seq[UI] + protected[diplomacy] val diParams: Seq[DI] // from connected nodes + protected[diplomacy] val uiParams: Seq[UI] // from this node protected[diplomacy] def bind(h: OutwardNode[DI, UI, BI], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo): Unit } -trait OutwardNodeHandle[DO, UO, BO <: Data] extends NoHandle +trait OutwardNodeHandle[DO, UO, EO, BO <: Data] extends NoHandle { def outward: OutwardNode[DO, UO, BO] - def parentsOut: Seq[LazyModule] = outward.parents + def outer: OutwardNodeImp[DO, UO, EO, BO] } -trait OutwardNode[DO, UO, BO <: Data] extends BaseNode with OutwardNodeHandle[DO, UO, BO] +trait OutwardNode[DO, UO, BO <: Data] extends BaseNode { - val outward = this - - protected[diplomacy] val numPO: Range.Inclusive - require (!numPO.isEmpty, s"No number of outputs would be acceptable to ${name}${lazyModule.line}") - require (numPO.start >= 0, s"${name} accepts a negative number of outputs${lazyModule.line}") - private val accPO = ListBuffer[(Int, InwardNode [DO, UO, BO], NodeBinding, Parameters, SourceInfo)]() private var oRealized = false protected[diplomacy] def oPushed = accPO.size protected[diplomacy] def oPush(index: Int, node: InwardNode [DO, UO, BO], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo) { val info = sourceLine(sourceInfo, " at ", "") - val noOs = numPO.size == 1 && numPO.contains(0) - require (!noOs, s"${name}${lazyModule.line} was incorrectly connected as a source" + info) require (!oRealized, s"${name}${lazyModule.line} was incorrectly connected as a source after its .module was used" + info) accPO += ((index, node, binding, p, sourceInfo)) } @@ -241,7 +230,8 @@ trait OutwardNode[DO, UO, BO <: Data] extends BaseNode with OutwardNodeHandle[DO protected[diplomacy] val oStar: Int protected[diplomacy] val oPortMapping: Seq[(Int, Int)] - protected[diplomacy] val oParams: Seq[DO] + protected[diplomacy] val uoParams: Seq[UO] // from connected nodes + protected[diplomacy] val doParams: Seq[DO] // from this node } abstract class CycleException(kind: String, loop: Seq[String]) extends Exception(s"Diplomatic ${kind} cycle detected involving ${loop}") @@ -251,13 +241,14 @@ case class UpwardCycleException(loop: Seq[String] = Nil) extends CycleException( case class Edges[EI, EO](in: EI, out: EO) sealed abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( - inner: InwardNodeImp [DI, UI, EI, BI], - outer: OutwardNodeImp[DO, UO, EO, BO])( - protected[diplomacy] val numPO: Range.Inclusive, - protected[diplomacy] val numPI: Range.Inclusive)( + val inner: InwardNodeImp [DI, UI, EI, BI], + val outer: OutwardNodeImp[DO, UO, EO, BO])( implicit valName: ValName) - extends BaseNode with NodeHandle[DI, UI, BI, DO, UO, BO] with InwardNode[DI, UI, BI] with OutwardNode[DO, UO, BO] + extends BaseNode with NodeHandle[DI, UI, EI, BI, DO, UO, EO, BO] with InwardNode[DI, UI, BI] with OutwardNode[DO, UO, BO] { + val inward = this + val outward = this + protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStar: Int, oStar: Int): (Int, Int) protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] @@ -287,8 +278,6 @@ sealed abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( case BIND_STAR => iStar }}.scanLeft(0)(_+_) val oTotal = oSum.lastOption.getOrElse(0) val iTotal = iSum.lastOption.getOrElse(0) - require(numPO.contains(oTotal), s"${name} has ${oTotal} outputs, expected ${numPO}${lazyModule.line}") - require(numPI.contains(iTotal), s"${name} has ${iTotal} inputs, expected ${numPI}${lazyModule.line}") (oSum.init zip oSum.tail, iSum.init zip iSum.tail, oStar, iStar) } catch { case c: StarCycleException => throw c.copy(loop = s"${name}${lazyModule.line}" +: c.loop) @@ -305,11 +294,12 @@ sealed abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( } private var oParamsCycleGuard = false - protected[diplomacy] lazy val oParams: Seq[DO] = { + protected[diplomacy] lazy val diParams: Seq[DI] = iPorts.map { case (i, n, _, _) => n.doParams(i) } + protected[diplomacy] lazy val doParams: Seq[DO] = { try { if (oParamsCycleGuard) throw DownwardCycleException() oParamsCycleGuard = true - val o = mapParamsD(oPorts.size, iPorts.map { case (i, n, _, _) => n.oParams(i) }) + val o = mapParamsD(oPorts.size, diParams) require (o.size == oPorts.size, s"Bug in diplomacy; ${name} has ${o.size} != ${oPorts.size} down/up outer parameters${lazyModule.line}") o.map(outer.mixO(_, this)) } catch { @@ -318,11 +308,12 @@ sealed abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( } private var iParamsCycleGuard = false - protected[diplomacy] lazy val iParams: Seq[UI] = { + protected[diplomacy] lazy val uoParams: Seq[UO] = oPorts.map { case (o, n, _, _) => n.uiParams(o) } + protected[diplomacy] lazy val uiParams: Seq[UI] = { try { if (iParamsCycleGuard) throw UpwardCycleException() iParamsCycleGuard = true - val i = mapParamsU(iPorts.size, oPorts.map { case (o, n, _, _) => n.iParams(o) }) + val i = mapParamsU(iPorts.size, uoParams) require (i.size == iPorts.size, s"Bug in diplomacy; ${name} has ${i.size} != ${iPorts.size} up/down inner parameters${lazyModule.line}") i.map(inner.mixI(_, this)) } catch { @@ -330,11 +321,11 @@ sealed abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( } } - protected[diplomacy] def gco = if (iParams.size != 1) None else inner.getO(iParams(0)) - protected[diplomacy] def gci = if (oParams.size != 1) None else outer.getI(oParams(0)) + protected[diplomacy] def gco = if (uiParams.size != 1) None else inner.getO(uiParams(0)) + protected[diplomacy] def gci = if (doParams.size != 1) None else outer.getI(doParams(0)) - protected[diplomacy] lazy val edgesOut = (oPorts zip oParams).map { case ((i, n, p, s), o) => outer.edgeO(o, n.iParams(i), p, s) } - protected[diplomacy] lazy val edgesIn = (iPorts zip iParams).map { case ((o, n, p, s), i) => inner.edgeI(n.oParams(o), i, p, s) } + protected[diplomacy] lazy val edgesOut = (oPorts zip doParams).map { case ((i, n, p, s), o) => outer.edgeO(o, n.uiParams(i), p, s) } + protected[diplomacy] lazy val edgesIn = (iPorts zip uiParams).map { case ((o, n, p, s), i) => inner.edgeI(n.doParams(o), i, p, s) } // If you need access to the edges of a foreign Node, use this method (in/out create bundles) lazy val edges = Edges(edgesIn, edgesOut) @@ -381,6 +372,10 @@ sealed abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( danglesOut ++ danglesIn } + protected[diplomacy] def finishInstantiate() = { + bundlesSafeNow = false + } + // connects the outward part of a node with the inward part of this node protected[diplomacy] def bind(h: OutwardNode[DI, UI, BI], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo) { val x = this // x := y @@ -406,10 +401,8 @@ sealed abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( abstract class MixedCustomNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( inner: InwardNodeImp [DI, UI, EI, BI], outer: OutwardNodeImp[DO, UO, EO, BO])( - numPO: Range.Inclusive, - numPI: Range.Inclusive)( implicit valName: ValName) - extends MixedNode(inner, outer)(numPO, numPI) + extends MixedNode(inner, outer) { def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] @@ -417,28 +410,28 @@ abstract class MixedCustomNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( } abstract class CustomNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])( - numPO: Range.Inclusive, - numPI: Range.Inclusive)( implicit valName: ValName) - extends MixedCustomNode(imp, imp)(numPO, numPI) + extends MixedCustomNode(imp, imp) class MixedAdapterNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( inner: InwardNodeImp [DI, UI, EI, BI], outer: OutwardNodeImp[DO, UO, EO, BO])( dFn: DI => DO, - uFn: UO => UI, - num: Range.Inclusive = 0 to 999)( + uFn: UO => UI)( implicit valName: ValName) - extends MixedNode(inner, outer)(num, num) + extends MixedNode(inner, outer) { protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { require (oStars + iStars <= 1, s"${name} (an adapter) appears left of a :*= ${iStars} times and right of a :=* ${oStars} times; at most once is allowed${lazyModule.line}") if (oStars > 0) { require (iKnown >= oKnown, s"${name} (an adapter) has ${oKnown} outputs and ${iKnown} inputs; cannot assign ${iKnown-oKnown} edges to resolve :=*${lazyModule.line}") (0, iKnown - oKnown) - } else { + } else if (iStars > 0) { require (oKnown >= iKnown, s"${name} (an adapter) has ${oKnown} outputs and ${iKnown} inputs; cannot assign ${oKnown-iKnown} edges to resolve :*=${lazyModule.line}") (oKnown - iKnown, 0) + } else { + require (oKnown == iKnown, s"${name} (an adapter) has ${oKnown} outputs and ${iKnown} inputs; these do not match") + (0, 0) } } protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] = { @@ -453,10 +446,9 @@ class MixedAdapterNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( class AdapterNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])( dFn: D => D, - uFn: U => U, - num: Range.Inclusive = 0 to 999)( + uFn: U => U)( implicit valName: ValName) - extends MixedAdapterNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn, num) + extends MixedAdapterNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn) // IdentityNodes automatically connect their inputs to outputs class IdentityNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])()(implicit valName: ValName) @@ -475,39 +467,39 @@ class MixedNexusNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( outer: OutwardNodeImp[DO, UO, EO, BO])( dFn: Seq[DI] => DO, uFn: Seq[UO] => UI, - numPO: Range.Inclusive = 1 to 999, - numPI: Range.Inclusive = 1 to 999)( + // no inputs and no outputs is always allowed + inputRequiresOutput: Boolean = true, + outputRequiresInput: Boolean = true)( implicit valName: ValName) - extends MixedNode(inner, outer)(numPO, numPI) + extends MixedNode(inner, outer) { -// require (numPO.end >= 1, s"${name} does not accept outputs${lazyModule.line}") -// require (numPI.end >= 1, s"${name} does not accept inputs${lazyModule.line}") - protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { - require (iStars == 0, s"${name} (a nexus) appears left of :*= (perhaps you should flip the '*' to :=*?)${lazyModule.line}") - require (oStars == 0, s"${name} (a nexus) appears right of a :=* (perhaps you should flip the '*' to :*=?)${lazyModule.line}") - (0, 0) + // a nexus treats :=* as a weak pointer + require (!outputRequiresInput || oKnown == 0 || iStars + iKnown != 0, s"${name} (a nexus) has ${oKnown} required outputs and no possible inputs") + require (!inputRequiresOutput || iKnown == 0 || oStars + oKnown != 0, s"${name} (a nexus) has ${iKnown} required inputs and no possible outputs") + if (iKnown == 0 && oKnown == 0) (0, 0) else (1, 1) } - protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] = { val a = dFn(p); Seq.fill(n)(a) } - protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] = { val a = uFn(p); Seq.fill(n)(a) } + protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] = { if (n > 0) { val a = dFn(p); Seq.fill(n)(a) } else Nil } + protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] = { if (n > 0) { val a = uFn(p); Seq.fill(n)(a) } else Nil } } class NexusNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])( dFn: Seq[D] => D, uFn: Seq[U] => U, - numPO: Range.Inclusive = 1 to 999, - numPI: Range.Inclusive = 1 to 999)( + inputRequiresOutput: Boolean = true, + outputRequiresInput: Boolean = true)( implicit valName: ValName) - extends MixedNexusNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn, numPO, numPI) + extends MixedNexusNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn, inputRequiresOutput, outputRequiresInput) // There are no Mixed SourceNodes class SourceNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(po: Seq[D])(implicit valName: ValName) - extends MixedNode(imp, imp)(po.size to po.size, 0 to 0) + extends MixedNode(imp, imp) { protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { require (oStars <= 1, s"${name} (a source) appears right of a :=* ${oStars} times; at most once is allowed${lazyModule.line}") require (iStars == 0, s"${name} (a source) cannot appear left of a :*=${lazyModule.line}") require (iKnown == 0, s"${name} (a source) cannot appear left of a :=${lazyModule.line}") + require (po.size == oKnown || oStars == 1, s"${name} (a source) has only ${oKnown} outputs connected out of ${po.size}") require (po.size >= oKnown, s"${name} (a source) has ${oKnown} outputs out of ${po.size}; cannot assign ${po.size - oKnown} edges to resolve :=*${lazyModule.line}") (0, po.size - oKnown) } @@ -517,15 +509,58 @@ class SourceNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(po: Seq // There are no Mixed SinkNodes class SinkNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(pi: Seq[U])(implicit valName: ValName) - extends MixedNode(imp, imp)(0 to 0, pi.size to pi.size) + extends MixedNode(imp, imp) { protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { require (iStars <= 1, s"${name} (a sink) appears left of a :*= ${iStars} times; at most once is allowed${lazyModule.line}") require (oStars == 0, s"${name} (a sink) cannot appear right of a :=*${lazyModule.line}") require (oKnown == 0, s"${name} (a sink) cannot appear right of a :=${lazyModule.line}") + require (pi.size == iKnown || iStars == 1, s"${name} (a sink) has only ${iKnown} inputs connected out of ${pi.size}") require (pi.size >= iKnown, s"${name} (a sink) has ${iKnown} inputs out of ${pi.size}; cannot assign ${pi.size - iKnown} edges to resolve :*=${lazyModule.line}") (pi.size - iKnown, 0) } protected[diplomacy] def mapParamsD(n: Int, p: Seq[D]): Seq[D] = Seq() protected[diplomacy] def mapParamsU(n: Int, p: Seq[U]): Seq[U] = pi } + +class MixedTestNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data] protected[diplomacy]( + node: NodeHandle [DI, UI, EI, BI, DO, UO, EO, BO], clone: CloneLazyModule)( + implicit valName: ValName) + extends MixedNode(node.inner, node.outer) +{ + // The devices connected to this test node must recreate these parameters: + def iParams: Seq[DI] = node.inward .diParams + def oParams: Seq[UO] = node.outward.uoParams + + protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { + require (oStars <= 1, s"${name} (a test node) appears right of a :=* ${oStars} times; at most once is allowed${lazyModule.line}") + require (iStars <= 1, s"${name} (a test node) appears left of a :*= ${iStars} times; at most once is allowed${lazyModule.line}") + require (node.inward .uiParams.size == iKnown || iStars == 1, s"${name} (a test node) has only ${iKnown} inputs connected out of ${node.inward.uiParams.size}") + require (node.outward.doParams.size == oKnown || oStars == 1, s"${name} (a test node) has only ${oKnown} outputs connected out of ${node.outward.doParams.size}") + (node.inward.uiParams.size - iKnown, node.outward.doParams.size - oKnown) + } + + protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] = node.inward .uiParams + protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] = node.outward.doParams + + override protected[diplomacy] def instantiate() = { + val dangles = super.instantiate() + val orig_module = clone.base.module + val clone_auto = clone.io("auto").asInstanceOf[AutoBundle] + + danglesOut.zipWithIndex.foreach { case (d, i) => + val orig = orig_module.dangles.find(_.source == HalfEdge(node.outward.serial, i)) + require (orig.isDefined, s"Cloned node ${node.outward.name} must be connected externally out ${orig_module.name}") + val io_name = orig_module.auto.elements.find(_._2 eq orig.get.data).get._1 + d.data <> clone_auto.elements(io_name) + } + danglesIn.zipWithIndex.foreach { case (d, i) => + val orig = orig_module.dangles.find(_.sink == HalfEdge(node.inward.serial, i)) + require (orig.isDefined, s"Cloned node ${node.inward.name} must be connected externally in ${orig_module.name}") + val io_name = orig_module.auto.elements.find(_._2 eq orig.get.data).get._1 + clone_auto.elements(io_name) <> d.data + } + + dangles + } +} diff --git a/src/main/scala/diplomacy/package.scala b/src/main/scala/diplomacy/package.scala index 6bcf60a6..b4b40f40 100644 --- a/src/main/scala/diplomacy/package.scala +++ b/src/main/scala/diplomacy/package.scala @@ -7,7 +7,7 @@ import freechips.rocketchip.config.Parameters package object diplomacy { - type SimpleNodeHandle[D, U, B <: Chisel.Data] = NodeHandle[D, U, B, D, U, B] + type SimpleNodeHandle[D, U, E, B <: Chisel.Data] = NodeHandle[D, U, E, B, D, U, E, B] def sourceLine(sourceInfo: SourceInfo, prefix: String = " (", suffix: String = ")") = sourceInfo match { case SourceLine(filename, line, col) => s"$prefix$filename:$line:$col$suffix" diff --git a/src/main/scala/interrupts/Crossing.scala b/src/main/scala/interrupts/Crossing.scala index 628dc53a..68054551 100644 --- a/src/main/scala/interrupts/Crossing.scala +++ b/src/main/scala/interrupts/Crossing.scala @@ -21,7 +21,11 @@ class IntXing(sync: Int = 3)(implicit p: Parameters) extends LazyModule object IntSyncCrossingSource { - def apply(alreadyRegistered: Boolean = false)(implicit p: Parameters) = LazyModule(new IntSyncCrossingSource(alreadyRegistered)).node + def apply(alreadyRegistered: Boolean = false)(implicit p: Parameters) = + { + val intsource = LazyModule(new IntSyncCrossingSource(alreadyRegistered)) + intsource.node + } } @@ -54,5 +58,9 @@ class IntSyncCrossingSink(sync: Int = 3)(implicit p: Parameters) extends LazyMod object IntSyncCrossingSink { - def apply(sync: Int = 3)(implicit p: Parameters) = LazyModule(new IntSyncCrossingSink(sync)).node + def apply(sync: Int = 3)(implicit p: Parameters) = + { + val intsink = LazyModule(new IntSyncCrossingSink(sync)) + intsink.node + } } diff --git a/src/main/scala/interrupts/Nodes.scala b/src/main/scala/interrupts/Nodes.scala index 6b431cc2..03df8c53 100644 --- a/src/main/scala/interrupts/Nodes.scala +++ b/src/main/scala/interrupts/Nodes.scala @@ -23,19 +23,18 @@ case class IntSourceNode(portParams: Seq[IntSourcePortParameters])(implicit valN case class IntSinkNode(portParams: Seq[IntSinkPortParameters])(implicit valName: ValName) extends SinkNode(IntImp)(portParams) case class IntAdapterNode( sourceFn: IntSourcePortParameters => IntSourcePortParameters = { s => s }, - sinkFn: IntSinkPortParameters => IntSinkPortParameters = { s => s }, - num: Range.Inclusive = 0 to 999)( + sinkFn: IntSinkPortParameters => IntSinkPortParameters = { s => s })( implicit valName: ValName) - extends AdapterNode(IntImp)(sourceFn, sinkFn, num) + extends AdapterNode(IntImp)(sourceFn, sinkFn) case class IntIdentityNode()(implicit valName: ValName) extends IdentityNode(IntImp)() case class IntNexusNode( sourceFn: Seq[IntSourcePortParameters] => IntSourcePortParameters, sinkFn: Seq[IntSinkPortParameters] => IntSinkPortParameters, - numSourcePorts: Range.Inclusive = 0 to 128, - numSinkPorts: Range.Inclusive = 0 to 128)( + inputRequiresOutput: Boolean = true, + outputRequiresInput: Boolean = true)( implicit valName: ValName) - extends NexusNode(IntImp)(sourceFn, sinkFn, numSourcePorts, numSinkPorts) + extends NexusNode(IntImp)(sourceFn, sinkFn, inputRequiresOutput, outputRequiresInput) object IntSyncImp extends SimpleNodeImp[IntSourcePortParameters, IntSinkPortParameters, IntEdge, SyncInterrupts] { diff --git a/src/main/scala/interrupts/package.scala b/src/main/scala/interrupts/package.scala index 36f50740..715eef55 100644 --- a/src/main/scala/interrupts/package.scala +++ b/src/main/scala/interrupts/package.scala @@ -7,7 +7,7 @@ import freechips.rocketchip.diplomacy._ package object interrupts { - type IntInwardNode = InwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, Vec[Bool]] - type IntOutwardNode = OutwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, Vec[Bool]] - type IntNode = SimpleNodeHandle[IntSourcePortParameters, IntSinkPortParameters, Vec[Bool]] + type IntInwardNode = InwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, Vec[Bool]] + type IntOutwardNode = OutwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, Vec[Bool]] + type IntNode = SimpleNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, Vec[Bool]] } diff --git a/src/main/scala/tilelink/AsyncCrossing.scala b/src/main/scala/tilelink/AsyncCrossing.scala index eb44cc15..4e4a9300 100644 --- a/src/main/scala/tilelink/AsyncCrossing.scala +++ b/src/main/scala/tilelink/AsyncCrossing.scala @@ -78,12 +78,20 @@ class TLAsyncCrossingSink(depth: Int = 8, sync: Int = 3)(implicit p: Parameters) object TLAsyncCrossingSource { - def apply(sync: Int = 3)(implicit p: Parameters) = LazyModule(new TLAsyncCrossingSource(sync)).node + def apply(sync: Int = 3)(implicit p: Parameters) = + { + val asource = LazyModule(new TLAsyncCrossingSource(sync)) + asource.node + } } object TLAsyncCrossingSink { - def apply(depth: Int = 8, sync: Int = 3)(implicit p: Parameters) = LazyModule(new TLAsyncCrossingSink(depth, sync)).node + def apply(depth: Int = 8, sync: Int = 3)(implicit p: Parameters) = + { + val asink = LazyModule(new TLAsyncCrossingSink(depth, sync)) + asink.node + } } @deprecated("TLAsyncCrossing is fragile. Use TLAsyncCrossingSource and TLAsyncCrossingSink", "rocket-chip 1.2") @@ -131,5 +139,6 @@ class TLRAMAsyncCrossing(txns: Int)(implicit p: Parameters) extends LazyModule { } class TLRAMAsyncCrossingTest(txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { - io.finished := Module(LazyModule(new TLRAMAsyncCrossing(txns)).module).io.finished + val dut = Module(LazyModule(new TLRAMAsyncCrossing(txns)).module) + io.finished := dut.io.finished } diff --git a/src/main/scala/tilelink/AtomicAutomata.scala b/src/main/scala/tilelink/AtomicAutomata.scala index 2e8a1a5b..53222472 100644 --- a/src/main/scala/tilelink/AtomicAutomata.scala +++ b/src/main/scala/tilelink/AtomicAutomata.scala @@ -266,7 +266,10 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc object TLAtomicAutomata { def apply(logical: Boolean = true, arithmetic: Boolean = true, concurrency: Int = 1, passthrough: Boolean = true)(implicit p: Parameters): TLNode = - LazyModule(new TLAtomicAutomata(logical, arithmetic, concurrency, passthrough)).node + { + val atomics = LazyModule(new TLAtomicAutomata(logical, arithmetic, concurrency, passthrough)) + atomics.node + } case class CAMParams(a: TLBundleParameters, domainsNeedingHelp: Int) @@ -318,5 +321,6 @@ class TLRAMAtomicAutomata(txns: Int)(implicit p: Parameters) extends LazyModule } class TLRAMAtomicAutomataTest(txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { - io.finished := Module(LazyModule(new TLRAMAtomicAutomata(txns)).module).io.finished + val dut = Module(LazyModule(new TLRAMAtomicAutomata(txns)).module) + io.finished := dut.io.finished } diff --git a/src/main/scala/tilelink/Broadcast.scala b/src/main/scala/tilelink/Broadcast.scala index 4681b8f3..1e289530 100644 --- a/src/main/scala/tilelink/Broadcast.scala +++ b/src/main/scala/tilelink/Broadcast.scala @@ -205,6 +205,15 @@ class TLBroadcast(lineBytes: Int, numTrackers: Int = 4, bufferless: Boolean = fa } } +object TLBroadcast +{ + def apply(lineBytes: Int, numTrackers: Int = 4, bufferless: Boolean = false)(implicit p: Parameters): TLNode = + { + val broadcast = LazyModule(new TLBroadcast(lineBytes, numTrackers, bufferless)) + broadcast.node + } +} + class TLBroadcastTracker(id: Int, lineBytes: Int, probeCountBits: Int, bufferless: Boolean, edgeIn: TLEdgeIn, edgeOut: TLEdgeOut) extends Module { val io = new Bundle { diff --git a/src/main/scala/tilelink/Buffer.scala b/src/main/scala/tilelink/Buffer.scala index 51310494..4305d1a5 100644 --- a/src/main/scala/tilelink/Buffer.scala +++ b/src/main/scala/tilelink/Buffer.scala @@ -64,7 +64,11 @@ object TLBuffer b: BufferParams, c: BufferParams, d: BufferParams, - e: BufferParams)(implicit p: Parameters): TLNode = LazyModule(new TLBuffer(a, b, c, d, e)).node + e: BufferParams)(implicit p: Parameters): TLNode = + { + val buffer = LazyModule(new TLBuffer(a, b, c, d, e)) + buffer.node + } def chain(depth: Int, name: Option[String] = None)(implicit p: Parameters): Seq[TLNode] = { val buffers = Seq.fill(depth) { LazyModule(new TLBuffer()) } diff --git a/src/main/scala/tilelink/CacheCork.scala b/src/main/scala/tilelink/CacheCork.scala index c614f02d..7a52f7c0 100644 --- a/src/main/scala/tilelink/CacheCork.scala +++ b/src/main/scala/tilelink/CacheCork.scala @@ -121,5 +121,9 @@ class TLCacheCork(unsafe: Boolean = false)(implicit p: Parameters) extends LazyM object TLCacheCork { - def apply(unsafe: Boolean = false)(implicit p: Parameters): TLNode = LazyModule(new TLCacheCork(unsafe)).node + def apply(unsafe: Boolean = false)(implicit p: Parameters): TLNode = + { + val cork = LazyModule(new TLCacheCork(unsafe)) + cork.node + } } diff --git a/src/main/scala/tilelink/Delayer.scala b/src/main/scala/tilelink/Delayer.scala index 11f75c05..965e3633 100644 --- a/src/main/scala/tilelink/Delayer.scala +++ b/src/main/scala/tilelink/Delayer.scala @@ -72,5 +72,9 @@ class TLDelayer(q: Double)(implicit p: Parameters) extends LazyModule object TLDelayer { - def apply(q: Double)(implicit p: Parameters): TLNode = LazyModule(new TLDelayer(q)).node + def apply(q: Double)(implicit p: Parameters): TLNode = + { + val delayer = LazyModule(new TLDelayer(q)) + delayer.node + } } diff --git a/src/main/scala/tilelink/ErrorEvaluator.scala b/src/main/scala/tilelink/ErrorEvaluator.scala index 1bcd71a0..37067d0b 100644 --- a/src/main/scala/tilelink/ErrorEvaluator.scala +++ b/src/main/scala/tilelink/ErrorEvaluator.scala @@ -62,5 +62,8 @@ class TLErrorEvaluator(test: RequestPattern, testOn: Boolean, testOff: Boolean)( object TLErrorEvaluator { def apply(test: RequestPattern, testOn: Boolean = false, testOff: Boolean = false)(implicit p: Parameters): TLNode = - LazyModule(new TLErrorEvaluator(test, testOn, testOff)).node + { + val errors = LazyModule(new TLErrorEvaluator(test, testOn, testOff)) + errors.node + } } diff --git a/src/main/scala/tilelink/FIFOFixer.scala b/src/main/scala/tilelink/FIFOFixer.scala index 38634a4f..bd3adab2 100644 --- a/src/main/scala/tilelink/FIFOFixer.scala +++ b/src/main/scala/tilelink/FIFOFixer.scala @@ -113,5 +113,9 @@ object TLFIFOFixer val allFIFO: Policy = m => m.fifoId.isDefined val allUncacheable: Policy = m => m.regionType <= UNCACHEABLE - def apply(policy: Policy = all)(implicit p: Parameters): TLNode = LazyModule(new TLFIFOFixer(policy)).node + def apply(policy: Policy = all)(implicit p: Parameters): TLNode = + { + val fixer = LazyModule(new TLFIFOFixer(policy)) + fixer.node + } } diff --git a/src/main/scala/tilelink/Filter.scala b/src/main/scala/tilelink/Filter.scala index 9465727a..be68b91c 100644 --- a/src/main/scala/tilelink/Filter.scala +++ b/src/main/scala/tilelink/Filter.scala @@ -91,5 +91,9 @@ object TLFilter def apply( Mfilter: TLManagerParameters => Option[TLManagerParameters] = TLFilter.Midentity, Cfilter: TLClientParameters => Option[TLClientParameters] = TLFilter.Cidentity - )(implicit p: Parameters): TLNode = LazyModule(new TLFilter(Mfilter, Cfilter)).node + )(implicit p: Parameters): TLNode = + { + val filter = LazyModule(new TLFilter(Mfilter, Cfilter)) + filter.node + } } diff --git a/src/main/scala/tilelink/Fragmenter.scala b/src/main/scala/tilelink/Fragmenter.scala index dad9bfc8..ae82a72e 100644 --- a/src/main/scala/tilelink/Fragmenter.scala +++ b/src/main/scala/tilelink/Fragmenter.scala @@ -294,7 +294,10 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean = object TLFragmenter { def apply(minSize: Int, maxSize: Int, alwaysMin: Boolean = false, earlyAck: EarlyAck.T = EarlyAck.None)(implicit p: Parameters): TLNode = - LazyModule(new TLFragmenter(minSize, maxSize, alwaysMin, earlyAck)).node + { + val fragmenter = LazyModule(new TLFragmenter(minSize, maxSize, alwaysMin, earlyAck)) + fragmenter.node + } } /** Synthesizeable unit tests */ @@ -324,5 +327,6 @@ class TLRAMFragmenter(ramBeatBytes: Int, maxSize: Int, txns: Int)(implicit p: Pa } class TLRAMFragmenterTest(ramBeatBytes: Int, maxSize: Int, txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { - io.finished := Module(LazyModule(new TLRAMFragmenter(ramBeatBytes,maxSize,txns)).module).io.finished + val dut = Module(LazyModule(new TLRAMFragmenter(ramBeatBytes,maxSize,txns)).module) + io.finished := dut.io.finished } diff --git a/src/main/scala/tilelink/Fuzzer.scala b/src/main/scala/tilelink/Fuzzer.scala index c2c03656..8c6fdc0b 100644 --- a/src/main/scala/tilelink/Fuzzer.scala +++ b/src/main/scala/tilelink/Fuzzer.scala @@ -221,6 +221,24 @@ class TLFuzzer( } } +object TLFuzzer +{ + def apply( + nOperations: Int, + inFlight: Int = 32, + noiseMaker: (Int, Bool, Int) => UInt = { + (wide: Int, increment: Bool, abs_values: Int) => + LFSRNoiseMaker(wide=wide, increment=increment) + }, + noModify: Boolean = false, + overrideAddress: Option[AddressSet] = None, + nOrdered: Option[Int] = None)(implicit p: Parameters): TLOutwardNode = + { + val fuzzer = LazyModule(new TLFuzzer(nOperations, inFlight, noiseMaker, noModify, overrideAddress, nOrdered)) + fuzzer.node + } +} + /** Synthesizeable integration test */ import freechips.rocketchip.unittest._ diff --git a/src/main/scala/tilelink/HintHandler.scala b/src/main/scala/tilelink/HintHandler.scala index 78003bbd..ba0ae383 100644 --- a/src/main/scala/tilelink/HintHandler.scala +++ b/src/main/scala/tilelink/HintHandler.scala @@ -92,7 +92,10 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f object TLHintHandler { def apply(supportManagers: Boolean = true, supportClients: Boolean = false, passthrough: Boolean = true)(implicit p: Parameters): TLNode = - LazyModule(new TLHintHandler(supportManagers, supportClients, passthrough)).node + { + val hints = LazyModule(new TLHintHandler(supportManagers, supportClients, passthrough)) + hints.node + } } /** Synthesizeable unit tests */ @@ -119,5 +122,6 @@ class TLRAMHintHandler(txns: Int)(implicit p: Parameters) extends LazyModule { } class TLRAMHintHandlerTest(txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { - io.finished := Module(LazyModule(new TLRAMHintHandler(txns)).module).io.finished + val dut = Module(LazyModule(new TLRAMHintHandler(txns)).module) + io.finished := dut.io.finished } diff --git a/src/main/scala/tilelink/Map.scala b/src/main/scala/tilelink/Map.scala index c0ceaabb..f63d0836 100644 --- a/src/main/scala/tilelink/Map.scala +++ b/src/main/scala/tilelink/Map.scala @@ -38,5 +38,9 @@ class TLMap(fn: AddressSet => BigInt)(implicit p: Parameters) extends LazyModule object TLMap { - def apply(fn: AddressSet => BigInt)(implicit p: Parameters): TLNode = LazyModule(new TLMap(fn)).node + def apply(fn: AddressSet => BigInt)(implicit p: Parameters): TLNode = + { + val map = LazyModule(new TLMap(fn)) + map.node + } } diff --git a/src/main/scala/tilelink/NodeNumberer.scala b/src/main/scala/tilelink/NodeNumberer.scala index 88e22f6a..57601b67 100644 --- a/src/main/scala/tilelink/NodeNumberer.scala +++ b/src/main/scala/tilelink/NodeNumberer.scala @@ -6,7 +6,7 @@ import Chisel._ import freechips.rocketchip.config.Parameters import freechips.rocketchip.diplomacy._ -case class TLNodeNumbererNode(nodeAddressOffset: Option[Int] = None)(implicit valName: ValName) extends TLCustomNode(0 to 999, 0 to 999) +case class TLNodeNumbererNode(nodeAddressOffset: Option[Int] = None)(implicit valName: ValName) extends TLCustomNode { def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { require (oStars + iStars <= 1, s"${name} (a custom adapter) appears left of a :*= ${iStars} times and right of a :=* ${oStars} times; at most once is allowed${lazyModule.line}") @@ -55,5 +55,9 @@ class TLNodeNumberer(nodeAddressOffset: Option[Int] = None)(implicit p: Paramete object TLNodeNumberer { - def apply(nodeAddressOffset: Option[Int] = None)(implicit p: Parameters): TLNode = LazyModule(new TLNodeNumberer(nodeAddressOffset)).node + def apply(nodeAddressOffset: Option[Int] = None)(implicit p: Parameters): TLNode = + { + val numberer = LazyModule(new TLNodeNumberer(nodeAddressOffset)) + numberer.node + } } diff --git a/src/main/scala/tilelink/Nodes.scala b/src/main/scala/tilelink/Nodes.scala index 605c1662..c629c0b9 100644 --- a/src/main/scala/tilelink/Nodes.scala +++ b/src/main/scala/tilelink/Nodes.scala @@ -49,26 +49,20 @@ case class TLManagerNode(portParams: Seq[TLManagerPortParameters])(implicit valN case class TLAdapterNode( clientFn: TLClientPortParameters => TLClientPortParameters = { s => s }, - managerFn: TLManagerPortParameters => TLManagerPortParameters = { s => s }, - num: Range.Inclusive = 0 to 999)( + managerFn: TLManagerPortParameters => TLManagerPortParameters = { s => s })( implicit valName: ValName) - extends AdapterNode(TLImp)(clientFn, managerFn, num) + extends AdapterNode(TLImp)(clientFn, managerFn) case class TLIdentityNode()(implicit valName: ValName) extends IdentityNode(TLImp)() case class TLNexusNode( clientFn: Seq[TLClientPortParameters] => TLClientPortParameters, - managerFn: Seq[TLManagerPortParameters] => TLManagerPortParameters, - numClientPorts: Range.Inclusive = 1 to 999, - numManagerPorts: Range.Inclusive = 1 to 999)( + managerFn: Seq[TLManagerPortParameters] => TLManagerPortParameters)( implicit valName: ValName) - extends NexusNode(TLImp)(clientFn, managerFn, numClientPorts, numManagerPorts) + extends NexusNode(TLImp)(clientFn, managerFn) -abstract class TLCustomNode( - numClientPorts: Range.Inclusive, - numManagerPorts: Range.Inclusive)( - implicit valName: ValName) - extends CustomNode(TLImp)(numClientPorts, numManagerPorts) +abstract class TLCustomNode(implicit valName: ValName) + extends CustomNode(TLImp) // Asynchronous crossings @@ -86,10 +80,9 @@ object TLAsyncImp extends SimpleNodeImp[TLAsyncClientPortParameters, TLAsyncMana case class TLAsyncAdapterNode( clientFn: TLAsyncClientPortParameters => TLAsyncClientPortParameters = { s => s }, - managerFn: TLAsyncManagerPortParameters => TLAsyncManagerPortParameters = { s => s }, - num: Range.Inclusive = 0 to 999)( + managerFn: TLAsyncManagerPortParameters => TLAsyncManagerPortParameters = { s => s })( implicit valName: ValName) - extends AdapterNode(TLAsyncImp)(clientFn, managerFn, num) + extends AdapterNode(TLAsyncImp)(clientFn, managerFn) case class TLAsyncIdentityNode()(implicit valName: ValName) extends IdentityNode(TLAsyncImp)() @@ -119,10 +112,9 @@ object TLRationalImp extends SimpleNodeImp[TLRationalClientPortParameters, TLRat case class TLRationalAdapterNode( clientFn: TLRationalClientPortParameters => TLRationalClientPortParameters = { s => s }, - managerFn: TLRationalManagerPortParameters => TLRationalManagerPortParameters = { s => s }, - num: Range.Inclusive = 0 to 999)( + managerFn: TLRationalManagerPortParameters => TLRationalManagerPortParameters = { s => s })( implicit valName: ValName) - extends AdapterNode(TLRationalImp)(clientFn, managerFn, num) + extends AdapterNode(TLRationalImp)(clientFn, managerFn) case class TLRationalIdentityNode()(implicit valName: ValName) extends IdentityNode(TLRationalImp)() diff --git a/src/main/scala/tilelink/PatternPusher.scala b/src/main/scala/tilelink/PatternPusher.scala index cb9d384e..60ab48cc 100644 --- a/src/main/scala/tilelink/PatternPusher.scala +++ b/src/main/scala/tilelink/PatternPusher.scala @@ -84,3 +84,12 @@ class TLPatternPusher(name: String, pattern: Seq[Pattern])(implicit p: Parameter tl_out.e.valid := Bool(false) } } + +object TLPatternPusher +{ + def apply(name: String, pattern: Seq[Pattern])(implicit p: Parameters): TLOutwardNode = + { + val pusher = LazyModule(new TLPatternPusher(name, pattern)) + pusher.node + } +} diff --git a/src/main/scala/tilelink/RAMModel.scala b/src/main/scala/tilelink/RAMModel.scala index c6e9113e..69900731 100644 --- a/src/main/scala/tilelink/RAMModel.scala +++ b/src/main/scala/tilelink/RAMModel.scala @@ -333,8 +333,11 @@ class TLRAMModel(log: String = "", ignoreErrorData: Boolean = false)(implicit p: object TLRAMModel { - def apply(log: String = "", ignoreErrorData: Boolean = false)(implicit p: Parameters) = - LazyModule(new TLRAMModel(log, ignoreErrorData)).node + def apply(log: String = "", ignoreErrorData: Boolean = false)(implicit p: Parameters): TLNode = + { + val model = LazyModule(new TLRAMModel(log, ignoreErrorData)) + model.node + } case class MonitorParameters(addressBits: Int, sizeBits: Int) diff --git a/src/main/scala/tilelink/RationalCrossing.scala b/src/main/scala/tilelink/RationalCrossing.scala index 9d935b68..0136b88d 100644 --- a/src/main/scala/tilelink/RationalCrossing.scala +++ b/src/main/scala/tilelink/RationalCrossing.scala @@ -78,12 +78,20 @@ class TLRationalCrossingSink(direction: RationalDirection = Symmetric)(implicit object TLRationalCrossingSource { - def apply()(implicit p: Parameters) = LazyModule(new TLRationalCrossingSource).node + def apply()(implicit p: Parameters) = + { + val rsource = LazyModule(new TLRationalCrossingSource) + rsource.node + } } object TLRationalCrossingSink { - def apply(direction: RationalDirection = Symmetric)(implicit p: Parameters) = LazyModule(new TLRationalCrossingSink(direction)).node + def apply(direction: RationalDirection = Symmetric)(implicit p: Parameters) = + { + val rsink = LazyModule(new TLRationalCrossingSink(direction)) + rsink.node + } } @deprecated("TLRationalCrossing is fragile. Use TLRationalCrossingSource and TLRationalCrossingSink", "rocket-chip 1.2") @@ -189,5 +197,6 @@ class TLRAMRationalCrossing(txns: Int)(implicit p: Parameters) extends LazyModul } class TLRAMRationalCrossingTest(txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { - io.finished := Module(LazyModule(new TLRAMRationalCrossing(txns)).module).io.finished + val dut = Module(LazyModule(new TLRAMRationalCrossing(txns)).module) + io.finished := dut.io.finished } diff --git a/src/main/scala/tilelink/RegisterRouterTest.scala b/src/main/scala/tilelink/RegisterRouterTest.scala index d7157c83..126e0ea6 100644 --- a/src/main/scala/tilelink/RegisterRouterTest.scala +++ b/src/main/scala/tilelink/RegisterRouterTest.scala @@ -268,7 +268,8 @@ class FuzzRRTest0(txns: Int)(implicit p: Parameters) extends LazyModule { } class TLRR0Test(txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { - io.finished := Module(LazyModule(new FuzzRRTest0(txns)).module).io.finished + val dut = Module(LazyModule(new FuzzRRTest0(txns)).module) + io.finished := dut.io.finished } class FuzzRRTest1(txns: Int)(implicit p: Parameters) extends LazyModule { @@ -283,6 +284,7 @@ class FuzzRRTest1(txns: Int)(implicit p: Parameters) extends LazyModule { } class TLRR1Test(txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { - io.finished := Module(LazyModule(new FuzzRRTest1(txns)).module).io.finished + val dut = Module(LazyModule(new FuzzRRTest1(txns)).module) + io.finished := dut.io.finished } diff --git a/src/main/scala/tilelink/SRAM.scala b/src/main/scala/tilelink/SRAM.scala index a98a1d8e..cc664db6 100644 --- a/src/main/scala/tilelink/SRAM.scala +++ b/src/main/scala/tilelink/SRAM.scala @@ -81,6 +81,21 @@ class TLRAM( } } +object TLRAM +{ + def apply( + address: AddressSet, + cacheable: Boolean = true, + executable: Boolean = true, + beatBytes: Int = 4, + devName: Option[String] = None, + errors: Seq[AddressSet] = Nil)(implicit p: Parameters): TLInwardNode = + { + val ram = LazyModule(new TLRAM(address, cacheable, executable, beatBytes, devName, errors)) + ram.node + } +} + /** Synthesizeable unit testing */ import freechips.rocketchip.unittest._ @@ -97,5 +112,6 @@ class TLRAMSimple(ramBeatBytes: Int, txns: Int)(implicit p: Parameters) extends } class TLRAMSimpleTest(ramBeatBytes: Int, txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { - io.finished := Module(LazyModule(new TLRAMSimple(ramBeatBytes, txns)).module).io.finished + val dut = Module(LazyModule(new TLRAMSimple(ramBeatBytes, txns)).module) + io.finished := dut.io.finished } diff --git a/src/main/scala/tilelink/SourceShrinker.scala b/src/main/scala/tilelink/SourceShrinker.scala index 255b4a37..380c8eaa 100644 --- a/src/main/scala/tilelink/SourceShrinker.scala +++ b/src/main/scala/tilelink/SourceShrinker.scala @@ -74,5 +74,9 @@ class TLSourceShrinker(maxInFlight: Int)(implicit p: Parameters) extends LazyMod object TLSourceShrinker { - def apply(maxInFlight: Int)(implicit p: Parameters): TLNode = LazyModule(new TLSourceShrinker(maxInFlight)).node + def apply(maxInFlight: Int)(implicit p: Parameters): TLNode = + { + val shrinker = LazyModule(new TLSourceShrinker(maxInFlight)) + shrinker.node + } } diff --git a/src/main/scala/tilelink/Splitter.scala b/src/main/scala/tilelink/Splitter.scala index f5da7e6c..74496c34 100644 --- a/src/main/scala/tilelink/Splitter.scala +++ b/src/main/scala/tilelink/Splitter.scala @@ -9,11 +9,9 @@ import freechips.rocketchip.diplomacy._ case class SplitterArg[T](newSize: Int, ports: Seq[T]) case class TLSplitterNode( clientFn: SplitterArg[TLClientPortParameters] => Seq[TLClientPortParameters], - managerFn: SplitterArg[TLManagerPortParameters] => Seq[TLManagerPortParameters], - numClientPorts: Range.Inclusive = 0 to 999, - numManagerPorts: Range.Inclusive = 0 to 999)( + managerFn: SplitterArg[TLManagerPortParameters] => Seq[TLManagerPortParameters])( implicit valName: ValName) - extends TLCustomNode(numClientPorts, numManagerPorts) + extends TLCustomNode { def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { require (oKnown == 0, s"${name} (a splitter) appears right of a := or :*=; use a :=* instead${lazyModule.line}") diff --git a/src/main/scala/tilelink/ToAHB.scala b/src/main/scala/tilelink/ToAHB.scala index 77b129d0..d95ba88e 100644 --- a/src/main/scala/tilelink/ToAHB.scala +++ b/src/main/scala/tilelink/ToAHB.scala @@ -186,5 +186,9 @@ class TLToAHB(val aFlow: Boolean = false)(implicit p: Parameters) extends LazyMo object TLToAHB { - def apply(aFlow: Boolean = true)(implicit p: Parameters) = LazyModule(new TLToAHB(aFlow)).node + def apply(aFlow: Boolean = true)(implicit p: Parameters) = + { + val tl2ahb = LazyModule(new TLToAHB(aFlow)) + tl2ahb.node + } } diff --git a/src/main/scala/tilelink/ToAPB.scala b/src/main/scala/tilelink/ToAPB.scala index b0146090..22b6ec21 100644 --- a/src/main/scala/tilelink/ToAPB.scala +++ b/src/main/scala/tilelink/ToAPB.scala @@ -85,5 +85,9 @@ class TLToAPB(val aFlow: Boolean = true)(implicit p: Parameters) extends LazyMod object TLToAPB { - def apply(aFlow: Boolean = true)(implicit p: Parameters) = LazyModule(new TLToAPB(aFlow)).node + def apply(aFlow: Boolean = true)(implicit p: Parameters) = + { + val tl2apb = LazyModule(new TLToAPB(aFlow)) + tl2apb.node + } } diff --git a/src/main/scala/tilelink/ToAXI4.scala b/src/main/scala/tilelink/ToAXI4.scala index ee3c07f3..2b733766 100644 --- a/src/main/scala/tilelink/ToAXI4.scala +++ b/src/main/scala/tilelink/ToAXI4.scala @@ -227,7 +227,10 @@ class TLToAXI4(val combinational: Boolean = true, val adapterName: Option[String object TLToAXI4 { def apply(combinational: Boolean = true, adapterName: Option[String] = None, stripBits: Int = 0)(implicit p: Parameters) = - LazyModule(new TLToAXI4(combinational, adapterName, stripBits)).node + { + val tl2axi4 = LazyModule(new TLToAXI4(combinational, adapterName, stripBits)) + tl2axi4.node + } def sortByType(a: TLClientParameters, b: TLClientParameters): Boolean = { if ( a.supportsProbe && !b.supportsProbe) return false diff --git a/src/main/scala/tilelink/WidthWidget.scala b/src/main/scala/tilelink/WidthWidget.scala index 1f3b9dd1..fa74cf1b 100644 --- a/src/main/scala/tilelink/WidthWidget.scala +++ b/src/main/scala/tilelink/WidthWidget.scala @@ -184,7 +184,11 @@ class TLWidthWidget(innerBeatBytes: Int)(implicit p: Parameters) extends LazyMod object TLWidthWidget { - def apply(innerBeatBytes: Int)(implicit p: Parameters): TLNode = LazyModule(new TLWidthWidget(innerBeatBytes)).node + def apply(innerBeatBytes: Int)(implicit p: Parameters): TLNode = + { + val widget = LazyModule(new TLWidthWidget(innerBeatBytes)) + widget.node + } } /** Synthesizeable unit tests */ @@ -210,5 +214,6 @@ class TLRAMWidthWidget(first: Int, second: Int, txns: Int)(implicit p: Parameter } class TLRAMWidthWidgetTest(little: Int, big: Int, txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { - io.finished := Module(LazyModule(new TLRAMWidthWidget(little,big,txns)).module).io.finished + val dut = Module(LazyModule(new TLRAMWidthWidget(little,big,txns)).module) + io.finished := dut.io.finished } diff --git a/src/main/scala/tilelink/Xbar.scala b/src/main/scala/tilelink/Xbar.scala index c9c39d96..52bb6d9e 100644 --- a/src/main/scala/tilelink/Xbar.scala +++ b/src/main/scala/tilelink/Xbar.scala @@ -31,8 +31,6 @@ private case object ForceFanoutKey extends Field(ForceFanoutParams(false, false, class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parameters) extends LazyModule { val node = TLNexusNode( - numClientPorts = 1 to 999, - numManagerPorts = 1 to 999, clientFn = { seq => seq(0).copy( minLatency = seq.map(_.minLatency).min, @@ -159,20 +157,20 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parame val addressA = (in zip edgesIn) map { case (i, e) => e.address(i.a.bits) } val addressC = (in zip edgesIn) map { case (i, e) => e.address(i.c.bits) } - val requestAIO = Vec(addressA.map { i => Vec(outputPorts.map { o => o(i) }) }) - val requestCIO = Vec(addressC.map { i => Vec(outputPorts.map { o => o(i) }) }) - val requestBOI = Vec(out.map { o => Vec(inputIdRanges.map { i => i.contains(o.b.bits.source) }) }) - val requestDOI = Vec(out.map { o => Vec(inputIdRanges.map { i => i.contains(o.d.bits.source) }) }) - val requestEIO = Vec(in.map { i => Vec(outputIdRanges.map { o => o.map(_.contains(i.e.bits.sink)).getOrElse(Bool(false)) }) }) + val requestAIO = addressA.map { i => outputPorts.map { o => o(i) } } + val requestCIO = addressC.map { i => outputPorts.map { o => o(i) } } + val requestBOI = out.map { o => inputIdRanges.map { i => i.contains(o.b.bits.source) } } + val requestDOI = out.map { o => inputIdRanges.map { i => i.contains(o.d.bits.source) } } + val requestEIO = in.map { i => outputIdRanges.map { o => o.map(_.contains(i.e.bits.sink)).getOrElse(Bool(false)) } } - val beatsAI = Vec((in zip edgesIn) map { case (i, e) => e.numBeats1(i.a.bits) }) - val beatsBO = Vec((out zip edgesOut) map { case (o, e) => e.numBeats1(o.b.bits) }) - val beatsCI = Vec((in zip edgesIn) map { case (i, e) => e.numBeats1(i.c.bits) }) - val beatsDO = Vec((out zip edgesOut) map { case (o, e) => e.numBeats1(o.d.bits) }) - val beatsEI = Vec((in zip edgesIn) map { case (i, e) => e.numBeats1(i.e.bits) }) + val beatsAI = (in zip edgesIn) map { case (i, e) => e.numBeats1(i.a.bits) } + val beatsBO = (out zip edgesOut) map { case (o, e) => e.numBeats1(o.b.bits) } + val beatsCI = (in zip edgesIn) map { case (i, e) => e.numBeats1(i.c.bits) } + val beatsDO = (out zip edgesOut) map { case (o, e) => e.numBeats1(o.d.bits) } + val beatsEI = (in zip edgesIn) map { case (i, e) => e.numBeats1(i.e.bits) } // Which pairs support support transfers - def transpose[T](x: Seq[Seq[T]]) = Seq.tabulate(x(0).size) { i => Seq.tabulate(x.size) { j => x(j)(i) } } + def transpose[T](x: Seq[Seq[T]]) = if (x.isEmpty) Nil else Seq.tabulate(x(0).size) { i => Seq.tabulate(x.size) { j => x(j)(i) } } def filter[T](data: Seq[T], mask: Seq[Boolean]) = (data zip mask).filter(_._2).map(_._1) // Fanout the input sources to the output sinks @@ -206,6 +204,12 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parame object TLXbar { + def apply(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parameters): TLNode = + { + val xbar = LazyModule(new TLXbar(policy)) + xbar.node + } + def mapInputIds (ports: Seq[TLClientPortParameters ]) = assignRanges(ports.map(_.endSourceId)).map(_.get) def mapOutputIds(ports: Seq[TLManagerPortParameters]) = assignRanges(ports.map(_.endSinkId)) @@ -266,7 +270,8 @@ class TLRAMXbar(nManagers: Int, txns: Int)(implicit p: Parameters) extends LazyM } class TLRAMXbarTest(nManagers: Int, txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { - io.finished := Module(LazyModule(new TLRAMXbar(nManagers,txns)).module).io.finished + val dut = Module(LazyModule(new TLRAMXbar(nManagers,txns)).module) + io.finished := dut.io.finished } class TLMulticlientXbar(nManagers: Int, nClients: Int, txns: Int)(implicit p: Parameters) extends LazyModule { @@ -289,5 +294,6 @@ class TLMulticlientXbar(nManagers: Int, nClients: Int, txns: Int)(implicit p: Pa } class TLMulticlientXbarTest(nManagers: Int, nClients: Int, txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { - io.finished := Module(LazyModule(new TLMulticlientXbar(nManagers, nClients, txns)).module).io.finished + val dut = Module(LazyModule(new TLMulticlientXbar(nManagers, nClients, txns)).module) + io.finished := dut.io.finished } diff --git a/src/main/scala/tilelink/package.scala b/src/main/scala/tilelink/package.scala index 9a6cba28..72379c53 100644 --- a/src/main/scala/tilelink/package.scala +++ b/src/main/scala/tilelink/package.scala @@ -7,7 +7,7 @@ import freechips.rocketchip.diplomacy._ package object tilelink { - type TLInwardNode = InwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLBundle] - type TLOutwardNode = OutwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLBundle] - type TLNode = SimpleNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLBundle] + type TLInwardNode = InwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLEdgeIn, TLBundle] + type TLOutwardNode = OutwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLBundle] + type TLNode = NodeHandle[TLClientPortParameters, TLManagerPortParameters, TLEdgeIn, TLBundle, TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLBundle] } diff --git a/src/main/scala/unittest/TestGenerator.scala b/src/main/scala/unittest/TestGenerator.scala new file mode 100644 index 00000000..668031ee --- /dev/null +++ b/src/main/scala/unittest/TestGenerator.scala @@ -0,0 +1,35 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.unittest + +import Chisel._ +import freechips.rocketchip.config._ +import freechips.rocketchip.diplomacy._ + +abstract class LazyUnitTest(implicit p: Parameters) extends LazyModule +{ self => + protected def finished: Bool + + lazy val module = new LazyModuleImp(this) { + val finished = IO(Bool(OUTPUT)) + finished := self.finished + } +} + +// FYI, you can call .finished on a Seq[LazyUnitTest] +class TestGenerator(gen: LazyModule => Seq[LazyUnitTest]) +{ + def apply(lm: LazyModule) = gen(lm) + def ++ (other: TestGenerator) = new TestGenerator(gen = lm => gen(lm) ++ other(lm)) +} + +object TestGenerator +{ + def apply(matcher: PartialFunction[LazyModule, Seq[LazyUnitTest]]): TestGenerator = + new TestGenerator(gen = matcher.lift(_).getOrElse(Nil)) + def recurse(other: TestGenerator): TestGenerator = { + def helper(lm: LazyModule, tail: Seq[LazyUnitTest]): Seq[LazyUnitTest] = + lm.getChildren.foldLeft(other(lm) ++ tail) { case (tail, child) => helper(child, tail) } + new TestGenerator(gen = helper(_, Nil)) + } +} diff --git a/src/main/scala/unittest/package.scala b/src/main/scala/unittest/package.scala new file mode 100644 index 00000000..9b58192c --- /dev/null +++ b/src/main/scala/unittest/package.scala @@ -0,0 +1,12 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip + +import Chisel._ + +package object unittest +{ + implicit class LazyUnitTestSeq(val seq: Seq[LazyUnitTest]) { + def finished = seq.map(_.module.finished).foldLeft(Bool(true))(_ && _) + } +}