diff --git a/src/main/resources/csrc/SimMemTrace.cc b/src/main/resources/csrc/SimMemTrace.cc index 397773d..b0be22a 100644 --- a/src/main/resources/csrc/SimMemTrace.cc +++ b/src/main/resources/csrc/SimMemTrace.cc @@ -47,12 +47,52 @@ public: MemTraceLine MemTraceReader::tick() { MemTraceLine line; - line.valid = false; - if (infile >> line.cycle >> line.loadstore >> line.core_id >> - line.thread_id >> std::hex >> line.address >> line.data >> std::dec >> - line.data_size) { + printf("MemTraceReader: started parsing\n"); + + while (infile >> line.cycle >> line.loadstore >> line.core_id >> + line.thread_id >> std::hex >> line.address >> line.data >> std::dec >> + line.data_size) { line.valid = true; - printf("cycle: %ld\n", line.cycle); + trace.push_back(line); + } + read_pos = trace.cbegin(); + + printf("MemTraceReader: finished parsing\n"); +} + +// 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; + line.valid = false; + + printf("tick(): cycle=%ld\n", cycle); + + if (finished()) { + return line; + } + + line = *read_pos; + // 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) { + // 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); + // FIXME! Currently thread_id is assumed to be in round-robin order, e.g. + // 0->1->2->3->0->..., both in the trace file and the order the caller calls + // this function. If this is not true, we cannot simply monotonically + // increment read_pos. + ++read_pos; } return line; @@ -63,11 +103,15 @@ extern "C" void memtrace_init(const char *filename) { printf("memtrace_init: filename=[%s]\n", filename); } -extern "C" void memtrace_tick(unsigned char *trace_read_valid, - unsigned char trace_read_ready, - unsigned long *trace_read_cycle, - unsigned long *trace_read_address) { - auto line = reader->tick(); +// 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, + unsigned char *trace_read_valid, + unsigned long *trace_read_address, + unsigned char *trace_read_finished) { + printf("memtrace_query(cycle=%ld, tid=%d)\n", trace_read_cycle, + trace_read_thread_id); *trace_read_valid = line.valid; *trace_read_cycle = line.cycle; diff --git a/src/main/scala/tilelink/Coalescing.scala b/src/main/scala/tilelink/Coalescing.scala index 5e1f6d9..59dbc0f 100644 --- a/src/main/scala/tilelink/Coalescing.scala +++ b/src/main/scala/tilelink/Coalescing.scala @@ -106,7 +106,7 @@ class MemTraceDriverImp(outer: MemTraceDriver, trace_file: String, threads : Int // 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)) + Module(new SimMemTrace(trace_file=ith_file_name, 4)) } // Connect each sim module to its respective TL connection @@ -116,10 +116,6 @@ class MemTraceDriverImp(outer: MemTraceDriver, trace_file: String, threads : Int sim.io.reset := reset.asBool sim.io.trace_read.ready := true.B - when(sim.io.trace_read.valid) { - println("sim.io.valid!") - } - 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( @@ -146,16 +142,18 @@ class MemTraceDriverImp(outer: MemTraceDriver, trace_file: String, threads : Int -class SimMemTrace(val trace_file: String) extends BlackBox(Map("TRACE_FILE" -> trace_file)) with HasBlackBoxResource { +class SimMemTrace(val trace_file: String, num_threads: Int) extends BlackBox(Map("TRACE_FILE" -> trace_file)) with HasBlackBoxResource { val io = IO(new Bundle { val clock = Input(Clock()) val reset = Input(Bool()) val trace_read = new Bundle { - val valid = Output(Bool()) val ready = Input(Bool()) - val cycle = Output(UInt(64.W)) - val address = Output(UInt(64.W)) + val valid = Output(UInt(num_threads.W)) + // Chisel can't interface with Verilog 2D port, so flatten all lanes into + // single wide 1D array. + val address = Output(UInt((64 * num_threads).W)) + val finished = Output(Bool()) } })