Cleanup dumper code (VCD/LXT/LXT2/none)

This patch fixes a number of problems associated with the various dumpers.

1. It catches the problem uncovered in pr1809904 and prevents the core
   dumps from happening. It prints a warning message if you try to change
   the file after the program has started dumping data to the file.

2. It makes all the dumpers work in the same manner. Before the VCD
   $dumpfile was processed at compile time, but the LXT/LXT2 versions
   did this at run time. The correct place for this is the run time so
   that you can pass the task a calculated name.

3. All the dumpers use common compiletf routines located in vcd_priv.c

4. Make the LXT/LXT2 $dumpfile commands only get the file name and
   let $dumpvars actually open the file. This matches the VCD code.

5. Fix the $dumpfile code to allow calculated file names.

6. Make dumpvars without a scope/variable match all toplevel modules
   not just the toplevel module the $dumpvars was located in. This
   now matches the standard (2001).

7. Simplify the no dumper code (vcdoff.c) and add missing functions.

8. Cleanup the code and messages.

9. vvp can take -none for no dumper.
This commit is contained in:
Cary R 2007-12-10 16:14:02 -08:00 committed by Stephen Williams
parent f245dc8d96
commit d3880d02c7
9 changed files with 591 additions and 787 deletions

View File

@ -144,6 +144,7 @@ static char *create_full_name(const char *name)
}
static char *dump_path = 0;
static struct lt_trace *dump_file = 0;
struct vcd_info {
@ -323,10 +324,8 @@ inline static int install_dumpvars_callback(void)
return 0;
if (dumpvars_status == 2) {
vpi_mcd_printf(1, "LXT warning:"
" $dumpvars ignored,"
" previously called at simtime %lu\n",
dumpvars_time);
vpi_mcd_printf(1, "LXT warning:" " $dumpvars ignored, previously"
" called at simtime %lu\n", dumpvars_time);
return 1;
}
@ -353,24 +352,21 @@ static PLI_INT32 sys_dumpoff_calltf(PLI_BYTE8*name)
s_vpi_time now;
PLI_UINT64 now64;
if (dump_is_off)
return 0;
if (dump_is_off) return 0;
dump_is_off = 1;
if (dump_file == 0)
return 0;
if (dump_header_pending())
return 0;
if (dump_file == 0) return 0;
if (dump_header_pending()) return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
now64 = timerec_to_time64(&now);
if (now64 > vcd_cur_time)
if (now64 > vcd_cur_time) {
lt_set_time64(dump_file, now64);
vcd_cur_time = now64;
vcd_cur_time = now64;
}
lt_set_dumpoff(dump_file);
vcd_checkpoint_x();
@ -383,24 +379,21 @@ static PLI_INT32 sys_dumpon_calltf(PLI_BYTE8*name)
s_vpi_time now;
PLI_UINT64 now64;
if (!dump_is_off)
return 0;
if (!dump_is_off) return 0;
dump_is_off = 0;
if (dump_file == 0)
return 0;
if (dump_header_pending())
return 0;
if (dump_file == 0) return 0;
if (dump_header_pending()) return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
now64 = timerec_to_time64(&now);
if (now64 > vcd_cur_time)
if (now64 > vcd_cur_time) {
lt_set_time64(dump_file, now64);
vcd_cur_time = now64;
vcd_cur_time = now64;
}
lt_set_dumpon(dump_file);
vcd_checkpoint();
@ -413,19 +406,18 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name)
s_vpi_time now;
PLI_UINT64 now64;
if (dump_file == 0)
return 0;
if (dump_header_pending())
return 0;
if (dump_is_off) return 0;
if (dump_file == 0) return 0;
if (dump_header_pending()) return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
now64 = timerec_to_time64(&now);
if (now64> vcd_cur_time)
if (now64> vcd_cur_time) {
lt_set_time64(dump_file, now64);
vcd_cur_time = now64;
vcd_cur_time = now64;
}
vcd_checkpoint();
@ -434,25 +426,26 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name)
static void *close_dumpfile(void)
{
lt_close(dump_file);
return(dump_file = NULL);
lt_close(dump_file);
return (dump_file = NULL);
}
static void open_dumpfile(const char*path)
static void open_dumpfile(void)
{
dump_file = lt_init(path);
if (dump_path == 0) dump_path = strdup("dump.lxt");
dump_file = lt_init(dump_path);
if (dump_file == 0) {
vpi_mcd_printf(1,
"LXT Error: Unable to open %s for output.\n",
path);
vpi_mcd_printf(1, "LXT Error: Unable to open %s for output.\n",
dump_path);
vpi_control(vpiFinish, 1);
return;
} else {
int prec = vpi_get(vpiTimePrecision, 0);
vpi_mcd_printf(1,
"LXT info: dumpfile %s opened for output.\n",
path);
vpi_mcd_printf(1, "LXT info: dumpfile %s opened for output.\n",
dump_path);
assert(prec >= -15);
lt_set_timescale(dump_file, prec);
@ -466,42 +459,33 @@ static void open_dumpfile(const char*path)
static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
s_vpi_value value;
char*path;
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle item;
if (argv && (item = vpi_scan(argv))) {
s_vpi_value value;
if (vpi_get(vpiType, item) != vpiConstant
|| vpi_get(vpiConstType, item) != vpiStringConst) {
vpi_mcd_printf(1,
"LXT Error:"
" %s parameter must be a string constant\n",
name);
return 0;
}
value.format = vpiStringVal;
vpi_get_value(item, &value);
path = strdup(value.value.str);
vpi_free_object(argv);
} else {
path = strdup("dump.lxt");
/* $dumpfile must be called before $dumpvars starts! */
if (dumpvars_status != 0) {
vpi_mcd_printf(1, "LXT warning: %s called after $dumpvars started"
",\n using existing file (%s).\n",
name, dump_path);
return 0;
}
if (dump_file)
close_dumpfile();
assert(argv);
value.format = vpiStringVal;
vpi_get_value(vpi_scan(argv), &value);
path = strdup(value.value.str);
assert(dump_file == 0);
open_dumpfile(path);
free(path);
if (dump_path) {
vpi_mcd_printf(1, "LXT warning: Overriding dump file %s with"
" %s\n", dump_path, path);
free(dump_path);
}
dump_path = path;
vpi_free_object(argv);
return 0;
}
@ -513,40 +497,6 @@ static PLI_INT32 sys_dumpflush_calltf(PLI_BYTE8*name)
return 0;
}
static PLI_INT32 sys_dumplimit_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle limit;
/* Check that there is a argument and get it. */
if (argv == 0) {
vpi_printf("ERROR: %s requires an argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
limit = vpi_scan(argv);
/* Check that we are not given a string. */
switch (vpi_get(vpiType, limit)) {
case vpiConstant:
case vpiParameter:
if (vpi_get(vpiConstType, limit) == vpiStringConst) {
vpi_printf("ERROR: %s's argument must be a number.\n", name);
}
}
/* Check that there is only a single argument. */
limit = vpi_scan(argv);
if (limit != 0) {
vpi_printf("ERROR: %s takes a single argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
return 0;
}
static PLI_INT32 sys_dumplimit_calltf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
@ -604,8 +554,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
case vpiTimeVar:
case vpiReg: type = "reg"; }
if (skip)
break;
if (skip) break;
name = vpi_get_str(vpiName, item);
nexus_id = vpi_get(_vpiNexusId, item);
@ -620,8 +569,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
ident = strdup_sh(&name_heap, tmp);
free(tmp);
if (nexus_id)
set_nexus_ident(nexus_id, ident);
if (nexus_id) set_nexus_ident(nexus_id, ident);
info = malloc(sizeof(*info));
@ -653,8 +601,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
case vpiRealVar:
if (skip)
break;
if (skip) break;
name = vpi_get_str(vpiName, item);
{ char*tmp = create_full_name(name);
@ -706,11 +653,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
if (!nskip)
vcd_names_add(&lxt_tab, fullname);
else
vpi_mcd_printf(1,
"LXT warning:"
" ignoring signals"
" in previously scanned scope %s\n",
fullname);
vpi_mcd_printf(1, "LXT warning: ignoring signals in"
" previously scanned scope %s\n", fullname);
name = vpi_get_str(vpiName, item);
@ -729,9 +673,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
break;
default:
vpi_mcd_printf(1,
"LXT Error: $lxtdumpvars: Unsupported parameter "
"type (%d)\n", vpi_get(vpiType, item));
vpi_mcd_printf(1, "LXT warning: $dumpvars: Unsupported parameter"
" type (%d)\n", vpi_get(vpiType, item));
}
}
@ -757,80 +700,54 @@ static int draw_scope(vpiHandle item)
default: type = "module"; break;
}
push_scope(name); /* keep in type info determination for possible future usage */
/* keep in type info determination for possible future usage */
push_scope(name);
return depth;
}
static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name)
{
unsigned depth;
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle item;
s_vpi_value value;
vpiHandle item = 0;
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv;
unsigned depth = 0;
if (dump_file == 0) {
open_dumpfile("dump.lxt");
if (dump_file == 0)
return 0;
open_dumpfile();
if (dump_file == 0) return 0;
}
if (install_dumpvars_callback()) {
return 0;
if (install_dumpvars_callback()) return 0;
/* Get the depth if it exists. */
if (argv) {
value.format = vpiIntVal;
vpi_get_value(vpi_scan(argv), &value);
depth = value.value.integer;
}
if (!depth) depth = 10000;
/* This dumps all the modules in the design if none are given. */
if (!argv || !(item = vpi_scan(argv))) {
argv = vpi_iterate(vpiModule, 0x0);
assert(argv); // There must be at least one top level module.
item = vpi_scan(argv);
}
argv = vpi_iterate(vpiArgument, sys);
depth = 0;
if (argv && (item = vpi_scan(argv)))
switch (vpi_get(vpiType, item)) {
case vpiConstant:
case vpiNet:
case vpiIntegerVar:
case vpiReg:
case vpiMemoryWord:
value.format = vpiIntVal;
vpi_get_value(item, &value);
depth = value.value.integer;
break;
}
if (!depth)
depth = 10000;
if (!argv) {
// $dumpvars;
// search for the toplevel module
vpiHandle parent = vpi_handle(vpiScope, sys);
while (parent) {
item = parent;
parent = vpi_handle(vpiScope, item);
}
} else if (!item || !(item = vpi_scan(argv))) {
// $dumpvars(level);
// $dumpvars();
// dump the current scope
item = vpi_handle(vpiScope, sys);
argv = 0x0;
}
for ( ; item; item = argv ? vpi_scan(argv) : 0x0) {
for ( ; item; item = vpi_scan(argv)) {
int dep = draw_scope(item);
vcd_names_sort(&lxt_tab);
scan_item(depth, item, 0);
while (dep--) {
pop_scope();
}
while (dep--) pop_scope();
}
/* Most effective compression. */
if (lxm_optimum_mode == LXM_SPACE)
lt_set_no_interlace(dump_file);
if (lxm_optimum_mode == LXM_SPACE) lt_set_no_interlace(dump_file);
return 0;
}
@ -856,34 +773,20 @@ void sys_lxt_register()
}
}
/* All the compiletf routines are located in vcd_priv.c. */
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpall";
tf_data.calltf = sys_dumpall_calltf;
tf_data.compiletf = 0;
tf_data.compiletf = sys_dumpall_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpall";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpoff";
tf_data.calltf = sys_dumpoff_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpoff";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpon";
tf_data.calltf = sys_dumpon_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpon";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpfile";
tf_data.calltf = sys_dumpfile_calltf;
tf_data.compiletf = 0;
tf_data.compiletf = sys_dumpfile_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpfile";
vpi_register_systf(&tf_data);
@ -891,7 +794,7 @@ void sys_lxt_register()
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpflush";
tf_data.calltf = sys_dumpflush_calltf;
tf_data.compiletf = 0;
tf_data.compiletf = sys_dumpflush_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpflush";
vpi_register_systf(&tf_data);
@ -904,10 +807,26 @@ void sys_lxt_register()
tf_data.user_data = "$dumplimit";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpoff";
tf_data.calltf = sys_dumpoff_calltf;
tf_data.compiletf = sys_dumpoff_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpoff";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpon";
tf_data.calltf = sys_dumpon_calltf;
tf_data.compiletf = sys_dumpon_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpon";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpvars";
tf_data.calltf = sys_dumpvars_calltf;
tf_data.compiletf = sys_vcd_dumpvars_compiletf;
tf_data.compiletf = sys_dumpvars_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpvars";
vpi_register_systf(&tf_data);

