1
0

tilelink2 Arbiter: allow preemption of first beat

This commit is contained in:
Wesley W. Terpstra 2016-10-12 18:35:16 -07:00
parent 0aebf9e341
commit b6e9b0c558
4 changed files with 14 additions and 18 deletions

View File

@ -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))
}
}

View File

@ -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) {

View File

@ -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

View File

@ -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) } }