Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CreditedIO to support register-register interfacing for AXI4 and TL #2555

Merged
merged 9 commits into from
Jul 29, 2020
9 changes: 9 additions & 0 deletions src/main/scala/amba/axi4/Bundles.scala
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,12 @@ class AXI4AsyncBundle(params: AXI4AsyncBundleParameters) extends AXI4AsyncBundle
val ar = new AsyncBundle(new AXI4BundleAR(params.base), params.async)
val r = new AsyncBundle(new AXI4BundleR (params.base), params.async).flip
}

class AXI4CreditedBundle(params: AXI4BundleParameters) extends AXI4BundleBase(params)
{
val aw = CreditedIO(new AXI4BundleAW(params))
val w = CreditedIO(new AXI4BundleW (params))
val b = CreditedIO(new AXI4BundleB (params)).flip
val ar = CreditedIO(new AXI4BundleAR(params))
val r = CreditedIO(new AXI4BundleR (params)).flip
}
113 changes: 113 additions & 0 deletions src/main/scala/amba/axi4/Credited.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// See LICENSE.SiFive for license details.

package freechips.rocketchip.amba.axi4

import chisel3._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.subsystem.CrossingWrapper
import freechips.rocketchip.util._

class AXI4CreditedBuffer(delay: AXI4CreditedDelay)(implicit p: Parameters) extends LazyModule
{
val node = AXI4CreditedAdapterNode(
masterFn = p => p.copy(delay = delay + p.delay),
slaveFn = p => p.copy(delay = delay + p.delay))

lazy val module = new LazyModuleImp(this) {
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
out.aw :<> in.aw.pipeline(delay.aw)
out.w :<> in.w.pipeline(delay.w)
in.b :<> out.b.pipeline(delay.b)
out.ar :<> in.ar.pipeline(delay.ar)
in.r :<> out.r.pipeline(delay.r)
}
}
}

object AXI4CreditedBuffer {
def apply(delay: AXI4CreditedDelay)(implicit p: Parameters): AXI4CreditedAdapterNode = {
val buffer = LazyModule(new AXI4CreditedBuffer(delay))
buffer.node
}
def apply(delay: CreditedDelay)(implicit p: Parameters): AXI4CreditedAdapterNode = apply(AXI4CreditedDelay(delay))
def apply()(implicit p: Parameters): AXI4CreditedAdapterNode = apply(CreditedDelay(1, 1))
}

class AXI4CreditedSource(delay: AXI4CreditedDelay)(implicit p: Parameters) extends LazyModule
{
val node = AXI4CreditedSourceNode(delay)
lazy val module = new LazyModuleImp(this) {
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val tld = edgeOut.delay
out.aw :<> CreditedIO.fromSender(in.aw, tld.aw.total).pipeline(delay.aw)
out.w :<> CreditedIO.fromSender(in.w, tld.w.total).pipeline(delay.w)
in.b :<> out.b.pipeline(delay.b).toReceiver(tld.b.total)
out.ar :<> CreditedIO.fromSender(in.ar, tld.ar.total).pipeline(delay.ar)
in.r :<> out.r.pipeline(delay.r).toReceiver(tld.r.total)
}
}
}

object AXI4CreditedSource {
def apply(delay: AXI4CreditedDelay)(implicit p: Parameters): AXI4CreditedSourceNode = {
val source = LazyModule(new AXI4CreditedSource(delay))
source.node
}
def apply(delay: CreditedDelay)(implicit p: Parameters): AXI4CreditedSourceNode = apply(AXI4CreditedDelay(delay))
def apply()(implicit p: Parameters): AXI4CreditedSourceNode = apply(CreditedDelay(1, 1))
}

