diff --git a/sim/firesim-lib/src/main/cc/bridges/tracerv.cc b/sim/firesim-lib/src/main/cc/bridges/tracerv.cc index 64e5af93..af908251 100644 --- a/sim/firesim-lib/src/main/cc/bridges/tracerv.cc +++ b/sim/firesim-lib/src/main/cc/bridges/tracerv.cc @@ -35,6 +35,9 @@ tracerv_t::tracerv_t(simif_t &sim, : streaming_bridge_driver_t(sim, stream, &KIND), mmio_addrs(mmio_addrs), stream_idx(stream_idx), stream_depth(stream_depth), max_core_ipc(max_core_ipc), clock_info(clock_info) { + // Biancolin: move into elaboration + assert(this->max_core_ipc <= 7 && + "TracerV only supports cores with a maximum IPC <= 7"); const char *tracefilename = nullptr; const char *dwarf_file_name = nullptr; this->tracefile = nullptr; @@ -271,6 +274,8 @@ void tracerv_t::serialize( OUTBUF[i + 0], q, OUTBUF[i + q + 1] & (~valid_mask)); + } else { + break; } } } diff --git a/sim/firesim-lib/src/main/cc/bridges/tracerv.h b/sim/firesim-lib/src/main/cc/bridges/tracerv.h index db8e68f1..33989c96 100644 --- a/sim/firesim-lib/src/main/cc/bridges/tracerv.h +++ b/sim/firesim-lib/src/main/cc/bridges/tracerv.h @@ -5,6 +5,7 @@ #include "core/bridge_driver.h" #include "core/clock_info.h" #include +#include #include class TraceTracker; diff --git a/sim/firesim-lib/src/main/scala/bridges/TracerVBridge.scala b/sim/firesim-lib/src/main/scala/bridges/TracerVBridge.scala index c8eacb61..4e2e6630 100644 --- a/sim/firesim-lib/src/main/scala/bridges/TracerVBridge.scala +++ b/sim/firesim-lib/src/main/scala/bridges/TracerVBridge.scala @@ -14,19 +14,20 @@ import midas.widgets._ class TracerVTargetIO(widths: TraceBundleWidths) extends Bundle { val trace = Input(new SerializableTileTraceIO(widths)) val triggerCredit = Output(Bool()) - val triggerDebit = Output(Bool()) + val triggerDebit = Output(Bool()) } - -/** Target-side module for the TracerV Bridge. +/** + * Target-side module for the TracerV Bridge. * - * @param insnWidths - * A case class containing the widths of configurable-length fields in the trace interface. + * @param insnWidths A case class containing the widths of configurable-length + * fields in the trace interface. * - * @param numInsns - * The number of instructions captured in a single a cycle (generally, the commit width of the pipeline) + * @param numInsns The number of instructions captured in a single a cycle + * (generally, the commit width of the pipeline) * - * Warning: If you're not going to use the companion object to instantiate this bridge you must call - * [[TracerVBridge.generateTriggerAnnotations] _in the parent module_. + * Warning: If you're not going to use the companion object to instantiate + * this bridge you must call [[TracerVBridge.generateTriggerAnnotations] _in + * the parent module_. */ class TracerVBridge(widths: TraceBundleWidths) extends BlackBox @@ -65,7 +66,7 @@ object TracerVBridge { tracerv } - def apply(tracedInsns: TileTraceIO)(implicit p: Parameters): TracerVBridge = { + def apply(tracedInsns: TileTraceIO)(implicit p:Parameters): TracerVBridge = { val tracerv = withClockAndReset(tracedInsns.clock, tracedInsns.reset) { TracerVBridge(tracedInsns.traceBundleWidths) } @@ -80,81 +81,81 @@ class TracerVBridgeModule(key: TraceBundleWidths)(implicit p: Parameters) // StreamToHostCPU mixin parameters // Use the legacy NIC depth - val toHostCPUQueueDepth = TokenQueueConsts.TOKEN_QUEUE_DEPTH + val toHostCPUQueueDepth = TokenQueueConsts.TOKEN_QUEUE_DEPTH lazy val module = new BridgeModuleImp(this) { val io = IO(new WidgetIO) val hPort = IO(HostPort(new TracerVTargetIO(key))) + // Mask off valid committed instructions when under reset val traces = hPort.hBits.trace.trace.insns.map({ unmasked => val masked = WireDefault(unmasked) masked.valid := unmasked.valid && !hPort.hBits.trace.reset.asBool masked }) - private val pcWidth = traces.map(_.iaddr.getWidth).max + private val pcWidth = traces.map(_.iaddr.getWidth).max private val insnWidth = traces.map(_.insn.getWidth).max - val cycleCountWidth = 64 + val cycleCountWidth = 64 // Set after trigger-dependent memory-mapped registers have been set, to // prevent spurious credits - val initDone = genWORegInit(Wire(Bool()), "initDone", false.B) + val initDone = genWORegInit(Wire(Bool()), "initDone", false.B) // When unset, diables token capture to improve FMR, while still enabling the // use of TracerV-based triggers - val traceEnable = genWORegInit(Wire(Bool()), "traceEnable", true.B) + val traceEnable = genWORegInit(Wire(Bool()), "traceEnable", true.B) //Program Counter trigger value can be configured externally val hostTriggerPCWidthOffset = pcWidth - p(CtrlNastiKey).dataBits - val hostTriggerPCLowWidth = if (hostTriggerPCWidthOffset > 0) p(CtrlNastiKey).dataBits else pcWidth - val hostTriggerPCHighWidth = if (hostTriggerPCWidthOffset > 0) hostTriggerPCWidthOffset else 0 + val hostTriggerPCLowWidth = if (hostTriggerPCWidthOffset > 0) p(CtrlNastiKey).dataBits else pcWidth + val hostTriggerPCHighWidth = if (hostTriggerPCWidthOffset > 0) hostTriggerPCWidthOffset else 0 val hostTriggerPCStartHigh = RegInit(0.U(hostTriggerPCHighWidth.W)) - val hostTriggerPCStartLow = RegInit(0.U(hostTriggerPCLowWidth.W)) + val hostTriggerPCStartLow = RegInit(0.U(hostTriggerPCLowWidth.W)) attach(hostTriggerPCStartHigh, "hostTriggerPCStartHigh", WriteOnly) attach(hostTriggerPCStartLow, "hostTriggerPCStartLow", WriteOnly) - val hostTriggerPCStart = Cat(hostTriggerPCStartHigh, hostTriggerPCStartLow) - val triggerPCStart = RegInit(0.U(pcWidth.W)) + val hostTriggerPCStart = Cat(hostTriggerPCStartHigh, hostTriggerPCStartLow) + val triggerPCStart = RegInit(0.U(pcWidth.W)) triggerPCStart := hostTriggerPCStart val hostTriggerPCEndHigh = RegInit(0.U(hostTriggerPCHighWidth.W)) - val hostTriggerPCEndLow = RegInit(0.U(hostTriggerPCLowWidth.W)) + val hostTriggerPCEndLow = RegInit(0.U(hostTriggerPCLowWidth.W)) attach(hostTriggerPCEndHigh, "hostTriggerPCEndHigh", WriteOnly) attach(hostTriggerPCEndLow, "hostTriggerPCEndLow", WriteOnly) - val hostTriggerPCEnd = Cat(hostTriggerPCEndHigh, hostTriggerPCEndLow) - val triggerPCEnd = RegInit(0.U(pcWidth.W)) + val hostTriggerPCEnd = Cat(hostTriggerPCEndHigh, hostTriggerPCEndLow) + val triggerPCEnd = RegInit(0.U(pcWidth.W)) triggerPCEnd := hostTriggerPCEnd //Cycle count trigger val hostTriggerCycleCountWidthOffset = 64 - p(CtrlNastiKey).dataBits - val hostTriggerCycleCountLowWidth = if (hostTriggerCycleCountWidthOffset > 0) p(CtrlNastiKey).dataBits else 64 - val hostTriggerCycleCountHighWidth = - if (hostTriggerCycleCountWidthOffset > 0) hostTriggerCycleCountWidthOffset else 0 + val hostTriggerCycleCountLowWidth = if (hostTriggerCycleCountWidthOffset > 0) p(CtrlNastiKey).dataBits else 64 + val hostTriggerCycleCountHighWidth = if (hostTriggerCycleCountWidthOffset > 0) hostTriggerCycleCountWidthOffset else 0 val hostTriggerCycleCountStartHigh = RegInit(0.U(hostTriggerCycleCountHighWidth.W)) - val hostTriggerCycleCountStartLow = RegInit(0.U(hostTriggerCycleCountLowWidth.W)) + val hostTriggerCycleCountStartLow = RegInit(0.U(hostTriggerCycleCountLowWidth.W)) attach(hostTriggerCycleCountStartHigh, "hostTriggerCycleCountStartHigh", WriteOnly) attach(hostTriggerCycleCountStartLow, "hostTriggerCycleCountStartLow", WriteOnly) - val hostTriggerCycleCountStart = Cat(hostTriggerCycleCountStartHigh, hostTriggerCycleCountStartLow) - val triggerCycleCountStart = RegInit(0.U(cycleCountWidth.W)) + val hostTriggerCycleCountStart = Cat(hostTriggerCycleCountStartHigh, hostTriggerCycleCountStartLow) + val triggerCycleCountStart = RegInit(0.U(cycleCountWidth.W)) triggerCycleCountStart := hostTriggerCycleCountStart val hostTriggerCycleCountEndHigh = RegInit(0.U(hostTriggerCycleCountHighWidth.W)) - val hostTriggerCycleCountEndLow = RegInit(0.U(hostTriggerCycleCountLowWidth.W)) + val hostTriggerCycleCountEndLow = RegInit(0.U(hostTriggerCycleCountLowWidth.W)) attach(hostTriggerCycleCountEndHigh, "hostTriggerCycleCountEndHigh", WriteOnly) attach(hostTriggerCycleCountEndLow, "hostTriggerCycleCountEndLow", WriteOnly) - val hostTriggerCycleCountEnd = Cat(hostTriggerCycleCountEndHigh, hostTriggerCycleCountEndLow) - val triggerCycleCountEnd = RegInit(0.U(cycleCountWidth.W)) + val hostTriggerCycleCountEnd = Cat(hostTriggerCycleCountEndHigh, hostTriggerCycleCountEndLow) + val triggerCycleCountEnd = RegInit(0.U(cycleCountWidth.W)) triggerCycleCountEnd := hostTriggerCycleCountEnd val trace_cycle_counter = RegInit(0.U(cycleCountWidth.W)) //target instruction type trigger (trigger through target software) //can configure the trigger instruction type externally though simulation driver - val hostTriggerStartInst = RegInit(0.U(insnWidth.W)) + val hostTriggerStartInst = RegInit(0.U(insnWidth.W)) val hostTriggerStartInstMask = RegInit(0.U(insnWidth.W)) attach(hostTriggerStartInst, "hostTriggerStartInst", WriteOnly) attach(hostTriggerStartInstMask, "hostTriggerStartInstMask", WriteOnly) - val hostTriggerEndInst = RegInit(0.U(insnWidth.W)) + val hostTriggerEndInst = RegInit(0.U(insnWidth.W)) val hostTriggerEndInstMask = RegInit(0.U(insnWidth.W)) attach(hostTriggerEndInst, "hostTriggerEndInst", WriteOnly) attach(hostTriggerEndInstMask, "hostTriggerEndInstMask", WriteOnly) @@ -170,10 +171,10 @@ class TracerVBridgeModule(key: TraceBundleWidths)(implicit p: Parameters) val triggerPCValVec = RegInit(VecInit(Seq.fill(traces.length)(false.B))) traces.zipWithIndex.foreach { case (trace, i) => - when(trace.valid) { - when(triggerPCStart === trace.iaddr) { + when (trace.valid) { + when (triggerPCStart === trace.iaddr) { triggerPCValVec(i) := true.B - }.elsewhen((triggerPCEnd === trace.iaddr) && triggerPCValVec(i)) { + } .elsewhen ((triggerPCEnd === trace.iaddr) && triggerPCValVec(i)) { triggerPCValVec(i) := false.B } } @@ -181,86 +182,36 @@ class TracerVBridgeModule(key: TraceBundleWidths)(implicit p: Parameters) val triggerInstValVec = RegInit(VecInit(Seq.fill(traces.length)(false.B))) traces.zipWithIndex.foreach { case (trace, i) => - when(trace.valid) { - when(!((hostTriggerStartInst ^ trace.insn) & hostTriggerStartInstMask).orR) { + when (trace.valid) { + when (!((hostTriggerStartInst ^ trace.insn) & hostTriggerStartInstMask).orR) { triggerInstValVec(i) := true.B - }.elsewhen(!((hostTriggerEndInst ^ trace.insn) & hostTriggerEndInstMask).orR) { + } .elsewhen (!((hostTriggerEndInst ^ trace.insn) & hostTriggerEndInstMask).orR) { triggerInstValVec(i) := false.B } } } - val trigger = MuxLookup( - triggerSelector, - false.B, - Seq( - 0.U -> true.B, - 1.U -> triggerCycleCountVal, - 2.U -> triggerPCValVec.reduce(_ || _), - 3.U -> triggerInstValVec.reduce(_ || _), - ), - ) + val trigger = MuxLookup(triggerSelector, false.B, Seq( + 0.U -> true.B, + 1.U -> triggerCycleCountVal, + 2.U -> triggerPCValVec.reduce(_ || _), + 3.U -> triggerInstValVec.reduce(_ || _))) val tFireHelper = DecoupledHelper(streamEnq.ready, hPort.toHost.hValid, hPort.fromHost.hReady, initDone) val triggerReg = RegEnable(trigger, false.B, tFireHelper.fire()) - hPort.hBits.triggerDebit := !trigger && triggerReg + hPort.hBits.triggerDebit := !trigger && triggerReg hPort.hBits.triggerCredit := trigger && !triggerReg + val uint_traces = (traces map (trace => Cat(trace.valid, trace.iaddr).pad(64))).reverse + streamEnq.bits := Cat(uint_traces :+ trace_cycle_counter.pad(64)).pad(BridgeStreamConstants.streamWidthBits) + + hPort.toHost.hReady := tFireHelper.fire(hPort.toHost.hValid) hPort.fromHost.hValid := tFireHelper.fire(hPort.fromHost.hReady) - // the maximum width of a single arm, this is determined by the 512 bit width of a single beat - val armWidth = 7 + streamEnq.valid := tFireHelper.fire(streamEnq.ready, trigger) && traceEnable - // divide with a ceiling round, to get the total number of arms - val armCount = (traces.length + armWidth - 1) / armWidth - - // A Seq of Seq which represents each arm of the mux - val allTraceArms = traces.grouped(armWidth).toSeq - - // an intermediate value used to build allStreamBits - val allUintTraces = allTraceArms.map(arm => arm.map((trace => Cat(trace.valid, trace.iaddr).pad(64))).reverse) - - // Literally each arm of the mux, these are directly the bits that get put into the bump - val allStreamBits = - allUintTraces.map(uarm => Cat(uarm :+ trace_cycle_counter.pad(64)).pad(BridgeStreamConstants.streamWidthBits)) - - // Number of bits to use for the counter, the +1 is required because the counter will count 1 past the number of arms - val counterBits = log2Ceil(armCount + 1) - - // This counter acts to select the mux arm - val counter = RegInit(0.U(counterBits.W)) - - // The main mux where the input arms are different possible valid traces, and the output goes to streamEnq - val streamMux = MuxLookup(counter, allStreamBits(0), Seq.tabulate(armCount)(x => x.U -> allStreamBits(x))) - - // a parallel set of arms to a parallel mux, true if any instructions in the arm are valid (OR reduction) - val anyValid = allTraceArms.map(arm => arm.map(trace => trace.valid).reduce((a, b) => (a | b))) - - // all of the valids of the larger indexed arms are OR reduced - val anyValidRemain = - Seq.tabulate(armCount)(idx => (idx until armCount).map(x => anyValid(x)).reduce((a, b) => (a | b))) - val anyValidRemainMux = MuxLookup(counter, false.B, Seq.tabulate(armCount)(x => x.U -> anyValidRemain(x))) - - streamEnq.bits := streamMux - - val maybeFire = !anyValidRemainMux || (counter === (armCount - 1).U) - val maybeEnq = anyValidRemainMux - - val do_enq_helper = DecoupledHelper(hPort.toHost.hValid, streamEnq.ready, maybeEnq, traceEnable) - val do_fire_helper = DecoupledHelper(hPort.toHost.hValid, streamEnq.ready, maybeFire) - - // Note, if we dequeue a token that wins out over the increment below - when(do_fire_helper.fire()) { - counter := 0.U - }.elsewhen(do_enq_helper.fire()) { - counter := counter + 1.U - } - - streamEnq.valid := do_enq_helper.fire(streamEnq.ready, trigger) - hPort.toHost.hReady := do_fire_helper.fire(hPort.toHost.hValid) - - when(hPort.toHost.fire) { + when (tFireHelper.fire()) { trace_cycle_counter := trace_cycle_counter + 1.U } @@ -268,17 +219,17 @@ class TracerVBridgeModule(key: TraceBundleWidths)(implicit p: Parameters) override def genHeader(base: BigInt, memoryRegions: Map[String, BigInt], sb: StringBuilder): Unit = { genConstructor( - base, - sb, - "tracerv_t", - "tracerv", - Seq( - UInt32(toHostStreamIdx), - UInt32(toHostCPUQueueDepth), - UInt32(traces.size), - Verbatim(clockDomainInfo.toC), - ), - hasStreams = true, + base, + sb, + "tracerv_t", + "tracerv", + Seq( + UInt32(toHostStreamIdx), + UInt32(toHostCPUQueueDepth), + UInt32(traces.size), + Verbatim(clockDomainInfo.toC) + ), + hasStreams = true ) } } diff --git a/sim/src/main/cc/bridges/TracerVModule.cc b/sim/src/main/cc/bridges/TracerVModule.cc index 777f9e91..280e2bb2 100644 --- a/sim/src/main/cc/bridges/TracerVModule.cc +++ b/sim/src/main/cc/bridges/TracerVModule.cc @@ -10,12 +10,10 @@ #include #include -static std::vector get_valids(uint64_t seed, unsigned total) { - assert(total <= 64 && "This test does not support more than 64 IPC"); - +static std::vector get_contiguous(unsigned bits, unsigned total) { std::vector ret; for (unsigned i = 0; i < total; i++) { - const bool value = seed & (1 << i); + const bool value = (i < bits); ret.emplace_back(value); } @@ -170,16 +168,12 @@ public: // calculate what TraverV should output, and save it if (bit[i]) { valid_i.emplace_back(iad[i]); - } else { - // write a magic value to signify an invalid instruction - // this magic value is test only and is not passed to the DUT - valid_i.emplace_back(-1); } } // place instructions onto the vector 7 at a time for (size_t i = 0; i < valid_i.size(); i += 7) { - const auto last = std::min(valid_i.size(), i + 7); + auto last = std::min(valid_i.size(), i + 7); std::vector chunk = std::vector(valid_i.begin() + i, valid_i.begin() + last); expected_pair.emplace_back(std::make_pair(e_cycle, chunk)); @@ -193,10 +187,10 @@ public: for (unsigned test_step = 0, total = get_total_trace_tests(); test_step < total; ++test_step) { - const uint64_t pull = rand_next(); + const uint64_t pull = rand_next(tracerv_width + 1); - const auto pull_bits = get_valids(pull, tracerv_width); - const auto pull_iaddr = get_iaddrs(test_step, tracerv_width); + auto pull_iaddr = get_iaddrs(test_step, tracerv_width); + auto pull_bits = get_contiguous(pull, tracerv_width); load(pull_iaddr, pull_bits); steps(1); @@ -316,12 +310,7 @@ public: assert(insns.size() < 8 && "Internal test error, filtered cannot " "have more than 8 instructions at once"); for (int i = 0; i < insns.size(); i++) { - // valid instruction, or invalid placeholder - if (insns[i] != -1) { - buffer[i + 1] = insns[i] | tracerv_t::valid_mask; - } else { - buffer[i + 1] = 0; - } + buffer[i + 1] = insns[i] | tracerv_t::valid_mask; } // because filtered doesn't contain the instruction value for non @@ -350,7 +339,7 @@ public: /** * Returns the next available random number, modulo limit. */ - uint64_t rand_next() { return gen(); } + uint64_t rand_next(uint64_t limit) { return gen() % limit; } private: unsigned get_total_trace_tests() const { return 128; } diff --git a/sim/src/main/scala/bridges/TracerVModule.scala b/sim/src/main/scala/bridges/TracerVModule.scala index d5ca9708..225e3ad5 100644 --- a/sim/src/main/scala/bridges/TracerVModule.scala +++ b/sim/src/main/scala/bridges/TracerVModule.scala @@ -34,11 +34,6 @@ class TracerVModuleTestCount7 7 }) -class TracerVModuleTestCount9 - extends Config((site, here, up) => { case TracerVModuleInstructionCount => - 9 - }) - class TracerVModuleTestCount14 extends Config((site, here, up) => { case TracerVModuleInstructionCount => 14 diff --git a/sim/src/test/scala/bridges/TracerVSuite.scala b/sim/src/test/scala/bridges/TracerVSuite.scala index 7d386366..eb5cb8ad 100644 --- a/sim/src/test/scala/bridges/TracerVSuite.scala +++ b/sim/src/test/scala/bridges/TracerVSuite.scala @@ -56,12 +56,9 @@ abstract class TracerVTestBase( } } -class TracerVF1TestCount1 extends TracerVTestBase(BaseConfigs.F1, 1); +class TracerVF1TestCount1 extends TracerVTestBase(BaseConfigs.F1, 1); // This test is disabled until FireSim issue #1428 is resolved // class TracerVF1TestCount5 extends TracerVTestBase(BaseConfigs.F1, 5, Some(3), Some("FF0000001C")); // in hex -class TracerVF1TestCount6 extends TracerVTestBase(BaseConfigs.F1, 6, Some(2), Some("3000")); // in hex -class TracerVF1TestCount7 extends TracerVTestBase(BaseConfigs.F1, 7, Some(1), Some("9")); // in decimal -class TracerVF1TestCount9 extends TracerVTestBase(BaseConfigs.F1, 9); -class TracerVVitisTest extends TracerVTestBase(BaseConfigs.Vitis, 14); -class TracerVF1TestCount14 extends TracerVTestBase(BaseConfigs.F1, 14, Some(1), Some("10")); // in decimal -class TracerVF1TestCount15 extends TracerVTestBase(BaseConfigs.F1, 15, Some(2), Some("4000")); +class TracerVF1TestCount6 extends TracerVTestBase(BaseConfigs.F1, 6, Some(2), Some("3000")); // in hex +class TracerVF1TestCount7 extends TracerVTestBase(BaseConfigs.F1, 7, Some(1), Some("9")); // in decimala +class TracerVVitisTest extends TracerVTestBase(BaseConfigs.Vitis, 7);