tilelink2 Arbiter: allow preemption of first beat
This commit is contained in:
parent
0aebf9e341
commit
b6e9b0c558
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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) } }
|
||||
|
Loading…
Reference in New Issue
Block a user