View File

@ -145,6 +145,7 @@ static char *create_full_name(const char *name)
}
static char *dump_path;
static struct lxt2_wr_trace *dump_file = 0;
struct vcd_info {
@ -256,10 +257,10 @@ static PLI_INT32 variable_cb_1(p_cb_data cause)
struct t_cb_data cb;
struct vcd_info*info = (struct vcd_info*)cause->user_data;
if (dump_is_full) return 0;
if (dump_is_off) return 0;
if (dump_is_full) return 0;
if (dump_is_off) return 0;
if (dump_header_pending()) return 0;
if (info->scheduled) return 0;
if (info->scheduled) return 0;
if ((dump_limit > 0) && (ftell(dump_file->handle) > dump_limit)) {
dump_is_full = 1;
@ -284,8 +285,7 @@ static PLI_INT32 variable_cb_1(p_cb_data cause)
static PLI_INT32 dumpvars_cb(p_cb_data cause)
{
if (dumpvars_status != 1)
return 0;
if (dumpvars_status != 1) return 0;
dumpvars_status = 2;
@ -302,8 +302,7 @@ static PLI_INT32 dumpvars_cb(p_cb_data cause)
static PLI_INT32 finish_cb(p_cb_data cause)
{
if (finish_status != 0)
return 0;
if (finish_status != 0) return 0;
finish_status = 1;
@ -320,14 +319,11 @@ inline static int install_dumpvars_callback(void)
struct t_cb_data cb;
static struct t_vpi_time time;
if (dumpvars_status == 1)
return 0;
if (dumpvars_status == 1) return 0;
if (dumpvars_status == 2) {
vpi_mcd_printf(1, "LXT2 warning:"
" $dumpvars ignored,"
" previously called at simtime %lu\n",
dumpvars_time);
vpi_mcd_printf(1, "LXT2 warning: $dumpvars ignored, previously"
" called at simtime %lu\n", dumpvars_time);
return 1;
}
@ -354,23 +350,21 @@ static PLI_INT32 sys_dumpoff_calltf(PLI_BYTE8*name)
s_vpi_time now;
PLI_UINT64 now64;
if (dump_is_off)
return 0;
if (dump_is_off) return 0;
dump_is_off = 1;
if (dump_file == 0)
return 0;
if (dump_header_pending())
return 0;
if (dump_file == 0) return 0;
if (dump_header_pending()) return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
now64 = timerec_to_time64(&now);
if (now64 > vcd_cur_time)
if (now64 > vcd_cur_time) {
lxt2_wr_set_time(dump_file, now64);
vcd_cur_time = now.low;
vcd_cur_time = now.low;
}
lxt2_wr_set_dumpoff(dump_file);
vcd_checkpoint_x();
@ -383,24 +377,21 @@ static PLI_INT32 sys_dumpon_calltf(PLI_BYTE8*name)
s_vpi_time now;
PLI_UINT64 now64;
if (!dump_is_off)
return 0;
if (!dump_is_off) return 0;
dump_is_off = 0;
if (dump_file == 0)
return 0;
if (dump_header_pending())
return 0;
if (dump_file == 0) return 0;
if (dump_header_pending()) return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
now64 = timerec_to_time64(&now);
if (now64 > vcd_cur_time)
if (now64 > vcd_cur_time) {
lxt2_wr_set_time64(dump_file, now64);
vcd_cur_time = now64;
vcd_cur_time = now64;
}
lxt2_wr_set_dumpon(dump_file);
vcd_checkpoint();
@ -413,15 +404,12 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name)
s_vpi_time now;
PLI_UINT64 now64;
if (dump_file == 0)
return 0;
if (dump_header_pending())
return 0;
if (dump_is_off) return 0;
if (dump_file == 0) return 0;
if (dump_header_pending()) return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
now64 = timerec_to_time64(&now);
if (now64 > vcd_cur_time)
@ -440,21 +428,22 @@ static void *close_dumpfile(void)
return 0;
}
static void open_dumpfile(const char*path)
static void open_dumpfile(void)
{
dump_file = lxt2_wr_init(path);
if (dump_path == 0) dump_path = strdup("dump.lx2");
dump_file = lxt2_wr_init(dump_path);
if (dump_file == 0) {
vpi_mcd_printf(1,
"LXT2 Error: Unable to open %s for output.\n",
path);
vpi_mcd_printf(1, "LXT2 Error: Unable to open %s for output.\n",
dump_path);
vpi_control(vpiFinish, 1);
return;
} else {
int prec = vpi_get(vpiTimePrecision, 0);
vpi_mcd_printf(1,
"LXT2 info: dumpfile %s opened for output.\n",
path);
vpi_mcd_printf(1, "LXT2 info: dumpfile %s opened for output.\n",
dump_path);
assert(prec >= -15);
lxt2_wr_set_timescale(dump_file, prec);
@ -470,42 +459,33 @@ static void open_dumpfile(const char*path)
static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name)
{
char*path;
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle item;
s_vpi_value value;
if (argv && (item = vpi_scan(argv))) {
s_vpi_value value;
char*path;
if (vpi_get(vpiType, item) != vpiConstant
|| vpi_get(vpiConstType, item) != vpiStringConst) {
vpi_mcd_printf(1,
"LXT2 Error:"
" %s parameter must be a string constant\n",
name);
return 0;
}
value.format = vpiStringVal;
vpi_get_value(item, &value);
path = strdup(value.value.str);
vpi_free_object(argv);
} else {
path = strdup("dump.lx2");
/* $dumpfile must be called before $dumpvars starts! */
if (dumpvars_status != 0) {
vpi_mcd_printf(1, "LXT2 warning: %s called after $dumpvars started"
",\n using existing file (%s).\n",
name, dump_path);
return 0;
}
if (dump_file)
close_dumpfile();
assert(argv);
value.format = vpiStringVal;
vpi_get_value(vpi_scan(argv), &value);
path = strdup(value.value.str);
assert(dump_file == 0);
open_dumpfile(path);
free(path);
if (dump_path) {
vpi_mcd_printf(1, "LXT2 warning: Overriding dump file %s with"
" %s.\n", dump_path, path);
free(dump_path);
}
dump_path = path;
vpi_free_object(argv);
return 0;
}
@ -519,39 +499,6 @@ static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name)
static PLI_INT32 sys_dumpflush_calltf(PLI_BYTE8*name)
{
if (dump_file) lxt2_wr_flush(dump_file);
return 0;
}
static PLI_INT32 sys_dumplimit_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle limit;
/* Check that there is a argument and get it. */
if (argv == 0) {
vpi_printf("ERROR: %s requires an argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
limit = vpi_scan(argv);
/* Check that we are not given a string. */
switch (vpi_get(vpiType, limit)) {
case vpiConstant:
case vpiParameter:
if (vpi_get(vpiConstType, limit) == vpiStringConst) {
vpi_printf("ERROR: %s's argument must be a number.\n", name);
}
}
/* Check that there is only a single argument. */
limit = vpi_scan(argv);
if (limit != 0) {
vpi_printf("ERROR: %s takes a single argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
return 0;
}
@ -560,12 +507,12 @@ static PLI_INT32 sys_dumplimit_calltf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle limit = vpi_scan(argv);
s_vpi_value val;
/* Get the value and set the dump limit. */
assert(argv);
val.format = vpiIntVal;
vpi_get_value(limit, &val);
vpi_get_value(vpi_scan(argv), &val);
dump_limit = val.value.integer;
vpi_free_object(argv);
@ -613,8 +560,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
case vpiTimeVar:
case vpiReg: type = "reg"; }
if (skip)
break;
if (skip) break;
name = vpi_get_str(vpiName, item);
nexus_id = vpi_get(_vpiNexusId, item);
@ -629,8 +575,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
ident = strdup_sh(&name_heap, tmp);
free(tmp);
if (nexus_id)
set_nexus_ident(nexus_id, ident);
if (nexus_id) set_nexus_ident(nexus_id, ident);
info = malloc(sizeof(*info));
@ -666,8 +611,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
case vpiRealVar:
if (skip)
break;
if (skip) break;
name = vpi_get_str(vpiName, item);
{ char*tmp = create_full_name(name);
@ -722,11 +666,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
if (!nskip)
vcd_names_add(&lxt_tab, fullname);
else
vpi_mcd_printf(1,
"LXT2 warning:"
" ignoring signals"
" in previously scanned scope %s\n",
fullname);
vpi_mcd_printf(1, "LXT2 warning: ignoring signals in"
" previously scanned scope %s\n", fullname);
name = vpi_get_str(vpiName, item);
@ -745,9 +686,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
break;
default:
vpi_mcd_printf(1,
"LXT2 Error: $lxtdumpvars: Unsupported parameter "
"type (%d)\n", vpi_get(vpiType, item));
vpi_mcd_printf(1, "LXT2 warning: $dumpvars: Unsupported parameter"
" type (%d)\n", vpi_get(vpiType, item));
}
}
@ -759,8 +699,7 @@ static int draw_scope(vpiHandle item)
char *type;
vpiHandle scope = vpi_handle(vpiScope, item);
if (!scope)
return 0;
if (!scope) return 0;
depth = 1 + draw_scope(scope);
name = vpi_get_str(vpiName, scope);
@ -773,75 +712,50 @@ static int draw_scope(vpiHandle item)
default: type = "module"; break;
}
push_scope(name); /* keep in type info determination for possible future usage */
/* keep in type info determination for possible future usage */
push_scope(name);
return depth;
}
static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name)
{
unsigned depth;
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle item;
s_vpi_value value;
vpiHandle item = 0;
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv;
unsigned depth = 0;
if (dump_file == 0) {
open_dumpfile("dump.lx2");
if (dump_file == 0)
return 0;
open_dumpfile();
if (dump_file == 0) return 0;
}
if (install_dumpvars_callback()) {
return 0;
if (install_dumpvars_callback()) return 0;
/* Get the depth if it exists. */
if (argv) {
value.format = vpiIntVal;
vpi_get_value(vpi_scan(argv), &value);
depth = value.value.integer;
}
if (!depth) depth = 10000;
/* This dumps all the modules in the design if none are given. */
if (!argv || !(item = vpi_scan(argv))) {
argv = vpi_iterate(vpiModule, 0x0);
assert(argv); // There must be at least one top level module.
item = vpi_scan(argv);
}
argv = vpi_iterate(vpiArgument, sys);
depth = 0;
if (argv && (item = vpi_scan(argv)))
switch (vpi_get(vpiType, item)) {
case vpiConstant:
case vpiNet:
case vpiIntegerVar:
case vpiReg:
case vpiMemoryWord:
value.format = vpiIntVal;
vpi_get_value(item, &value);
depth = value.value.integer;
break;
}
if (!depth)
depth = 10000;
if (!argv) {
// $dumpvars;
// search for the toplevel module
vpiHandle parent = vpi_handle(vpiScope, sys);
while (parent) {
item = parent;
parent = vpi_handle(vpiScope, item);
}
} else if (!item || !(item = vpi_scan(argv))) {
// $dumpvars(level);
// $dumpvars();
// dump the current scope
item = vpi_handle(vpiScope, sys);
argv = 0x0;
}
for ( ; item; item = argv ? vpi_scan(argv) : 0x0) {
for ( ; item; item = vpi_scan(argv)) {
int dep = draw_scope(item);
vcd_names_sort(&lxt_tab);
scan_item(depth, item, 0);
while (dep--) {
pop_scope();
}
while (dep--) pop_scope();
}
/* Most effective compression. */
@ -874,34 +788,20 @@ void sys_lxt2_register()
}
}
/* All the compiletf routines are located in vcd_priv.c. */
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpall";
tf_data.calltf = sys_dumpall_calltf;
tf_data.compiletf = 0;
tf_data.compiletf = sys_dumpall_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpall";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpoff";
tf_data.calltf = sys_dumpoff_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpoff";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpon";
tf_data.calltf = sys_dumpon_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpon";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpfile";
tf_data.calltf = sys_dumpfile_calltf;
tf_data.compiletf = 0;
tf_data.compiletf = sys_dumpfile_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpfile";
vpi_register_systf(&tf_data);
@ -909,7 +809,7 @@ void sys_lxt2_register()
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpflush";
tf_data.calltf = sys_dumpflush_calltf;
tf_data.compiletf = 0;
tf_data.compiletf = sys_dumpflush_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpflush";
vpi_register_systf(&tf_data);
@ -922,10 +822,26 @@ void sys_lxt2_register()
tf_data.user_data = "$dumplimit";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpoff";
tf_data.calltf = sys_dumpoff_calltf;
tf_data.compiletf = sys_dumpoff_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpoff";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpon";
tf_data.calltf = sys_dumpon_calltf;
tf_data.compiletf = sys_dumpon_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpon";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpvars";
tf_data.calltf = sys_dumpvars_calltf;
tf_data.compiletf = sys_vcd_dumpvars_compiletf;
tf_data.compiletf = sys_dumpvars_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpvars";
vpi_register_systf(&tf_data);

View File

@ -25,12 +25,6 @@
# include "vpi_config.h"
# include "vpi_user.h"
/*
* This function is used by sys_vcd and sys_lxt as the dumpvars
* compiletf function.
*/
extern PLI_INT32 sys_vcd_dumpvars_compiletf(PLI_BYTE8*name);
/*
* Context structure for PRNG in mt19937int.c
*/
@ -56,32 +50,4 @@ struct timeformat_info_s {
extern struct timeformat_info_s timeformat_info;
/*
* $Log: sys_priv.h,v $
* Revision 1.8 2007/03/14 04:05:51 steve
* VPI tasks take PLI_BYTE* by the standard.
*
* Revision 1.7 2006/10/30 22:45:37 steve
* Updates for Cygwin portability (pr1585922)
*
* Revision 1.6 2006/08/12 03:38:12 steve
* scanf support for real values.
*
* Revision 1.5 2004/01/21 01:22:53 steve
* Give the vip directory its own configure and vpi_config.h
*
* Revision 1.4 2003/10/30 03:43:20 steve
* Rearrange fileio functions, and add ungetc.
*
* Revision 1.3 2003/09/30 01:33:39 steve
* dumpers must be aware of 64bit time.
*
* Revision 1.2 2003/05/14 04:18:16 steve
* Use seed to store random number context.
*
* Revision 1.1 2002/08/15 02:12:20 steve
* add dumpvars_compiletf to check first argument.
*
*/
#endif

View File

@ -124,6 +124,9 @@ static void sys_lxt_or_vcd_register()
} else if (strcmp(vlog_info.argv[idx],"-vcd-none") == 0) {
dumper = "none";
} else if (strcmp(vlog_info.argv[idx],"-none") == 0) {
dumper = "none";
}
}
@ -158,8 +161,8 @@ static void sys_lxt_or_vcd_register()
sys_vcdoff_register();
else {
fprintf(stderr, "system.vpi: Unknown dumper format: %s\n",
dumper);
vpi_mcd_printf(1, "system.vpi: Unknown dumper format: %s,"
" using VCD instead.\n", dumper);
sys_vcd_register();
}
}

