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 "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;
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<MemTraceReader>(filename);
// parse file upfront
// driver trace file is assumed to not have source id

View File

@@ -2,6 +2,8 @@
#include <memory>
#include <fstream>
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,

View File

@@ -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<MemTraceWriter>(is_response, filename));
loggers.emplace_back(
std::make_unique<MemTraceWriter>(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;
}

View File

@@ -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

View File

@@ -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
)
)