diff --git a/src/main/scala/uncore/tilelink2/Edges.scala b/src/main/scala/uncore/tilelink2/Edges.scala index aac8338c..ee5a8bcb 100644 --- a/src/main/scala/uncore/tilelink2/Edges.scala +++ b/src/main/scala/uncore/tilelink2/Edges.scala @@ -4,6 +4,7 @@ package uncore.tilelink2 import Chisel._ import chisel3.internal.sourceinfo.SourceInfo +import chisel3.util.IrrevocableIO import diplomacy._ class TLEdge( @@ -218,6 +219,20 @@ class TLEdge( } } } + + def firstlast(bits: TLChannel, fire: Bool): (Bool, Bool, UInt) = { + val beats1 = numBeats1(bits) + val counter = RegInit(UInt(0, width = log2Up(maxTransfer / manager.beatBytes))) + val counter1 = counter - UInt(1) + val first = counter === UInt(0) + val last = counter === UInt(1) || beats1 === UInt(0) + when (fire) { + counter := Mux(first, beats1, counter1) + } + (first, last, beats1 & ~counter1) + } + + def firstlast(x: IrrevocableIO[TLChannel]): (Bool, Bool, UInt) = firstlast(x.bits, x.fire()) } class TLEdgeOut( diff --git a/src/main/scala/uncore/tilelink2/Fuzzer.scala b/src/main/scala/uncore/tilelink2/Fuzzer.scala index 64c3ace8..4063985d 100644 --- a/src/main/scala/uncore/tilelink2/Fuzzer.scala +++ b/src/main/scala/uncore/tilelink2/Fuzzer.scala @@ -113,19 +113,11 @@ class TLFuzzer( // Progress within each operation val a = out.a.bits - val a_beats1 = edge.numBeats1(a) - val a_counter = RegInit(UInt(0, width = maxLgBeats)) - val a_counter1 = a_counter - UInt(1) - val a_first = a_counter === UInt(0) - val a_last = a_counter === UInt(1) || a_beats1 === UInt(0) + val (a_first, a_last, _) = edge.firstlast(out.a) val req_done = out.a.fire() && a_last val d = out.d.bits - val d_beats1 = edge.numBeats1(d) - val d_counter = RegInit(UInt(0, width = maxLgBeats)) - val d_counter1 = d_counter - UInt(1) - val d_first = d_counter === UInt(0) - val d_last = d_counter === UInt(1) || d_beats1 === UInt(0) + val (d_first, d_last, _) = edge.firstlast(out.d) val resp_done = out.d.fire() && d_last // Source ID generation @@ -199,14 +191,12 @@ class TLFuzzer( inc := !legal || req_done inc_beat := !legal || out.a.fire() - when (out.a.fire()) { - a_counter := Mux(a_first, a_beats1, a_counter1) - when(a_last) { num_reqs := num_reqs - UInt(1) } + when (out.a.fire() && a_last) { + num_reqs := num_reqs - UInt(1) } - when (out.d.fire()) { - d_counter := Mux(d_first, d_beats1, d_counter1) - when(d_last) { num_resps := num_resps - UInt(1) } + when (out.d.fire() && d_last) { + num_resps := num_resps - UInt(1) } } } diff --git a/src/main/scala/uncore/tilelink2/Monitor.scala b/src/main/scala/uncore/tilelink2/Monitor.scala index c0fc51a8..e6dbab2b 100644 --- a/src/main/scala/uncore/tilelink2/Monitor.scala +++ b/src/main/scala/uncore/tilelink2/Monitor.scala @@ -282,68 +282,60 @@ class TLMonitor(gen: () => TLBundleSnoop, edge: () => TLEdge, sourceInfo: Source } def legalizeMultibeatA(a: IrrevocableSnoop[TLBundleA], edge: TLEdge)(implicit sourceInfo: SourceInfo) { - val counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer))) + val (a_first, _, _) = edge.firstlast(a.bits, a.fire()) val opcode = Reg(UInt()) val param = Reg(UInt()) val size = Reg(UInt()) val source = Reg(UInt()) val addr_hi = Reg(UInt()) - when (a.valid && counter =/= UInt(0)) { + when (a.valid && !a_first) { assert (a.bits.opcode === opcode, "'A' channel opcode changed within multibeat operation" + extra) assert (a.bits.param === param, "'A' channel param changed within multibeat operation" + extra) assert (a.bits.size === size, "'A' channel size changed within multibeat operation" + extra) assert (a.bits.source === source, "'A' channel source changed within multibeat operation" + extra) assert (a.bits.addr_hi=== addr_hi,"'A' channel addr_hi changed with multibeat operation" + extra) } - when (a.fire()) { - counter := counter - UInt(1) - when (counter === UInt(0)) { - counter := edge.numBeats(a.bits) - UInt(1) - opcode := a.bits.opcode - param := a.bits.param - size := a.bits.size - source := a.bits.source - addr_hi := a.bits.addr_hi - } + when (a.fire() && a_first) { + opcode := a.bits.opcode + param := a.bits.param + size := a.bits.size + source := a.bits.source + addr_hi := a.bits.addr_hi } } def legalizeMultibeatB(b: IrrevocableSnoop[TLBundleB], edge: TLEdge)(implicit sourceInfo: SourceInfo) { - val counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer))) + val (b_first, _, _) = edge.firstlast(b.bits, b.fire()) val opcode = Reg(UInt()) val param = Reg(UInt()) val size = Reg(UInt()) val source = Reg(UInt()) val addr_hi = Reg(UInt()) - when (b.valid && counter =/= UInt(0)) { + when (b.valid && !b_first) { assert (b.bits.opcode === opcode, "'B' channel opcode changed within multibeat operation" + extra) assert (b.bits.param === param, "'B' channel param changed within multibeat operation" + extra) assert (b.bits.size === size, "'B' channel size changed within multibeat operation" + extra) assert (b.bits.source === source, "'B' channel source changed within multibeat operation" + extra) assert (b.bits.addr_hi=== addr_hi,"'B' channel addr_hi changed with multibeat operation" + extra) } - when (b.fire()) { - counter := counter - UInt(1) - when (counter === UInt(0)) { - counter := edge.numBeats(b.bits) - UInt(1) - opcode := b.bits.opcode - param := b.bits.param - size := b.bits.size - source := b.bits.source - addr_hi := b.bits.addr_hi - } + when (b.fire() && b_first) { + opcode := b.bits.opcode + param := b.bits.param + size := b.bits.size + source := b.bits.source + addr_hi := b.bits.addr_hi } } def legalizeMultibeatC(c: IrrevocableSnoop[TLBundleC], edge: TLEdge)(implicit sourceInfo: SourceInfo) { - val counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer))) + val (c_first, _, _) = edge.firstlast(c.bits, c.fire()) val opcode = Reg(UInt()) val param = Reg(UInt()) val size = Reg(UInt()) val source = Reg(UInt()) val addr_hi = Reg(UInt()) val addr_lo = Reg(UInt()) - when (c.valid && counter =/= UInt(0)) { + when (c.valid && !c_first) { assert (c.bits.opcode === opcode, "'C' channel opcode changed within multibeat operation" + extra) assert (c.bits.param === param, "'C' channel param changed within multibeat operation" + extra) assert (c.bits.size === size, "'C' channel size changed within multibeat operation" + extra) @@ -351,29 +343,25 @@ class TLMonitor(gen: () => TLBundleSnoop, edge: () => TLEdge, sourceInfo: Source assert (c.bits.addr_hi=== addr_hi,"'C' channel addr_hi changed with multibeat operation" + extra) assert (c.bits.addr_lo=== addr_lo,"'C' channel addr_lo changed with multibeat operation" + extra) } - when (c.fire()) { - counter := counter - UInt(1) - when (counter === UInt(0)) { - counter := edge.numBeats(c.bits) - UInt(1) - opcode := c.bits.opcode - param := c.bits.param - size := c.bits.size - source := c.bits.source - addr_hi := c.bits.addr_hi - addr_lo := c.bits.addr_lo - } + when (c.fire() && c_first) { + opcode := c.bits.opcode + param := c.bits.param + size := c.bits.size + source := c.bits.source + addr_hi := c.bits.addr_hi + addr_lo := c.bits.addr_lo } } def legalizeMultibeatD(d: IrrevocableSnoop[TLBundleD], edge: TLEdge)(implicit sourceInfo: SourceInfo) { - val counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer))) + val (d_first, _, _) = edge.firstlast(d.bits, d.fire()) val opcode = Reg(UInt()) val param = Reg(UInt()) val size = Reg(UInt()) val source = Reg(UInt()) val sink = Reg(UInt()) val addr_lo = Reg(UInt()) - when (d.valid && counter =/= UInt(0)) { + when (d.valid && !d_first) { assert (d.bits.opcode === opcode, "'D' channel opcode changed within multibeat operation" + extra) assert (d.bits.param === param, "'D' channel param changed within multibeat operation" + extra) assert (d.bits.size === size, "'D' channel size changed within multibeat operation" + extra) @@ -381,17 +369,13 @@ class TLMonitor(gen: () => TLBundleSnoop, edge: () => TLEdge, sourceInfo: Source assert (d.bits.sink === sink, "'D' channel sink changed with multibeat operation" + extra) assert (d.bits.addr_lo=== addr_lo,"'D' channel addr_lo changed with multibeat operation" + extra) } - when (d.fire()) { - counter := counter - UInt(1) - when (counter === UInt(0)) { - counter := edge.numBeats(d.bits) - UInt(1) - opcode := d.bits.opcode - param := d.bits.param - size := d.bits.size - source := d.bits.source - sink := d.bits.sink - addr_lo := d.bits.addr_lo - } + when (d.fire() && d_first) { + opcode := d.bits.opcode + param := d.bits.param + size := d.bits.size + source := d.bits.source + sink := d.bits.sink + addr_lo := d.bits.addr_lo } } @@ -425,15 +409,8 @@ class TLMonitor(gen: () => TLBundleSnoop, edge: () => TLEdge, sourceInfo: Source def legalizeSourceUnique(bundle: TLBundleSnoop, edge: TLEdge)(implicit sourceInfo: SourceInfo) { val inflight = RegInit(UInt(0, width = edge.client.endSourceId)) - val a_counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer))) - val a_beats1 = edge.numBeats1(bundle.a.bits) - val a_first = a_counter === UInt(0) - val a_last = a_counter === UInt(1) || a_beats1 === UInt(0) - - val d_counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer))) - val d_beats1 = edge.numBeats1(bundle.d.bits) - val d_first = d_counter === UInt(0) - val d_last = d_counter === UInt(1) || d_beats1 === UInt(0) + val (_, a_last, _) = edge.firstlast(bundle.a.bits, bundle.a.fire()) + val (_, d_last, _) = edge.firstlast(bundle.d.bits, bundle.d.fire()) val bypass = bundle.a.bits.source === bundle.d.bits.source val a_bypass = bypass && bundle.d.valid && d_last @@ -445,14 +422,12 @@ class TLMonitor(gen: () => TLBundleSnoop, edge: () => TLEdge, sourceInfo: Source val a_set = Wire(init = UInt(0, width = edge.client.endSourceId)) when (bundle.a.fire()) { - a_counter := Mux(a_first, a_beats1, a_counter - UInt(1)) when (a_last) { a_set := UIntToOH(bundle.a.bits.source) } assert(a_bypass || !inflight(bundle.a.bits.source), "'A' channel re-used a source ID" + extra) } val d_clr = Wire(init = UInt(0, width = edge.client.endSourceId)) when (bundle.d.fire() && bundle.d.bits.opcode =/= TLMessages.ReleaseAck) { - d_counter := Mux(d_first, d_beats1, d_counter - UInt(1)) when (d_last) { d_clr := UIntToOH(bundle.d.bits.source) } assert(d_bypass || inflight(bundle.d.bits.source), "'D' channel acknowledged for nothing inflight" + extra) } diff --git a/src/main/scala/uncore/tilelink2/RAMModel.scala b/src/main/scala/uncore/tilelink2/RAMModel.scala index b8d46c61..cfeb8cce 100644 --- a/src/main/scala/uncore/tilelink2/RAMModel.scala +++ b/src/main/scala/uncore/tilelink2/RAMModel.scala @@ -110,13 +110,10 @@ class TLRAMModel extends LazyModule // Process A access requests val a = Reg(next = in.a.bits) val a_fire = Reg(next = in.a.fire(), init = Bool(false)) - val a_beats1 = edge.numBeats1(a) + val (a_first, a_last, a_address_inc) = edge.firstlast(a, a_fire) val a_size = edge.size(a) val a_sizeOH = UIntToOH(a_size) - val a_counter = RegInit(UInt(0, width = maxLgBeats)) - val a_counter1 = a_counter - UInt(1) - val a_first = a_counter === UInt(0) - val a_addr_hi = a.addr_hi | (a_beats1 & ~a_counter1) + val a_addr_hi = a.addr_hi | a_address_inc val a_base = edge.address(a) val a_mask = edge.mask(a_base, a_size) val a_fifo = edge.manager.hasFifoIdFast(a_base) @@ -133,8 +130,6 @@ class TLRAMModel extends LazyModule when (a_fire) { // Record the request so we can handle it's response - a_counter := Mux(a_first, a_beats1, a_counter1) - assert (a.opcode =/= TLMessages.Acquire) // Mark the operation as valid @@ -199,15 +194,11 @@ class TLRAMModel extends LazyModule // Process D access responses val d = RegNext(out.d.bits) val d_fire = Reg(next = out.d.fire(), init = Bool(false)) - val d_beats1 = edge.numBeats1(d) + val (d_first, d_last, d_address_inc) = edge.firstlast(d, d_fire) val d_size = edge.size(d) val d_sizeOH = UIntToOH(d_size) - val d_counter = RegInit(UInt(0, width = maxLgBeats)) - val d_counter1 = d_counter - UInt(1) - val d_first = d_counter === UInt(0) - val d_last = d_counter === UInt(1) || d_beats1 === UInt(0) val d_base = d_flight.base - val d_addr_hi = d_base >> shift | (d_beats1 & ~d_counter1) + val d_addr_hi = d_base >> shift | d_address_inc val d_mask = edge.mask(d_base, d_size) val d_fifo = edge.manager.hasFifoIdFast(d_flight.base) @@ -224,8 +215,6 @@ class TLRAMModel extends LazyModule val d_valid = valid(d.source) when (d_fire) { - d_counter := Mux(d_first, d_beats1, d_counter1) - // Check the response is correct assert (d_size === d_flight.size) assert (edge.manager.findIdStartFast(d_flight.base) <= d.sink)