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 };
|
||||
|
||||
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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
* values.
|
||||
*/
|
||||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
|
|
@ -168,37 +160,6 @@ __inline__ static int dump_header_pending(void)
|
|||
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)
|
||||
{
|
||||
|
|
@ -273,13 +234,13 @@ static PLI_INT32 dumpvars_cb(p_cb_data cause)
|
|||
if (!dump_is_off) {
|
||||
fprintf(dump_file, "$comment Show the parameter values. $end\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, "#%" 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");
|
||||
}
|
||||
|
||||
|
|
@ -377,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;
|
||||
|
|
@ -407,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;
|
||||
|
|
@ -434,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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Reference in New Issue