diff --git a/src/main/scala/diplomacy/Nodes.scala b/src/main/scala/diplomacy/Nodes.scala index 3fea4d3c..ee54a425 100644 --- a/src/main/scala/diplomacy/Nodes.scala +++ b/src/main/scala/diplomacy/Nodes.scala @@ -16,7 +16,9 @@ trait InwardNodeImp[DI, UI, EI, BI <: Data] def edgeI(pd: DI, pu: UI): EI def bundleI(ei: Seq[EI]): Vec[BI] def colour: String - def connect(bo: => BI, bi: => BI, e: => EI)(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) + def connect(bindings: () => Seq[(EI, BI, BI)])(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = { + (None, () => bindings().foreach { case (_, i, o) => i <> o }) + } // optional methods to track node graph def mixI(pu: UI, node: InwardNode[DI, UI, BI]): UI = pu // insert node into parameters @@ -233,17 +235,17 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( case BIND_STAR => BIND_QUERY case BIND_QUERY => BIND_STAR }) x.iPush(o, y, binding) - def connect() { + def bindings() = { val (iStart, iEnd) = x.iPortMapping(i) val (oStart, oEnd) = y.oPortMapping(o) require (iEnd - iStart == oEnd - oStart, s"Bug in diplomacy; ${iEnd-iStart} != ${oEnd-oStart} means port resolution failed") - for (i <- 0 until (iEnd - iStart)) { - x.bundleIn(iStart+i) <> y.bundleOut(oStart+i) + Seq.tabulate(iEnd - iStart) { j => + (x.edgesIn(iStart+j), x.bundleIn(iStart+j), y.bundleOut(oStart+j)) } } -// !!! val (out, binding) = inner.connect(y.bundleOut(o), x.bundleIn(i), x.edgesIn(i)) - LazyModule.stack.head.bindings = connect _ :: LazyModule.stack.head.bindings - None + val (out, newbinding) = inner.connect(bindings _) + LazyModule.stack.head.bindings = newbinding :: LazyModule.stack.head.bindings + out } override def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[LazyModule] = bind(h, BIND_ONCE) diff --git a/src/main/scala/uncore/ahb/Nodes.scala b/src/main/scala/uncore/ahb/Nodes.scala index 44f4b669..50843943 100644 --- a/src/main/scala/uncore/ahb/Nodes.scala +++ b/src/main/scala/uncore/ahb/Nodes.scala @@ -19,10 +19,6 @@ object AHBImp extends NodeImp[AHBMasterPortParameters, AHBSlavePortParameters, A override def labelI(ei: AHBEdgeParameters) = (ei.slave.beatBytes * 8).toString override def labelO(eo: AHBEdgeParameters) = (eo.slave.beatBytes * 8).toString - def connect(bo: => AHBBundle, bi: => AHBBundle, ei: => AHBEdgeParameters)(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = { - (None, () => { bi <> bo }) - } - override def mixO(pd: AHBMasterPortParameters, node: OutwardNode[AHBMasterPortParameters, AHBSlavePortParameters, AHBBundle]): AHBMasterPortParameters = pd.copy(masters = pd.masters.map { c => c.copy (nodePath = node +: c.nodePath) }) override def mixI(pu: AHBSlavePortParameters, node: InwardNode[AHBMasterPortParameters, AHBSlavePortParameters, AHBBundle]): AHBSlavePortParameters = diff --git a/src/main/scala/uncore/apb/Nodes.scala b/src/main/scala/uncore/apb/Nodes.scala index 98bb598a..999d23b2 100644 --- a/src/main/scala/uncore/apb/Nodes.scala +++ b/src/main/scala/uncore/apb/Nodes.scala @@ -19,10 +19,6 @@ object APBImp extends NodeImp[APBMasterPortParameters, APBSlavePortParameters, A override def labelI(ei: APBEdgeParameters) = (ei.slave.beatBytes * 8).toString override def labelO(eo: APBEdgeParameters) = (eo.slave.beatBytes * 8).toString - def connect(bo: => APBBundle, bi: => APBBundle, ei: => APBEdgeParameters)(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = { - (None, () => { bi <> bo }) - } - override def mixO(pd: APBMasterPortParameters, node: OutwardNode[APBMasterPortParameters, APBSlavePortParameters, APBBundle]): APBMasterPortParameters = pd.copy(masters = pd.masters.map { c => c.copy (nodePath = node +: c.nodePath) }) override def mixI(pu: APBSlavePortParameters, node: InwardNode[APBMasterPortParameters, APBSlavePortParameters, APBBundle]): APBSlavePortParameters = diff --git a/src/main/scala/uncore/axi4/Nodes.scala b/src/main/scala/uncore/axi4/Nodes.scala index 097c0aed..fafe4c62 100644 --- a/src/main/scala/uncore/axi4/Nodes.scala +++ b/src/main/scala/uncore/axi4/Nodes.scala @@ -19,10 +19,6 @@ object AXI4Imp extends NodeImp[AXI4MasterPortParameters, AXI4SlavePortParameters override def labelI(ei: AXI4EdgeParameters) = (ei.slave.beatBytes * 8).toString override def labelO(eo: AXI4EdgeParameters) = (eo.slave.beatBytes * 8).toString - def connect(bo: => AXI4Bundle, bi: => AXI4Bundle, ei: => AXI4EdgeParameters)(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = { - (None, () => { bi <> bo }) - } - override def mixO(pd: AXI4MasterPortParameters, node: OutwardNode[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4Bundle]): AXI4MasterPortParameters = pd.copy(masters = pd.masters.map { c => c.copy (nodePath = node +: c.nodePath) }) override def mixI(pu: AXI4SlavePortParameters, node: InwardNode[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4Bundle]): AXI4SlavePortParameters = diff --git a/src/main/scala/uncore/tilelink2/Bundles.scala b/src/main/scala/uncore/tilelink2/Bundles.scala index 38e076b1..69d0f969 100644 --- a/src/main/scala/uncore/tilelink2/Bundles.scala +++ b/src/main/scala/uncore/tilelink2/Bundles.scala @@ -210,11 +210,11 @@ final class DecoupledSnoop[+T <: Data](gen: T) extends Bundle object DecoupledSnoop { - def apply[T <: Data](i: DecoupledIO[T]) = { - val out = Wire(new DecoupledSnoop(i.bits)) - out.ready := i.ready - out.valid := i.valid - out.bits := i.bits + def apply[T <: Data](source: DecoupledIO[T], sink: DecoupledIO[T]) = { + val out = Wire(new DecoupledSnoop(sink.bits)) + out.ready := sink.ready + out.valid := source.valid + out.bits := source.bits out } } @@ -230,13 +230,13 @@ class TLBundleSnoop(params: TLBundleParameters) extends TLBundleBase(params) object TLBundleSnoop { - def apply(x: TLBundle) = { - val out = Wire(new TLBundleSnoop(x.params)) - out.a <> DecoupledSnoop(x.a) - out.b <> DecoupledSnoop(x.b) - out.c <> DecoupledSnoop(x.c) - out.d <> DecoupledSnoop(x.d) - out.e <> DecoupledSnoop(x.e) + def apply(source: TLBundle, sink: TLBundle) = { + val out = Wire(new TLBundleSnoop(sink.params)) + out.a := DecoupledSnoop(source.a, sink.a) + out.b := DecoupledSnoop(sink.b, source.b) + out.c := DecoupledSnoop(source.c, sink.c) + out.d := DecoupledSnoop(sink.d, source.d) + out.e := DecoupledSnoop(source.e, sink.e) out } } diff --git a/src/main/scala/uncore/tilelink2/Monitor.scala b/src/main/scala/uncore/tilelink2/Monitor.scala index c0ce44e1..e540f00a 100644 --- a/src/main/scala/uncore/tilelink2/Monitor.scala +++ b/src/main/scala/uncore/tilelink2/Monitor.scala @@ -7,7 +7,7 @@ import chisel3.internal.sourceinfo.{SourceInfo, SourceLine} import config._ import diplomacy._ -case class TLMonitorArgs(gen: () => TLBundleSnoop, edge: () => TLEdge, sourceInfo: SourceInfo, p: Parameters) +case class TLMonitorArgs(edge: () => Seq[TLEdge], sourceInfo: SourceInfo, p: Parameters) abstract class TLMonitorBase(args: TLMonitorArgs) extends LazyModule()(args.p) { @@ -16,11 +16,12 @@ abstract class TLMonitorBase(args: TLMonitorArgs) extends LazyModule()(args.p) def legalize(bundle: TLBundleSnoop, edge: TLEdge, reset: Bool): Unit lazy val module = new LazyModuleImp(this) { + val edges = args.edge() val io = new Bundle { - val in = args.gen().asInput + val in = Vec(edges.size, new TLBundleSnoop(TLBundleParameters.union(edges.map(_.bundle)))).flip } - legalize(io.in, args.edge(), reset) + (edges zip io.in).foreach { case (e, in) => legalize(in, e, reset) } } } diff --git a/src/main/scala/uncore/tilelink2/Nodes.scala b/src/main/scala/uncore/tilelink2/Nodes.scala index 3cd6e26d..82044873 100644 --- a/src/main/scala/uncore/tilelink2/Nodes.scala +++ b/src/main/scala/uncore/tilelink2/Nodes.scala @@ -24,44 +24,47 @@ object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TL override def labelI(ei: TLEdgeIn) = (ei.manager.beatBytes * 8).toString override def labelO(eo: TLEdgeOut) = (eo.manager.beatBytes * 8).toString - def connect(bo: => TLBundle, bi: => TLBundle, ei: => TLEdgeIn)(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = { - val monitor = p(TLMonitorBuilder)(TLMonitorArgs(() => new TLBundleSnoop(bo.params), () => ei, sourceInfo, p)) + override def connect(bindings: () => Seq[(TLEdgeIn, TLBundle, TLBundle)])(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = { + val monitor = p(TLMonitorBuilder)(TLMonitorArgs(() => bindings().map(_._1), sourceInfo, p)) (monitor, () => { - bi <> bo - monitor.foreach { _.module.io.in := TLBundleSnoop(bo) } - if (p(TLCombinationalCheck)) { - // It is forbidden for valid to depend on ready in TL2 - // If someone did that, then this will create a detectable combinational loop - bo.a.ready := bi.a.ready && bo.a.valid - bi.b.ready := bo.b.ready && bi.b.valid - bo.c.ready := bi.c.ready && bo.c.valid - bi.d.ready := bo.d.ready && bi.d.valid - bo.e.ready := bi.e.ready && bo.e.valid - } - if (p(TLCombinationalCheck)) { - // Randomly stall the transfers - val allow = LFSRNoiseMaker(5) - bi.a.valid := bo.a.valid && allow(0) - bo.a.ready := bi.a.ready && allow(0) - bo.b.valid := bi.b.valid && allow(1) - bi.b.ready := bo.b.ready && allow(1) - bi.c.valid := bo.c.valid && allow(2) - bo.c.ready := bi.c.ready && allow(2) - bo.d.valid := bi.d.valid && allow(3) - bi.d.ready := bo.d.ready && allow(3) - bi.e.valid := bo.e.valid && allow(4) - bo.e.ready := bi.e.ready && allow(4) - // Inject garbage whenever not valid - val bits_a = bo.a.bits.fromBits(LFSRNoiseMaker(bo.a.bits.asUInt.getWidth)) - val bits_b = bi.b.bits.fromBits(LFSRNoiseMaker(bi.b.bits.asUInt.getWidth)) - val bits_c = bo.c.bits.fromBits(LFSRNoiseMaker(bo.c.bits.asUInt.getWidth)) - val bits_d = bi.d.bits.fromBits(LFSRNoiseMaker(bi.d.bits.asUInt.getWidth)) - val bits_e = bo.e.bits.fromBits(LFSRNoiseMaker(bo.e.bits.asUInt.getWidth)) - when (!bi.a.valid) { bi.a.bits := bits_a } - when (!bo.b.valid) { bo.b.bits := bits_b } - when (!bi.c.valid) { bi.c.bits := bits_c } - when (!bo.d.valid) { bo.d.bits := bits_d } - when (!bi.e.valid) { bi.e.bits := bits_e } + val eval = bindings () + monitor.foreach { m => (eval zip m.module.io.in) foreach { case ((_,i,o), m) => m := TLBundleSnoop(o,i) } } + eval.foreach { case (_, bi, bo) => + bi <> bo + if (p(TLCombinationalCheck)) { + // It is forbidden for valid to depend on ready in TL2 + // If someone did that, then this will create a detectable combinational loop + bo.a.ready := bi.a.ready && bo.a.valid + bi.b.ready := bo.b.ready && bi.b.valid + bo.c.ready := bi.c.ready && bo.c.valid + bi.d.ready := bo.d.ready && bi.d.valid + bo.e.ready := bi.e.ready && bo.e.valid + } + if (p(TLCombinationalCheck)) { + // Randomly stall the transfers + val allow = LFSRNoiseMaker(5) + bi.a.valid := bo.a.valid && allow(0) + bo.a.ready := bi.a.ready && allow(0) + bo.b.valid := bi.b.valid && allow(1) + bi.b.ready := bo.b.ready && allow(1) + bi.c.valid := bo.c.valid && allow(2) + bo.c.ready := bi.c.ready && allow(2) + bo.d.valid := bi.d.valid && allow(3) + bi.d.ready := bo.d.ready && allow(3) + bi.e.valid := bo.e.valid && allow(4) + bo.e.ready := bi.e.ready && allow(4) + // Inject garbage whenever not valid + val bits_a = bo.a.bits.fromBits(LFSRNoiseMaker(bo.a.bits.asUInt.getWidth)) + val bits_b = bi.b.bits.fromBits(LFSRNoiseMaker(bi.b.bits.asUInt.getWidth)) + val bits_c = bo.c.bits.fromBits(LFSRNoiseMaker(bo.c.bits.asUInt.getWidth)) + val bits_d = bi.d.bits.fromBits(LFSRNoiseMaker(bi.d.bits.asUInt.getWidth)) + val bits_e = bo.e.bits.fromBits(LFSRNoiseMaker(bo.e.bits.asUInt.getWidth)) + when (!bi.a.valid) { bi.a.bits := bits_a } + when (!bo.b.valid) { bo.b.bits := bits_b } + when (!bi.c.valid) { bi.c.bits := bits_c } + when (!bo.d.valid) { bo.d.bits := bits_d } + when (!bi.e.valid) { bi.e.bits := bits_e } + } } }) } @@ -159,10 +162,6 @@ object TLAsyncImp extends NodeImp[TLAsyncClientPortParameters, TLAsyncManagerPor override def labelI(ei: TLAsyncEdgeParameters) = ei.manager.depth.toString override def labelO(eo: TLAsyncEdgeParameters) = eo.manager.depth.toString - def connect(bo: => TLAsyncBundle, bi: => TLAsyncBundle, ei: => TLAsyncEdgeParameters)(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = { - (None, () => { bi <> bo }) - } - override def mixO(pd: TLAsyncClientPortParameters, node: OutwardNode[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncBundle]): TLAsyncClientPortParameters = pd.copy(base = pd.base.copy(clients = pd.base.clients.map { c => c.copy (nodePath = node +: c.nodePath) })) override def mixI(pu: TLAsyncManagerPortParameters, node: InwardNode[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncBundle]): TLAsyncManagerPortParameters = @@ -193,10 +192,6 @@ object TLRationalImp extends NodeImp[TLClientPortParameters, TLManagerPortParame def colour = "#00ff00" // green - def connect(bo: => TLRationalBundle, bi: => TLRationalBundle, ei: => TLEdgeParameters)(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = { - (None, () => { bi <> bo }) - } - override def mixO(pd: TLClientPortParameters, node: OutwardNode[TLClientPortParameters, TLManagerPortParameters, TLRationalBundle]): TLClientPortParameters = pd.copy(clients = pd.clients.map { c => c.copy (nodePath = node +: c.nodePath) }) override def mixI(pu: TLManagerPortParameters, node: InwardNode[TLClientPortParameters, TLManagerPortParameters, TLRationalBundle]): TLManagerPortParameters =