More coverage of $dump related commands.

This commit is contained in:
steve 2001-10-14 18:32:06 +00:00
parent 2fcab15704
commit f7fa2f1f4d
1 changed files with 196 additions and 142 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) && !defined(macintosh) #if !defined(WINNT) && !defined(macintosh)
#ident "$Id: sys_vcd.c,v 1.22 2001/10/08 23:33:00 steve Exp $" #ident "$Id: sys_vcd.c,v 1.23 2001/10/14 18:32:06 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -116,6 +116,16 @@ static void show_this_item(struct vcd_info*info)
} }
static void show_this_item_x(struct vcd_info*info)
{
if (vpi_get(vpiSize, info->item) == 1) {
fprintf(dump_file, "x%s\n", info->ident);
} else {
fprintf(dump_file, "bx %s\n", info->ident);
}
}
/* /*
* managed qsorted list of scope names for duplicates bsearching * managed qsorted list of scope names for duplicates bsearching
*/ */
@ -208,6 +218,14 @@ static void vcd_checkpoint()
show_this_item(cur); show_this_item(cur);
} }
static void vcd_checkpoint_x()
{
struct vcd_info*cur;
for (cur = vcd_list ; cur ; cur = cur->next)
show_this_item_x(cur);
}
static int variable_cb(p_cb_data cause) static int variable_cb(p_cb_data cause)
{ {
unsigned long now = cause->time->low; unsigned long now = cause->time->low;
@ -266,12 +284,10 @@ inline static int install_dumpvars_callback(void)
return 0; return 0;
if (dumpvars_status == 2) { if (dumpvars_status == 2) {
fprintf(stderr, vpi_mcd_printf(6, "VCD Error:"
"VCD error:" " $dumpvars ignored,"
" $dumpvars ignored\n" " previously called at simtime %lu\n",
"VCD error:" dumpvars_time);
" $dumpvars was previously called at simtime %lu\n",
dumpvars_time);
return 1; return 1;
} }
@ -290,13 +306,38 @@ inline static int install_dumpvars_callback(void)
static int sys_dumpoff_calltf(char*name) static int sys_dumpoff_calltf(char*name)
{ {
s_vpi_time now;
if (dump_is_off)
return 0;
dump_is_off = 1; dump_is_off = 1;
if (dump_file == 0)
return 0;
if (dump_header_pending())
return 0;
vpi_get_time(0, &now);
if (now.low > vcd_cur_time)
fprintf(dump_file, "#%u\n", now.low);
vcd_cur_time = now.low;
fprintf(dump_file, "$dumpoff\n");
vcd_checkpoint_x();
fprintf(dump_file, "$end\n");
return 0; return 0;
} }
static int sys_dumpon_calltf(char*name) static int sys_dumpon_calltf(char*name)
{ {
s_vpi_time now; s_vpi_time now;
if (!dump_is_off)
return 0;
dump_is_off = 0; dump_is_off = 0;
if (dump_file == 0) if (dump_file == 0)
@ -306,11 +347,13 @@ static int sys_dumpon_calltf(char*name)
return 0; return 0;
vpi_get_time(0, &now); vpi_get_time(0, &now);
if (now.low > vcd_cur_time) { if (now.low > vcd_cur_time)
fprintf(dump_file, "#%u\n", now.low); fprintf(dump_file, "#%u\n", now.low);
vcd_cur_time = now.low; vcd_cur_time = now.low;
vcd_checkpoint();
} fprintf(dump_file, "$dumpon\n");
vcd_checkpoint();
fprintf(dump_file, "$end\n");
return 0; return 0;
} }
@ -326,9 +369,13 @@ static int sys_dumpall_calltf(char*name)
return 0; return 0;
vpi_get_time(0, &now); vpi_get_time(0, &now);
fprintf(dump_file, "#%u\n", now.low); if (now.low > vcd_cur_time)
fprintf(dump_file, "#%u\n", now.low);
vcd_cur_time = now.low; vcd_cur_time = now.low;
fprintf(dump_file, "$dumpall\n");
vcd_checkpoint(); vcd_checkpoint();
fprintf(dump_file, "$end\n");
return 0; return 0;
} }
@ -338,7 +385,9 @@ static void open_dumpfile(const char*path)
dump_file = fopen(path, "w"); dump_file = fopen(path, "w");
if (dump_file == 0) { if (dump_file == 0) {
vpi_printf("ERROR: Unable to open %s for output.\n", path); vpi_mcd_printf(6,
"VCD Error: Unable to open %s for output.\n",
path);
return; return;
} else { } else {
int prec = vpi_get(vpiTimePrecision, 0); int prec = vpi_get(vpiTimePrecision, 0);
@ -376,18 +425,17 @@ static int sys_dumpfile_calltf(char*name)
vpiHandle sys = vpi_handle(vpiSysTfCall, 0); vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys); vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle item;
if (argv) { if (argv && (item = vpi_scan(argv))) {
vpiHandle item = vpi_scan(argv);
s_vpi_value value; s_vpi_value value;
if (vpi_get(vpiType, item) != vpiConstant) { if (vpi_get(vpiType, item) != vpiConstant
vpi_printf("ERROR: %s parameter must be a constant\n", name); || vpi_get(vpiConstType, item) != vpiStringConst) {
return 0; vpi_mcd_printf(6,
} "VCD Error:"
" %s parameter must be a string constant\n",
if (vpi_get(vpiConstType, item) != vpiStringConst) { name);
vpi_printf("ERROR: %s parameter must be a constant\n", name);
return 0; return 0;
} }
@ -474,115 +522,110 @@ inline static void set_nexus_ident(int nex, const char *id)
vcd_ids[ihash(nex)] = bucket; vcd_ids[ihash(nex)] = bucket;
} }
static void scan_item(unsigned depth, vpiHandle item, int skip)
static void scan_scope(unsigned depth, vpiHandle argv, int skip)
{ {
struct t_cb_data cb; struct t_cb_data cb;
struct vcd_info*info; struct vcd_info* info;
vpiHandle item; const char* type;
vpiHandle sublist; const char* fullname;
const char* ident;
int nexus_id;
cb.reason = cbValueChange; switch (vpi_get(vpiType, item)) {
cb.cb_rtn = variable_cb; case vpiNet:
case vpiReg:
for (item = vpi_scan(argv) ; item ; item = vpi_scan(argv)) { if (skip)
const char*type;
const char*fullname;
const char* ident;
int nexus_id;
switch (vpi_get(vpiType, item)) {
case vpiNet:
case vpiReg:
if (skip)
break;
fullname = vpi_get_str(vpiFullName, item);
type = "wire";
if (vpi_get(vpiType, item) == vpiReg)
type = "reg";
nexus_id = vpi_get(_vpiNexusId, item);
if (nexus_id) {
ident = find_nexus_ident(nexus_id);
} else {
ident = 0;
}
if (!ident) {
ident = strdup(vcdid);
gen_new_vcd_id();
if (nexus_id)
set_nexus_ident(nexus_id, ident);
info = malloc(sizeof(*info));
info->time.type = vpiSimTime;
cb.time = &info->time;
cb.user_data = (char*)info;
cb.obj = item;
info->item = item;
info->ident = ident;
info->cb = vpi_register_cb(&cb);
info->next = vcd_list;
vcd_list = info;
}
fprintf(dump_file, "$var %s %u %s %s $end\n",
type, vpi_get(vpiSize, item), ident,
fullname);
break; break;
case vpiModule: fullname = vpi_get_str(vpiFullName, item);
case vpiNamedBegin:
case vpiTask: type = "wire";
case vpiFunction: if (vpi_get(vpiType, item) == vpiReg)
if (depth > 0) { type = "reg";
static int scan_depth = 0;
nexus_id = vpi_get(_vpiNexusId, item);
const char* fullname =
vpi_get_str(vpiFullName, item); if (nexus_id) {
ident = find_nexus_ident(nexus_id);
} else {
ident = 0;
}
if (!ident) {
ident = strdup(vcdid);
gen_new_vcd_id();
if (nexus_id)
set_nexus_ident(nexus_id, ident);
info = malloc(sizeof(*info));
int nskip; info->time.type = vpiSimTime;
info->item = item;
/* info->ident = ident;
Scopes can be scanned multiple times if
arguments to $dumpvars() overlap.
While we are decending into a scope, we cannot
encounter duplicates from the current root scope.
So we need to add the list of previously scanned
scopes only before scanning a new root scope.
Explicitely specified signals are not covered. cb.time = &info->time;
*/ cb.user_data = (char*)info;
cb.obj = item;
cb.reason = cbValueChange;
cb.cb_rtn = variable_cb;
if (scan_depth == 0) info->next = vcd_list;
vcd_names_sort(); vcd_list = info;
nskip = sorted_names && fullname info->cb = vpi_register_cb(&cb);
&& vcd_names_search(fullname); }
fprintf(dump_file, "$var %s %u %s %s $end\n",
type, vpi_get(vpiSize, item), ident,
fullname);
break;
case vpiModule:
case vpiNamedBegin:
case vpiTask:
case vpiFunction:
if (depth > 0) {
int nskip;
vpiHandle argv;
if (!nskip) const char* fullname =
vcd_names_add(fullname); vpi_get_str(vpiFullName, item);
sublist = vpi_iterate(vpiInternalScope, item); vpi_mcd_printf(4,
if (sublist) { "VCD info:"
scan_depth++; " scanning scope %s, %u levels\n",
scan_scope(depth-1, sublist, nskip); fullname, depth);
scan_depth--;
nskip = sorted_names && fullname
&& vcd_names_search(fullname);
if (!nskip)
vcd_names_add(fullname);
else
vpi_mcd_printf(6,
"VCD warning:"
" ignoring signals"
" in previously scanned scope %s\n",
fullname);
argv = vpi_iterate(vpiInternalScope, item);
if (argv) {
for (item = vpi_scan(argv) ;
item ;
item = vpi_scan(argv)) {
scan_item(depth-1, item, nskip);
} }
} }
break;
default:
vpi_printf("ERROR: $dumpvars: Unsupported parameter "
"type (%d)\n", vpi_get(vpiType, item));
} }
break;
default:
vpi_mcd_printf(6,
"VCD Error: $dumpvars: Unsupported parameter "
"type (%d)\n", vpi_get(vpiType, item));
} }
} }
@ -590,19 +633,14 @@ static int sys_dumpvars_calltf(char*name)
{ {
unsigned depth; unsigned depth;
s_vpi_value value; s_vpi_value value;
vpiHandle item; vpiHandle item = 0;
vpiHandle sys = vpi_handle(vpiSysTfCall, 0); vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv; vpiHandle argv;
if (dump_file == 0) { if (dump_file == 0) {
vpi_printf("warning: %s caused default dumpfile "
"dumpfile.vcd to be opened.\n", name);
open_dumpfile("dumpfile.vcd"); open_dumpfile("dumpfile.vcd");
if (dump_file == 0) { if (dump_file == 0)
vpi_printf("error: Unable to open "
"dumpfile.vcd for output.\n");
return 0; return 0;
}
} }
if (install_dumpvars_callback()) { if (install_dumpvars_callback()) {
@ -610,29 +648,42 @@ static int sys_dumpvars_calltf(char*name)
} }
argv = vpi_iterate(vpiArgument, sys); argv = vpi_iterate(vpiArgument, sys);
if (argv == 0) {
vpi_printf("SORRY: %s requires arguments\n", name); depth = 0;
if (argv && (item = vpi_scan(argv)))
switch (vpi_get(vpiType, item)) {
case vpiConstant:
case vpiNet:
case vpiReg:
case vpiMemoryWord:
value.format = vpiIntVal;
vpi_get_value(item, &value);
depth = value.value.integer;
break;
}
if (!depth)
depth = 10000;
if (!argv) {
// item = (how do I get the top level scope?);
// assert(item);
// scan_item(depth, item, 0);
// return 0
}
if (!argv || !item || !(item = vpi_scan(argv))) {
item = vpi_handle(vpiScope, sys);
assert(item);
scan_item(depth, item, 0);
return 0; return 0;
} }
item = vpi_scan(argv); for ( ; item; item = vpi_scan(argv)) {
switch (vpi_get(vpiType, item)) { vcd_names_sort();
case vpiConstant: scan_item(depth, item, 0);
case vpiNet:
case vpiReg:
case vpiMemoryWord:
value.format = vpiIntVal;
vpi_get_value(item, &value);
break;
default:
value.value.integer = 0;
break;
} }
depth = value.value.integer == 0? 0xffffU : value.value.integer;
scan_scope(depth, argv, 0);
return 0; return 0;
} }
@ -683,6 +734,9 @@ void sys_vcd_register()
/* /*
* $Log: sys_vcd.c,v $ * $Log: sys_vcd.c,v $
* Revision 1.23 2001/10/14 18:32:06 steve
* More coverage of $dump related commands.
*
* Revision 1.22 2001/10/08 23:33:00 steve * Revision 1.22 2001/10/08 23:33:00 steve
* Fix pr283: signal values before enddefinitions in vcd. (Stephan Boettcher) * Fix pr283: signal values before enddefinitions in vcd. (Stephan Boettcher)
* *