View File

@ -92,18 +92,13 @@ static char *truncate_bitvec(char *s)
char l, r;
r=*s;
if(r=='1')
return s;
else
s += 1;
if(r=='1') return s;
else s += 1;
for(;;s++) {
l=r; r=*s;
if(!r) return (s-1);
if(l!=r)
return(((l=='0')&&(r=='1'))?s:s-1);
if(l!=r) return(((l=='0')&&(r=='1'))?s:s-1);
}
}
@ -123,8 +118,7 @@ static void show_this_item(struct vcd_info*info)
} else {
value.format = vpiBinStrVal;
vpi_get_value(info->item, &value);
fprintf(dump_file, "b%s %s\n",
truncate_bitvec(value.value.str),
fprintf(dump_file, "b%s %s\n", truncate_bitvec(value.value.str),
info->ident);
}
}
@ -203,10 +197,10 @@ static PLI_INT32 variable_cb_1(p_cb_data cause)
struct t_cb_data cb;
struct vcd_info*info = (struct vcd_info*)cause->user_data;
if (dump_is_full) return 0;
if (dump_is_off) return 0;
if (dump_is_full) return 0;
if (dump_is_off) return 0;
if (dump_header_pending()) return 0;
if (info->scheduled) return 0;
if (info->scheduled) return 0;
if ((dump_limit > 0) && (ftell(dump_file) > dump_limit)) {
dump_is_full = 1;
@ -233,8 +227,7 @@ static PLI_INT32 variable_cb_1(p_cb_data cause)
static PLI_INT32 dumpvars_cb(p_cb_data cause)
{
if (dumpvars_status != 1)
return 0;
if (dumpvars_status != 1) return 0;
dumpvars_status = 2;
@ -255,8 +248,7 @@ static PLI_INT32 dumpvars_cb(p_cb_data cause)
static PLI_INT32 finish_cb(p_cb_data cause)
{
if (finish_status != 0)
return 0;
if (finish_status != 0) return 0;
finish_status = 1;
@ -274,13 +266,11 @@ inline static int install_dumpvars_callback(void)
struct t_cb_data cb;
static struct t_vpi_time time;
if (dumpvars_status == 1)
return 0;
if (dumpvars_status == 1) return 0;
if (dumpvars_status == 2) {
vpi_mcd_printf(1, "VCD warning:"
" $dumpvars ignored,"
" previously called at simtime %" PLI_UINT64_FMT "\n",
vpi_mcd_printf(1, "VCD warning: $dumpvars ignored, previously"
" called at simtime %" PLI_UINT64_FMT "\n",
dumpvars_time);
return 1;
}
@ -308,24 +298,21 @@ static PLI_INT32 sys_dumpoff_calltf(PLI_BYTE8*name)
s_vpi_time now;
PLI_UINT64 now64;
if (dump_is_off)
return 0;
if (dump_is_off) return 0;
dump_is_off = 1;
if (dump_file == 0)
return 0;
if (dump_header_pending())
return 0;
if (dump_file == 0) return 0;
if (dump_header_pending()) return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
now64 = timerec_to_time64(&now);
if (now64 > vcd_cur_time)
if (now64 > vcd_cur_time) {
fprintf(dump_file, "#%" PLI_UINT64_FMT "\n", now64);
vcd_cur_time = now64;
vcd_cur_time = now64;
}
fprintf(dump_file, "$dumpoff\n");
vcd_checkpoint_x();
@ -339,24 +326,21 @@ static PLI_INT32 sys_dumpon_calltf(PLI_BYTE8*name)
s_vpi_time now;
PLI_UINT64 now64;
if (!dump_is_off)
return 0;
if (!dump_is_off) return 0;
dump_is_off = 0;
if (dump_file == 0)
return 0;
if (dump_header_pending())
return 0;
if (dump_file == 0) return 0;
if (dump_header_pending()) return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
now64 = timerec_to_time64(&now);
if (now64 > vcd_cur_time)
if (now64 > vcd_cur_time) {
fprintf(dump_file, "#%" PLI_UINT64_FMT "\n", now64);
vcd_cur_time = now64;
vcd_cur_time = now64;
}
fprintf(dump_file, "$dumpon\n");
vcd_checkpoint();
@ -370,19 +354,18 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name)
s_vpi_time now;
PLI_UINT64 now64;
if (dump_file == 0)
return 0;
if (dump_header_pending())
return 0;
if (dump_is_off) return 0;
if (dump_file == 0) return 0;
if (dump_header_pending()) return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
now64 = timerec_to_time64(&now);
if (now64 > vcd_cur_time)
if (now64 > vcd_cur_time) {
fprintf(dump_file, "#%" PLI_UINT64_FMT "\n", now64);
vcd_cur_time = now.low;
vcd_cur_time = now64;
}
fprintf(dump_file, "$dumpall\n");
vcd_checkpoint();
@ -393,16 +376,14 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name)
static void open_dumpfile(void)
{
if (dump_path == 0) {
dump_path = strdup("dump.vcd");
}
if (dump_path == 0) dump_path = strdup("dump.vcd");
dump_file = fopen(dump_path, "w");
if (dump_file == 0) {
vpi_mcd_printf(1,
"VCD Error: Unable to open %s for output.\n",
vpi_mcd_printf(1, "VCD Error: Unable to open %s for output.\n",
dump_path);
vpi_control(vpiFinish, 1);
return;
} else {
int prec = vpi_get(vpiTimePrecision, 0);
@ -410,8 +391,7 @@ static void open_dumpfile(void)
unsigned udx = 0;
time_t walltime;
vpi_mcd_printf(1,
"VCD info: dumpfile %s opened for output.\n",
vpi_mcd_printf(1, "VCD info: dumpfile %s opened for output.\n",
dump_path);
time(&walltime);
@ -438,91 +418,41 @@ static void open_dumpfile(void)
}
}
static PLI_INT32 sys_dumpfile_compiletf(PLI_BYTE8*name)
static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name)
{
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle item;
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
s_vpi_value value;
char*path;
if (argv && (item = vpi_scan(argv))) {
s_vpi_value value;
if (vpi_get(vpiType, item) != vpiConstant
|| vpi_get(vpiConstType, item) != vpiStringConst) {
vpi_mcd_printf(1,
"VCD Error:"
" %s parameter must be a string constant\n",
name);
return 0;
}
value.format = vpiStringVal;
vpi_get_value(item, &value);
path = strdup(value.value.str);
vpi_free_object(argv);
} else {
path = strdup("dump.vcd");
/* $dumpfile must be called before $dumpvars starts! */
if (dumpvars_status != 0) {
vpi_mcd_printf(1, "VCD warning: %s called after $dumpvars started"
",\n using existing file (%s).\n",
name, dump_path);
return 0;
}
assert(argv);
value.format = vpiStringVal;
vpi_get_value(vpi_scan(argv), &value);
path = strdup(value.value.str);
if (dump_path) {
vpi_mcd_printf(1, "VCD Warning:"
" Overriding dumpfile path %s with %s\n",
dump_path, path);
vpi_mcd_printf(1, "VCD warning: Overriding dump file %s with"
" %s\n", dump_path, path);
free(dump_path);
}
dump_path = path;
return 0;
}
static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name)
{
vpi_free_object(argv);
return 0;
}
static PLI_INT32 sys_dumpflush_calltf(PLI_BYTE8*name)
{
if (dump_file)
fflush(dump_file);
return 0;
}
static PLI_INT32 sys_dumplimit_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle limit;
/* Check that there is a argument and get it. */
if (argv == 0) {
vpi_printf("ERROR: %s requires an argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
limit = vpi_scan(argv);
/* Check that we are not given a string. */
switch (vpi_get(vpiType, limit)) {
case vpiConstant:
case vpiParameter:
if (vpi_get(vpiConstType, limit) == vpiStringConst) {
vpi_printf("ERROR: %s's argument must be a number.\n", name);
}
}
/* Check that there is only a single argument. */
limit = vpi_scan(argv);
if (limit != 0) {
vpi_printf("ERROR: %s takes a single argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
if (dump_file) fflush(dump_file);
return 0;
}
@ -531,12 +461,12 @@ static PLI_INT32 sys_dumplimit_calltf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle limit = vpi_scan(argv);
s_vpi_value val;
/* Get the value and set the dump limit. */
assert(argv);
val.format = vpiIntVal;
vpi_get_value(limit, &val);
vpi_get_value(vpi_scan(argv), &val);
dump_limit = val.value.integer;
vpi_free_object(argv);
@ -593,8 +523,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
break;
}
if (skip)
break;
if (skip) break;
name = vpi_get_str(vpiName, item);
prefix = is_escaped_id(name) ? "\\" : "";
@ -611,8 +540,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
ident = strdup(vcdid);
gen_new_vcd_id();
if (nexus_id)
set_nexus_ident(nexus_id, ident);
if (nexus_id) set_nexus_ident(nexus_id, ident);
info = malloc(sizeof(*info));
@ -660,8 +588,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
break;
}
if (skip)
break;
if (skip) break;
/* Declare the variable in the VCD file. */
name = vpi_get_str(vpiName, item);
@ -718,11 +645,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
if (!nskip)
vcd_names_add(&vcd_tab, fullname);
else
vpi_mcd_printf(1,
"VCD warning:"
" ignoring signals"
" in previously scanned scope %s\n",
fullname);
vpi_mcd_printf(1, "VCD warning: ignoring signals in"
" previously scanned scope %s\n", fullname);
name = vpi_get_str(vpiName, item);
@ -741,8 +665,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
break;
default:
vpi_mcd_printf(1,
"VCD Error: $dumpvars: Unsupported parameter "
vpi_mcd_printf(1, "VCD warning: $dumpvars: Unsupported parameter "
"type (%d)\n", vpi_get(vpiType, item));
}
}
@ -754,8 +677,7 @@ static int draw_scope(vpiHandle item)
char *type;
vpiHandle scope = vpi_handle(vpiScope, item);
if (!scope)
return 0;
if (!scope) return 0;
depth = 1 + draw_scope(scope);
name = vpi_get_str(vpiName, scope);
@ -773,103 +695,37 @@ static int draw_scope(vpiHandle item)
return depth;
}
/*
* This function is also used in sys_lxt to check the arguments of the
* lxt variant of $dumpvars.
*/
PLI_INT32 sys_vcd_dumpvars_compiletf(PLI_BYTE8*name)
{
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle tmp;
if (argv == 0)
return 0;
tmp = vpi_scan(argv);
assert(tmp);
switch (vpi_get(vpiType, tmp)) {
case vpiConstant:
if (vpi_get(vpiConstType, tmp) == vpiStringConst) {
vpi_printf("ERROR: %s argument must be "
"a number constant.\n", name);
vpi_control(vpiFinish, 1);
}
break;
case vpiNet:
case vpiReg:
case vpiIntegerVar:
case vpiMemoryWord:
break;
default:
vpi_printf("ERROR: %s argument must be "
"a number constant.\n", name);
vpi_control(vpiFinish, 1);
break;
}
vpi_free_object(argv);
return 0;
}
static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name)
{
unsigned depth;
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle item;
s_vpi_value value;
vpiHandle item = 0;
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv;
unsigned depth = 0;
if (dump_file == 0) {
open_dumpfile();
if (dump_file == 0)
return 0;
if (dump_file == 0) return 0;
}
if (install_dumpvars_callback()) {
return 0;
if (install_dumpvars_callback()) return 0;
/* Get the depth if it exists. */
if (argv) {
value.format = vpiIntVal;
vpi_get_value(vpi_scan(argv), &value);
depth = value.value.integer;
}
if (!depth) depth = 10000;
/* This dumps all the modules in the design if none are given. */
if (!argv || !(item = vpi_scan(argv))) {
argv = vpi_iterate(vpiModule, 0x0);
assert(argv); // There must be at least one top level module.
item = vpi_scan(argv);
}
argv = vpi_iterate(vpiArgument, sys);
depth = 0;
if (argv && (item = vpi_scan(argv)))
switch (vpi_get(vpiType, item)) {
case vpiConstant:
case vpiNet:
case vpiReg:
case vpiIntegerVar:
case vpiMemoryWord:
value.format = vpiIntVal;
vpi_get_value(item, &value);
depth = value.value.integer;
break;
}
if (!depth)
depth = 10000;
if (!argv) {
// $dumpvars;
// search for the toplevel module
vpiHandle parent = vpi_handle(vpiScope, sys);
while (parent) {
item = parent;
parent = vpi_handle(vpiScope, item);
}
} else if (!item || !(item = vpi_scan(argv))) {
// $dumpvars(level);
// $dumpvars();
// dump the current scope
item = vpi_handle(vpiScope, sys);
argv = 0x0;
}
for ( ; item; item = argv ? vpi_scan(argv) : 0x0) {
for ( ; item; item = vpi_scan(argv)) {
const char *scname;
int add_var = 0;
@ -879,6 +735,7 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name)
* been included. */
switch (vpi_get(vpiType, item)) {
case vpiIntegerVar:
/* What about MemoryWord? */
case vpiNet:
case vpiRealVar:
case vpiReg:
@ -898,9 +755,7 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name)
scan_item(depth, item, 0);
while (dep--) {
fprintf(dump_file, "$upscope $end\n");
}
while (dep--) fprintf(dump_file, "$upscope $end\n");
/* Add this signal to the variable list so we can verify it
* is not included twice. This must be done after it has
@ -918,30 +773,16 @@ void sys_vcd_register()
{
s_vpi_systf_data tf_data;
/* All the compiletf routines are located in vcd_priv.c. */
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpall";
tf_data.calltf = sys_dumpall_calltf;
tf_data.compiletf = 0;
tf_data.compiletf = sys_dumpall_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpall";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpoff";
tf_data.calltf = sys_dumpoff_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpoff";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpon";
tf_data.calltf = sys_dumpon_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpon";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpfile";
tf_data.calltf = sys_dumpfile_calltf;
@ -953,7 +794,7 @@ void sys_vcd_register()
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpflush";
tf_data.calltf = sys_dumpflush_calltf;
tf_data.compiletf = 0;
tf_data.compiletf = sys_dumpflush_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpflush";
vpi_register_systf(&tf_data);
@ -966,10 +807,26 @@ void sys_vcd_register()
tf_data.user_data = "$dumplimit";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpoff";
tf_data.calltf = sys_dumpoff_calltf;
tf_data.compiletf = sys_dumpoff_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpoff";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpon";
tf_data.calltf = sys_dumpon_calltf;
tf_data.compiletf = sys_dumpon_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpon";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpvars";
tf_data.calltf = sys_dumpvars_calltf;
tf_data.compiletf = sys_vcd_dumpvars_compiletf;
tf_data.compiletf = sys_dumpvars_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpvars";
vpi_register_systf(&tf_data);

View File

@ -23,8 +23,7 @@
# include "sys_priv.h"
/*
* This file contains the implementations of the VCD related
* functions. These are stub versions
* This file contains do nothing stubs of all the VCD routines.
*/
# include "vpi_user.h"
@ -39,86 +38,18 @@
# include "vcd_priv.h"
static FILE*dump_file = 0;
static int dump_flag = 0;
static PLI_INT32 sys_dumpoff_calltf(PLI_BYTE8*name)
static PLI_INT32 sys_dump_calltf(PLI_BYTE8*name)
{
return 0;
}
static PLI_INT32 sys_dumpon_calltf(PLI_BYTE8*name)
{
return 0;
}
static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name)
{
return 0;
}
static void open_dumpfile(const char*path)
{
dump_file = fopen(path, "w");
if (dump_file == 0) {
vpi_mcd_printf(6,
"VCD Error: Unable to open %s for output.\n",
path);
return;
} else {
fprintf(dump_file, "VCD Dump suppressed.\n");
}
}
static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name)
{
char*path;
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle item;
if (argv && (item = vpi_scan(argv))) {
s_vpi_value value;
if (vpi_get(vpiType, item) != vpiConstant
|| vpi_get(vpiConstType, item) != vpiStringConst) {
vpi_mcd_printf(6,
"VCD Error:"
" %s parameter must be a string constant\n",
name);
return 0;
}
value.format = vpiStringVal;
vpi_get_value(item, &value);
path = strdup(value.value.str);
vpi_free_object(argv);
} else {
path = strdup("dumpfile.vcd");
}
if (dump_file) {
fclose(dump_file);
dump_file = 0;
}
assert(dump_file == 0);
open_dumpfile(path);
free(path);
return 0;
}
static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name)
{
if (dump_file == 0) {
open_dumpfile("dumpfile.vcd");
if (dump_file == 0)
return 0;
if (dump_flag == 0) {
vpi_mcd_printf(1, "VCD info: dumping is suppressed.\n");
dump_flag = 1;
}
return 0;
@ -128,63 +59,62 @@ void sys_vcdoff_register()
{
s_vpi_systf_data tf_data;
/* All the compiletf routines are located in vcd_priv.c. */
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpall";
tf_data.calltf = sys_dumpall_calltf;
tf_data.compiletf = 0;
tf_data.calltf = sys_dump_calltf;
tf_data.compiletf = sys_dumpall_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpall";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpfile";
tf_data.calltf = sys_dump_calltf;
tf_data.compiletf = sys_dumpfile_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpfile";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpflush";
tf_data.calltf = sys_dump_calltf;
tf_data.compiletf = sys_dumpflush_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpflush";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumplimit";
tf_data.calltf = sys_dump_calltf;
tf_data.compiletf = sys_dumplimit_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumplimit";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpoff";
tf_data.calltf = sys_dumpoff_calltf;
tf_data.compiletf = 0;
tf_data.calltf = sys_dump_calltf;
tf_data.compiletf = sys_dumpoff_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpoff";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpon";
tf_data.calltf = sys_dumpon_calltf;
tf_data.compiletf = 0;
tf_data.calltf = sys_dump_calltf;
tf_data.compiletf = sys_dumpon_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpon";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpfile";
tf_data.calltf = sys_dumpfile_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpfile";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysTask;
tf_data.tfname = "$dumpvars";
tf_data.calltf = sys_dumpvars_calltf;
tf_data.compiletf = sys_vcd_dumpvars_compiletf;
tf_data.compiletf = sys_dumpvars_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$dumpvars";
vpi_register_systf(&tf_data);
}
/*
* $Log: sys_vcdoff.c,v $
* Revision 1.5 2007/03/14 04:05:52 steve
* VPI tasks take PLI_BYTE* by the standard.
*
* Revision 1.4 2006/10/30 22:45:38 steve
* Updates for Cygwin portability (pr1585922)
*
* Revision 1.3 2004/10/04 01:10:58 steve
* Clean up spurious trailing white space.
*
* Revision 1.2 2004/01/21 01:22:53 steve
* Give the vip directory its own configure and vpi_config.h
*
* Revision 1.1 2003/03/06 20:04:42 steve
* Add means to suppress wveform output
*
*/

View File

@ -188,3 +188,205 @@ void set_nexus_ident(int nex, const char *id)
vcd_ids[ihash(nex)] = bucket;
}
/* This is used by the compiletf routines to check if an argument
* is numeric. */
static void check_numeric_arg(vpiHandle arg, char *msg, PLI_BYTE8 *name)
{
assert(arg);
switch (vpi_get(vpiType, arg)) {
case vpiConstant:
case vpiParameter:
/* String constants are invalid numeric values. */
if (vpi_get(vpiConstType, arg) == vpiStringConst) {
vpi_mcd_printf(1, msg, name);
vpi_control(vpiFinish, 1);
}
break;
/* These have valid numeric values. */
case vpiIntegerVar:
case vpiMemoryWord:
case vpiNet:
case vpiRealVar:
case vpiReg:
case vpiTimeVar:
break;
default:
/* Anything else is not a numeric value. */
vpi_mcd_printf(1, msg, name);
vpi_control(vpiFinish, 1);
break;
}
}
/* This is used by the compiletf routines to check if an argument
* is a string value. */
static void check_string_arg(vpiHandle arg, char *msg, PLI_BYTE8 *name)
{
assert(arg);
PLI_INT32 ctype = 0;
switch (vpi_get(vpiType, arg)) {
case vpiConstant:
case vpiParameter:
/* These must be a string or binary constant. */
ctype = vpi_get(vpiConstType, arg);
if (ctype != vpiStringConst && ctype != vpiBinaryConst) {
vpi_mcd_printf(1, msg, name);
vpi_control(vpiFinish, 1);
}
break;
/* These have valid string values. */
case vpiIntegerVar:
case vpiMemoryWord:
case vpiNet:
case vpiReg:
case vpiTimeVar:
break;
default:
/* Anything else is not a string. */
vpi_mcd_printf(1, msg, name);
vpi_control(vpiFinish, 1);
break;
}
}
/*
* Since the compiletf routines are all the same they are located here,
* so we only need a single copy.
*/
/* $dumpall does not take an argument. */
PLI_INT32 sys_dumpall_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
if (argv != 0) {
vpi_mcd_printf(1, "ERROR: %s does not take an argument.\n", name);
vpi_control(vpiFinish, 1);
}
return 0;
}
/* $dumpfile takes a single string argument. */
PLI_INT32 sys_dumpfile_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle file;
/* Check that there is an argument and that it is a string. */
if (argv == 0) {
vpi_mcd_printf(1, "ERROR: %s requires an argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
check_string_arg(vpi_scan(argv), "ERROR: %s's argument must be a"
" string.\n", name);
/* Check that there is only a single argument. */
if (vpi_scan(argv) != 0) {
vpi_mcd_printf(1, "ERROR: %s takes a single argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
return 0;
}
/* $dumpflush does not take an argument. */
PLI_INT32 sys_dumpflush_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
if (argv != 0) {
vpi_mcd_printf(1, "ERROR: %s does not take an argument.\n", name);
vpi_control(vpiFinish, 1);
}
return 0;
}
/* $dumplimit takes a single numeric argument. */
PLI_INT32 sys_dumplimit_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
/* Check that there is an argument and that it is numeric. */
if (argv == 0) {
vpi_mcd_printf(1, "ERROR: %s requires an argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
check_numeric_arg(vpi_scan(argv), "ERROR: %s's argument must be"
" numeric.\n", name);
/* Check that there is only a single argument. */
if (vpi_scan(argv) != 0) {
vpi_mcd_printf(1, "ERROR: %s takes a single argument.\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
return 0;
}
/* $dumpoff does not take an argument. */
PLI_INT32 sys_dumpoff_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
if (argv != 0) {
vpi_mcd_printf(1, "ERROR: %s does not take an argument.\n", name);
vpi_control(vpiFinish, 1);
}
return 0;
}
/* $dumpon does not take an argument. */
PLI_INT32 sys_dumpon_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
if (argv != 0) {
vpi_mcd_printf(1, "ERROR: %s does not take an argument.\n", name);
vpi_control(vpiFinish, 1);
}
return 0;
}
/* $dumpvars takes a variety of arguments. */
PLI_INT32 sys_dumpvars_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle arg;
/* No arguments is OK, dump everything. */
if (argv == 0)
return 0;
/* The first argument is the numeric level. */
check_numeric_arg(vpi_scan(argv), "ERROR: %s's first argument must be"
" numeric.\n", name);
/* The rest of the arguments are either a module or a variable. */
while (arg = vpi_scan(argv)) {
/* Need variable checks here. */
}
return 0;
}

View File

@ -22,6 +22,8 @@
#ident "$Id: vcd_priv.h,v 1.2 2003/02/13 18:13:28 steve Exp $"
#endif
#include "vpi_user.h"
extern int is_escaped_id(const char *name);
struct vcd_names_s;
@ -44,4 +46,13 @@ extern void vcd_names_sort(struct vcd_names_list_s*tab);
extern const char*find_nexus_ident(int nex);
extern void set_nexus_ident(int nex, const char *id);
/* The compiletf routines are common for the VCD, LXT and LXT2 dumpers. */
extern PLI_INT32 sys_dumpall_compiletf(PLI_BYTE8 *name);
extern PLI_INT32 sys_dumpfile_compiletf(PLI_BYTE8 *name);
extern PLI_INT32 sys_dumpflush_compiletf(PLI_BYTE8 *name);
extern PLI_INT32 sys_dumplimit_compiletf(PLI_BYTE8 *name);
extern PLI_INT32 sys_dumpoff_compiletf(PLI_BYTE8 *name);
extern PLI_INT32 sys_dumpon_compiletf(PLI_BYTE8 *name);
extern PLI_INT32 sys_dumpvars_compiletf(PLI_BYTE8 *name);
#endif

View File

@ -68,26 +68,20 @@ There are a few extended arguments that are interpreted by the
standard system.vpi module, which implements the standard system tasks
and so is always included. These arguments are described here.
.TP 8
.B -vcd\fR|\fP-vcd-none
.B -vcd
This extended argument sets the wave dump format to VCD. This is the
default in the absence of any \fBIVERILOG_DUMPER\fP environment
variable. The VCD dump files are large and ponderous, but are also
maximally compatible with third party tools that read waveform dumps.
.PP
The \fB-vcd-none\fP variant actually suppresses all waveform
output. This can make long simulations run faster.
.TP 8
.B -lxt\fR|\fP-lxt-speed\fR|\fP-lxt-space\fR|\fP-lxt-none
.B -lxt\fR|\fP-lxt-speed\fR|\fP-lxt-space
These extended arguments set the wave dump format to lxt, possibly with
format optimizations. The \fB-lxt-space\fP flag sets the output
format to lxt with full compression enabled. The resulting files are
quite small. The \fB-lxt-speed\fP chooses the lxt compression mode
that leads to the best execution time and the fastest read time, at
the expense of some file size.
.PP
The \fB-lxt-none\fP variant actually suppresses all waveform
output. This can make long simulations run faster.
.TP 8
.B -lxt2\fR|\fP-lx2
@ -96,14 +90,20 @@ space, and is written out incrementally. Thus, you can view lxt2 files
while a simulation is still running (or paused) or if your simulation
crashes or is killed, you still have a useful dump.
.TP 8
.B -none
This flag can be used by itself or appended to the end of the above
dumpers (vcd/lxt/lxt2/lx2) to suppress all waveform output. This can
make long simulations run faster.
.TP 8
.B -sdf-warn
When loading an SDF annnotation file, this option causes the annotator
When loading an SDF annotation file, this option causes the annotator
to print warnings for questionable but non-fatal issues.
.TP 8
.B -sdf-info
When loading an SDF annnotation file, this option causes the annotator
When loading an SDF annotation file, this option causes the annotator
to print information about the annotation.
.TP 8