Add support for a command line dumpfile option

The -dumpfile=<path> vvp extended argument sets the default nanme to use
for the various dumpers. If this flag is not given, the default is "dump".
The $dumpfile system task overrides the default or this command line flag.

This commit also factors out all the dumpfile selection code for the various
dumper implementations.
This commit is contained in:
Stephen Williams 2023-02-26 14:05:42 -08:00
parent 378c812fe2
commit 29ac33493e
10 changed files with 138 additions and 178 deletions

View File

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

View File

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

View File

@ -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");
}
/*

View File

@ -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");
}
/*

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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