class AXI4CreditedSink(delay: AXI4CreditedDelay)(implicit p: Parameters) extends LazyModule
{
val node = AXI4CreditedSinkNode(delay)
lazy val module = new LazyModuleImp(this) {
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val tld = edgeIn.delay
out.aw :<> in.aw.pipeline(delay.aw).toReceiver(tld.aw.total)
out.w :<> in.w.pipeline(delay.w).toReceiver(tld.w.total)
in.b :<> CreditedIO.fromSender(out.b, tld.b.total).pipeline(delay.b)
out.ar :<> in.ar.pipeline(delay.ar).toReceiver(tld.ar.total)
in.r :<> CreditedIO.fromSender(out.r, tld.r.total).pipeline(delay.r)
}
}
}

object AXI4CreditedSink {
def apply(delay: AXI4CreditedDelay)(implicit p: Parameters): AXI4CreditedSinkNode = {
val sink = LazyModule(new AXI4CreditedSink(delay))
sink.node
}
def apply(delay: CreditedDelay)(implicit p: Parameters): AXI4CreditedSinkNode = apply(AXI4CreditedDelay(delay))
def apply()(implicit p: Parameters): AXI4CreditedSinkNode = apply(CreditedDelay(1, 1))
}

/** Synthesizeable unit tests */
import freechips.rocketchip.unittest._

class AXI4RAMCreditedCrossing(txns: Int, params: CreditedCrossing)(implicit p: Parameters) extends LazyModule {
val model = LazyModule(new TLRAMModel("AXI4CreditedCrossing"))
val fuzz = LazyModule(new TLFuzzer(txns))
val toaxi = LazyModule(new TLToAXI4)
val island = LazyModule(new CrossingWrapper(params))
val ram = island { LazyModule(new AXI4RAM(AddressSet(0x0, 0x3ff))) }

island.crossAXI4In(ram.node) := toaxi.node := TLDelayer(0.1) := model.node := fuzz.node

lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
}
}

class AXI4RAMCreditedCrossingTest(txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) {
val dut_1000 = Module(LazyModule(new AXI4RAMCreditedCrossing(txns, CreditedCrossing(CreditedDelay(1, 0), CreditedDelay(0, 0)))).module)
val dut_0100 = Module(LazyModule(new AXI4RAMCreditedCrossing(txns, CreditedCrossing(CreditedDelay(0, 1), CreditedDelay(0, 0)))).module)
val dut_0010 = Module(LazyModule(new AXI4RAMCreditedCrossing(txns, CreditedCrossing(CreditedDelay(0, 0), CreditedDelay(1, 0)))).module)
val dut_0001 = Module(LazyModule(new AXI4RAMCreditedCrossing(txns, CreditedCrossing(CreditedDelay(0, 0), CreditedDelay(0, 1)))).module)
val dut_1111 = Module(LazyModule(new AXI4RAMCreditedCrossing(txns, CreditedCrossing(CreditedDelay(1, 1), CreditedDelay(1, 1)))).module)

val duts = Seq(dut_1000, dut_0100, dut_0010, dut_0001, dut_1111)
duts.foreach { _.io.start := true.B }
io.finished := duts.map(_.io.finished).reduce(_ && _)
}
4 changes: 4 additions & 0 deletions src/main/scala/amba/axi4/CrossingHelper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ case class AXI4InwardCrossingHelper(name: String, scope: LazyScope, node: AXI4In
throw new IllegalArgumentException("AXI4 Rational crossing unimplemented")
case SynchronousCrossing(buffer) =>
node :*=* scope { AXI4Buffer(buffer) :*=* AXI4NameNode(name) } :*=* AXI4NameNode(name)
case CreditedCrossing(sourceDelay, sinkDelay) =>
node :*=* scope { AXI4CreditedSink(sinkDelay) :*=* AXI4CreditedNameNode(name) } :*=* AXI4CreditedNameNode(name) :*=* AXI4CreditedSource(sourceDelay)
}
}
}
Expand All @@ -27,6 +29,8 @@ case class AXI4OutwardCrossingHelper(name: String, scope: LazyScope, node: AXI4O
throw new IllegalArgumentException("AXI4 Rational crossing unimplemented")
case SynchronousCrossing(buffer) =>
AXI4NameNode(name) :*=* scope { AXI4NameNode(name) :*=* AXI4Buffer(buffer) } :*=* node
case CreditedCrossing(sourceDelay, sinkDelay) =>
AXI4CreditedSink(sinkDelay) :*=* AXI4CreditedNameNode(name) :*=* scope { AXI4CreditedNameNode(name) :*=* AXI4CreditedSource(sourceDelay) } :*=* node
}
}
}
36 changes: 36 additions & 0 deletions src/main/scala/amba/axi4/Nodes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,39 @@ object AXI4AsyncNameNode {
def apply(name: Option[String]): AXI4AsyncIdentityNode = apply((ValName(name.getOrElse("with_no_name"))))
def apply(name: String): AXI4AsyncIdentityNode = apply(Some(name))
}

