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"
This commit is contained in:
Hansung Kim
2023-05-28 22:15:32 -07:00
parent af01e39b5a
commit e40b7f0b8b
5 changed files with 36 additions and 15 deletions

View File

@@ -10,7 +10,10 @@
#include <unistd.h> #include <unistd.h>
#include "SimMemTrace.h" #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<MemTraceReader> reader; static std::unique_ptr<MemTraceReader> reader;
MemTraceReader::MemTraceReader(const std::string &filename) MemTraceReader::MemTraceReader(const std::string &filename)
@@ -72,8 +75,6 @@ void MemTraceReader::parse(const bool has_source) {
error(fileline, "failed parsing address..size"); error(fileline, "failed parsing address..size");
} }
if (infile.get() != '\n') { 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"); 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) { extern "C" void memtrace_init(const char *filename, bool has_source) {
#ifndef NO_VPI #ifndef NO_VPI
// If VPI option is given, override filename set from Chisel/Verilog.
s_vpi_vlog_info info; s_vpi_vlog_info info;
if (!vpi_get_vlog_info(&info)) { if (!vpi_get_vlog_info(&info)) {
fprintf(stderr, "fatal: failed to get plusargs from VCS\n"); 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]; char *input_arg = info.argv[i];
if (strncmp(input_arg, TRACEFILENAME_PLUSARG, if (strncmp(input_arg, TRACEFILENAME_PLUSARG,
strlen(TRACEFILENAME_PLUSARG)) == 0) { strlen(TRACEFILENAME_PLUSARG)) == 0) {
printf(
"memtrace_init: +memtracefile given, overriding Verilog parameter\n");
filename = input_arg + strlen(TRACEFILENAME_PLUSARG); filename = input_arg + strlen(TRACEFILENAME_PLUSARG);
break; break;
} }
@@ -174,6 +178,8 @@ extern "C" void memtrace_init(const char *filename, bool has_source) {
printf("memtrace_init: filename=[%s]\n", filename); printf("memtrace_init: filename=[%s]\n", filename);
tracefilename = filename;
reader = std::make_unique<MemTraceReader>(filename); reader = std::make_unique<MemTraceReader>(filename);
// parse file upfront // parse file upfront
// driver trace file is assumed to not have source id // driver trace file is assumed to not have source id

View File

@@ -2,6 +2,8 @@
#include <memory> #include <memory>
#include <fstream> #include <fstream>
extern std::string tracefilename;
struct MemTraceLine { struct MemTraceLine {
bool valid = false; bool valid = false;
long cycle = 0; long cycle = 0;
@@ -54,7 +56,8 @@ extern "C" void memtrace_query(unsigned char trace_read_ready,
int *trace_read_size, int *trace_read_size,
unsigned long *trace_read_data, unsigned long *trace_read_data,
unsigned char *trace_read_finished); 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, extern "C" void memtracelogger_log(int handle,
unsigned char trace_log_valid, unsigned char trace_log_valid,
unsigned long trace_log_cycle, unsigned long trace_log_cycle,

View File

@@ -41,8 +41,10 @@ void MemTraceWriter::write_line_to_trace(const MemTraceLine line) {
} }
// Returns the "handle" ID for this particular logger instance. // 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 #ifndef NO_VPI
// If VPI option is given, override filename set from Chisel/Verilog.
s_vpi_vlog_info info; s_vpi_vlog_info info;
if (!vpi_get_vlog_info(&info)) { if (!vpi_get_vlog_info(&info)) {
fprintf(stderr, "fatal: failed to get plusargs from VCS\n"); 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 #endif
auto fullfilename = std::string{filename} + std::string{filename_suffix};
int handle = loggers.size(); int handle = loggers.size();
loggers.emplace_back(std::make_unique<MemTraceWriter>(is_response, filename)); loggers.emplace_back(
std::make_unique<MemTraceWriter>(is_response, fullfilename));
loggers.back()->handle = handle; loggers.back()->handle = handle;
printf("memtracelogger_init: handle=%d, is_response=%d, filename=[%s]\n", printf("memtracelogger_init: handle=%d, is_response=%d, filename=[%s]\n",
handle, is_response, filename); handle, is_response, fullfilename.c_str());
return handle; return handle;
} }

View File

@@ -6,7 +6,8 @@
import "DPI-C" function int memtracelogger_init( import "DPI-C" function int memtracelogger_init(
input bit is_response, input bit is_response,
input string filename input string filename,
input string filename_suffix
); );
// Make sure to sync the parameters for: // Make sure to sync the parameters for:
@@ -29,7 +30,8 @@ import "DPI-C" function void memtracelogger_log
module SimMemTraceLogger #(parameter module SimMemTraceLogger #(parameter
IS_RESPONSE = 0, IS_RESPONSE = 0,
FILENAME = "undefined", FILENAME_BASE = "undefined",
FILENAME_SUFFIX = ".log",
NUM_LANES = 4) ( NUM_LANES = 4) (
input clock, input clock,
input reset, input reset,
@@ -77,7 +79,7 @@ module SimMemTraceLogger #(parameter
initial begin initial begin
/* $value$plusargs("uartlog=%s", __uartlog); */ /* $value$plusargs("uartlog=%s", __uartlog); */
logger_handle = memtracelogger_init(IS_RESPONSE, FILENAME); logger_handle = memtracelogger_init(IS_RESPONSE, FILENAME_BASE, FILENAME_SUFFIX);
end end
always @(posedge clock) begin always @(posedge clock) begin

View File

@@ -1615,11 +1615,11 @@ class MemTraceLogger(
val simReq = val simReq =
if (reqEnable) 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 else None
val simResp = val simResp =
if (respEnable) 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 else None
if (simReq.isDefined) { if (simReq.isDefined) {
simReq.get.io.clock := clock simReq.get.io.clock := clock
@@ -1787,11 +1787,16 @@ class MemTraceLogger(
// itself whether it's logging the request stream or the response stream. This // itself whether it's logging the request stream or the response stream. This
// is necessary because we have to generate slightly different trace format // is necessary because we have to generate slightly different trace format
// depending on this, e.g. response trace will not contain an address column. // depending on this, e.g. response trace will not contain an address column.
class SimMemTraceLogger(isResponse: Boolean, filename: String, numLanes: Int) class SimMemTraceLogger(
extends BlackBox( isResponse: Boolean,
filenameBase: String, // usually the same as `filename` of SimMemTrace
filenameSuffix: String, // can be ".req", ".resp", .etc
numLanes: Int
) extends BlackBox(
Map( Map(
"IS_RESPONSE" -> (if (isResponse) 1 else 0), "IS_RESPONSE" -> (if (isResponse) 1 else 0),
"FILENAME" -> filename, "FILENAME_BASE" -> filenameBase,
"FILENAME_SUFFIX" -> filenameSuffix,
"NUM_LANES" -> numLanes "NUM_LANES" -> numLanes
) )
) )