From 99c7003d11999af46cb2472293efbb92c1a16cb0 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 12 Oct 2016 20:11:05 -0700 Subject: [PATCH] tilelink2: allow preemption of Fragmenter and WidthWidget --- .../scala/uncore/tilelink2/Fragmenter.scala | 9 ++--- .../scala/uncore/tilelink2/Repeater.scala | 37 +++++++++++++++++++ .../scala/uncore/tilelink2/WidthWidget.scala | 10 +++-- 3 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 src/main/scala/uncore/tilelink2/Repeater.scala diff --git a/src/main/scala/uncore/tilelink2/Fragmenter.scala b/src/main/scala/uncore/tilelink2/Fragmenter.scala index 3d91cc51..e1083009 100644 --- a/src/main/scala/uncore/tilelink2/Fragmenter.scala +++ b/src/main/scala/uncore/tilelink2/Fragmenter.scala @@ -191,7 +191,8 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten val maxLgHints = maxHints .map(m => if (m == 0) lgMinSize else UInt(log2Ceil(m))) // Make the request Irrevocable - val in_a = Queue(in.a, 1, flow=true) + val repeat = Wire(Bool()) + val in_a = Repeater(in.a, repeat) // If this is infront of a single manager, these become constants val find = manager.findFast(edgeIn.address(in_a.bits)) @@ -226,10 +227,8 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten when (out.a.fire()) { gennum := new_gennum } - val delay = !aHasData && aFragnum =/= UInt(0) - out.a.valid := in_a.valid - in_a.ready := out.a.ready && !delay - out.a.bits := in_a.bits + repeat := !aHasData && aFragnum =/= UInt(0) + out.a <> in_a out.a.bits.addr_hi := in_a.bits.addr_hi | (~aFragnum << log2Ceil(minSize/beatBytes) & aOrigOH1 >> log2Ceil(beatBytes)) out.a.bits.source := Cat(in_a.bits.source, aFragnum) out.a.bits.size := aFrag diff --git a/src/main/scala/uncore/tilelink2/Repeater.scala b/src/main/scala/uncore/tilelink2/Repeater.scala new file mode 100644 index 00000000..9835911e --- /dev/null +++ b/src/main/scala/uncore/tilelink2/Repeater.scala @@ -0,0 +1,37 @@ +// See LICENSE for license details. + +package uncore.tilelink2 + +import Chisel._ + +// A Repeater passes it's input to it's output, unless repeat is asserted. +// When repeat is asserted, the Repeater copies the input and repeats it next cycle. +class Repeater[T <: Data](gen: T) extends Module +{ + val io = new Bundle { + val repeat = Bool(INPUT) + val enq = Decoupled(gen).flip + val deq = Decoupled(gen) + } + + val full = RegInit(Bool(false)) + val saved = Reg(gen) + + // When !full, a repeater is pass-through + io.deq.valid := io.enq.valid || full + io.enq.ready := io.deq.ready && !full + io.deq.bits := Mux(full, saved, io.enq.bits) + + when (io.enq.fire() && io.repeat) { full := Bool(true); saved := io.enq.bits } + when (io.deq.fire() && !io.repeat) { full := Bool(false) } +} + +object Repeater +{ + def apply[T <: Data](enq: DecoupledIO[T], repeat: Bool): DecoupledIO[T] = { + val repeater = Module(new Repeater(enq.bits)) + repeater.io.repeat := repeat + repeater.io.enq := enq + repeater.io.deq + } +} diff --git a/src/main/scala/uncore/tilelink2/WidthWidget.scala b/src/main/scala/uncore/tilelink2/WidthWidget.scala index 45530383..32dc793b 100644 --- a/src/main/scala/uncore/tilelink2/WidthWidget.scala +++ b/src/main/scala/uncore/tilelink2/WidthWidget.scala @@ -120,9 +120,7 @@ class TLWidthWidget(innerBeatBytes: Int) extends LazyModule val dataOut = if (edgeIn.staticHasData(in.bits) == Some(false)) UInt(0) else Mux1H(select, dataSlices) val maskOut = Mux1H(select, maskSlices) - in.ready := out.ready && last - out.valid := in.valid - out.bits := in.bits + out <> in edgeOut.data(out.bits) := dataOut out.bits match { @@ -133,6 +131,9 @@ class TLWidthWidget(innerBeatBytes: Int) extends LazyModule } // addr_lo gets truncated automagically + + // Repeat the input if we're not last + !last } def splice[T <: TLDataChannel](edgeIn: TLEdge, in: DecoupledIO[T], edgeOut: TLEdge, out: DecoupledIO[T]) = { @@ -141,7 +142,8 @@ class TLWidthWidget(innerBeatBytes: Int) extends LazyModule out <> in } else if (edgeIn.manager.beatBytes > edgeOut.manager.beatBytes) { // split input to output - split(edgeIn, Queue(in, 1, flow=true), edgeOut, out) + val repeat = Wire(Bool()) + repeat := split(edgeIn, Repeater(in, repeat), edgeOut, out) } else { // merge input to output merge(edgeIn, in, edgeOut, out)