object AXI4CreditedImp extends SimpleNodeImp[AXI4CreditedMasterPortParameters, AXI4CreditedSlavePortParameters, AXI4CreditedEdgeParameters, AXI4CreditedBundle]
{
def edge(pd: AXI4CreditedMasterPortParameters, pu: AXI4CreditedSlavePortParameters, p: Parameters, sourceInfo: SourceInfo) = AXI4CreditedEdgeParameters(pd, pu, p, sourceInfo)
def bundle(e: AXI4CreditedEdgeParameters) = new AXI4CreditedBundle(e.bundle)
def render(e: AXI4CreditedEdgeParameters) = RenderedEdge(colour = "#ffff00" /* yellow */, label = e.delay.toString)

override def mixO(pd: AXI4CreditedMasterPortParameters, node: OutwardNode[AXI4CreditedMasterPortParameters, AXI4CreditedSlavePortParameters, AXI4CreditedBundle]): AXI4CreditedMasterPortParameters =
pd.copy(base = pd.base.copy(masters = pd.base.masters.map { c => c.copy (nodePath = node +: c.nodePath) }))
override def mixI(pu: AXI4CreditedSlavePortParameters, node: InwardNode[AXI4CreditedMasterPortParameters, AXI4CreditedSlavePortParameters, AXI4CreditedBundle]): AXI4CreditedSlavePortParameters =
pu.copy(base = pu.base.copy(slaves = pu.base.slaves.map { m => m.copy (nodePath = node +: m.nodePath) }))
}

case class AXI4CreditedSourceNode(delay: AXI4CreditedDelay)(implicit valName: ValName)
extends MixedAdapterNode(AXI4Imp, AXI4CreditedImp)(
dFn = { p => AXI4CreditedMasterPortParameters(delay, p) },
uFn = { p => p.base.copy(minLatency = 1) })

case class AXI4CreditedSinkNode(delay: AXI4CreditedDelay)(implicit valName: ValName)
extends MixedAdapterNode(AXI4CreditedImp, AXI4Imp)(
dFn = { p => p.base },
uFn = { p => AXI4CreditedSlavePortParameters(delay, p) })

case class AXI4CreditedAdapterNode(
masterFn: AXI4CreditedMasterPortParameters => AXI4CreditedMasterPortParameters = { s => s },
slaveFn: AXI4CreditedSlavePortParameters => AXI4CreditedSlavePortParameters = { s => s })(
implicit valName: ValName)
extends AdapterNode(AXI4CreditedImp)(masterFn, slaveFn)

case class AXI4CreditedIdentityNode()(implicit valName: ValName) extends IdentityNode(AXI4CreditedImp)()

object AXI4CreditedNameNode {
def apply(name: ValName) = AXI4CreditedIdentityNode()(name)
def apply(name: Option[String]): AXI4CreditedIdentityNode = apply((ValName(name.getOrElse("with_no_name"))))
def apply(name: String): AXI4CreditedIdentityNode = apply(Some(name))
}
29 changes: 29 additions & 0 deletions src/main/scala/amba/axi4/Parameters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,35 @@ case class AXI4BufferParams(
def copyInOut(x: BufferParams) = this.copyIn(x).copyOut(x)
}

case class AXI4CreditedDelay(
aw: CreditedDelay,
w: CreditedDelay,
b: CreditedDelay,
ar: CreditedDelay,
r: CreditedDelay)
{
def + (that: AXI4CreditedDelay): AXI4CreditedDelay = AXI4CreditedDelay(
aw = aw + that.aw,
w = w + that.w,
b = b + that.b,
ar = ar + that.ar,
r = r + that.r)

override def toString = s"(${aw}, ${w}, ${b}, ${ar}, ${r})"
}

object AXI4CreditedDelay {
def apply(delay: CreditedDelay): AXI4CreditedDelay = apply(delay, delay, delay.flip, delay, delay.flip)
}

case class AXI4CreditedSlavePortParameters(delay: AXI4CreditedDelay, base: AXI4SlavePortParameters)
case class AXI4CreditedMasterPortParameters(delay: AXI4CreditedDelay, base: AXI4MasterPortParameters)
case class AXI4CreditedEdgeParameters(master: AXI4CreditedMasterPortParameters, slave: AXI4CreditedSlavePortParameters, params: Parameters, sourceInfo: SourceInfo)
{
val delay = master.delay + slave.delay
val bundle = AXI4BundleParameters(master.base, slave.base)
}

/** Pretty printing of AXI4 source id maps */
class AXI4IdMap(axi4: AXI4MasterPortParameters) extends IdMap[AXI4IdMapEntry] {
private val axi4Digits = String.valueOf(axi4.endId-1).length()
Expand Down
8 changes: 7 additions & 1 deletion src/main/scala/diplomacy/Parameters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package freechips.rocketchip.diplomacy

import Chisel._
import chisel3.util.{IrrevocableIO,ReadyValidIO}
import freechips.rocketchip.util.{ShiftQueue, RationalDirection, FastToSlow, AsyncQueueParams}
import freechips.rocketchip.util.{ShiftQueue, RationalDirection, FastToSlow, AsyncQueueParams, CreditedDelay}
import scala.reflect.ClassTag

/** Options for describing the attributes of memory regions */
Expand Down Expand Up @@ -316,6 +316,12 @@ case class AsynchronousCrossing(depth: Int = 8, sourceSync: Int = 3, sinkSync: I
{
def asSinkParams = AsyncQueueParams(depth, sinkSync, safe, narrow)
}
case class CreditedCrossing(sourceDelay: CreditedDelay, sinkDelay: CreditedDelay) extends ClockCrossingType

object CreditedCrossing {
def apply(delay: CreditedDelay): CreditedCrossing = CreditedCrossing(delay, delay.flip)
def apply(): CreditedCrossing = CreditedCrossing(CreditedDelay(1, 1))
}

trait DirectedBuffers[T] {
def copyIn(x: BufferParams): T
Expand Down
5 changes: 5 additions & 0 deletions src/main/scala/interrupts/CrossingHelper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package freechips.rocketchip.interrupts

import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.util.CreditedDelay

case class IntInwardCrossingHelper(name: String, scope: LazyScope, node: IntInwardNode) {
def apply(xing: ClockCrossingType = NoCrossing, alreadyRegistered: Boolean = false)(implicit p: Parameters): IntInwardNode = {
Expand All @@ -14,6 +15,8 @@ case class IntInwardCrossingHelper(name: String, scope: LazyScope, node: IntInwa
node :*=* scope { IntSyncRationalCrossingSink() :*=* IntSyncNameNode(name) } :*=* IntSyncNameNode(name) :*=* IntSyncCrossingSource(alreadyRegistered)
case SynchronousCrossing(_) =>
node :*=* scope { IntSyncSyncCrossingSink() :*=* IntSyncNameNode(name) } :*=* IntSyncNameNode(name) :*=* IntSyncCrossingSource(alreadyRegistered)
case CreditedCrossing(CreditedDelay(sourceDebit, _), CreditedDelay(sinkDebit, _)) =>
node :*=* scope { IntSyncSyncCrossingSink(/*sinkDebit==0*/) :*=* IntSyncNameNode(name) } :*=* IntSyncNameNode(name) :*=* IntSyncCrossingSource(sourceDebit==0)
}
}
}
Expand All @@ -27,6 +30,8 @@ case class IntOutwardCrossingHelper(name: String, scope: LazyScope, node: IntOut
IntSyncRationalCrossingSink() :*=* IntSyncNameNode(name) :*=* scope { IntSyncNameNode(name) :*=* IntSyncCrossingSource(alreadyRegistered) } :*=* node
case SynchronousCrossing(buffer) =>
IntSyncSyncCrossingSink() :*=* IntSyncNameNode(name) :*=* scope { IntSyncNameNode(name) :*=* IntSyncCrossingSource(alreadyRegistered) } :*=* node
case CreditedCrossing(CreditedDelay(sourceDebit, _), CreditedDelay(sinkDebit, _)) =>
IntSyncSyncCrossingSink(/*sinkDebit==0*/) :*=* IntSyncNameNode(name) :*=* scope { IntSyncNameNode(name) :*=* IntSyncCrossingSource(sourceDebit==0) } :*=* node
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is sinkDebit ignored here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The IntSyncCrossingSink does not support a register stage. I could change that. Should I?

Copy link
Member

@hcook hcook Jul 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No I guess I would just leave it, though I confess I don't really understand the semantics of IntSync are as it relates to what circuits outcomes represent "safe" crossings. Would a user explicitly controlling sinkDebit be surprised to not get a buffer?

}
}
}
9 changes: 9 additions & 0 deletions src/main/scala/tilelink/Bundles.scala
Original file line number Diff line number Diff line change
Expand Up @@ -306,3 +306,12 @@ class TLRationalBundle(params: TLBundleParameters) extends TLBundleBase(params)
val d = RationalIO(new TLBundleD(params)).flip
val e = RationalIO(new TLBundleE(params))
}

