axi4: make maxFlight a per-master parameter
This commit is contained in:
parent
e1a072a644
commit
d27e1928dd
@ -13,11 +13,26 @@ class AXI4IdIndexer(idBits: Int)(implicit p: Parameters) extends LazyModule
|
||||
require (idBits >= 0)
|
||||
|
||||
val node = AXI4AdapterNode(
|
||||
masterFn = { mp => mp.copy(
|
||||
masterFn = { mp =>
|
||||
// Create one new "master" per ID
|
||||
val masters = Array.tabulate(1 << idBits) { i => AXI4MasterParameters(
|
||||
id = IdRange(i, i+1),
|
||||
aligned = true,
|
||||
maxFlight = Some(0))
|
||||
}
|
||||
// Squash the information from original masters into new ID masters
|
||||
mp.masters.foreach { m =>
|
||||
for (i <- m.id.start until m.id.end) {
|
||||
val j = i % (1 << idBits)
|
||||
val old = masters(j)
|
||||
masters(j) = old.copy(
|
||||
aligned = old.aligned && m.aligned,
|
||||
maxFlight = old.maxFlight.flatMap { o => m.maxFlight.map { n => o+n } })
|
||||
}
|
||||
}
|
||||
mp.copy(
|
||||
userBits = mp.userBits + max(0, log2Ceil(mp.endId) - idBits),
|
||||
masters = Seq(AXI4MasterParameters(
|
||||
id = IdRange(0, min(mp.endId, 1 << idBits)),
|
||||
aligned = mp.masters.map(_.aligned).reduce(_ && _))))
|
||||
masters = masters)
|
||||
},
|
||||
slaveFn = { sp => sp.copy(
|
||||
slaves = sp.slaves.map(s => s.copy(
|
||||
|
@ -64,19 +64,19 @@ case class AXI4SlavePortParameters(
|
||||
case class AXI4MasterParameters(
|
||||
id: IdRange = IdRange(0, 1),
|
||||
aligned: Boolean = false,
|
||||
maxFlight: Option[Int] = None, // None = infinite, else is a per-ID cap
|
||||
nodePath: Seq[BaseNode] = Seq())
|
||||
{
|
||||
val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected")
|
||||
maxFlight.foreach { m => require (m >= 0) }
|
||||
}
|
||||
|
||||
case class AXI4MasterPortParameters(
|
||||
masters: Seq[AXI4MasterParameters],
|
||||
userBits: Int = 0,
|
||||
maxFlight: Int = 0) // at most X transactions per ID (0 = unlimited)
|
||||
userBits: Int = 0)
|
||||
{
|
||||
val endId = masters.map(_.id.end).max
|
||||
require (userBits >= 0)
|
||||
require (maxFlight >= 0)
|
||||
|
||||
// Require disjoint ranges for ids
|
||||
masters.combinations(2).foreach { case Seq(x,y) => require (!x.id.overlaps(y.id), s"$x and $y overlap") }
|
||||
|
@ -9,8 +9,9 @@ import diplomacy._
|
||||
import uncore.tilelink2._
|
||||
|
||||
case class AXI4ToTLNode() extends MixedAdapterNode(AXI4Imp, TLImp)(
|
||||
dFn = { case AXI4MasterPortParameters(masters, userBits, maxFlight) =>
|
||||
require (maxFlight > 0, "AXI4 must include a maximum transactions per ID to convert to TL")
|
||||
dFn = { case AXI4MasterPortParameters(masters, userBits) =>
|
||||
masters.foreach { m => require (m.maxFlight.isDefined, "AXI4 must include a transaction maximum per ID to convert to TL") }
|
||||
val maxFlight = masters.map(_.maxFlight.get).max
|
||||
TLClientPortParameters(
|
||||
clients = masters.flatMap { m =>
|
||||
for (id <- m.id.start until m.id.end)
|
||||
@ -50,7 +51,7 @@ class AXI4ToTL()(implicit p: Parameters) extends LazyModule
|
||||
val numIds = edgeIn.master.endId
|
||||
val beatBytes = edgeOut.manager.beatBytes
|
||||
val countBits = AXI4Parameters.lenBits + (1 << AXI4Parameters.sizeBits) - 1
|
||||
val maxFlight = edgeIn.master.maxFlight
|
||||
val maxFlight = edgeIn.master.masters.map(_.maxFlight.get).max
|
||||
val addedBits = log2Ceil(maxFlight) + 1
|
||||
|
||||
require (edgeIn.master.userBits == 0, "AXI4 user bits cannot be transported by TL")
|
||||
|
@ -10,12 +10,15 @@ import uncore.tilelink2.UIntToOH1
|
||||
|
||||
class AXI4UserYanker(capMaxFlight: Option[Int] = None)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
// !!! make maxFlightPerId a cap and maxFlight a per AXI4 Master parameter
|
||||
val maxFlightPerId = capMaxFlight.getOrElse(8)
|
||||
require (maxFlightPerId >= 1)
|
||||
|
||||
val node = AXI4AdapterNode(
|
||||
masterFn = { mp => mp.copy(maxFlight = maxFlightPerId, userBits = 0) },
|
||||
masterFn = { mp => mp.copy(
|
||||
userBits = 0,
|
||||
masters = mp.masters.map { m => m.copy(
|
||||
maxFlight = (m.maxFlight, capMaxFlight) match {
|
||||
case (Some(x), Some(y)) => Some(x min y)
|
||||
case (Some(x), None) => Some(x)
|
||||
case (None, Some(y)) => Some(y)
|
||||
case (None, None) => None })})},
|
||||
slaveFn = { sp => sp })
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
@ -29,18 +32,31 @@ class AXI4UserYanker(capMaxFlight: Option[Int] = None)(implicit p: Parameters) e
|
||||
val need_bypass = edgeOut.slave.minLatency < 1
|
||||
require (bits > 0) // useless UserYanker!
|
||||
|
||||
val rqueues = Seq.fill(edgeIn.master.endId) { Module(new Queue(UInt(width = bits), maxFlightPerId, flow=need_bypass)) }
|
||||
val wqueues = Seq.fill(edgeIn.master.endId) { Module(new Queue(UInt(width = bits), maxFlightPerId, flow=need_bypass)) }
|
||||
edgeOut.master.masters.foreach { m =>
|
||||
require (m.maxFlight.isDefined, "UserYanker needs a flight cap on each ID")
|
||||
}
|
||||
|
||||
def queue(id: Int) = {
|
||||
val depth = edgeOut.master.masters.find(_.id.contains(id)).flatMap(_.maxFlight).getOrElse(0)
|
||||
if (depth == 0) {
|
||||
Wire(new QueueIO(UInt(width = bits), 1)) // unused ID => undefined value
|
||||
} else {
|
||||
Module(new Queue(UInt(width = bits), depth, flow=need_bypass)).io
|
||||
}
|
||||
}
|
||||
|
||||
val rqueues = Seq.tabulate(edgeIn.master.endId) { i => queue(i) }
|
||||
val wqueues = Seq.tabulate(edgeIn.master.endId) { i => queue(i) }
|
||||
|
||||
val arid = in.ar.bits.id
|
||||
val ar_ready = Vec(rqueues.map(_.io.enq.ready))(arid)
|
||||
val ar_ready = Vec(rqueues.map(_.enq.ready))(arid)
|
||||
in .ar.ready := out.ar.ready && ar_ready
|
||||
out.ar.valid := in .ar.valid && ar_ready
|
||||
out.ar.bits := in .ar.bits
|
||||
|
||||
val rid = out.r.bits.id
|
||||
val r_valid = Vec(rqueues.map(_.io.deq.valid))(rid)
|
||||
val r_bits = Vec(rqueues.map(_.io.deq.bits))(rid)
|
||||
val r_valid = Vec(rqueues.map(_.deq.valid))(rid)
|
||||
val r_bits = Vec(rqueues.map(_.deq.bits))(rid)
|
||||
assert (!out.r.valid || r_valid) // Q must be ready faster than the response
|
||||
in.r <> out.r
|
||||
in.r.bits.user.get := r_bits
|
||||
@ -48,20 +64,20 @@ class AXI4UserYanker(capMaxFlight: Option[Int] = None)(implicit p: Parameters) e
|
||||
val arsel = UIntToOH(arid, edgeIn.master.endId).toBools
|
||||
val rsel = UIntToOH(rid, edgeIn.master.endId).toBools
|
||||
(rqueues zip (arsel zip rsel)) foreach { case (q, (ar, r)) =>
|
||||
q.io.deq.ready := out.r .valid && in .r .ready && r && out.r.bits.last
|
||||
q.io.enq.valid := in .ar.valid && out.ar.ready && ar
|
||||
q.io.enq.bits := in.ar.bits.user.get
|
||||
q.deq.ready := out.r .valid && in .r .ready && r && out.r.bits.last
|
||||
q.enq.valid := in .ar.valid && out.ar.ready && ar
|
||||
q.enq.bits := in.ar.bits.user.get
|
||||
}
|
||||
|
||||
val awid = in.aw.bits.id
|
||||
val aw_ready = Vec(wqueues.map(_.io.enq.ready))(awid)
|
||||
val aw_ready = Vec(wqueues.map(_.enq.ready))(awid)
|
||||
in .aw.ready := out.aw.ready && aw_ready
|
||||
out.aw.valid := in .aw.valid && aw_ready
|
||||
out.aw.bits := in .aw.bits
|
||||
|
||||
val bid = out.b.bits.id
|
||||
val b_valid = Vec(wqueues.map(_.io.deq.valid))(bid)
|
||||
val b_bits = Vec(wqueues.map(_.io.deq.bits))(bid)
|
||||
val b_valid = Vec(wqueues.map(_.deq.valid))(bid)
|
||||
val b_bits = Vec(wqueues.map(_.deq.bits))(bid)
|
||||
assert (!out.b.valid || b_valid) // Q must be ready faster than the response
|
||||
in.b <> out.b
|
||||
in.b.bits.user.get := b_bits
|
||||
@ -69,9 +85,9 @@ class AXI4UserYanker(capMaxFlight: Option[Int] = None)(implicit p: Parameters) e
|
||||
val awsel = UIntToOH(awid, edgeIn.master.endId).toBools
|
||||
val bsel = UIntToOH(bid, edgeIn.master.endId).toBools
|
||||
(wqueues zip (awsel zip bsel)) foreach { case (q, (aw, b)) =>
|
||||
q.io.deq.ready := out.b .valid && in .b .ready && b
|
||||
q.io.enq.valid := in .aw.valid && out.aw.ready && aw
|
||||
q.io.enq.bits := in.aw.bits.user.get
|
||||
q.deq.ready := out.b .valid && in .b .ready && b
|
||||
q.enq.valid := in .aw.valid && out.aw.ready && aw
|
||||
q.enq.bits := in.aw.bits.user.get
|
||||
}
|
||||
|
||||
out.w <> in.w
|
||||
|
@ -18,6 +18,7 @@ case class TLToAXI4Node(beatBytes: Int) extends MixedAdapterNode(TLImp, AXI4Imp)
|
||||
AXI4MasterParameters(
|
||||
id = IdRange(start, start+size),
|
||||
aligned = true,
|
||||
maxFlight = Some(if (c.requestFifo) c.sourceId.size else 1),
|
||||
nodePath = c.nodePath)
|
||||
}
|
||||
AXI4MasterPortParameters(
|
||||
|
Loading…
Reference in New Issue
Block a user