Merge pull request #714 from steveicarus/steveicarus/issue156-vcd-dump-parameter

Add parameters to vcd dumps
This commit is contained in:
Stephen Williams 2022-05-17 08:37:21 -07:00 committed by GitHub
commit 5d97405724
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 205 additions and 95 deletions

View File

@ -1,5 +1,5 @@
$date
Tue Apr 21 18:40:22 2009
Sun May 15 18:09:10 2022
$end
$version
Icarus Verilog
@ -17,6 +17,9 @@ $scope module top $end
$var reg 8 # \array[2] [7:0] $end
$upscope $end
$enddefinitions $end
$comment Show the parameter values. $end
$dumpall
$end
#0
$dumpvars
bx #

View File

@ -0,0 +1,25 @@
$date
Sun May 15 09:20:23 2022
$end
$version
Icarus Verilog
$end
$timescale
1s
$end
$scope module main $end
$var wire 4 ! bat [3:0] $end
$var parameter 4 " bar $end
$var parameter 4 # foo $end
$upscope $end
$enddefinitions $end
$comment Show the parameter values. $end
$dumpall
b101 #
b111 "
$end
#0
$dumpvars
b1100 !
$end
#1

View File

@ -1,5 +1,5 @@
$date
Wed Jun 4 10:37:42 2008
Sun May 15 18:09:25 2022
$end
$version
Icarus Verilog
@ -11,6 +11,9 @@ $scope module top $end
$var reg 8 ! \arr[4] [7:0] $end
$upscope $end
$enddefinitions $end
$comment Show the parameter values. $end
$dumpall
$end
#0
$dumpvars
b0 !

View File

@ -1,5 +1,5 @@
$date
Tue Sep 15 16:56:35 2009
Sun May 15 18:19:07 2022
$end
$version
Icarus Verilog
@ -16,6 +16,9 @@ $scope module top $end
$var reg 4 " \array[1] [3:0] $end
$upscope $end
$enddefinitions $end
$comment Show the parameter values. $end
$dumpall
$end
#0
$dumpvars
bx "

View File

@ -1,5 +1,5 @@
$date
Fri Oct 16 08:46:35 2009
Sun May 15 15:15:18 2022
$end
$version
Icarus Verilog
@ -53,6 +53,9 @@ $upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
$comment Show the parameter values. $end
$dumpall
$end
#0
$dumpvars
x/

View File

@ -0,0 +1,17 @@
//
// This tests that the parameter and localparam show up in the vcd dump.
//
module main;
parameter [3:0] foo = 4'd5;
localparam [3:0] bar = 7;
wire [3:0] bat = foo + bar;
initial begin
$dumpfile("work/br_gh156.vcd");
$dumpvars(0, main);
#1 $finish;
end
endmodule // main

View File

@ -309,6 +309,7 @@ br_gh127e normal ivltests gold=br_gh127e.gold
br_gh127f normal ivltests gold=br_gh127f.gold
br_gh142 CE ivltests
br_gh152 CE ivltests
br_gh156 normal ivltests diff=work/br_gh156.vcd:gold/br_gh156.vcd.gold:2
br_gh157 CE ivltests gold=br_gh157.gold
br_gh162 normal ivltests
br_gh163 CE ivltests

View File

