From 73f40f73b0327ec36d4bd3b5f5992102755567ec Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Mon, 16 May 2022 20:47:32 -0700 Subject: [PATCH] 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. --- vpi/sys_fst.c | 96 ++++++++++++++++++++++++++------------------------ vpi/sys_vcd.c | 53 ++++------------------------ vpi/vcd_priv.h | 29 +++++++++++++++ 3 files changed, 86 insertions(+), 92 deletions(-) diff --git a/vpi/sys_fst.c b/vpi/sys_fst.c index 0b3a423a6..ea471a5c4 100644 --- a/vpi/sys_fst.c +++ b/vpi/sys_fst.c @@ -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 */ diff --git a/vpi/sys_vcd.c b/vpi/sys_vcd.c index a2ad3b076..0a72e9ea0 100644 --- a/vpi/sys_vcd.c +++ b/vpi/sys_vcd.c @@ -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; diff --git a/vpi/vcd_priv.h b/vpi/vcd_priv.h index 43430c490..629b9ed05 100644 --- a/vpi/vcd_priv.h +++ b/vpi/vcd_priv.h @@ -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 */