diff --git a/src/main/resources/csrc/SimMemTrace.cc b/src/main/resources/csrc/SimMemTrace.cc index 8a636a7..99bf113 100644 --- a/src/main/resources/csrc/SimMemTrace.cc +++ b/src/main/resources/csrc/SimMemTrace.cc @@ -3,13 +3,16 @@ #include #endif #include -#include +#include #include #include #include #include #include "SimMemTrace.h" +// Global singleton instance +static std::unique_ptr reader; + MemTraceReader::MemTraceReader(const std::string &filename) { char cwd[4096]; if (getcwd(cwd, sizeof(cwd))) { @@ -36,11 +39,14 @@ void MemTraceReader::parse() { printf("MemTraceReader: started parsing\n"); long size = 0; - while (infile >> line.cycle >> line.loadstore >> line.core_id >> + std::string loadstore; // FIXME: likely slow + while (infile >> line.cycle >> loadstore >> line.core_id >> line.lane_id >> std::hex >> line.address >> line.data >> std::dec >> size) { line.valid = true; + line.is_store = (loadstore == "STORE"); + assert(size > 0 && "invalid size in trace"); int lgsize = static_cast(log2(size)); assert((size & ~(~0lu << lgsize)) == 0 && @@ -84,8 +90,9 @@ MemTraceLine MemTraceReader::read_trace_at(const long cycle, // read it right now. return MemTraceLine{}; } else if (line.cycle == cycle && line.lane_id == lane_id) { - printf("fire! cycle=%ld, valid=%d, %s addr=%lx, size=%d \n", cycle, line.valid, - line.loadstore, line.address, line.log_data_size); + printf("fire! cycle=%ld, valid=%d, %s addr=%lx, size=%d \n", cycle, + line.valid, (line.is_store ? "STORE" : "LOAD"), line.address, + line.log_data_size); // FIXME! Currently lane_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 @@ -145,7 +152,7 @@ extern "C" void memtrace_query(unsigned char trace_read_ready, auto line = reader->read_trace_at(trace_read_cycle, trace_read_lane_id); *trace_read_valid = line.valid; *trace_read_address = line.address; - *trace_read_is_store = (strcmp(line.loadstore, "STORE") == 0); + *trace_read_is_store = line.is_store; *trace_read_size = line.log_data_size; *trace_read_data = line.data; // This means finished and valid will go up at the same cycle. Need to diff --git a/src/main/resources/csrc/SimMemTrace.h b/src/main/resources/csrc/SimMemTrace.h index 14045b5..b45fea4 100644 --- a/src/main/resources/csrc/SimMemTrace.h +++ b/src/main/resources/csrc/SimMemTrace.h @@ -2,15 +2,10 @@ #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]; + bool is_store = 0; int core_id = 0; int lane_id = 0; unsigned long address = 0; @@ -31,6 +26,19 @@ public: std::vector::const_iterator read_pos; }; +class MemTraceWriter { +public: + MemTraceWriter(const std::string &filename); + ~MemTraceWriter(); + // void parse(); + void write_trace_at(const MemTraceLine line); + // bool finished() const { return read_pos == trace.cend(); } + + FILE *outfile; + // 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, @@ -41,3 +49,12 @@ extern "C" void memtrace_query(unsigned char trace_read_ready, int *trace_read_size, unsigned long *trace_read_data, unsigned char *trace_read_finished); +extern "C" void memtracelogger_init(const char *filename); +extern "C" void memtracelogger_log(unsigned char trace_log_valid, + unsigned long trace_log_cycle, + unsigned long trace_log_address, + int trace_log_lane_id, + unsigned char trace_log_is_store, + int trace_log_size, + unsigned long trace_log_data, + unsigned char *trace_log_ready); diff --git a/src/main/resources/csrc/SimMemTraceLogger.cc b/src/main/resources/csrc/SimMemTraceLogger.cc index b685e83..52de1f7 100644 --- a/src/main/resources/csrc/SimMemTraceLogger.cc +++ b/src/main/resources/csrc/SimMemTraceLogger.cc @@ -8,95 +8,34 @@ #include #include #include -#include "SimMemTraceLogger.h" +#include "SimMemTrace.h" // Global singleton instance -static std::unique_ptr logger; +static std::unique_ptr logger; -MemTraceLogger::MemTraceLogger(const std::string &filename) { +MemTraceWriter::MemTraceWriter(const std::string &filename) { char cwd[4096]; if (getcwd(cwd, sizeof(cwd))) { printf("MemTraceLogger: current working dir: %s\n", cwd); } - infile.open(filename); - if (infile.fail()) { + outfile = fopen(filename.c_str(), "w"); + if (!outfile) { fprintf(stderr, "failed to open file %s\n", filename.c_str()); } } -MemTraceLogger::~MemTraceLogger() { - infile.close(); - printf("MemTraceLogger destroyed\n"); +MemTraceWriter::~MemTraceWriter() { + fclose(outfile); + printf("MemTraceWriter destroyed\n"); } -#if 0 -// 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 MemTraceLogger::parse() { - MemTraceLine line; +void MemTraceWriter::write_trace_at(const MemTraceLine line) { + printf("tick(): cycle=%ld\n", line.cycle); - printf("MemTraceLogger: started parsing\n"); - - while (infile >> line.cycle >> line.loadstore >> line.core_id >> - line.lane_id >> std::hex >> line.address >> line.data >> std::dec >> - line.data_size) { - line.valid = true; - trace.push_back(line); - } - read_pos = trace.cbegin(); - - printf("MemTraceLogger: finished parsing\n"); + fprintf(outfile, "cycle=%ld\n", line.cycle); } -// 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 MemTraceLogger::read_trace_at(const long cycle, - const int lane_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.lane_id != lane_id) { - line.valid = false; - } - 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 && line.lane_id == lane_id) { - printf("fire! cycle=%ld, valid=%d, %s addr=%x \n", cycle, line.valid, - line.loadstore, line.address); - - // FIXME! Currently lane_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. - - // Only advance pointer when cycle and threa_id both match - // now increaseing sequence is fine (0, 1, 3), but unordered is not fine (0, 3, 1) - ++read_pos; - } - - return line; -} -#endif - extern "C" void memtracelogger_init(const char *filename) { #ifndef NO_VPI s_vpi_vlog_info info; @@ -117,7 +56,7 @@ extern "C" void memtracelogger_init(const char *filename) { printf("memtrace_init: filename=[%s]\n", filename); - logger = std::make_unique(filename); + logger = std::make_unique(filename); } // TODO: accept core_id as well @@ -133,9 +72,22 @@ extern "C" void memtracelogger_log(unsigned char trace_log_valid, // trace_read_lane_id); *trace_log_ready = 1; - if (trace_log_valid) { - printf("%s: [%lu] valid: address=%lx, tid=%u, size=%d\n", __func__, - trace_log_cycle, trace_log_address, trace_log_lane_id, - trace_log_size); + if (!trace_log_valid) { + return; } + + printf("%s: [%lu] valid: address=%lx, tid=%u, size=%d\n", __func__, + trace_log_cycle, trace_log_address, trace_log_lane_id, + trace_log_size); + + MemTraceLine line{.valid = (trace_log_valid == 1), + .cycle = static_cast(trace_log_cycle), + .is_store = (trace_log_is_store == 1), + .core_id = 0, // TODO support multicores + .lane_id = trace_log_lane_id, + .address = trace_log_address, + .data = trace_log_data, + .log_data_size = trace_log_size}; + + logger->write_trace_at(line); } diff --git a/src/main/scala/tilelink/Coalescing.scala b/src/main/scala/tilelink/Coalescing.scala index 9d0adc1..2cfc950 100644 --- a/src/main/scala/tilelink/Coalescing.scala +++ b/src/main/scala/tilelink/Coalescing.scala @@ -741,7 +741,7 @@ class SimMemTrace(filename: String, numLanes: Int) addResource("/csrc/SimMemTrace.h") } -class MemTraceLogger(numLanes: Int = 4, filename: String = "vecadd.core1.thread4.trace")(implicit +class MemTraceLogger(numLanes: Int = 4, filename: String = "vecadd.core1.thread4.out.trace")(implicit p: Parameters ) extends LazyModule { val node = TLIdentityNode() @@ -882,7 +882,7 @@ class SimMemTraceLogger(filename: String, numLanes: Int) addResource("/vsrc/SimMemTraceLogger.v") addResource("/csrc/SimMemTraceLogger.cc") - addResource("/csrc/SimMemTraceLogger.h") + addResource("/csrc/SimMemTrace.h") } class TracePrintf {}