Add parameters to fst dumps
Add support for parameters (constants) in fst dumps. And while we are at it, factor out some of the declarations shared with sys_vcd.
This commit is contained in:
parent
a1485906ca
commit
73f40f73b0
|
|
@ -38,26 +38,17 @@ static struct fstContext *dump_file = NULL;
|
||||||
|
|
||||||
static struct t_vpi_time zero_delay = { vpiSimTime, 0, 0, 0.0 };
|
static struct t_vpi_time zero_delay = { vpiSimTime, 0, 0, 0.0 };
|
||||||
|
|
||||||
struct vcd_info {
|
DECLARE_VCD_INFO(vcd_info, fstHandle);
|
||||||
vpiHandle item;
|
|
||||||
vpiHandle cb;
|
|
||||||
struct t_vpi_time time;
|
|
||||||
struct vcd_info *next;
|
|
||||||
struct vcd_info *dmp_next;
|
|
||||||
fstHandle handle;
|
|
||||||
int scheduled;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static struct vcd_info *vcd_list = NULL;
|
static struct vcd_info *vcd_list = NULL;
|
||||||
|
static struct vcd_info *vcd_const_list = NULL;
|
||||||
static struct vcd_info *vcd_dmp_list = NULL;
|
static struct vcd_info *vcd_dmp_list = NULL;
|
||||||
|
|
||||||
static PLI_UINT64 vcd_cur_time = 0;
|
static PLI_UINT64 vcd_cur_time = 0;
|
||||||
static int dump_is_off = 0;
|
static int dump_is_off = 0;
|
||||||
static long dump_limit = 0;
|
static long dump_limit = 0;
|
||||||
static int dump_is_full = 0;
|
static int dump_is_full = 0;
|
||||||
static int finish_status = 0;
|
static int finish_status = 0;
|
||||||
|
|
||||||
|
|
||||||
static enum lxm_optimum_mode_e {
|
static enum lxm_optimum_mode_e {
|
||||||
LXM_NONE = 0,
|
LXM_NONE = 0,
|
||||||
LXM_SPACE = 1,
|
LXM_SPACE = 1,
|
||||||
|
|
@ -82,11 +73,11 @@ static void show_this_item(struct vcd_info*info)
|
||||||
if (type == vpiRealVar) {
|
if (type == vpiRealVar) {
|
||||||
value.format = vpiRealVal;
|
value.format = vpiRealVal;
|
||||||
vpi_get_value(info->item, &value);
|
vpi_get_value(info->item, &value);
|
||||||
fstWriterEmitValueChange(dump_file, info->handle, &value.value.real);
|
fstWriterEmitValueChange(dump_file, info->ident, &value.value.real);
|
||||||
} else {
|
} else {
|
||||||
value.format = vpiBinStrVal;
|
value.format = vpiBinStrVal;
|
||||||
vpi_get_value(info->item, &value);
|
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) {
|
if (type == vpiRealVar) {
|
||||||
/* Some tools dump nothing here...? */
|
/* Some tools dump nothing here...? */
|
||||||
double mynan = strtod("NaN", NULL);
|
double mynan = strtod("NaN", NULL);
|
||||||
fstWriterEmitValueChange(dump_file, info->handle, &mynan);
|
fstWriterEmitValueChange(dump_file, info->ident, &mynan);
|
||||||
} else if (type == vpiNamedEvent) {
|
} else if (type == vpiNamedEvent) {
|
||||||
/* Do nothing for named events. */
|
/* Do nothing for named events. */
|
||||||
} else {
|
} else {
|
||||||
int siz = vpi_get(vpiSize, info->item);
|
int siz = vpi_get(vpiSize, info->item);
|
||||||
char *xmem = malloc(siz);
|
char *xmem = malloc(siz);
|
||||||
memset(xmem, 'x', siz);
|
memset(xmem, 'x', siz);
|
||||||
fstWriterEmitValueChange(dump_file, info->handle, xmem);
|
fstWriterEmitValueChange(dump_file, info->ident, xmem);
|
||||||
free(xmem);
|
free(xmem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -126,26 +117,6 @@ __inline__ static int dump_header_pending(void)
|
||||||
return dumpvars_status != 2;
|
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)
|
static PLI_INT32 variable_cb_2(p_cb_data cause)
|
||||||
{
|
{
|
||||||
struct vcd_info* info = vcd_dmp_list;
|
struct vcd_info* info = vcd_dmp_list;
|
||||||
|
|
@ -212,7 +183,8 @@ static PLI_INT32 dumpvars_cb(p_cb_data cause)
|
||||||
if (!dump_is_off) {
|
if (!dump_is_off) {
|
||||||
fstWriterEmitTimeChange(dump_file, dumpvars_time);
|
fstWriterEmitTimeChange(dump_file, dumpvars_time);
|
||||||
/* nothing to do for $dumpvars... */
|
/* 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 */
|
/* ...nothing to do for $end */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,6 +212,11 @@ static PLI_INT32 finish_cb(p_cb_data cause)
|
||||||
free(cur);
|
free(cur);
|
||||||
}
|
}
|
||||||
vcd_list = 0;
|
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_tab);
|
||||||
vcd_names_delete(&fst_var);
|
vcd_names_delete(&fst_var);
|
||||||
nexus_ident_delete();
|
nexus_ident_delete();
|
||||||
|
|
@ -303,7 +280,7 @@ static PLI_INT32 sys_dumpoff_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fstWriterEmitDumpActive(dump_file, 0); /* $dumpoff */
|
fstWriterEmitDumpActive(dump_file, 0); /* $dumpoff */
|
||||||
vcd_checkpoint_x();
|
ITERATE_VCD_INFO(vcd_list, vcd_info, next, show_this_item_x);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -332,7 +309,7 @@ static PLI_INT32 sys_dumpon_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fstWriterEmitDumpActive(dump_file, 1); /* $dumpon */
|
fstWriterEmitDumpActive(dump_file, 1); /* $dumpon */
|
||||||
vcd_checkpoint();
|
ITERATE_VCD_INFO(vcd_list, vcd_info, next, show_this_item);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -358,7 +335,7 @@ static PLI_INT32 sys_dumpall_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* nothing to do for $dumpall... */
|
/* nothing to do for $dumpall... */
|
||||||
vcd_checkpoint();
|
ITERATE_VCD_INFO(vcd_list, vcd_info, next, show_this_item);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -574,10 +551,6 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
|
|
||||||
/* Generate the $var or $scope commands. */
|
/* Generate the $var or $scope commands. */
|
||||||
switch (item_type) {
|
switch (item_type) {
|
||||||
case vpiParameter:
|
|
||||||
vpi_printf("FST sorry: $dumpvars: can not dump parameters.\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case vpiNamedEvent:
|
case vpiNamedEvent:
|
||||||
case vpiIntegerVar:
|
case vpiIntegerVar:
|
||||||
case vpiBitVar:
|
case vpiBitVar:
|
||||||
|
|
@ -648,7 +621,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
|
|
||||||
info->time.type = vpiSimTime;
|
info->time.type = vpiSimTime;
|
||||||
info->item = item;
|
info->item = item;
|
||||||
info->handle = new_ident;
|
info->ident = new_ident;
|
||||||
info->scheduled = 0;
|
info->scheduled = 0;
|
||||||
|
|
||||||
cb.time = &info->time;
|
cb.time = &info->time;
|
||||||
|
|
@ -667,6 +640,37 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
|
|
||||||
break;
|
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 vpiModule:
|
||||||
case vpiPackage:
|
case vpiPackage:
|
||||||
case vpiGenScope:
|
case vpiGenScope:
|
||||||
|
|
@ -683,7 +687,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
/* Value */
|
/* Value */
|
||||||
vpiNamedEvent,
|
vpiNamedEvent,
|
||||||
vpiNet,
|
vpiNet,
|
||||||
/* vpiParameter, */
|
vpiParameter,
|
||||||
vpiReg,
|
vpiReg,
|
||||||
vpiVariables,
|
vpiVariables,
|
||||||
/* Scope */
|
/* Scope */
|
||||||
|
|
|
||||||
|
|
@ -47,19 +47,11 @@ static struct t_vpi_time zero_delay = { vpiSimTime, 0, 0, 0.0 };
|
||||||
* dumped. This list is scanned less often, since parameters do not change
|
* dumped. This list is scanned less often, since parameters do not change
|
||||||
* values.
|
* values.
|
||||||
*/
|
*/
|
||||||
struct vcd_info {
|
DECLARE_VCD_INFO(vcd_info, const char*);
|
||||||
vpiHandle item;
|
|
||||||
vpiHandle cb;
|
|
||||||
struct t_vpi_time time;
|
|
||||||
const char *ident;
|
|
||||||
struct vcd_info *next;
|
|
||||||
struct vcd_info *dmp_next;
|
|
||||||
int scheduled;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct vcd_info *vcd_const_list = NULL;
|
static struct vcd_info *vcd_const_list = NULL;
|
||||||
static struct vcd_info *vcd_list = NULL;
|
static struct vcd_info *vcd_list = NULL;
|
||||||
static struct vcd_info *vcd_dmp_list = NULL;
|
static struct vcd_info *vcd_dmp_list = NULL;
|
||||||
|
|
||||||
static PLI_UINT64 vcd_cur_time = 0;
|
static PLI_UINT64 vcd_cur_time = 0;
|
||||||
static int dump_is_off = 0;
|
static int dump_is_off = 0;
|
||||||
static long dump_limit = 0;
|
static long dump_limit = 0;
|
||||||
|
|
@ -168,37 +160,6 @@ __inline__ static int dump_header_pending(void)
|
||||||
return dumpvars_status != 2;
|
return dumpvars_status != 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* This function writes out all the traced parameters. They never change, so
|
|
||||||
* this is the only way they get written.
|
|
||||||
*/
|
|
||||||
static void vcd_const_checkpoint(void)
|
|
||||||
{
|
|
||||||
struct vcd_info *cur;
|
|
||||||
|
|
||||||
for (cur = vcd_const_list ; cur ; cur = cur->next)
|
|
||||||
show_this_item(cur);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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)
|
static PLI_INT32 variable_cb_2(p_cb_data cause)
|
||||||
{
|
{
|
||||||
|
|
@ -273,13 +234,13 @@ static PLI_INT32 dumpvars_cb(p_cb_data cause)
|
||||||
if (!dump_is_off) {
|
if (!dump_is_off) {
|
||||||
fprintf(dump_file, "$comment Show the parameter values. $end\n");
|
fprintf(dump_file, "$comment Show the parameter values. $end\n");
|
||||||
fprintf(dump_file, "$dumpall\n");
|
fprintf(dump_file, "$dumpall\n");
|
||||||
vcd_const_checkpoint();
|
ITERATE_VCD_INFO(vcd_const_list, vcd_info, next, show_this_item);
|
||||||
fprintf(dump_file, "$end\n");
|
fprintf(dump_file, "$end\n");
|
||||||
|
|
||||||
fprintf(dump_file, "#%" PLI_UINT64_FMT "\n", dumpvars_time);
|
fprintf(dump_file, "#%" PLI_UINT64_FMT "\n", dumpvars_time);
|
||||||
|
|
||||||
fprintf(dump_file, "$dumpvars\n");
|
fprintf(dump_file, "$dumpvars\n");
|
||||||
vcd_checkpoint();
|
ITERATE_VCD_INFO(vcd_list, vcd_info, next, show_this_item);
|
||||||
fprintf(dump_file, "$end\n");
|
fprintf(dump_file, "$end\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -377,7 +338,7 @@ static PLI_INT32 sys_dumpoff_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(dump_file, "$dumpoff\n");
|
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");
|
fprintf(dump_file, "$end\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -407,7 +368,7 @@ static PLI_INT32 sys_dumpon_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(dump_file, "$dumpon\n");
|
fprintf(dump_file, "$dumpon\n");
|
||||||
vcd_checkpoint();
|
ITERATE_VCD_INFO(vcd_list, vcd_info, next, show_this_item);
|
||||||
fprintf(dump_file, "$end\n");
|
fprintf(dump_file, "$end\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -434,7 +395,7 @@ static PLI_INT32 sys_dumpall_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(dump_file, "$dumpall\n");
|
fprintf(dump_file, "$dumpall\n");
|
||||||
vcd_checkpoint();
|
ITERATE_VCD_INFO(vcd_list, vcd_info, next, show_this_item);
|
||||||
fprintf(dump_file, "$end\n");
|
fprintf(dump_file, "$end\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -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. */
|
/* The compiletf routines are common for the VCD, LXT and LXT2 dumpers. */
|
||||||
EXTERN PLI_INT32 sys_dumpvars_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name);
|
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
|
#undef EXTERN
|
||||||
|
|
||||||
#endif /* IVL_vcd_priv_H */
|
#endif /* IVL_vcd_priv_H */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue