diff --git a/src/main/scala/uncore/tilelink2/Arbiter.scala b/src/main/scala/uncore/tilelink2/Arbiter.scala index 446e855f..a0891a0f 100644 --- a/src/main/scala/uncore/tilelink2/Arbiter.scala +++ b/src/main/scala/uncore/tilelink2/Arbiter.scala @@ -7,10 +7,10 @@ import diplomacy._ object TLArbiter { - // (valids, idle) => readys + // (valids, granted) => readys type Policy = (Seq[Bool], Bool) => Seq[Bool] - val lowestIndexFirst: Policy = (valids, idle) => + val lowestIndexFirst: Policy = (valids, granted) => valids.scanLeft(Bool(true))(_ && !_).init def apply[T <: Data](policy: Policy)(sink: DecoupledIO[T], sources: (UInt, DecoupledIO[T])*) { @@ -24,11 +24,12 @@ object TLArbiter // The number of beats which remain to be sent val beatsLeft = RegInit(UInt(0)) val idle = beatsLeft === UInt(0) + val latch = idle && sink.ready // winner (if any) claims sink // Who wants access to the sink? val valids = sourcesIn.map(_.valid) // Arbitrate amongst the requests - val readys = Vec(policy(valids, idle)) + val readys = Vec(policy(valids, latch)) // Which request wins arbitration? val winners = Vec((readys zip valids) map { case (r,v) => r&&v }) @@ -43,19 +44,13 @@ object TLArbiter // Track remaining beats val maskedBeats = (winners zip beatsIn) map { case (w,b) => Mux(w, b, UInt(0)) } val initBeats = maskedBeats.reduce(_ | _) // no winner => 0 beats - val todoBeats = Mux(idle, initBeats, beatsLeft) - beatsLeft := todoBeats - sink.fire() - assert (!sink.fire() || todoBeats =/= UInt(0)) // underflow is impoosible + beatsLeft := Mux(latch, initBeats, beatsLeft - sink.fire()) // The one-hot source granted access in the previous cycle val state = RegInit(Vec.fill(sources.size)(Bool(false))) val muxState = Mux(idle, winners, state) state := muxState - val ones = Vec.fill(sources.size)(Bool(true)) - val picked = Mux(idle, ones, state) - sink.valid := Mux1H(picked, valids) - if (sources.size > 1) { val allowed = Mux(idle, readys, state) (sourcesIn zip allowed) foreach { case (s, r) => @@ -65,6 +60,7 @@ object TLArbiter sourcesIn(0).ready := sink.ready } + sink.valid := Mux(idle, valids.reduce(_||_), Mux1H(state, valids)) sink.bits := Mux1H(muxState, sourcesIn.map(_.bits)) } } diff --git a/src/main/scala/uncore/tilelink2/AtomicAutomata.scala b/src/main/scala/uncore/tilelink2/AtomicAutomata.scala index 8bea60de..70bacae2 100644 --- a/src/main/scala/uncore/tilelink2/AtomicAutomata.scala +++ b/src/main/scala/uncore/tilelink2/AtomicAutomata.scala @@ -175,7 +175,7 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc source_c.bits := edgeOut.Put(a_cam_a.bits.source, edgeIn.address(a_cam_a.bits), a_cam_a.bits.size, amo_data)._2 // Finishing an AMO from the CAM has highest priority - TLArbiter(TLArbiter.lowestIndexFirst)(out.a, (UInt(1), source_c), (edgeOut.numBeats(in.a.bits), source_i)) + TLArbiter(TLArbiter.lowestIndexFirst)(out.a, (UInt(0), source_c), (edgeOut.numBeats1(in.a.bits), source_i)) // Capture the A state into the CAM when (source_i.fire() && !a_isSupported) { diff --git a/src/main/scala/uncore/tilelink2/HintHandler.scala b/src/main/scala/uncore/tilelink2/HintHandler.scala index 61161f9c..16d36a8e 100644 --- a/src/main/scala/uncore/tilelink2/HintHandler.scala +++ b/src/main/scala/uncore/tilelink2/HintHandler.scala @@ -46,7 +46,7 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f hint.bits := edgeIn.HintAck(in.a.bits, edgeOut.manager.findIdStartFast(address)) out.a.bits := in.a.bits - TLArbiter(TLArbiter.lowestIndexFirst)(in.d, (edgeOut.numBeats(out.d.bits), out.d), (UInt(1), hint)) + TLArbiter(TLArbiter.lowestIndexFirst)(in.d, (edgeOut.numBeats1(out.d.bits), out.d), (UInt(0), hint)) } else { out.a.valid := in.a.valid in.a.ready := out.a.ready @@ -69,7 +69,7 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f hint.bits := edgeOut.HintAck(out.b.bits) in.b.bits := out.b.bits - TLArbiter(TLArbiter.lowestIndexFirst)(out.c, (edgeIn.numBeats(in.c.bits), in.c), (UInt(1), hint)) + TLArbiter(TLArbiter.lowestIndexFirst)(out.c, (edgeIn.numBeats1(in.c.bits), in.c), (UInt(0), hint)) } else if (bce) { in.b.valid := out.b.valid out.b.ready := in.b.ready diff --git a/src/main/scala/uncore/tilelink2/Xbar.scala b/src/main/scala/uncore/tilelink2/Xbar.scala index 258c8b5f..058353a6 100644 --- a/src/main/scala/uncore/tilelink2/Xbar.scala +++ b/src/main/scala/uncore/tilelink2/Xbar.scala @@ -129,11 +129,11 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.lowestIndexFirst) extends Lazy 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.contains(i.e.bits.sink) }) }) - val beatsAI = Vec((in zip node.edgesIn) map { case (i, e) => e.numBeats(i.a.bits) }) - val beatsBO = Vec((out zip node.edgesOut) map { case (o, e) => e.numBeats(o.b.bits) }) - val beatsCI = Vec((in zip node.edgesIn) map { case (i, e) => e.numBeats(i.c.bits) }) - val beatsDO = Vec((out zip node.edgesOut) map { case (o, e) => e.numBeats(o.d.bits) }) - val beatsEI = Vec((in zip node.edgesIn) map { case (i, e) => e.numBeats(i.e.bits) }) + val beatsAI = Vec((in zip node.edgesIn) map { case (i, e) => e.numBeats1(i.a.bits) }) + val beatsBO = Vec((out zip node.edgesOut) map { case (o, e) => e.numBeats1(o.b.bits) }) + val beatsCI = Vec((in zip node.edgesIn) map { case (i, e) => e.numBeats1(i.c.bits) }) + val beatsDO = Vec((out zip node.edgesOut) map { case (o, e) => e.numBeats1(o.d.bits) }) + val beatsEI = Vec((in zip node.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) } }