From 43c9f5fe7e6b655696d5d531e85c9bbaaa757b3c Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 9 May 2017 16:29:21 -0700 Subject: [PATCH 1/3] tilelink2: keep earlyAck Fragmenter sources distinct --- .../scala/uncore/tilelink2/Fragmenter.scala | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/main/scala/uncore/tilelink2/Fragmenter.scala b/src/main/scala/uncore/tilelink2/Fragmenter.scala index a1a28591..0325c20f 100644 --- a/src/main/scala/uncore/tilelink2/Fragmenter.scala +++ b/src/main/scala/uncore/tilelink2/Fragmenter.scala @@ -20,7 +20,11 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean = require (isPow2 (minSize)) 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 toggleBits = if (earlyAck) 1 else 0 + val addedBits = fragmentBits + toggleBits def expandTransfer(x: TransferSizes) = if (!x) x else { 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 // Thus we need to compact all of the masters into one big master clientFn = { c => c.copy(clients = Seq(TLClientParameters( - sourceId = IdRange(0, c.endSourceId << fragmentBits), + sourceId = IdRange(0, c.endSourceId << addedBits), requestFifo = true))) }, 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.bits := out.d.bits // pass most stuff unchanged 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) 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 new_gennum = ~(~old_gennum1 | (aMask >> log2Ceil(beatBytes))) // ~(~x|y) is width safe val aFragnum = ~(~(old_gennum1 >> log2Ceil(minSize/beatBytes)) | (aFragOH1 >> log2Ceil(minSize))) + val aLast = aFragnum === UInt(0) 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) out.a <> in_a 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 // Optimize away some of the Repeater's registers From 3e7bdcbf5e66013bb453054a2eb7f783ff37a1a8 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 9 May 2017 16:37:36 -0700 Subject: [PATCH 2/3] tilelink2: Fragmenter should ignore error when not valid --- src/main/scala/uncore/tilelink2/Fragmenter.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/uncore/tilelink2/Fragmenter.scala b/src/main/scala/uncore/tilelink2/Fragmenter.scala index 0325c20f..4fcef13e 100644 --- a/src/main/scala/uncore/tilelink2/Fragmenter.scala +++ b/src/main/scala/uncore/tilelink2/Fragmenter.scala @@ -174,7 +174,7 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean = if (earlyAck) { // If you do early Ack, errors may not be dropped // ... 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 } else { // Combine the error flag From 3eaa973da71eefb7a01b75a37006c065fdb617fc Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 9 May 2017 16:34:29 -0700 Subject: [PATCH 3/3] tilelink2: add earlyAck to regression --- src/main/scala/uncore/tilelink2/Fragmenter.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/uncore/tilelink2/Fragmenter.scala b/src/main/scala/uncore/tilelink2/Fragmenter.scala index 4fcef13e..f30e579a 100644 --- a/src/main/scala/uncore/tilelink2/Fragmenter.scala +++ b/src/main/scala/uncore/tilelink2/Fragmenter.scala @@ -296,7 +296,7 @@ class TLRAMFragmenter(ramBeatBytes: Int, maxSize: Int)(implicit p: Parameters) e TLDelayer(0.1)( TLBuffer(BufferParams.flow)( TLDelayer(0.1)( - TLFragmenter(ramBeatBytes, maxSize)( + TLFragmenter(ramBeatBytes, maxSize, earlyAck = true)( TLDelayer(0.1)( TLBuffer(BufferParams.flow)( TLFragmenter(ramBeatBytes, maxSize/2)(