axi4: switch arbiter to round robin
This commit is contained in:
parent
976af7a8c7
commit
661015a78d
@ -105,7 +105,7 @@ class AXI4ToTL()(implicit p: Parameters) extends LazyModule
|
||||
when (in.aw.fire() && s) { r := r + UInt(1) }
|
||||
}
|
||||
|
||||
TLArbiter(TLArbiter.lowestIndexFirst)(out.a, (UInt(0), r_out), (in.aw.bits.len, w_out))
|
||||
TLArbiter(TLArbiter.roundRobin)(out.a, (UInt(0), r_out), (in.aw.bits.len, w_out))
|
||||
|
||||
val ok_b = Wire(in.b)
|
||||
val ok_r = Wire(in.r)
|
||||
|
@ -3,15 +3,28 @@
|
||||
package uncore.tilelink2
|
||||
|
||||
import Chisel._
|
||||
import config._
|
||||
import diplomacy._
|
||||
|
||||
object TLArbiter
|
||||
{
|
||||
// (valids, granted) => readys
|
||||
type Policy = (Seq[Bool], Bool) => Seq[Bool]
|
||||
// (valids, select) => readys
|
||||
type Policy = (Integer, UInt, Bool) => UInt
|
||||
|
||||
val lowestIndexFirst: Policy = (valids, granted) =>
|
||||
valids.scanLeft(Bool(true))(_ && !_).init
|
||||
val lowestIndexFirst: Policy = (width, valids, select) => ~(leftOR(valids) << 1)(width-1, 0)
|
||||
|
||||
val roundRobin: Policy = (width, valids, select) => {
|
||||
val valid = valids(width-1, 0)
|
||||
assert (valid === valids)
|
||||
val mask = RegInit(~UInt(0, width=width))
|
||||
val filter = Cat(valid & ~mask, valid)
|
||||
val unready = (rightOR(filter, width*2) >> 1) | (mask << width) // last right shift unneeded
|
||||
val readys = ~((unready >> width) & unready(width-1, 0))
|
||||
when (select && valid.orR) {
|
||||
mask := leftOR(readys & valid, width)
|
||||
}
|
||||
readys(width-1, 0)
|
||||
}
|
||||
|
||||
def lowestFromSeq[T <: TLChannel](edge: TLEdge, sink: DecoupledIO[T], sources: Seq[DecoupledIO[T]]) {
|
||||
apply(lowestIndexFirst)(sink, sources.map(s => (edge.numBeats1(s.bits), s)):_*)
|
||||
@ -21,6 +34,10 @@ object TLArbiter
|
||||
apply(lowestIndexFirst)(sink, sources.toList.map(s => (edge.numBeats1(s.bits), s)):_*)
|
||||
}
|
||||
|
||||
def robin[T <: TLChannel](edge: TLEdge, sink: DecoupledIO[T], sources: DecoupledIO[T]*) {
|
||||
apply(roundRobin)(sink, sources.toList.map(s => (edge.numBeats1(s.bits), s)):_*)
|
||||
}
|
||||
|
||||
def apply[T <: Data](policy: Policy)(sink: DecoupledIO[T], sources: (UInt, DecoupledIO[T])*) {
|
||||
if (sources.isEmpty) {
|
||||
sink.valid := Bool(false)
|
||||
@ -37,13 +54,13 @@ object TLArbiter
|
||||
// Who wants access to the sink?
|
||||
val valids = sourcesIn.map(_.valid)
|
||||
// Arbitrate amongst the requests
|
||||
val readys = Vec(policy(valids, latch))
|
||||
val readys = Vec(policy(valids.size, Cat(valids.reverse), latch).toBools)
|
||||
// Which request wins arbitration?
|
||||
val winner = Vec((readys zip valids) map { case (r,v) => r&&v })
|
||||
|
||||
// Confirm the policy works properly
|
||||
require (readys.size == valids.size)
|
||||
// Never two winner
|
||||
// Never two winners
|
||||
val prefixOR = winner.scanLeft(Bool(false))(_||_).init
|
||||
assert((prefixOR zip winner) map { case (p,w) => !p || !w } reduce {_ && _})
|
||||
// If there was any request, there is a winner
|
||||
@ -73,3 +90,32 @@ object TLArbiter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Synthesizeable unit tests */
|
||||
import unittest._
|
||||
|
||||
class TestRobin()(implicit p: Parameters) extends UnitTest(timeout = 500000) {
|
||||
val sources = Wire(Vec(6, DecoupledIO(UInt(width=3))))
|
||||
val sink = Wire(DecoupledIO(UInt(width=3)))
|
||||
val count = RegInit(UInt(0, width=8))
|
||||
|
||||
val lfsr = LFSR16(Bool(true))
|
||||
val valid = lfsr(0)
|
||||
val ready = lfsr(15)
|
||||
|
||||
sources.zipWithIndex.map { case (z, i) => z.bits := UInt(i) }
|
||||
sources(0).valid := valid
|
||||
sources(1).valid := Bool(false)
|
||||
sources(2).valid := valid
|
||||
sources(3).valid := valid
|
||||
sources(4).valid := Bool(false)
|
||||
sources(5).valid := valid
|
||||
sink.ready := ready
|
||||
|
||||
TLArbiter(TLArbiter.roundRobin)(sink, sources.zipWithIndex.map { case (z, i) => (UInt(i), z) }:_*)
|
||||
when (sink.fire()) { printf("TestRobin: %d\n", sink.bits) }
|
||||
when (!sink.fire()) { printf("TestRobin: idle (%d %d)\n", valid, ready) }
|
||||
|
||||
count := count + UInt(1)
|
||||
io.finished := count >= UInt(128)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user