Merge pull request #873 from steveicarus/steveicarus/issue202-dumpfile-cmdline
Add support for a command line dumpfile option
This commit is contained in:
commit
a4aade5d1a
|
|
@ -77,3 +77,17 @@ iverilog-args (optional)
|
|||
|
||||
If this is specified, it is a list of strings that are passed as arguments to
|
||||
the iverilog command line.
|
||||
|
||||
vvp-args (optional)
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If this is specified, it is a list of strings that are passed as arguments to
|
||||
the vvp command. These arguments go before the vvp input file that is to be
|
||||
run.
|
||||
|
||||
vvp-args-extended (optional)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If this is specified, it is a lost of strings that are passed as arguments to
|
||||
the vvp command. These are extended arguments, and are placed after the vvp
|
||||
input file that is being run. This is where you place things like plusargs.
|
||||
|
|
|
|||
|
|
@ -82,6 +82,13 @@ behavior.
|
|||
Generate LXT or LXT2format instead of VCD format waveform dumps. The LXT2
|
||||
format is more advanced.
|
||||
|
||||
* -dumpfile=<name>
|
||||
|
||||
Set the default dumpfile. If unspecified, the default is "dump". This
|
||||
command line flag allows you do change it. If no suffix is specified,
|
||||
then the suffix will be chosen based on the dump type. In any case, the
|
||||
$dumpfile system task overrides this flag.
|
||||
|
||||
SDF Support
|
||||
^^^^^^^^^^^
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
VCD info: dumpfile foo.vcd opened for output.
|
||||
ivltests/dumpfile.v:11: $finish called at 30 (1s)
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// Github Issue #202
|
||||
|
||||
module main;
|
||||
reg clk = 0;
|
||||
|
||||
initial begin
|
||||
//$dumpfile("foo"); // We really want to test the command line flag
|
||||
$dumpvars(0, main);
|
||||
#10 clk <= 1;
|
||||
#10 clk <= 0;
|
||||
#10 $finish;
|
||||
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
|
|
@ -20,6 +20,7 @@ dffsynth8 vvp_tests/dffsynth8.json
|
|||
dffsynth9 vvp_tests/dffsynth9.json
|
||||
dffsynth10 vvp_tests/dffsynth10.json
|
||||
dffsynth11 vvp_tests/dffsynth11.json
|
||||
dumpfile vvp_tests/dumpfile.json
|
||||
macro_str_esc vvp_tests/macro_str_esc.json
|
||||
memsynth1 vvp_tests/memsynth1.json
|
||||
struct_packed_write_read vvp_tests/struct_packed_write_read.json
|
||||
|
|
|
|||
|
|
@ -18,7 +18,10 @@ def assemble_iverilog_cmd(source: str, it_dir: str, args: list) -> list:
|
|||
|
||||
|
||||
def assemble_vvp_cmd(args: list = [], plusargs: list = []) -> list:
|
||||
res = ["vvp", os.path.join("work", "a.out")]
|
||||
res = ["vvp"]
|
||||
res = res + args
|
||||
res.append(os.path.join("work", "a.out"))
|
||||
res = res + plusargs
|
||||
return res
|
||||
|
||||
|
||||
|
|
@ -130,6 +133,8 @@ def do_run_normal(options : dict, expected_fail : bool) -> list:
|
|||
it_key = options['key']
|
||||
it_dir = options['directory']
|
||||
it_iverilog_args = options['iverilog_args']
|
||||
it_vvp_args = options['vvp_args']
|
||||
it_vvp_args_extended = options['vvp_args_extended']
|
||||
it_gold = options['gold']
|
||||
it_diff = options['diff']
|
||||
|
||||
|
|
@ -144,7 +149,7 @@ def do_run_normal(options : dict, expected_fail : bool) -> list:
|
|||
return [1, "Failed - Compile failed"]
|
||||
|
||||
# run the vvp command
|
||||
vvp_cmd = assemble_vvp_cmd()
|
||||
vvp_cmd = assemble_vvp_cmd(it_vvp_args, it_vvp_args_extended)
|
||||
vvp_res = subprocess.run(vvp_cmd, capture_output=True)
|
||||
log_results(it_key, "vvp", vvp_res);
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,9 @@ def process_test(item: list) -> str:
|
|||
'source' : it_dict['source'],
|
||||
'modulename' : None,
|
||||
'gold' : it_dict.get('gold', None),
|
||||
'diff' : None
|
||||
'diff' : None,
|
||||
'vvp_args' : it_dict.get('vvp-args', [ ]),
|
||||
'vvp_args_extended' : it_dict.get('vvp-args-extended', [ ])
|
||||
}
|
||||
|
||||
if it_type == "NI":
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "dumpfile.v",
|
||||
"gold" : "dumpfile",
|
||||
"vvp-args-extended" : [ "-vcd", "-dumpfile=foo" ]
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2023 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -32,7 +32,6 @@
|
|||
# include <time.h>
|
||||
# include "ivl_alloc.h"
|
||||
|
||||
static char *dump_path = NULL;
|
||||
static int dump_no_date = 0;
|
||||
static struct fstContext *dump_file = NULL;
|
||||
|
||||
|
|
@ -114,7 +113,6 @@ struct vcd_names_list_s fst_tab = { 0, 0, 0, 0 };
|
|||
struct vcd_names_list_s fst_var = { 0, 0, 0, 0 };
|
||||
|
||||
|
||||
static int dumpvars_status = 0; /* 0:fresh 1:cb installed, 2:callback done */
|
||||
static PLI_UINT64 dumpvars_time;
|
||||
__inline__ static int dump_header_pending(void)
|
||||
{
|
||||
|
|
@ -224,8 +222,7 @@ static PLI_INT32 finish_cb(p_cb_data cause)
|
|||
vcd_names_delete(&fst_tab);
|
||||
vcd_names_delete(&fst_var);
|
||||
nexus_ident_delete();
|
||||
free(dump_path);
|
||||
dump_path = 0;
|
||||
vcd_free_dump_path();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -346,18 +343,17 @@ static PLI_INT32 sys_dumpall_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
|||
|
||||
static void open_dumpfile(vpiHandle callh)
|
||||
{
|
||||
if (dump_path == 0) dump_path = strdup("dump.fst");
|
||||
char* use_dump_path = vcd_get_dump_path("fst");
|
||||
|
||||
dump_file = fstWriterCreate(dump_path, 1);
|
||||
dump_file = fstWriterCreate(use_dump_path, 1);
|
||||
|
||||
if (dump_file == 0) {
|
||||
vpi_printf("FST Error: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("Unable to open %s for output.\n", dump_path);
|
||||
vpi_printf("Unable to open %s for output.\n", use_dump_path);
|
||||
vpip_set_return_value(1);
|
||||
vpi_control(vpiFinish, 1);
|
||||
free(dump_path);
|
||||
dump_path = 0;
|
||||
vcd_free_dump_path();
|
||||
return;
|
||||
} else {
|
||||
int prec = vpi_get(vpiTimePrecision, 0);
|
||||
|
|
@ -367,7 +363,7 @@ static void open_dumpfile(vpiHandle callh)
|
|||
char scale_buf[65];
|
||||
|
||||
vpi_printf("FST info: dumpfile %s opened for output.\n",
|
||||
dump_path);
|
||||
use_dump_path);
|
||||
|
||||
time(&walltime);
|
||||
|
||||
|
|
@ -381,10 +377,10 @@ static void open_dumpfile(vpiHandle callh)
|
|||
prec -= 1;
|
||||
}
|
||||
|
||||
if (!dump_no_date)
|
||||
fstWriterSetDate(dump_file, asctime(localtime(&walltime)));
|
||||
else
|
||||
fstWriterSetDate(dump_file, "");
|
||||
if (!dump_no_date)
|
||||
fstWriterSetDate(dump_file, asctime(localtime(&walltime)));
|
||||
else
|
||||
fstWriterSetDate(dump_file, "");
|
||||
fstWriterSetVersion(dump_file, "Icarus Verilog");
|
||||
sprintf(scale_buf, "\t%u%s\n", scale, units_names[udx]);
|
||||
fstWriterSetTimescaleFromString(dump_file, scale_buf);
|
||||
|
|
@ -403,37 +399,8 @@ static void open_dumpfile(vpiHandle callh)
|
|||
|
||||
static PLI_INT32 sys_dumpfile_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||
{
|
||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
||||
char *path;
|
||||
|
||||
/* $dumpfile must be called before $dumpvars starts! */
|
||||
if (dumpvars_status != 0) {
|
||||
char msg[64];
|
||||
snprintf(msg, sizeof(msg), "FST warning: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
msg[sizeof(msg)-1] = 0;
|
||||
vpi_printf("%s %s called after $dumpvars started,\n", msg, name);
|
||||
vpi_printf("%*s using existing file (%s).\n",
|
||||
(int) strlen(msg), " ", dump_path);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
path = get_filename_with_suffix(callh, name, vpi_scan(argv), "fst");
|
||||
vpi_free_object(argv);
|
||||
if (! path) return 0;
|
||||
|
||||
if (dump_path) {
|
||||
vpi_printf("FST warning: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("Overriding dump file %s with %s.\n", dump_path, path);
|
||||
free(dump_path);
|
||||
}
|
||||
dump_path = path;
|
||||
|
||||
return 0;
|
||||
(void)name;
|
||||
return sys_dumpfile_common("FST", "fst");
|
||||
}
|
||||
|
||||
static PLI_INT32 sys_dumpflush_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2021 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2023 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -35,7 +35,6 @@
|
|||
# include "ivl_alloc.h"
|
||||
|
||||
|
||||
static char *dump_path = NULL;
|
||||
static struct lt_trace *dump_file = NULL;
|
||||
|
||||
static struct t_vpi_time zero_delay = { vpiSimTime, 0, 0, 0.0 };
|
||||
|
|
@ -197,7 +196,6 @@ static void show_this_item_x(struct vcd_info*info)
|
|||
struct vcd_names_list_s lxt_tab;
|
||||
|
||||
|
||||
static int dumpvars_status = 0; /* 0:fresh 1:cb installed, 2:callback done */
|
||||
static PLI_UINT64 dumpvars_time;
|
||||
__inline__ static int dump_header_pending(void)
|
||||
{
|
||||
|
|
@ -314,8 +312,7 @@ static PLI_INT32 finish_cb(p_cb_data cause)
|
|||
|
||||
vcd_names_delete(&lxt_tab);
|
||||
nexus_ident_delete();
|
||||
free(dump_path);
|
||||
dump_path = 0;
|
||||
vcd_free_dump_path();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -442,24 +439,23 @@ static void *close_dumpfile(void)
|
|||
|
||||
static void open_dumpfile(vpiHandle callh)
|
||||
{
|
||||
if (dump_path == 0) dump_path = strdup("dump.lxt");
|
||||
char* use_dump_path = vcd_get_dump_path("lxt");
|
||||
|
||||
dump_file = lt_init(dump_path);
|
||||
dump_file = lt_init(use_dump_path);
|
||||
|
||||
if (dump_file == 0) {
|
||||
vpi_printf("LXT Error: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("Unable to open %s for output.\n", dump_path);
|
||||
vpi_printf("Unable to open %s for output.\n", use_dump_path);
|
||||
vpip_set_return_value(1);
|
||||
vpi_control(vpiFinish, 1);
|
||||
free(dump_path);
|
||||
dump_path = 0;
|
||||
vcd_free_dump_path();
|
||||
return;
|
||||
} else {
|
||||
int prec = vpi_get(vpiTimePrecision, 0);
|
||||
|
||||
vpi_printf("LXT info: dumpfile %s opened for output.\n",
|
||||
dump_path);
|
||||
use_dump_path);
|
||||
|
||||
assert(prec >= -15);
|
||||
lt_set_timescale(dump_file, prec);
|
||||
|
|
@ -473,37 +469,8 @@ static void open_dumpfile(vpiHandle callh)
|
|||
|
||||
static PLI_INT32 sys_dumpfile_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||
{
|
||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
||||
char *path;
|
||||
|
||||
/* $dumpfile must be called before $dumpvars starts! */
|
||||
if (dumpvars_status != 0) {
|
||||
char msg[64];
|
||||
snprintf(msg, sizeof(msg), "LXT warning: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
msg[sizeof(msg)-1] = 0;
|
||||
vpi_printf("%s %s called after $dumpvars started,\n", msg, name);
|
||||
vpi_printf("%*s using existing file (%s).\n",
|
||||
(int) strlen(msg), " ", dump_path);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
path = get_filename_with_suffix(callh, name, vpi_scan(argv), "lxt");
|
||||
vpi_free_object(argv);
|
||||
if (! path) return 0;
|
||||
|
||||
if (dump_path) {
|
||||
vpi_printf("LXT warning: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("Overriding dump file %s with %s.\n", dump_path, path);
|
||||
free(dump_path);
|
||||
}
|
||||
dump_path = path;
|
||||
|
||||
return 0;
|
||||
(void)name;
|
||||
return sys_dumpfile_common("LXT", "lxt");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2021 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2023 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -35,7 +35,6 @@
|
|||
# include "ivl_alloc.h"
|
||||
|
||||
|
||||
static char *dump_path = NULL;
|
||||
static struct lxt2_wr_trace *dump_file = NULL;
|
||||
|
||||
static void* lxt2_thread(void*arg);
|
||||
|
|
@ -244,7 +243,6 @@ static void show_this_item_x(struct vcd_info*info)
|
|||
}
|
||||
|
||||
|
||||
static int dumpvars_status = 0; /* 0:fresh 1:cb installed, 2:callback done */
|
||||
static PLI_UINT64 dumpvars_time;
|
||||
__inline__ static int dump_header_pending(void)
|
||||
{
|
||||
|
|
@ -349,8 +347,7 @@ static PLI_INT32 finish_cb(p_cb_data cause)
|
|||
|
||||
vcd_scope_names_delete();
|
||||
nexus_ident_delete();
|
||||
free(dump_path);
|
||||
dump_path = 0;
|
||||
vcd_free_dump_path();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -479,9 +476,9 @@ static void *close_dumpfile(void)
|
|||
static void open_dumpfile(vpiHandle callh)
|
||||
{
|
||||
off_t use_file_size_limit = lxt2_file_size_limit;
|
||||
if (dump_path == 0) dump_path = strdup("dump.lx2");
|
||||
char* use_dump_path = vcd_get_dump_path("lx2");
|
||||
|
||||
dump_file = lxt2_wr_init(dump_path);
|
||||
dump_file = lxt2_wr_init(use_dump_path);
|
||||
|
||||
if (getenv("LXT_FILE_SIZE_LIMIT")) {
|
||||
const char*limit_string = getenv("LXT_FILE_SIZE_LIMIT");
|
||||
|
|
@ -499,17 +496,16 @@ static void open_dumpfile(vpiHandle callh)
|
|||
if (dump_file == 0) {
|
||||
vpi_printf("LXT2 Error: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("Unable to open %s for output.\n", dump_path);
|
||||
vpi_printf("Unable to open %s for output.\n", use_dump_path);
|
||||
vpip_set_return_value(1);
|
||||
vpi_control(vpiFinish, 1);
|
||||
free(dump_path);
|
||||
dump_path = 0;
|
||||
vcd_free_dump_path();
|
||||
return;
|
||||
} else {
|
||||
int prec = vpi_get(vpiTimePrecision, 0);
|
||||
|
||||
vpi_printf("LXT2 info: dumpfile %s opened for output.\n",
|
||||
dump_path);
|
||||
use_dump_path);
|
||||
|
||||
assert(prec >= -15);
|
||||
lxt2_wr_set_timescale(dump_file, prec);
|
||||
|
|
@ -526,37 +522,8 @@ static void open_dumpfile(vpiHandle callh)
|
|||
|
||||
static PLI_INT32 sys_dumpfile_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||
{
|
||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
||||
char *path;
|
||||
|
||||
/* $dumpfile must be called before $dumpvars starts! */
|
||||
if (dumpvars_status != 0) {
|
||||
char msg[64];
|
||||
snprintf(msg, sizeof(msg), "LXT2 warning: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
msg[sizeof(msg)-1] = 0;
|
||||
vpi_printf("%s %s called after $dumpvars started,\n", msg, name);
|
||||
vpi_printf("%*s using existing file (%s).\n",
|
||||
(int) strlen(msg), " ", dump_path);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
path = get_filename_with_suffix(callh, name, vpi_scan(argv), "lx2");
|
||||
vpi_free_object(argv);
|
||||
if (! path) return 0;
|
||||
|
||||
if (dump_path) {
|
||||
vpi_printf("LXT2 warning: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("Overriding dump file %s with %s.\n", dump_path, path);
|
||||
free(dump_path);
|
||||
}
|
||||
dump_path = path;
|
||||
|
||||
return 0;
|
||||
(void)name;
|
||||
return sys_dumpfile_common("LXT2", "lx2");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -104,11 +104,11 @@ char *get_filename(vpiHandle callh, const char *name, vpiHandle file)
|
|||
return strdup(val.value.str);
|
||||
}
|
||||
|
||||
char* get_filename_with_suffix(vpiHandle callh, const char *name, vpiHandle file, const char*suff)
|
||||
/*
|
||||
* Create a new copy of the path with the suffix appended.
|
||||
*/
|
||||
char* attach_suffix_to_filename(char *path, const char*suff)
|
||||
{
|
||||
char*path = get_filename(callh, name, file);
|
||||
if (path == 0) return 0;
|
||||
|
||||
/* If the name already has a suffix, then don't replace it or
|
||||
add another suffix. Just return this path. */
|
||||
char*tailp = strrchr(path, '.');
|
||||
|
|
@ -124,6 +124,14 @@ char* get_filename_with_suffix(vpiHandle callh, const char *name, vpiHandle file
|
|||
return new_path;
|
||||
}
|
||||
|
||||
char* get_filename_with_suffix(vpiHandle callh, const char *name, vpiHandle file, const char*suff)
|
||||
{
|
||||
char*path = get_filename(callh, name, file);
|
||||
if (path == 0) return 0;
|
||||
|
||||
return attach_suffix_to_filename(path, suff);
|
||||
}
|
||||
|
||||
void check_for_extra_args(vpiHandle argv, vpiHandle callh, const char *name,
|
||||
const char *arg_str, unsigned opt)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ extern char *as_escaped(char *arg);
|
|||
extern char *get_filename(vpiHandle callh, const char *name, vpiHandle file);
|
||||
extern char *get_filename_with_suffix(vpiHandle callh, const char*name,
|
||||
vpiHandle file, const char*suff);
|
||||
extern char *attach_suffix_to_filename(char *path, const char*suff);
|
||||
|
||||
extern void check_for_extra_args(vpiHandle argv, vpiHandle callh, const char *name,
|
||||
const char *arg_str, unsigned opt);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
# include "vpi_config.h"
|
||||
# include "vpi_user.h"
|
||||
# include "vcd_priv.h"
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
|
|
@ -149,6 +150,8 @@ static void sys_lxt_or_vcd_register(void)
|
|||
} else if (strcmp(vlog_info.argv[idx],"-none") == 0) {
|
||||
dumper = "none";
|
||||
|
||||
} else if (strncmp(vlog_info.argv[idx],"-dumpfile=",10) == 0) {
|
||||
vcd_set_dump_path_default(vlog_info.argv[idx]+10);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2023 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -31,7 +31,6 @@
|
|||
# include <time.h>
|
||||
# include "ivl_alloc.h"
|
||||
|
||||
static char *dump_path = NULL;
|
||||
static FILE *dump_file = NULL;
|
||||
static int dump_no_date = 0;
|
||||
|
||||
|
|
@ -158,7 +157,6 @@ struct vcd_names_list_s vcd_tab = { 0, 0, 0, 0 };
|
|||
struct vcd_names_list_s vcd_var = { 0, 0, 0, 0 };
|
||||
|
||||
|
||||
static int dumpvars_status = 0; /* 0:fresh 1:cb installed, 2:callback done */
|
||||
static PLI_UINT64 dumpvars_time;
|
||||
__inline__ static int dump_header_pending(void)
|
||||
{
|
||||
|
|
@ -283,8 +281,7 @@ static PLI_INT32 finish_cb(p_cb_data cause)
|
|||
vcd_names_delete(&vcd_tab);
|
||||
vcd_names_delete(&vcd_var);
|
||||
nexus_ident_delete();
|
||||
free(dump_path);
|
||||
dump_path = 0;
|
||||
vcd_free_dump_path();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -408,18 +405,17 @@ static PLI_INT32 sys_dumpall_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
|||
|
||||
static void open_dumpfile(vpiHandle callh)
|
||||
{
|
||||
if (dump_path == 0) dump_path = strdup("dump.vcd");
|
||||
char* use_dump_path = vcd_get_dump_path("vcd");
|
||||
|
||||
dump_file = fopen(dump_path, "w");
|
||||
dump_file = fopen(use_dump_path, "w");
|
||||
|
||||
if (dump_file == 0) {
|
||||
vpi_printf("VCD Error: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("Unable to open %s for output.\n", dump_path);
|
||||
vpi_printf("Unable to open %s for output.\n", use_dump_path);
|
||||
vpip_set_return_value(1);
|
||||
vpi_control(vpiFinish, 1);
|
||||
free(dump_path);
|
||||
dump_path = 0;
|
||||
vcd_free_dump_path();
|
||||
return;
|
||||
} else {
|
||||
int prec = vpi_get(vpiTimePrecision, 0);
|
||||
|
|
@ -428,7 +424,7 @@ static void open_dumpfile(vpiHandle callh)
|
|||
time_t walltime;
|
||||
|
||||
vpi_printf("VCD info: dumpfile %s opened for output.\n",
|
||||
dump_path);
|
||||
use_dump_path);
|
||||
|
||||
time(&walltime);
|
||||
|
||||
|
|
@ -458,37 +454,8 @@ static void open_dumpfile(vpiHandle callh)
|
|||
|
||||
static PLI_INT32 sys_dumpfile_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||
{
|
||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
||||
char *path;
|
||||
|
||||
/* $dumpfile must be called before $dumpvars starts! */
|
||||
if (dumpvars_status != 0) {
|
||||
char msg[64];
|
||||
snprintf(msg, sizeof(msg), "VCD warning: %s:%d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
msg[sizeof(msg)-1] = 0;
|
||||
vpi_printf("%s %s called after $dumpvars started,\n", msg, name);
|
||||
vpi_printf("%*s using existing file (%s).\n",
|
||||
(int) strlen(msg), " ", dump_path);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
path = get_filename_with_suffix(callh, name, vpi_scan(argv), "vcd");
|
||||
vpi_free_object(argv);
|
||||
if (! path) return 0;
|
||||
|
||||
if (dump_path) {
|
||||
vpi_printf("VCD warning: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("Overriding dump file %s with %s.\n", dump_path, path);
|
||||
free(dump_path);
|
||||
}
|
||||
dump_path = path;
|
||||
|
||||
return 0;
|
||||
(void) name;
|
||||
return sys_dumpfile_common("VCD", "vcd");
|
||||
}
|
||||
|
||||
static PLI_INT32 sys_dumpflush_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2021 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2023 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -27,6 +27,10 @@
|
|||
#include <ctype.h>
|
||||
#include "stringheap.h"
|
||||
|
||||
static const char* vcd_dump_path_default = "dump";
|
||||
static char* vcd_dump_path = NULL;
|
||||
int dumpvars_status = 0; /* 0:fresh 1:cb installed, 2:callback done */
|
||||
|
||||
int is_escaped_id(const char *name)
|
||||
{
|
||||
assert(name);
|
||||
|
|
@ -220,3 +224,63 @@ PLI_INT32 sys_dumpvars_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vcd_set_dump_path_default(const char*text)
|
||||
{
|
||||
vcd_dump_path_default = text;
|
||||
}
|
||||
|
||||
char* vcd_get_dump_path(const char*suffix)
|
||||
{
|
||||
if (vcd_dump_path)
|
||||
return vcd_dump_path;
|
||||
|
||||
vcd_dump_path = attach_suffix_to_filename(strdup(vcd_dump_path_default), suffix);
|
||||
return vcd_dump_path;
|
||||
}
|
||||
|
||||
void vcd_free_dump_path(void)
|
||||
{
|
||||
free(vcd_dump_path);
|
||||
vcd_dump_path = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Common implementation of $dumpfile() for the various dumper types.
|
||||
* string argument is the title to use in error messages.
|
||||
*/
|
||||
PLI_INT32 sys_dumpfile_common(const char*title, const char*suffix)
|
||||
{
|
||||
static const char* name = "$dumpfile";
|
||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
||||
char *path;
|
||||
|
||||
/* $dumpfile must be called before $dumpvars starts! */
|
||||
if (dumpvars_status != 0) {
|
||||
char msg[64];
|
||||
snprintf(msg, sizeof(msg), "%s warning: %s:%d:", title,
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
msg[sizeof(msg)-1] = 0;
|
||||
vpi_printf("%s %s called after $dumpvars started,\n", msg, name);
|
||||
vpi_printf("%*s using existing file (%s).\n",
|
||||
(int) strlen(msg), " ", vcd_dump_path);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
path = get_filename_with_suffix(callh, name, vpi_scan(argv), suffix);
|
||||
vpi_free_object(argv);
|
||||
if (! path) return 0;
|
||||
|
||||
if (vcd_dump_path) {
|
||||
vpi_printf("%s warning: %s:%d: ", title, vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("Overriding dump file %s with %s.\n", vcd_dump_path, path);
|
||||
free(vcd_dump_path);
|
||||
}
|
||||
vcd_dump_path = path;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IVL_vcd_priv_H
|
||||
#define IVL_vcd_priv_H
|
||||
/*
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2023 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -129,6 +129,15 @@ EXTERN void vcd_work_emit_bits(struct lxt2_wr_symbol*sym, const char*bits);
|
|||
/* The compiletf routines are common for the VCD, LXT and LXT2 dumpers. */
|
||||
EXTERN PLI_INT32 sys_dumpvars_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name);
|
||||
|
||||
/*
|
||||
* Common implementation of the sys_dumpfile calltf.
|
||||
*/
|
||||
EXTERN PLI_INT32 sys_dumpfile_common(const char*title, const char*suffix);
|
||||
EXTERN void vcd_set_dump_path_default(const char*text);
|
||||
EXTERN char* vcd_get_dump_path(const char*suffix);
|
||||
EXTERN void vcd_free_dump_path(void);
|
||||
EXTERN int dumpvars_status;
|
||||
|
||||
/*
|
||||
* The vcd_list is the list of all the objects that are tracked for
|
||||
* dumping. The vcd_checkpoint goes through the list to dump the current
|
||||
|
|
|
|||
Loading…
Reference in New Issue