diff --git a/src/main/scala/tilelink/AtomicAutomata.scala b/src/main/scala/tilelink/AtomicAutomata.scala index de2604a9..201f0569 100644 --- a/src/main/scala/tilelink/AtomicAutomata.scala +++ b/src/main/scala/tilelink/AtomicAutomata.scala @@ -190,6 +190,7 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc } // We need to deal with a potential D response in the same cycle as the A request + val d_first = edgeOut.first(out.d) val d_cam_sel_raw = cam_a.map(_.bits.source === in.d.bits.source) val d_cam_sel_match = (d_cam_sel_raw zip cam_dmatch) map { case (a,b) => a&&b } val d_cam_data = Mux1H(d_cam_sel_match, cam_d.map(_.data)) @@ -200,7 +201,7 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc val d_ackd = out.d.bits.opcode === TLMessages.AccessAckData val d_ack = out.d.bits.opcode === TLMessages.AccessAck - when (out.d.fire()) { + when (out.d.fire() && d_first) { (d_cam_sel zip cam_d) foreach { case (en, r) => when (en && d_ackd) { r.data := out.d.bits.data @@ -214,8 +215,8 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc } } - val d_drop = d_ackd && d_cam_sel_any - val d_replace = d_ack && d_cam_sel_match.reduce(_ || _) + val d_drop = d_first && d_ackd && d_cam_sel_any + val d_replace = d_first && d_ack && d_cam_sel_match.reduce(_ || _) in.d.valid := out.d.valid && !d_drop out.d.ready := in.d.ready || d_drop diff --git a/src/main/scala/tilelink/Fuzzer.scala b/src/main/scala/tilelink/Fuzzer.scala index f3932582..6bd65c87 100644 --- a/src/main/scala/tilelink/Fuzzer.scala +++ b/src/main/scala/tilelink/Fuzzer.scala @@ -14,12 +14,11 @@ class IDMapGenerator(numIds: Int) extends Module { val alloc = Decoupled(UInt(width = w)) } + io.free.ready := Bool(true) + // True indicates that the id is available val bitmap = RegInit(UInt((BigInt(1) << numIds) - 1, width = numIds)) - io.free.ready := Bool(true) - assert (!io.free.valid || !bitmap(io.free.bits)) // No double freeing - val select = ~(leftOR(bitmap) << 1) & bitmap io.alloc.bits := OHToUInt(select) io.alloc.valid := bitmap.orR() @@ -31,6 +30,7 @@ class IDMapGenerator(numIds: Int) extends Module { when (io.free.fire()) { set := UIntToOH(io.free.bits) } bitmap := (bitmap & ~clr) | set + assert (!io.free.valid || !(bitmap & ~clr)(io.free.bits)) // No double freeing } object LFSR64 @@ -111,7 +111,7 @@ class TLFuzzer( val num_reqs = Reg(init = UInt(nOperations, log2Up(nOperations+1))) val num_resps = Reg(init = UInt(nOperations, log2Up(nOperations+1))) if (nOperations>0) { - io.finished := num_resps === UInt(0) + io.finished := num_resps === UInt(0) } else { io.finished := Bool(false) } @@ -125,12 +125,7 @@ class TLFuzzer( // Source ID generation val idMap = Module(new IDMapGenerator(inFlight)) - val alloc = Queue.irrevocable(idMap.io.alloc, 1, pipe = true) - val src = alloc.bits - alloc.ready := req_done - idMap.io.free.valid := resp_done - idMap.io.free.bits := out.d.bits.source - + val src = idMap.io.alloc.bits holdUnless a_first // Increment random number generation for the following subfields val inc = Wire(Bool()) val inc_beat = Wire(Bool()) @@ -183,12 +178,13 @@ class TLFuzzer( UInt("b100") -> lbits, UInt("b101") -> hbits)) - // Wire both the used and un-used channel signals - if (nOperations>0) { - out.a.valid := legal && alloc.valid && num_reqs =/= UInt(0) - } else { - out.a.valid := legal && alloc.valid - } + // Wire up Fuzzer flow control + val a_gen = if (nOperations>0) num_reqs =/= UInt(0) else Bool(true) + out.a.valid := a_gen && legal && (!a_first || idMap.io.alloc.valid) + idMap.io.alloc.ready := a_gen && legal && a_first && out.a.ready + idMap.io.free.valid := d_first && out.d.fire() + idMap.io.free.bits := out.d.bits.source + out.a.bits := bits out.b.ready := Bool(true) out.c.valid := Bool(false) diff --git a/src/main/scala/tilelink/RAMModel.scala b/src/main/scala/tilelink/RAMModel.scala index 6fb138a3..88f8cc38 100644 --- a/src/main/scala/tilelink/RAMModel.scala +++ b/src/main/scala/tilelink/RAMModel.scala @@ -95,7 +95,7 @@ class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule when (in.a.fire()) { flight(in.a.bits.source) := a_flight } val bypass = if (edge.manager.minLatency > 0) Bool(false) else in.a.valid && in.a.bits.source === out.d.bits.source - val d_flight = RegNext(Mux(bypass, a_flight, flight(out.d.bits.source))) + val d_flight = RegEnable(Mux(bypass, a_flight, flight(out.d.bits.source)), edge.first(out.d)) // Process A access requests val a = Reg(next = in.a.bits) diff --git a/src/main/scala/tilelink/SourceShrinker.scala b/src/main/scala/tilelink/SourceShrinker.scala index 57558b42..3a1e9a30 100644 --- a/src/main/scala/tilelink/SourceShrinker.scala +++ b/src/main/scala/tilelink/SourceShrinker.scala @@ -60,8 +60,9 @@ class TLSourceShrinker(maxInFlight: Int)(implicit p: Parameters) extends LazyMod out.a.bits := in.a.bits out.a.bits.source := nextFree holdUnless a_first + val bypass = Bool(edgeOut.manager.minLatency == 0) && in.a.fire() && a_first && nextFree === out.d.bits.source in.d <> out.d - in.d.bits.source := sourceIdMap(out.d.bits.source) + in.d.bits.source := Mux(bypass, in.a.bits.source, sourceIdMap(out.d.bits.source)) when (a_first && in.a.fire()) { sourceIdMap(nextFree) := in.a.bits.source