diff --git a/src/main/resources/csrc/SimMemTrace.cc b/src/main/resources/csrc/SimMemTrace.cc index 1857985..45542b1 100644 --- a/src/main/resources/csrc/SimMemTrace.cc +++ b/src/main/resources/csrc/SimMemTrace.cc @@ -44,9 +44,9 @@ void MemTraceReader::parse() { printf("MemTraceReader: finished parsing\n"); } -// Try to read a memory request that might have happened at a given cycle, on -// given thread. In case no request happened at that point, return an empty -// line with .valid = false. +// Try to read a memory request that might have happened at a given cycle, on a +// given SIMD lane (= "thread"). In case no request happened at that point, +// return an empty line with .valid = false. MemTraceLine MemTraceReader::read_trace_at(const long cycle, const int thread_id) { MemTraceLine line; @@ -59,14 +59,16 @@ MemTraceLine MemTraceReader::read_trace_at(const long cycle, } line = *read_pos; - // It should always be guaranteed that the next line is not read yet. + // It should always be guaranteed that we consumed all of the past lines, and + // the next line is in the future. if (line.cycle < cycle) { fprintf(stderr, "line.cycle=%ld, cycle=%ld\n", line.cycle, cycle); assert(false && "some trace lines are left unread in the past"); } if (line.cycle > cycle) { - // It's not ready to read this line yet. + // We haven't reached the cycle mark specified in this line yet, so we don't + // read it right now. return MemTraceLine{}; } else if (line.cycle == cycle) { printf("fire! cycle=%ld, valid=%d\n", cycle, line.valid); @@ -88,6 +90,7 @@ extern "C" void memtrace_init(const char *filename) { reader->parse(); } +// TODO: accept core_id as well extern "C" void memtrace_query(unsigned char trace_read_ready, unsigned long trace_read_cycle, int trace_read_thread_id, diff --git a/src/main/scala/tilelink/Coalescing.scala b/src/main/scala/tilelink/Coalescing.scala index c7d61d4..691aa37 100644 --- a/src/main/scala/tilelink/Coalescing.scala +++ b/src/main/scala/tilelink/Coalescing.scala @@ -8,141 +8,130 @@ import freechips.rocketchip.config.Parameters import freechips.rocketchip.diplomacy._ import freechips.rocketchip.unittest._ - -class CoalescingLogic(threads : Int = 1)(implicit p: Parameters) +class CoalescingLogic(threads: Int = 1)(implicit p: Parameters) extends LazyModule { + val node = TLIdentityNode() - val node = TLIdentityNode() + // Creating N number of Manager node + val beatBytes = 8 + val seqparam = Seq( + TLSlaveParameters.v1( + address = Seq(AddressSet(0x0000, 0xffffff)), + // resources = device.reg, + regionType = RegionType.UNCACHED, + executable = true, + supportsArithmetic = TransferSizes(1, beatBytes), + supportsLogical = TransferSizes(1, beatBytes), + supportsGet = TransferSizes(1, beatBytes), + supportsPutFull = TransferSizes(1, beatBytes), + supportsPutPartial = TransferSizes(1, beatBytes), + supportsHint = TransferSizes(1, beatBytes), + fifoId = Some(0) + ) + ) + val vec_node_entry = Seq.tabulate(threads) { _ => + TLManagerNode(Seq(TLSlavePortParameters.v1(seqparam, beatBytes))) + } + // Assign each vec_node to the identity node + vec_node_entry.foreach { n => n := node } - // Creating N number of Manager node - val beatBytes = 8 - val seqparam = Seq(TLSlaveParameters.v1( - address = Seq(AddressSet(0x0000, 0xffffff)), - //resources = device.reg, - regionType = RegionType.UNCACHED, - executable = true, - supportsArithmetic = TransferSizes(1, beatBytes), - supportsLogical = TransferSizes(1, beatBytes), - supportsGet = TransferSizes(1, beatBytes), - supportsPutFull = TransferSizes(1, beatBytes), - supportsPutPartial = TransferSizes(1, beatBytes), - supportsHint = TransferSizes(1, beatBytes), - fifoId = Some(0)) - ) - val vec_node_entry = Seq.tabulate(threads){ - _ => TLManagerNode(Seq(TLSlavePortParameters.v1(seqparam, beatBytes))) - } - //Assign each vec_node to the identity node - vec_node_entry.foreach { n => n := node } + lazy val module = new Impl + class Impl extends LazyModuleImp(this) { + // Example 1: accessing the entire A channel data for Thread 0 + val (tl_in_0, edge0) = vec_node_entry(0).in(0) + dontTouch(tl_in_0.a) + // Example 2: accssing the entire A channel data for Thread 1 + val (tl_in_1, edge1) = vec_node_entry(1).in(0) + dontTouch(tl_in_1.a) + } +} - lazy val module = new Impl - class Impl extends LazyModuleImp(this) { - - //Example 1: accessing the entire A channel data for Thread 0 - val (tl_in_0, edge0) = vec_node_entry(0).in(0) - dontTouch(tl_in_0.a) - - // Example 2: accssing the entire A channel data for Thread 1 - val (tl_in_1, edge1) = vec_node_entry(1).in(0) - dontTouch(tl_in_1.a) - } - } - - - -class CoalescingEntry(txns: Int = 5000)(implicit p: Parameters) +class CoalescingEntry(implicit p: Parameters) extends LazyModule { - val node = TLIdentityNode() lazy val module = new Impl class Impl extends LazyModuleImp(this) { - - (node.in zip node.out) foreach { - case((in, edgeIn), (out, edgeOut)) => - out.a <> in.a - in.d <> out.d - dontTouch(in.a) - dontTouch(in.d) + (node.in zip node.out) foreach { case ((in, _), (out, _)) => + out.a <> in.a + in.d <> out.d + dontTouch(in.a) + dontTouch(in.d) } - } - } -class MemTraceDriver(threads : Int = 1)(implicit p: Parameters) extends LazyModule { - - +class MemTraceDriver(threads: Int = 1)(implicit p: Parameters) + extends LazyModule { // Create N client nodes together - val vec_trace_node = Seq.tabulate(threads) { i => - - val clients = Seq(TLMasterParameters.v1( - name = "MemTraceDriver" + i.toString, - sourceId = IdRange(0,4) - ) - ) + val thread_nodes = Seq.tabulate(threads) { i => + val clients = Seq( + TLMasterParameters.v1( + name = "MemTraceDriver" + i.toString, + sourceId = IdRange(0, 4) + ) + ) TLClientNode(Seq(TLMasterPortParameters.v1(clients))) } - - // Combine N outgoing client node into 1 idenity node for diplomatic connection + // Combine N outgoing client node into 1 idenity node for diplomatic + // connection val node = TLIdentityNode() - vec_trace_node.foreach{ thread_node => - node := thread_node + thread_nodes.foreach { thread_node => + node := thread_node } - lazy val module = new MemTraceDriverImp(this, "YourTraceFileName", threads) - } - -class MemTraceDriverImp(outer: MemTraceDriver, trace_file: String, threads : Int) (implicit p: Parameters) extends LazyModuleImp(outer) with UnitTestModule { - - - // Creating N indepdent behaving thread modules - val vec_sim = Seq.tabulate(threads) { i => - val ith_file_name = trace_file + (i+1).toString - Module(new SimMemTrace(trace_file=ith_file_name, 4)) - } - - // Connect each sim module to its respective TL connection - vec_sim.zipWithIndex.foreach{ - case (sim, i) => - sim.io.clock := clock - sim.io.reset := reset.asBool - sim.io.trace_read.ready := true.B - - val (tl_out, edgesOut) = outer.vec_trace_node(i).out(0) - tl_out.a.valid := sim.io.trace_read.valid - tl_out.a.bits := edgesOut.Put( - fromSource = 0.U, - toAddress = 0.U, - // 64 bits = 8 bytes = 2**(3) bytes - lgSize = 3.U, - data = (i+100).U)._2 - //tl_out.a.bits.mask := 0xf.U - dontTouch(tl_out.a) - - tl_out.d.ready := true.B - - } - - - - - // FIXME, current this simulation terminates when thread 0 terminates - // we're finished when there is no more memtrace to read - io.finished := !vec_sim(0).io.trace_read.valid - +class MemTraceDriverImp( + outer: MemTraceDriver, + trace_file: String, + num_threads: Int +) extends LazyModuleImp(outer) + with UnitTestModule { + // Creating N indepdent behaving thread modules + val sims = Seq.tabulate(num_threads) { i => + val ith_file_name = trace_file + (i + 1).toString + Module(new SimMemTrace(trace_file = ith_file_name, 4)) } + // Connect each sim module to its respective TL connection + sims.zipWithIndex.foreach { case (sim, i) => + sim.io.clock := clock + sim.io.reset := reset.asBool + sim.io.trace_read.ready := true.B + val (tl_out, edge) = outer.thread_nodes(i).out(0) + tl_out.a.valid := sim.io.trace_read.valid + tl_out.a.bits := edge + .Put( + fromSource = 0.U, + toAddress = 0.U, + // 64 bits = 8 bytes = 2**(3) bytes + lgSize = 3.U, + data = (i + 100).U + ) + ._2 + // tl_out.a.bits.mask := 0xf.U + dontTouch(tl_out.a) -class SimMemTrace(val trace_file: String, num_threads: Int) extends BlackBox(Map("TRACE_FILE" -> trace_file)) with HasBlackBoxResource { + tl_out.d.ready := true.B + } + + // FIXME, current this simulation terminates when thread 0 terminates + // we're finished when there is no more memtrace to read + io.finished := !sims(0).io.trace_read.valid +} + +class SimMemTrace(val trace_file: String, num_threads: Int) + extends BlackBox( + Map("TRACE_FILE" -> trace_file, "NUM_THREADS" -> num_threads) + ) + with HasBlackBoxResource { val io = IO(new Bundle { val clock = Input(Clock()) val reset = Input(Bool()) @@ -162,29 +151,24 @@ class SimMemTrace(val trace_file: String, num_threads: Int) extends BlackBox(Map addResource("/csrc/SimMemTrace.h") } +class CoalConnectTrace(implicit p: Parameters) extends LazyModule { + val coal_entry = LazyModule(new CoalescingEntry) + val coal_logic = LazyModule(new CoalescingLogic(threads = 2)) + val driver = LazyModule(new MemTraceDriver(threads = 2)) -class CoalConnectTrace(txns: Int)(implicit p: Parameters) extends LazyModule { + coal_logic.node :=* coal_entry.node :=* driver.node - val coal_entry = LazyModule(new CoalescingEntry(txns)) - val coal_logic = LazyModule(new CoalescingLogic(threads=2)) - val driver = LazyModule(new MemTraceDriver(threads=2)) - - coal_logic.node :=* coal_entry.node :=* driver.node - - lazy val module = new Impl - class Impl extends LazyModuleImp(this) with UnitTestModule { + lazy val module = new Impl + class Impl extends LazyModuleImp(this) with UnitTestModule { driver.module.io.start := io.start io.finished := driver.module.io.finished } - } -class CoalescingUnitTest(txns: Int = 5000, timeout: Int = 500000)(implicit +class CoalescingUnitTest(timeout: Int = 500000)(implicit p: Parameters ) extends UnitTest(timeout) { - - val dut = Module(LazyModule(new CoalConnectTrace(txns)).module) + val dut = Module(LazyModule(new CoalConnectTrace).module) dut.io.start := io.start io.finished := dut.io.finished - }