Merge pull request #735 from ucb-bar/early-ack-frag-fix
tilelink2: keep earlyAck Fragmenter sources distinct
This commit is contained in:
commit
9720a53eae
@ -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,13 +168,13 @@ 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) {
|
||||||
// If you do early Ack, errors may not be dropped
|
// If you do early Ack, errors may not be dropped
|
||||||
// ... which roughly means: Puts may not fail
|
// ... which roughly means: Puts may not fail
|
||||||
assert (!out.d.bits.error || !drop)
|
assert (!out.d.valid || !out.d.bits.error || !drop)
|
||||||
in.d.bits.error := out.d.bits.error
|
in.d.bits.error := out.d.bits.error
|
||||||
} else {
|
} else {
|
||||||
// Combine the error flag
|
// Combine the error flag
|
||||||
@ -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
|
||||||
@ -282,7 +296,7 @@ class TLRAMFragmenter(ramBeatBytes: Int, maxSize: Int)(implicit p: Parameters) e
|
|||||||
TLDelayer(0.1)(
|
TLDelayer(0.1)(
|
||||||
TLBuffer(BufferParams.flow)(
|
TLBuffer(BufferParams.flow)(
|
||||||
TLDelayer(0.1)(
|
TLDelayer(0.1)(
|
||||||
TLFragmenter(ramBeatBytes, maxSize)(
|
TLFragmenter(ramBeatBytes, maxSize, earlyAck = true)(
|
||||||
TLDelayer(0.1)(
|
TLDelayer(0.1)(
|
||||||
TLBuffer(BufferParams.flow)(
|
TLBuffer(BufferParams.flow)(
|
||||||
TLFragmenter(ramBeatBytes, maxSize/2)(
|
TLFragmenter(ramBeatBytes, maxSize/2)(
|
||||||
|
Loading…
Reference in New Issue
Block a user