1
0

tilelink2: keep earlyAck Fragmenter sources distinct

This commit is contained in:
Wesley W. Terpstra 2017-05-09 16:29:21 -07:00
parent 19db0389b6
commit 43c9f5fe7e

View File

@ -20,7 +20,11 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean =
require (isPow2 (minSize)) require (isPow2 (minSize))
require (minSize < maxSize) require (minSize < maxSize)
// EarlyAck means that 1.999 transactions can be inflight at a time
// Thus, we need an extra toggle bit to prevent source collisions
val fragmentBits = log2Ceil(maxSize / minSize) val fragmentBits = log2Ceil(maxSize / minSize)
val toggleBits = if (earlyAck) 1 else 0
val addedBits = fragmentBits + toggleBits
def expandTransfer(x: TransferSizes) = if (!x) x else { def expandTransfer(x: TransferSizes) = if (!x) x else {
require (x.max >= minSize) // validate that we can apply the fragmenter correctly require (x.max >= minSize) // validate that we can apply the fragmenter correctly
@ -42,7 +46,7 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean =
// We require that all the responses are mutually FIFO // We require that all the responses are mutually FIFO
// Thus we need to compact all of the masters into one big master // Thus we need to compact all of the masters into one big master
clientFn = { c => c.copy(clients = Seq(TLClientParameters( clientFn = { c => c.copy(clients = Seq(TLClientParameters(
sourceId = IdRange(0, c.endSourceId << fragmentBits), sourceId = IdRange(0, c.endSourceId << addedBits),
requestFifo = true))) }, requestFifo = true))) },
managerFn = { m => m.copy(managers = m.managers.map(mapManager)) }) managerFn = { m => m.copy(managers = m.managers.map(mapManager)) })
@ -164,7 +168,7 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean =
in.d.valid := out.d.valid && !drop in.d.valid := out.d.valid && !drop
in.d.bits := out.d.bits // pass most stuff unchanged in.d.bits := out.d.bits // pass most stuff unchanged
in.d.bits.addr_lo := out.d.bits.addr_lo & ~dsizeOH1 in.d.bits.addr_lo := out.d.bits.addr_lo & ~dsizeOH1
in.d.bits.source := out.d.bits.source >> fragmentBits in.d.bits.source := out.d.bits.source >> addedBits
in.d.bits.size := Mux(dFirst, dFirst_size, dOrig) in.d.bits.size := Mux(dFirst, dFirst_size, dOrig)
if (earlyAck) { if (earlyAck) {
@ -232,13 +236,23 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean =
val old_gennum1 = Mux(aFirst, aOrigOH1 >> log2Ceil(beatBytes), gennum - UInt(1)) val old_gennum1 = Mux(aFirst, aOrigOH1 >> log2Ceil(beatBytes), gennum - UInt(1))
val new_gennum = ~(~old_gennum1 | (aMask >> log2Ceil(beatBytes))) // ~(~x|y) is width safe val new_gennum = ~(~old_gennum1 | (aMask >> log2Ceil(beatBytes))) // ~(~x|y) is width safe
val aFragnum = ~(~(old_gennum1 >> log2Ceil(minSize/beatBytes)) | (aFragOH1 >> log2Ceil(minSize))) val aFragnum = ~(~(old_gennum1 >> log2Ceil(minSize/beatBytes)) | (aFragOH1 >> log2Ceil(minSize)))
val aLast = aFragnum === UInt(0)
when (out.a.fire()) { gennum := new_gennum } when (out.a.fire()) { gennum := new_gennum }
// We need to alternate bits by source to handle the 1.999 txns inflight per Id
val toggleBitOpt = if (!earlyAck) None else {
val state = Reg(UInt(width = edgeIn.client.endSourceId))
val toggle = Wire(init = UInt(0, width = edgeIn.client.endSourceId))
when (in_a.fire() && aLast) { toggle := UIntToOH(in_a.bits.source) }
state := state ^ toggle
Some(state(in_a.bits.source))
}
repeater.io.repeat := !aHasData && aFragnum =/= UInt(0) repeater.io.repeat := !aHasData && aFragnum =/= UInt(0)
out.a <> in_a out.a <> in_a
out.a.bits.address := in_a.bits.address | ~(old_gennum1 << log2Ceil(beatBytes) | ~aOrigOH1 | aFragOH1 | UInt(minSize-1)) out.a.bits.address := in_a.bits.address | ~(old_gennum1 << log2Ceil(beatBytes) | ~aOrigOH1 | aFragOH1 | UInt(minSize-1))
out.a.bits.source := Cat(in_a.bits.source, aFragnum) out.a.bits.source := Cat(Seq(in_a.bits.source) ++ toggleBitOpt.toList ++ Seq(aFragnum))
out.a.bits.size := aFrag out.a.bits.size := aFrag
// Optimize away some of the Repeater's registers // Optimize away some of the Repeater's registers