From e40b7f0b8b41cb82ad4f6cdd1e44b7d9b4ed396d Mon Sep 17 00:00:00 2001 From: Hansung Kim Date: Sun, 28 May 2023 22:15:32 -0700 Subject: [PATCH] Support receiving trace filename from VPI for loggers Useful for testing with different memtraces without having to recompile design. This worked before for the trace driver but not for trace logger. Usage: make CONFIG=MemtraceCoreConfig run-binary-debug BINARY=none \ EXTRA_SIM_FLAGS="+memtracefile=nvbit.vecadd.n100000.filter_sm0.lane4.broken.trace" --- src/main/resources/csrc/SimMemTrace.cc | 12 +++++++++--- src/main/resources/csrc/SimMemTrace.h | 5 ++++- src/main/resources/csrc/SimMemTraceLogger.cc | 11 ++++++++--- src/main/resources/vsrc/SimMemTraceLogger.v | 8 +++++--- src/main/scala/tilelink/Coalescing.scala | 15 ++++++++++----- 5 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/main/resources/csrc/SimMemTrace.cc b/src/main/resources/csrc/SimMemTrace.cc index f217374..7a3dc84 100644 --- a/src/main/resources/csrc/SimMemTrace.cc +++ b/src/main/resources/csrc/SimMemTrace.cc @@ -10,7 +10,10 @@ #include #include "SimMemTrace.h" -// Global singleton instance +// Single driver trace file used across the simulation. +// Currently doesn't support multiple driver traces. +std::string tracefilename{}; +// Global singleton reader instance static std::unique_ptr reader; MemTraceReader::MemTraceReader(const std::string &filename) @@ -72,8 +75,6 @@ void MemTraceReader::parse(const bool has_source) { error(fileline, "failed parsing address..size"); } if (infile.get() != '\n') { - printf("Error: trailing characters at the end of the line\n"); - printf("this could also occur if the last line is not an empty line"); error(fileline, "trailing characters at the end of the line"); } @@ -156,6 +157,7 @@ MemTraceLine MemTraceReader::read_trace_at(const long cycle, const int lane_id, extern "C" void memtrace_init(const char *filename, bool has_source) { #ifndef NO_VPI + // If VPI option is given, override filename set from Chisel/Verilog. s_vpi_vlog_info info; if (!vpi_get_vlog_info(&info)) { fprintf(stderr, "fatal: failed to get plusargs from VCS\n"); @@ -166,6 +168,8 @@ extern "C" void memtrace_init(const char *filename, bool has_source) { char *input_arg = info.argv[i]; if (strncmp(input_arg, TRACEFILENAME_PLUSARG, strlen(TRACEFILENAME_PLUSARG)) == 0) { + printf( + "memtrace_init: +memtracefile given, overriding Verilog parameter\n"); filename = input_arg + strlen(TRACEFILENAME_PLUSARG); break; } @@ -174,6 +178,8 @@ extern "C" void memtrace_init(const char *filename, bool has_source) { printf("memtrace_init: filename=[%s]\n", filename); + tracefilename = filename; + reader = std::make_unique(filename); // parse file upfront // driver trace file is assumed to not have source id diff --git a/src/main/resources/csrc/SimMemTrace.h b/src/main/resources/csrc/SimMemTrace.h index 0f9126c..987aaa8 100644 --- a/src/main/resources/csrc/SimMemTrace.h +++ b/src/main/resources/csrc/SimMemTrace.h @@ -2,6 +2,8 @@ #include #include +extern std::string tracefilename; + struct MemTraceLine { bool valid = false; long cycle = 0; @@ -54,7 +56,8 @@ 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" int memtracelogger_init(int is_response, const char *filename); +extern "C" int memtracelogger_init(int is_response, const char *filename, + const char *filename_suffix); extern "C" void memtracelogger_log(int handle, unsigned char trace_log_valid, unsigned long trace_log_cycle, diff --git a/src/main/resources/csrc/SimMemTraceLogger.cc b/src/main/resources/csrc/SimMemTraceLogger.cc index 3963417..2707b7a 100644 --- a/src/main/resources/csrc/SimMemTraceLogger.cc +++ b/src/main/resources/csrc/SimMemTraceLogger.cc @@ -41,8 +41,10 @@ void MemTraceWriter::write_line_to_trace(const MemTraceLine line) { } // Returns the "handle" ID for this particular logger instance. -extern "C" int memtracelogger_init(int is_response, const char *filename) { +extern "C" int memtracelogger_init(int is_response, const char *filename, + const char *filename_suffix) { #ifndef NO_VPI + // If VPI option is given, override filename set from Chisel/Verilog. s_vpi_vlog_info info; if (!vpi_get_vlog_info(&info)) { fprintf(stderr, "fatal: failed to get plusargs from VCS\n"); @@ -59,12 +61,15 @@ extern "C" int memtracelogger_init(int is_response, const char *filename) { } #endif + auto fullfilename = std::string{filename} + std::string{filename_suffix}; + int handle = loggers.size(); - loggers.emplace_back(std::make_unique(is_response, filename)); + loggers.emplace_back( + std::make_unique(is_response, fullfilename)); loggers.back()->handle = handle; printf("memtracelogger_init: handle=%d, is_response=%d, filename=[%s]\n", - handle, is_response, filename); + handle, is_response, fullfilename.c_str()); return handle; } diff --git a/src/main/resources/vsrc/SimMemTraceLogger.v b/src/main/resources/vsrc/SimMemTraceLogger.v index 3ffa794..03839df 100644 --- a/src/main/resources/vsrc/SimMemTraceLogger.v +++ b/src/main/resources/vsrc/SimMemTraceLogger.v @@ -6,7 +6,8 @@ import "DPI-C" function int memtracelogger_init( input bit is_response, - input string filename + input string filename, + input string filename_suffix ); // Make sure to sync the parameters for: @@ -29,7 +30,8 @@ import "DPI-C" function void memtracelogger_log module SimMemTraceLogger #(parameter IS_RESPONSE = 0, - FILENAME = "undefined", + FILENAME_BASE = "undefined", + FILENAME_SUFFIX = ".log", NUM_LANES = 4) ( input clock, input reset, @@ -77,7 +79,7 @@ module SimMemTraceLogger #(parameter initial begin /* $value$plusargs("uartlog=%s", __uartlog); */ - logger_handle = memtracelogger_init(IS_RESPONSE, FILENAME); + logger_handle = memtracelogger_init(IS_RESPONSE, FILENAME_BASE, FILENAME_SUFFIX); end always @(posedge clock) begin diff --git a/src/main/scala/tilelink/Coalescing.scala b/src/main/scala/tilelink/Coalescing.scala index f0ac6a6..dc68b2a 100644 --- a/src/main/scala/tilelink/Coalescing.scala +++ b/src/main/scala/tilelink/Coalescing.scala @@ -1615,11 +1615,11 @@ class MemTraceLogger( val simReq = if (reqEnable) - Some(Module(new SimMemTraceLogger(false, s"${filename}.${loggerName}.req", numLanes))) + Some(Module(new SimMemTraceLogger(false, s"${filename}", s".${loggerName}.req", numLanes))) else None val simResp = if (respEnable) - Some(Module(new SimMemTraceLogger(true, s"${filename}.${loggerName}.resp", numLanes))) + Some(Module(new SimMemTraceLogger(true, s"${filename}", s".${loggerName}.resp", numLanes))) else None if (simReq.isDefined) { simReq.get.io.clock := clock @@ -1787,11 +1787,16 @@ class MemTraceLogger( // itself whether it's logging the request stream or the response stream. This // is necessary because we have to generate slightly different trace format // depending on this, e.g. response trace will not contain an address column. -class SimMemTraceLogger(isResponse: Boolean, filename: String, numLanes: Int) - extends BlackBox( +class SimMemTraceLogger( + isResponse: Boolean, + filenameBase: String, // usually the same as `filename` of SimMemTrace + filenameSuffix: String, // can be ".req", ".resp", .etc + numLanes: Int +) extends BlackBox( Map( "IS_RESPONSE" -> (if (isResponse) 1 else 0), - "FILENAME" -> filename, + "FILENAME_BASE" -> filenameBase, + "FILENAME_SUFFIX" -> filenameSuffix, "NUM_LANES" -> numLanes ) )