From 5f55a7578f52e5eaf8e3e7bf2f934043abfa46f7 Mon Sep 17 00:00:00 2001 From: Hansung Kim Date: Fri, 3 Mar 2023 22:36:54 -0800 Subject: [PATCH] Recover lost changes --- src/main/resources/csrc/SimMemTrace.cc | 85 +++++++-------- src/main/resources/csrc/SimMemTrace.h | 40 +++++++ src/main/resources/vsrc/SimMemTrace.v | 128 +++++++++++++++-------- src/main/scala/tilelink/Coalescing.scala | 1 + 4 files changed, 162 insertions(+), 92 deletions(-) create mode 100644 src/main/resources/csrc/SimMemTrace.h diff --git a/src/main/resources/csrc/SimMemTrace.cc b/src/main/resources/csrc/SimMemTrace.cc index b0be22a..1857985 100644 --- a/src/main/resources/csrc/SimMemTrace.cc +++ b/src/main/resources/csrc/SimMemTrace.cc @@ -1,50 +1,34 @@ +#ifndef NO_VPI #include #include -#include +#endif #include -#include #include +#include #include +#include "SimMemTrace.h" -class MemTraceReader; - -// Global singleton instance of MemTraceReader -static std::unique_ptr reader; - -struct MemTraceLine { - bool valid = false; - unsigned long cycle = 0; - char loadstore[10]; - int core_id = 0; - int thread_id = 0; - unsigned long address = 0; - unsigned long data = 0; - int data_size = 0; -}; - -class MemTraceReader { -public: - MemTraceReader(const std::string &filename) { - char cwd[4096]; - if (getcwd(cwd, sizeof(cwd))) { - printf("MemTraceReader: current working dir: %s\n", cwd); - } - - infile.open(filename); - if (infile.fail()) { - fprintf(stderr, "failed to open file %s\n", filename); - } +MemTraceReader::MemTraceReader(const std::string &filename) { + char cwd[4096]; + if (getcwd(cwd, sizeof(cwd))) { + printf("MemTraceReader: current working dir: %s\n", cwd); } - ~MemTraceReader() { - infile.close(); - printf("MemTraceReader destroyed\n"); + + infile.open(filename); + if (infile.fail()) { + fprintf(stderr, "failed to open file %s\n", filename.c_str()); } - MemTraceLine tick(); +} - std::ifstream infile; -}; +MemTraceReader::~MemTraceReader() { + infile.close(); + printf("MemTraceReader destroyed\n"); +} -MemTraceLine MemTraceReader::tick() { +// Parse trace file in its entirety and store it into internal structure. +// TODO: might block for a long time when the trace gets big, check if need to +// be broken down +void MemTraceReader::parse() { MemTraceLine line; printf("MemTraceReader: started parsing\n"); @@ -60,9 +44,9 @@ MemTraceLine MemTraceReader::tick() { 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. +// 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. MemTraceLine MemTraceReader::read_trace_at(const long cycle, const int thread_id) { MemTraceLine line; @@ -75,16 +59,14 @@ MemTraceLine MemTraceReader::read_trace_at(const long cycle, } line = *read_pos; - // It should always be guaranteed that we consumed all of the past lines, and - // the next line is in the future. + // It should always be guaranteed that the next line is not read yet. 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. + // It's not ready to read this line yet. return MemTraceLine{}; } else if (line.cycle == cycle) { printf("fire! cycle=%ld, valid=%d\n", cycle, line.valid); @@ -99,11 +81,13 @@ MemTraceLine MemTraceReader::read_trace_at(const long cycle, } extern "C" void memtrace_init(const char *filename) { - reader = std::make_unique(filename); printf("memtrace_init: filename=[%s]\n", filename); + + reader = std::make_unique(filename); + // parse file upfront + 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, @@ -113,9 +97,16 @@ extern "C" void memtrace_query(unsigned char trace_read_ready, printf("memtrace_query(cycle=%ld, tid=%d)\n", trace_read_cycle, trace_read_thread_id); + if (!trace_read_ready) { + return; + } + + auto line = reader->read_trace_at(trace_read_cycle, trace_read_thread_id); *trace_read_valid = line.valid; - *trace_read_cycle = line.cycle; *trace_read_address = line.address; + // This means finished and valid will go up at the same cycle. Need to + // handle this without skipping the last line. + *trace_read_finished = reader->finished(); return; } diff --git a/src/main/resources/csrc/SimMemTrace.h b/src/main/resources/csrc/SimMemTrace.h new file mode 100644 index 0000000..2f45b8d --- /dev/null +++ b/src/main/resources/csrc/SimMemTrace.h @@ -0,0 +1,40 @@ +#include +#include +#include + +class MemTraceReader; + +// Global singleton instance of MemTraceReader +static std::unique_ptr reader; + +struct MemTraceLine { + bool valid = false; + long cycle = 0; + char loadstore[10]; + int core_id = 0; + int thread_id = 0; + unsigned long address = 0; + unsigned long data = 0; + int data_size = 0; +}; + +class MemTraceReader { +public: + MemTraceReader(const std::string &filename); + ~MemTraceReader(); + void parse(); + MemTraceLine read_trace_at(const long cycle, const int thread_id); + bool finished() const { return read_pos == trace.cend(); } + + std::ifstream infile; + std::vector trace; + std::vector::const_iterator read_pos; +}; + +extern "C" void memtrace_init(const char *filename); +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); diff --git a/src/main/resources/vsrc/SimMemTrace.v b/src/main/resources/vsrc/SimMemTrace.v index da9238d..19960db 100644 --- a/src/main/resources/vsrc/SimMemTrace.v +++ b/src/main/resources/vsrc/SimMemTrace.v @@ -1,65 +1,103 @@ `define DATA_WIDTH 64 +`define MAX_NUM_THREADS 32 import "DPI-C" function void memtrace_init( - input string filename + input string filename ); -import "DPI-C" function void memtrace_tick +// Make sure to sync the parameters for: +// (1) import "DPI-C" declaration +// (2) C function declaration +// (3) DPI function calls inside initial/always blocks +import "DPI-C" function void memtrace_query ( - output bit trace_read_valid, - input bit trace_read_ready, - output longint trace_read_cycle, - output longint trace_read_address + input bit trace_read_ready, + input longint trace_read_cycle, + input int trace_read_tid, + output bit trace_read_valid, + output longint trace_read_address, + output bit trace_read_finished ); -module SimMemTrace ( - input clock, - input reset, +module SimMemTrace #(parameter NUM_THREADS = 4) ( + input clock, + input reset, - output trace_read_valid, - input trace_read_ready, - output [`DATA_WIDTH-1:0] trace_read_cycle, - output [`DATA_WIDTH-1:0] trace_read_address + // These have to match the IO port of the Chisel wrapper module. + input trace_read_ready, + output [NUM_THREADS-1:0] trace_read_valid, + output [`DATA_WIDTH*NUM_THREADS-1:0] trace_read_address, + output trace_read_finished ); + bit __in_valid[NUM_THREADS-1:0]; + longint __in_address[NUM_THREADS-1:0]; + bit __in_finished; + string __uartlog; - bit __in_valid; - longint __in_cycle; - longint __in_address; - string __uartlog; - int __uartno; + // Cycle counter that is used to query C parser whether we have a request + // coming in at the current cycle. + reg [`DATA_WIDTH-1:0] cycle_counter; + wire [`DATA_WIDTH-1:0] next_cycle_counter; + assign next_cycle_counter = cycle_counter + 1'b1; - initial begin - $value$plusargs("uartlog=%s", __uartlog); - memtrace_init("vecadd.core1.thread4.trace"); + // registers that stage outputs of the C parser + reg [NUM_THREADS-1:0] __in_valid_reg; + reg [`DATA_WIDTH-1:0] __in_address_reg [NUM_THREADS-1:0]; + reg __in_finished_reg; + + genvar g; + + generate + for (g = 0; g < NUM_THREADS; g = g + 1) begin + assign trace_read_valid[g] = __in_valid_reg[g]; + assign trace_read_address[`DATA_WIDTH*(g+1)-1:`DATA_WIDTH*g] = __in_address_reg[g]; end + endgenerate + assign trace_read_finished = __in_finished_reg; - reg __in_valid_reg; - reg [`DATA_WIDTH-1:0] __in_cycle_reg; - reg [`DATA_WIDTH-1:0] __in_address_reg; + initial begin + /* $value$plusargs("uartlog=%s", __uartlog); */ + memtrace_init("vecadd.core1.thread4.trace"); + end - assign trace_read_valid = __in_valid_reg; - assign trace_read_cycle = __in_cycle_reg; - assign trace_read_address = __in_address_reg; + // Evaluate the signals on the positive edge + always @(posedge clock) begin + if (reset) begin + for (integer tid = 0; tid < NUM_THREADS; tid = tid + 1) begin + __in_valid[tid] = 1'b0; + __in_address[tid] = `DATA_WIDTH'b0; + end + __in_finished = 1'b0; - // Evaluate the signals on the positive edge - always @(posedge clock) begin - if (reset) begin - __in_valid = 1'b0; + cycle_counter <= `DATA_WIDTH'b0; - __in_valid_reg <= 1'b0; - __in_cycle_reg <= `DATA_WIDTH'b0; - end else begin - memtrace_tick( - __in_valid, - trace_read_ready, - __in_cycle, - __in_address - ); + for (integer tid = 0; tid < NUM_THREADS; tid = tid + 1) begin + __in_valid_reg[tid] <= 1'b0; + __in_address_reg[tid] <= `DATA_WIDTH'b0; + end + __in_finished_reg <= 1'b0; + end else begin + cycle_counter <= next_cycle_counter; - __in_valid_reg <= __in_valid; - __in_cycle_reg <= __in_cycle; - __in_address_reg <= __in_address; - end + for (integer tid = 0; tid < NUM_THREADS; tid = tid + 1) begin + memtrace_query( + trace_read_ready, + // Since parsed results are latched to the output on the next + // cycle due to staging registers, we need to pass in the next cycle + // to sync up. + next_cycle_counter, + tid, + __in_valid[tid], + __in_address[tid], + __in_finished + ); + end + + for (integer tid = 0; tid < NUM_THREADS; tid = tid + 1) begin + __in_valid_reg[tid] <= __in_valid[tid]; + __in_address_reg[tid] <= __in_address[tid]; + end + __in_finished_reg <= __in_finished; end - + end endmodule diff --git a/src/main/scala/tilelink/Coalescing.scala b/src/main/scala/tilelink/Coalescing.scala index 59dbc0f..c7d61d4 100644 --- a/src/main/scala/tilelink/Coalescing.scala +++ b/src/main/scala/tilelink/Coalescing.scala @@ -159,6 +159,7 @@ class SimMemTrace(val trace_file: String, num_threads: Int) extends BlackBox(Map addResource("/vsrc/SimMemTrace.v") addResource("/csrc/SimMemTrace.cc") + addResource("/csrc/SimMemTrace.h") }