@ -38,26 +38,17 @@ static struct fstContext *dump_file = NULL;
static struct t_vpi_time zero_delay = { vpiSimTime, 0, 0, 0.0 };
struct vcd_info {
vpiHandle item;
vpiHandle cb;
struct t_vpi_time time;
struct vcd_info *next;
struct vcd_info *dmp_next;
fstHandle handle;
int scheduled;
};
DECLARE_VCD_INFO(vcd_info, fstHandle);
static struct vcd_info *vcd_list = NULL;
static struct vcd_info *vcd_const_list = NULL;
static struct vcd_info *vcd_dmp_list = NULL;
static PLI_UINT64 vcd_cur_time = 0;
static int dump_is_off = 0;
static long dump_limit = 0;
static int dump_is_full = 0;
static int finish_status = 0;
static enum lxm_optimum_mode_e {
LXM_NONE = 0,
LXM_SPACE = 1,
@ -82,11 +73,11 @@ static void show_this_item(struct vcd_info*info)
if (type == vpiRealVar) {
value.format = vpiRealVal;
vpi_get_value(info->item, &value);
fstWriterEmitValueChange(dump_file, info->handle, &value.value.real);
fstWriterEmitValueChange(dump_file, info->ident, &value.value.real);
} else {
value.format = vpiBinStrVal;
vpi_get_value(info->item, &value);
fstWriterEmitValueChange(dump_file, info->handle, (type != vpiNamedEvent) ? value.value.str : "1");
fstWriterEmitValueChange(dump_file, info->ident, (type != vpiNamedEvent) ? value.value.str : "1");
}
}
@ -98,14 +89,14 @@ static void show_this_item_x(struct vcd_info*info)
if (type == vpiRealVar) {
/* Some tools dump nothing here...? */
double mynan = strtod("NaN", NULL);
fstWriterEmitValueChange(dump_file, info->handle, &mynan);
fstWriterEmitValueChange(dump_file, info->ident, &mynan);
} else if (type == vpiNamedEvent) {
/* Do nothing for named events. */
} else {
int siz = vpi_get(vpiSize, info->item);
char *xmem = malloc(siz);
memset(xmem, 'x', siz);
fstWriterEmitValueChange(dump_file, info->handle, xmem);
fstWriterEmitValueChange(dump_file, info->ident, xmem);
free(xmem);
}
}
@ -126,26 +117,6 @@ __inline__ static int dump_header_pending(void)
return dumpvars_status != 2;
}
/*
* This function writes out all the traced variables, whether they
* changed or not.
*/
static void vcd_checkpoint(void)
{
struct vcd_info*cur;
for (cur = vcd_list ; cur ; cur = cur->next)
show_this_item(cur);
}
static void vcd_checkpoint_x(void)
{
struct vcd_info*cur;
for (cur = vcd_list ; cur ; cur = cur->next)
show_this_item_x(cur);
}
static PLI_INT32 variable_cb_2(p_cb_data cause)
{
struct vcd_info* info = vcd_dmp_list;
@ -212,7 +183,8 @@ static PLI_INT32 dumpvars_cb(p_cb_data cause)
if (!dump_is_off) {
fstWriterEmitTimeChange(dump_file, dumpvars_time);
/* nothing to do for $dumpvars... */
vcd_checkpoint();
ITERATE_VCD_INFO(vcd_const_list, vcd_info, next, show_this_item);
ITERATE_VCD_INFO(vcd_list, vcd_info, next, show_this_item);
/* ...nothing to do for $end */
}
@ -240,6 +212,11 @@ static PLI_INT32 finish_cb(p_cb_data cause)
free(cur);
}
vcd_list = 0;
for (cur = vcd_const_list ; cur ; cur = next) {
next = cur->next;
free(cur);
}
vcd_const_list = 0;
vcd_names_delete(&fst_tab);
vcd_names_delete(&fst_var);
nexus_ident_delete();
@ -303,7 +280,7 @@ static PLI_INT32 sys_dumpoff_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
}
fstWriterEmitDumpActive(dump_file, 0); /* $dumpoff */
vcd_checkpoint_x();
ITERATE_VCD_INFO(vcd_list, vcd_info, next, show_this_item_x);
return 0;
}
@ -332,7 +309,7 @@ static PLI_INT32 sys_dumpon_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
}
fstWriterEmitDumpActive(dump_file, 1); /* $dumpon */
vcd_checkpoint();
ITERATE_VCD_INFO(vcd_list, vcd_info, next, show_this_item);
return 0;
}
@ -358,7 +335,7 @@ static PLI_INT32 sys_dumpall_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
}
/* nothing to do for $dumpall... */
vcd_checkpoint();
ITERATE_VCD_INFO(vcd_list, vcd_info, next, show_this_item);
return 0;
}
@ -574,10 +551,6 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
/* Generate the $var or $scope commands. */
switch (item_type) {
case vpiParameter:
vpi_printf("FST sorry: $dumpvars: can not dump parameters.\n");
break;
case vpiNamedEvent:
case vpiIntegerVar:
case vpiBitVar:
@ -648,7 +621,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
info->time.type = vpiSimTime;
info->item = item;
info->handle = new_ident;
info->ident = new_ident;
info->scheduled = 0;
cb.time = &info->time;
@ -667,6 +640,37 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
break;
case vpiParameter:
/* If we are skipping all pamaeters then just return. */
if (skip) return;
/* Skip this signal if it has already been included.
* This can only happen for implicitly given signals. */
if (vcd_names_search(&fst_var, fullname)) return;
name = vpi_get_str(vpiName, item);
if (is_escaped_id(name)) {
escname = malloc(strlen(name) + 2);
sprintf(escname, "\\%s", name);
} else escname = strdup(name);
size = vpi_get(vpiSize, item);
dir = FST_VD_IMPLICIT;
new_ident = fstWriterCreateVar(dump_file, type,
dir, size, escname, 0);
free(escname);
info = malloc(sizeof(*info));
info->item = item;
info->ident = new_ident;
info->scheduled = 0;
info->dmp_next = 0;
info->next = vcd_const_list;
info->cb = NULL;
vcd_const_list = info;
break;
case vpiModule:
case vpiPackage:
case vpiGenScope:
@ -683,7 +687,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
/* Value */
vpiNamedEvent,
vpiNet,
/* vpiParameter, */
vpiParameter,
vpiReg,
vpiVariables,
/* Scope */

View File

@ -37,19 +37,21 @@ static int dump_no_date = 0;
static struct t_vpi_time zero_delay = { vpiSimTime, 0, 0, 0.0 };
struct vcd_info {
vpiHandle item;
vpiHandle cb;
struct t_vpi_time time;
const char *ident;
struct vcd_info *next;
struct vcd_info *dmp_next;
int scheduled;
};
/*
* 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
* values for everything. When the item has a value change, it is added to the
* vcd_dmp_list for dumping in the current time step.
*
* The vcd_const_list is a list of all of the parameters that are being
* dumped. This list is scanned less often, since parameters do not change
* values.
*/
DECLARE_VCD_INFO(vcd_info, const char*);
static struct vcd_info *vcd_const_list = NULL;
static struct vcd_info *vcd_list = NULL;
static struct vcd_info *vcd_dmp_list = NULL;
static PLI_UINT64 vcd_cur_time = 0;
static int dump_is_off = 0;
static long dump_limit = 0;
@ -158,25 +160,6 @@ __inline__ static int dump_header_pending(void)
return dumpvars_status != 2;
}
/*
* This function writes out all the traced variables, whether they
* changed or not.
*/
static void vcd_checkpoint(void)
{
struct vcd_info*cur;
for (cur = vcd_list ; cur ; cur = cur->next)
show_this_item(cur);
}
static void vcd_checkpoint_x(void)
{
struct vcd_info*cur;
for (cur = vcd_list ; cur ; cur = cur->next)
show_this_item_x(cur);
}
static PLI_INT32 variable_cb_2(p_cb_data cause)
{
@ -232,6 +215,11 @@ static PLI_INT32 variable_cb_1(p_cb_data cause)
return 0;
}
/*
* This is called at the end of the timestep where the $dumpvars task is
* called. This allows for values to settle for the timestep, so that the
* checkpoint gets the current values.
*/
static PLI_INT32 dumpvars_cb(p_cb_data cause)
{
if (dumpvars_status != 1) return 0;
@ -244,9 +232,15 @@ static PLI_INT32 dumpvars_cb(p_cb_data cause)
fprintf(dump_file, "$enddefinitions $end\n");
if (!dump_is_off) {
fprintf(dump_file, "$comment Show the parameter values. $end\n");
fprintf(dump_file, "$dumpall\n");
ITERATE_VCD_INFO(vcd_const_list, vcd_info, next, show_this_item);
fprintf(dump_file, "$end\n");
fprintf(dump_file, "#%" PLI_UINT64_FMT "\n", dumpvars_time);
fprintf(dump_file, "$dumpvars\n");
vcd_checkpoint();
ITERATE_VCD_INFO(vcd_list, vcd_info, next, show_this_item);
fprintf(dump_file, "$end\n");
}
@ -275,6 +269,12 @@ static PLI_INT32 finish_cb(p_cb_data cause)
free(cur);
}
vcd_list = 0;
for (cur = vcd_const_list ; cur ; cur = next) {
next = cur->next;
free((char *)cur->ident);
free(cur);
}
vcd_const_list = 0;
vcd_names_delete(&vcd_tab);
vcd_names_delete(&vcd_var);
nexus_ident_delete();
@ -338,7 +338,7 @@ static PLI_INT32 sys_dumpoff_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
}
fprintf(dump_file, "$dumpoff\n");
vcd_checkpoint_x();
ITERATE_VCD_INFO(vcd_list, vcd_info, next, show_this_item_x);
fprintf(dump_file, "$end\n");
return 0;
@ -368,7 +368,7 @@ static PLI_INT32 sys_dumpon_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
}
fprintf(dump_file, "$dumpon\n");
vcd_checkpoint();
ITERATE_VCD_INFO(vcd_list, vcd_info, next, show_this_item);
fprintf(dump_file, "$end\n");
return 0;
@ -395,7 +395,7 @@ static PLI_INT32 sys_dumpall_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
}
fprintf(dump_file, "$dumpall\n");
vcd_checkpoint();
ITERATE_VCD_INFO(vcd_list, vcd_info, next, show_this_item);
fprintf(dump_file, "$end\n");
return 0;
@ -601,10 +601,6 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
/* Generate the $var or $scope commands. */
switch (item_type) {
case vpiParameter:
vpi_printf("VCD sorry: $dumpvars: can not dump parameters.\n");
break;
case vpiNamedEvent:
case vpiIntegerVar:
case vpiBitVar:
@ -618,7 +614,6 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
case vpiTimeVar:
case vpiNet:
/* If we are skipping all signal or this is in an automatic
* scope then just return. */
if (skip || vpi_get(vpiAutomatic, item)) return;
@ -684,6 +679,35 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
fprintf(dump_file, " $end\n");
break;
case vpiParameter:
/* If we are skipping all pamaeters then just return. */
if (skip) return;
size = vpi_get(vpiSize, item);
/* Declare the parameter in the VCD file. */
name = vpi_get_str(vpiName, item);
prefix = is_escaped_id(name) ? "\\" : "";
ident = strdup(vcdid);
gen_new_vcd_id();
/* Make an info item to go in the vcd_const_list. */
info = malloc(sizeof(*info));
info->item = item;
info->ident = ident;
info->scheduled = 0;
info->dmp_next = 0;
info->next = vcd_const_list;
vcd_const_list = info;
info->cb = NULL;
/* Generate the $var record. Now the parameter is declared. */
fprintf(dump_file, "$var %s %u %s %s%s $end\n",
type, size, ident, prefix, name);
break;
case vpiModule:
case vpiGenScope:
case vpiFunction:
@ -697,7 +721,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
/* Value */
vpiNamedEvent,
vpiNet,
/* vpiParameter, */
vpiParameter,
vpiReg,
vpiVariables,
/* Scope */

View File

@ -129,6 +129,35 @@ 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);
/*
* 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
* values for everything. When the item has a value change, it is added to the
* vcd_dmp_list for dumping in the current time step.
*
* The vcd_const_list is a list of all of the parameters that are being
* dumped. This list is scanned less often, since parameters do not change
* values.
*/
#define DECLARE_VCD_INFO(type_name, ident_type) \
struct type_name { \
vpiHandle item; \
vpiHandle cb;\
struct t_vpi_time time; \
struct vcd_info *next; \
struct vcd_info *dmp_next; \
int scheduled; \
ident_type ident; \
}
#define ITERATE_VCD_INFO(use_list, use_type, use_next, method) \
do { \
struct use_type*cur; \
for (cur = use_list ; cur ; cur = cur->use_next) \
method(cur); \
} while (0)
#undef EXTERN
#endif /* IVL_vcd_priv_H */

View File

@ -133,10 +133,9 @@ objects.
The syntax of a parameter is:
<label> .param/str <name>, <value>;
<label> .param/b <name>, <value> [<msb>,<lsb>];
<label> .param/l <name>, <value> [<msb>,<lsb>];
<label> .param/r <name>, <value>;
<label> .param/str <name> <local-flag> <file-idx> <lineno>, <value>;
<label> .param/l <name> <local-flag> <file-idx> <lineno>, <value>;
<label> .param/r <name> <local-flag> <file-idx> <lineno>, <value>;
The <name> is a string that names the parameter. The name is placed in
the current scope as a vpiParameter object. The .param suffix
@ -144,7 +143,6 @@ specifies the parameter type.
.param/str -- The parameter has a string value
.param/l -- The parameter has a logic vector value
.param/b -- The parameter has a boolean vector value
.param/r -- The parameter has a real value
The value, then, is appropriate for the data type. For example: