From e64cb7a282f9e7176740c1fdc274d7abca33b1ec Mon Sep 17 00:00:00 2001 From: Hansung Kim Date: Sat, 6 May 2023 23:13:45 -0700 Subject: [PATCH] Backport SimMemTrace: enable parsing source, report errors --- src/main/resources/csrc/SimMemTrace.cc | 78 +++++++++++++++++++------- src/main/resources/csrc/SimMemTrace.h | 12 +++- 2 files changed, 66 insertions(+), 24 deletions(-) diff --git a/src/main/resources/csrc/SimMemTrace.cc b/src/main/resources/csrc/SimMemTrace.cc index ca411b2..0b6635d 100644 --- a/src/main/resources/csrc/SimMemTrace.cc +++ b/src/main/resources/csrc/SimMemTrace.cc @@ -13,7 +13,8 @@ // Global singleton instance static std::unique_ptr reader; -MemTraceReader::MemTraceReader(const std::string &filename) { +MemTraceReader::MemTraceReader(const std::string &filename) + : filename(filename) { char cwd[4096]; if (getcwd(cwd, sizeof(cwd))) { printf("MemTraceReader: current working dir: %s\n", cwd); @@ -30,32 +31,64 @@ MemTraceReader::~MemTraceReader() { printf("MemTraceReader destroyed\n"); } -// Parse trace file in its entirety and store it into internal structure. +void MemTraceReader::error(long fileline, const std::string &msg) { + fprintf(stderr, "parse error at %s:%ld: %s\n", filename.c_str(), fileline, + msg.c_str()); + exit(EXIT_FAILURE); +} + +// Parse trace file in its entirety and store it into an internal structure. +// If `has_source` is true, assumes the trace has an additional column after +// core and lane_id for source id and tries to parse that. // TODO: might block for a long time when the trace gets big, check if need to // be broken down -void MemTraceReader::parse() { +void MemTraceReader::parse(const bool has_source) { MemTraceLine line; printf("MemTraceReader: started parsing\n"); long size = 0; - 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) { + long source = 0; + std::string loadstore; // slow? + for (long fileline = 1;; fileline++) { + if (infile.peek() == '\n') { + infile.get(); + continue; + } + if (infile.eof()) { + break; + } + + if (!(infile >> line.cycle >> loadstore >> line.core_id >> line.lane_id)) { + printf("char=[%c]\n", infile.peek()); + // assert(!infile.eof()); + error(fileline, "failed parsing cycle..lane_id"); + } + if (has_source && !(infile >> source)) { + error(fileline, "failed parsing source"); + } + if (!(infile >> std::hex >> line.address >> line.data >> std::dec >> + size)) { + error(fileline, "failed parsing address..size"); + } + if (infile.get() != '\n') { + error(fileline, "trailing characters at the end of the line"); + } + line.valid = true; - line.is_store = (loadstore == "STORE"); - - assert(size > 0 && "invalid size in trace"); + if (size <= 0) { + error(fileline, "invalid size in trace"); + } int lgsize = static_cast(log2(size)); - assert((size & ~(~0lu << lgsize)) == 0 && - "non-power-of-2 size detected in trace"); + if ((size & ~(~0lu << lgsize)) != 0) { + error(fileline, "non-power-of-2 size detected in trace"); + } line.log_data_size = lgsize; - trace.push_back(line); + trace_buf.push_back(line); } - read_pos = trace.cbegin(); + read_pos = trace_buf.cbegin(); printf("MemTraceReader: finished parsing\n"); } @@ -90,7 +123,6 @@ MemTraceLine MemTraceReader::read_trace_at(const long cycle, const int lane_id, } else if (line.lane_id != lane_id) { return MemTraceLine{}; } else if (line.cycle == cycle && line.lane_id == lane_id) { - if (trace_read_ready) { printf("Fire! cycle=%ld, valid=%d, %s addr=%lx, size=%d \n", cycle, line.valid, (line.is_store ? "STORE" : "LOAD"), line.address, @@ -102,11 +134,14 @@ MemTraceLine MemTraceReader::read_trace_at(const long cycle, const int lane_id, // monotonically increment read_pos. lane_id need not be contiguous, e.g. // 0->1->3 is fine. ++read_pos; - } else { // we do not want to advance read_pos + return line; + } else { + // For debugging purposes, instead of early-returning on + // !trace_read_ready, print something to notify we are blocking a valid + // trace line. printf("All Lanes Blocked on this cycle! cycle=%ld \n", cycle); + return MemTraceLine{}; } - - return line; } assert(!"unreachable"); @@ -119,9 +154,9 @@ extern "C" void memtrace_init(const char *filename) { fprintf(stderr, "fatal: failed to get plusargs from VCS\n"); exit(1); } - const char* TRACEFILENAME_PLUSARG = "+memtracefile="; + const char *TRACEFILENAME_PLUSARG = "+memtracefile="; for (int i = 0; i < info.argc; i++) { - char* input_arg = info.argv[i]; + char *input_arg = info.argv[i]; if (strncmp(input_arg, TRACEFILENAME_PLUSARG, strlen(TRACEFILENAME_PLUSARG)) == 0) { filename = input_arg + strlen(TRACEFILENAME_PLUSARG); @@ -134,7 +169,8 @@ extern "C" void memtrace_init(const char *filename) { reader = std::make_unique(filename); // parse file upfront - reader->parse(); + // driver trace file is assumed to not have source id + reader->parse(false); } // TODO: accept core_id as well diff --git a/src/main/resources/csrc/SimMemTrace.h b/src/main/resources/csrc/SimMemTrace.h index 9b90918..753385e 100644 --- a/src/main/resources/csrc/SimMemTrace.h +++ b/src/main/resources/csrc/SimMemTrace.h @@ -18,12 +18,18 @@ class MemTraceReader { public: MemTraceReader(const std::string &filename); ~MemTraceReader(); - void parse(); + void parse(const bool has_source); MemTraceLine read_trace_at(const long cycle, const int lane_id, unsigned char trace_read_ready); - bool finished() const { return read_pos == trace.cend(); } + bool finished() const { return read_pos == trace_buf.cend(); } + MemTraceLine peek() const { return *read_pos; } + void next() { read_pos++; } + void error(long fileline, const std::string &msg); + const std::string filename; + +private: std::ifstream infile; - std::vector trace; + std::vector trace_buf; std::vector::const_iterator read_pos; };