class TLCreditedBundle(params: TLBundleParameters) extends TLBundleBase(params)
{
val a = CreditedIO(new TLBundleA(params))
val b = CreditedIO(new TLBundleB(params)).flip
val c = CreditedIO(new TLBundleC(params))
val d = CreditedIO(new TLBundleD(params)).flip
val e = CreditedIO(new TLBundleE(params))
}
112 changes: 112 additions & 0 deletions src/main/scala/tilelink/Credited.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// See LICENSE.SiFive for license details.

package freechips.rocketchip.tilelink

import chisel3._
import chisel3.util.Decoupled
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.subsystem.CrossingWrapper
import freechips.rocketchip.util._

class TLCreditedBuffer(delay: TLCreditedDelay)(implicit p: Parameters) extends LazyModule
{
val node = TLCreditedAdapterNode(
clientFn = p => p.copy(delay = delay + p.delay),
managerFn = p => p.copy(delay = delay + p.delay))

lazy val module = new LazyModuleImp(this) {
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
out.a :<> in.a.pipeline(delay.a)
in.b :<> out.b.pipeline(delay.b)
out.c :<> in.c.pipeline(delay.c)
in.d :<> out.d.pipeline(delay.d)
out.e :<> in.e.pipeline(delay.e)
}
}
}

object TLCreditedBuffer {
def apply(delay: TLCreditedDelay)(implicit p: Parameters): TLCreditedAdapterNode = {
val buffer = LazyModule(new TLCreditedBuffer(delay))
buffer.node
}
def apply(delay: CreditedDelay)(implicit p: Parameters): TLCreditedAdapterNode = apply(TLCreditedDelay(delay))
def apply()(implicit p: Parameters): TLCreditedAdapterNode = apply(CreditedDelay(1, 1))
}

class TLCreditedSource(delay: TLCreditedDelay)(implicit p: Parameters) extends LazyModule
{
val node = TLCreditedSourceNode(delay)
lazy val module = new LazyModuleImp(this) {
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val tld = edgeOut.delay
out.a :<> CreditedIO.fromSender(in.a, tld.a.total).pipeline(delay.a)
in.b :<> Decoupled(out.b.pipeline(delay.b).toReceiver(tld.b.total))
out.c :<> CreditedIO.fromSender(in.c, tld.c.total).pipeline(delay.c)
in.d :<> Decoupled(out.d.pipeline(delay.d).toReceiver(tld.d.total))
out.e :<> CreditedIO.fromSender(in.e, tld.e.total).pipeline(delay.e)
}
}
}

object TLCreditedSource {
def apply(delay: TLCreditedDelay)(implicit p: Parameters): TLCreditedSourceNode = {
val source = LazyModule(new TLCreditedSource(delay))
source.node
}
def apply(delay: CreditedDelay)(implicit p: Parameters): TLCreditedSourceNode = apply(TLCreditedDelay(delay))
def apply()(implicit p: Parameters): TLCreditedSourceNode = apply(CreditedDelay(1, 1))
}

class TLCreditedSink(delay: TLCreditedDelay)(implicit p: Parameters) extends LazyModule
{
val node = TLCreditedSinkNode(delay)
lazy val module = new LazyModuleImp(this) {
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val tld = edgeIn.delay
out.a :<> Decoupled(in.a.pipeline(delay.a).toReceiver(tld.a.total))
in.b :<> CreditedIO.fromSender(out.b, tld.b.total).pipeline(delay.b)
out.c :<> Decoupled(in.c.pipeline(delay.c).toReceiver(tld.c.total))
in.d :<> CreditedIO.fromSender(out.d, tld.d.total).pipeline(delay.d)
out.e :<> Decoupled(in.e.pipeline(delay.e).toReceiver(tld.e.total))
}
}
}

object TLCreditedSink {
def apply(delay: TLCreditedDelay)(implicit p: Parameters): TLCreditedSinkNode = {
val sink = LazyModule(new TLCreditedSink(delay))
sink.node
}
def apply(delay: CreditedDelay)(implicit p: Parameters): TLCreditedSinkNode = apply(TLCreditedDelay(delay))
def apply()(implicit p: Parameters): TLCreditedSinkNode = apply(CreditedDelay(1, 1))
}

/** Synthesizeable unit tests */
import freechips.rocketchip.unittest._

class TLRAMCreditedCrossing(txns: Int, params: CreditedCrossing)(implicit p: Parameters) extends LazyModule {
val model = LazyModule(new TLRAMModel("CreditedCrossing"))
val fuzz = LazyModule(new TLFuzzer(txns))
val island = LazyModule(new CrossingWrapper(params))
val ram = island { LazyModule(new TLRAM(AddressSet(0x0, 0x3ff))) }

island.crossTLIn(ram.node) := TLFragmenter(4, 256) := TLDelayer(0.1) := model.node := fuzz.node

lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
}
}

class TLRAMCreditedCrossingTest(txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) {
val dut_1000 = Module(LazyModule(new TLRAMCreditedCrossing(txns, CreditedCrossing(CreditedDelay(1, 0), CreditedDelay(0, 0)))).module)
val dut_0100 = Module(LazyModule(new TLRAMCreditedCrossing(txns, CreditedCrossing(CreditedDelay(0, 1), CreditedDelay(0, 0)))).module)
val dut_0010 = Module(LazyModule(new TLRAMCreditedCrossing(txns, CreditedCrossing(CreditedDelay(0, 0), CreditedDelay(1, 0)))).module)
val dut_0001 = Module(LazyModule(new TLRAMCreditedCrossing(txns, CreditedCrossing(CreditedDelay(0, 0), CreditedDelay(0, 1)))).module)
val dut_1111 = Module(LazyModule(new TLRAMCreditedCrossing(txns, CreditedCrossing(CreditedDelay(1, 1), CreditedDelay(1, 1)))).module)

val duts = Seq(dut_1000, dut_0100, dut_0010, dut_0001, dut_1111)
duts.foreach { _.io.start := true.B }
io.finished := duts.map(_.io.finished).reduce(_ && _)
}
Loading