From 354d6004531cde57f104e6a8cf5f49d639f1ce30 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 22 Jun 2009 15:35:38 -0700 Subject: [PATCH 1/5] Use the correct suffix default for 0.10. --- aclocal.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aclocal.m4 b/aclocal.m4 index 44421f6c6..f7f8f36a8 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -8,7 +8,7 @@ AC_DEFUN([AX_ENABLE_SUFFIX], [AC_ARG_ENABLE([suffix],[Set the installation command suffix],[true],[enable_suffix=no]) if test X$enable_suffix = Xyes; then - install_suffix='-0.9' + install_suffix='-0.10' elif test X$enable_suffix = Xno; then install_suffix='' else From 236f56949fffd5e4a0eca090aef739f2a6297925 Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 24 Jun 2009 10:07:12 -0700 Subject: [PATCH 2/5] Use correct sign for signal and constant addition. This was incorrectly using the expression sign not checking if the two sub-expressions are both signed. This likely used to work, but in the context of $signed which sets the expression to signed so we can have a signed expression without both sub-expressions being signed. --- tgt-vvp/eval_expr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index f9c72b1ef..cd8bb004a 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -1396,9 +1396,9 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid) struct vector_info lv; struct vector_info rv; - const char*sign_string = ivl_expr_signed(le) && ivl_expr_signed(re)? "/s" : ""; + int signed_flag = ivl_expr_signed(le) && ivl_expr_signed(re) ? 1 : 0; + const char*sign_string = signed_flag ? "/s" : ""; - int signed_flag = ivl_expr_signed(exp)? 1 : 0; if ((ivl_expr_opcode(exp) == '+') && (ivl_expr_type(le) == IVL_EX_SIGNAL) From 7e3a7b87ff32c55354232a2c69ce26e394d61f4b Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 25 Jun 2009 10:48:05 -0700 Subject: [PATCH 3/5] Add basic support for events and cleanup VCD dumper. This patch adds support for dumping named events to the VCD dumper only. The LXT and LXT2 will be added once this has been tested more. It also reworks the $dumpvars routine to be more consistent concerning warning messages for duplicate signal dump requests and fixes some bugs. For events you will get extra events at T0 and at $dumpon. I plan to fix this, but that is much more involved. For duplicate signal warnings. Implicit duplicates loaded automatically from a scope will not display a warning. Only an explicit signal request will print a warning if it was already included. All other will be silently ignored. This should limit the warning to only what the user cares about. For example: $dumpvars(0, var, scope_that_includes_var); Will work without a warning message. $dumpvars(0, scope_that_includes_var, var); Will generate a warning since the var was already included by the scope request. Other enhancements include the start of including type information in the output. For now integer is added, the other type information will require changes to the code generator and hence will only be done in development. --- vpi/sys_vcd.c | 241 +++++++++++++++++++++++++++---------------------- vpi/vcd_priv.c | 11 +++ vpi_user.h | 10 ++ 3 files changed, 155 insertions(+), 107 deletions(-) diff --git a/vpi/sys_vcd.c b/vpi/sys_vcd.c index 6fbbfd95c..a9c41196d 100644 --- a/vpi/sys_vcd.c +++ b/vpi/sys_vcd.c @@ -103,12 +103,14 @@ static char *truncate_bitvec(char *s) static void show_this_item(struct vcd_info*info) { s_vpi_value value; + PLI_INT32 type = vpi_get(vpiType, info->item); - if (vpi_get(vpiType, info->item) == vpiRealVar) { + if (type == vpiRealVar) { value.format = vpiRealVal; vpi_get_value(info->item, &value); fprintf(dump_file, "r%.16g %s\n", value.value.real, info->ident); - + } else if (type == vpiNamedEvent) { + fprintf(dump_file, "1%s\n", info->ident); } else if (vpi_get(vpiSize, info->item) == 1) { value.format = vpiBinStrVal; vpi_get_value(info->item, &value); @@ -121,12 +123,16 @@ static void show_this_item(struct vcd_info*info) } } - +/* Dump values for a $dumpoff. */ static void show_this_item_x(struct vcd_info*info) { - if (vpi_get(vpiType, info->item) == vpiRealVar) { + PLI_INT32 type = vpi_get(vpiType, info->item); + + if (type == vpiRealVar) { /* Some tools dump nothing here...? */ fprintf(dump_file, "rNaN %s\n", info->ident); + } else if (type == vpiNamedEvent) { + /* Do nothing for named events. */ } else if (vpi_get(vpiSize, info->item) == 1) { fprintf(dump_file, "x%s\n", info->ident); } else { @@ -489,22 +495,27 @@ static PLI_INT32 sys_dumplimit_calltf(PLI_BYTE8 *name) return 0; } -static void scan_item(unsigned depth, vpiHandle item, int skip) +static void scan_item(unsigned depth, vpiHandle item, int skip, int expl) { struct t_cb_data cb; struct vcd_info* info; const char* type; const char* name; + const char* fullname; const char* prefix; const char* ident; int nexus_id; + unsigned size; + PLI_INT32 item_type; /* list of types to iterate upon */ int i; static int types[] = { /* Value */ + vpiNamedEvent, vpiNet, +// vpiParameter, vpiReg, vpiVariables, /* Scope */ @@ -516,50 +527,113 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) -1 }; - switch (vpi_get(vpiType, item)) { - - case vpiNet: type = "wire"; if(0){ + /* Get the displayed type for the various $var and $scope types. */ + /* Not all of these are supported now, but they should be in a + * future development version. */ + item_type = vpi_get(vpiType, item); + switch (item_type) { + case vpiNamedEvent: type = "event"; break; + case vpiIntegerVar: type = "integer"; break; + case vpiParameter: type = "parameter"; break; + /* Icarus converts realtime to real. */ + case vpiRealVar: type = "real"; break; case vpiMemoryWord: + case vpiReg: type = "reg"; break; + /* Icarus converts a time to a plain register. */ + case vpiTimeVar: type = "time"; break; + case vpiNet: + switch (vpi_get(vpiNetType, item)) { + case vpiWand: type = "wand"; break; + case vpiWor: type = "wor"; break; + case vpiTri: type = "tri"; break; + case vpiTri0: type = "tri0"; break; + case vpiTri1: type = "tri1"; break; + case vpiTriReg: type = "trireg"; break; + case vpiTriAnd: type = "triand"; break; + case vpiTriOr: type = "trior"; break; + case vpiSupply1: type = "supply1"; break; + case vpiSupply0: type = "supply0"; break; + default: type = "wire"; break; + } + break; + + case vpiNamedBegin: type = "begin"; break; + case vpiNamedFork: type = "fork"; break; + case vpiFunction: type = "function"; break; + case vpiModule: type = "module"; break; + case vpiTask: type = "task"; break; + + default: + vpi_printf("VCD warning: $dumpvars: Unsupported argument " + "type (%s)\n", vpi_get_str(vpiType, item)); + return; + } + + /* Do some special processing/checking on array words. Dumping + * array words is an Icarus extension. */ + if (item_type == vpiMemoryWord) { + /* Turn a non-constant array word select into a constant + * word select. */ if (vpi_get(vpiConstantSelect, item) == 0) { - /* Turn a non-constant array word select into a - * constant word select. */ vpiHandle array = vpi_handle(vpiParent, item); PLI_INT32 index = vpi_get(vpiIndex, item); item = vpi_handle_by_index(array, index); } - case vpiIntegerVar: - case vpiTimeVar: - case vpiReg: type = "reg"; } - - /* Skip this signal if it has already been included. */ - if (vcd_names_search(&vcd_var, vpi_get_str(vpiFullName, item))) { - vpi_printf("VCD warning: skipping signal %s, it was " - "previously included.\n", - vpi_get_str(vpiFullName, item)); - break; - } /* An array word is implicitly escaped so look for an * escaped identifier that this could conflict with. */ + /* This does not work as expected since we always find at + * least the array word. We likely need a custom routine. */ if (vpi_get(vpiType, item) == vpiMemoryWord && vpi_handle_by_name(vpi_get_str(vpiFullName, item), 0)) { - vpi_printf("VCD warning: dumping array word %s will " - "conflict with an escaped identifier.\n", + vpi_printf("VCD warning: array word %s will conflict " + "with an escaped identifier.\n", vpi_get_str(vpiFullName, item)); } + } - if (skip || vpi_get(vpiAutomatic, item)) break; + fullname = vpi_get_str(vpiFullName, item); + /* 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 vpiParameter: + case vpiRealVar: + case vpiMemoryWord: + case vpiReg: + 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; + + /* Skip this signal if it has already been included. */ + if (vcd_names_search(&vcd_var, fullname)) { + /* Only warn when the variable is given explicitly. */ + if (expl) + vpi_printf("VCD warning: skipping signal %s, it was " + "previously included.\n", fullname); + return; + } + + /* Add implicit signals here. */ + if (!expl) vcd_names_add(&vcd_var, fullname); + + /* Declare the variable in the VCD file. */ name = vpi_get_str(vpiName, item); prefix = is_escaped_id(name) ? "\\" : ""; + /* Some signals can have an alias so handle that. */ nexus_id = vpi_get(_vpiNexusId, item); - if (nexus_id) { - ident = find_nexus_ident(nexus_id); - } else { - ident = 0; - } + ident = 0; + if (nexus_id) ident = find_nexus_ident(nexus_id); if (!ident) { ident = strdup(vcdid); @@ -567,6 +641,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) if (nexus_id) set_nexus_ident(nexus_id, ident); + /* Add a callback for the signal. */ info = malloc(sizeof(*info)); info->time.type = vpiSimTime; @@ -588,107 +663,57 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) info->cb = vpi_register_cb(&cb); } + /* Named events do not have a size, but other tools use + * a size of 1 and some viewers do not accept a width of + * zero so we will also use a width of one for events. */ + if (item_type == vpiNamedEvent) size = 1; + else size = vpi_get(vpiSize, item); + fprintf(dump_file, "$var %s %u %s %s%s", - type, vpi_get(vpiSize, item), ident, - prefix, name); - /* FIXME - if (vpi_get(vpiVector, item) - */ + type, size, ident, prefix, name); + + /* Add a range for vectored values. */ if (vpi_get(vpiSize, item) > 1 || vpi_get(vpiLeftRange, item) != 0) { fprintf(dump_file, " [%i:%i]", vpi_get(vpiLeftRange, item), vpi_get(vpiRightRange, item)); } + fprintf(dump_file, " $end\n"); break; - case vpiRealVar: - - /* Skip this signal if it has already been included. */ - if (vcd_names_search(&vcd_var, vpi_get_str(vpiFullName, item))) { - vpi_printf("VCD warning: skipping signal %s, it was " - "previously included.\n", - vpi_get_str(vpiFullName, item)); - break; - } - - if (skip || vpi_get(vpiAutomatic, item)) break; - - /* Declare the variable in the VCD file. */ - name = vpi_get_str(vpiName, item); - prefix = is_escaped_id(name) ? "\\" : ""; - ident = strdup(vcdid); - gen_new_vcd_id(); - fprintf(dump_file, "$var real 1 %s %s%s $end\n", - ident, prefix, name); - - /* Add a callback for the variable. */ - info = malloc(sizeof(*info)); - - info->time.type = vpiSimTime; - info->item = item; - info->ident = ident; - info->scheduled = 0; - - cb.time = &info->time; - cb.user_data = (char*)info; - cb.value = NULL; - cb.obj = item; - cb.reason = cbValueChange; - cb.cb_rtn = variable_cb_1; - - info->next = vcd_list; - info->dmp_next = 0; - vcd_list = info; - - info->cb = vpi_register_cb(&cb); - - break; - - case vpiModule: type = "module"; if(0){ - case vpiNamedBegin: type = "begin"; }if(0){ - case vpiTask: type = "task"; }if(0){ - case vpiFunction: type = "function"; }if(0){ - case vpiNamedFork: type = "fork"; } + case vpiModule: + case vpiNamedBegin: + case vpiTask: + case vpiFunction: + case vpiNamedFork: if (depth > 0) { - int nskip; - vpiHandle argv; + int nskip = (vcd_names_search(&vcd_tab, fullname) != 0); - const char* fullname = - vpi_get_str(vpiFullName, item); - -#if 0 - vpi_printf("VCD info: scanning scope %s, %u levels\n", - fullname, depth); -#endif - nskip = 0 != vcd_names_search(&vcd_tab, fullname); - - if (!nskip) - vcd_names_add(&vcd_tab, fullname); - else - vpi_printf("VCD warning: ignoring signals in " - "previously scanned scope %s\n", fullname); + /* We have to always scan the scope because the + * depth could be different for this call. */ + if (nskip) { + vpi_printf("VCD warning: ignoring signals in " + "previously scanned scope %s.\n", fullname); + } else vcd_names_add(&vcd_tab, fullname); name = vpi_get_str(vpiName, item); - fprintf(dump_file, "$scope %s %s $end\n", type, name); for (i=0; types[i]>0; i++) { vpiHandle hand; - argv = vpi_iterate(types[i], item); + vpiHandle argv = vpi_iterate(types[i], item); while (argv && (hand = vpi_scan(argv))) { - scan_item(depth-1, hand, nskip); + scan_item(depth-1, hand, nskip, 0); } } + /* Sort any signals that we added above. */ + if (!nskip) vcd_names_sort(&vcd_var); fprintf(dump_file, "$upscope $end\n"); } break; - - default: - vpi_printf("VCD warning: $dumpvars: Unsupported parameter " - "type (%s)\n", vpi_get_str(vpiType, item)); } } @@ -770,12 +795,14 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name) switch (vpi_get(vpiType, item)) { case vpiIntegerVar: case vpiMemoryWord: + case vpiNamedEvent: case vpiNet: + case vpiParameter: case vpiRealVar: case vpiReg: case vpiTimeVar: scname = vpi_get_str(vpiFullName, vpi_handle(vpiScope, item)); - if (vcd_names_search(&vcd_tab, scname)) { + if (vcd_names_search(&vcd_var, scname)) { vpi_printf("VCD warning: skipping signal %s, " "it was previously included.\n", vpi_get_str(vpiFullName, item)); @@ -787,7 +814,7 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name) dep = draw_scope(item, callh); - scan_item(depth, item, 0); + scan_item(depth, item, 0, 1); while (dep--) fprintf(dump_file, "$upscope $end\n"); diff --git a/vpi/vcd_priv.c b/vpi/vcd_priv.c index e3e2c6af0..cac66f968 100644 --- a/vpi/vcd_priv.c +++ b/vpi/vcd_priv.c @@ -271,12 +271,23 @@ PLI_INT32 sys_dumpvars_compiletf(PLI_BYTE8 *name) case vpiNamedBegin: case vpiNamedFork: /* The variable types. */ +#if 0 + case vpiParameter: /* A constant! */ +#endif case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar: case vpiRealVar: + case vpiNamedEvent: break; + + case vpiParameter: /* A constant! */ + vpi_printf("SORRY: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s cannot currently dump a parameter.\n", name); + break; + default: vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); diff --git a/vpi_user.h b/vpi_user.h index ba019190b..3c0ba4ae7 100644 --- a/vpi_user.h +++ b/vpi_user.h @@ -320,6 +320,16 @@ typedef struct t_vpi_delay { #define vpiDefLineNo 16 #define vpiNetType 22 # define vpiWire 1 +# define vpiWand 2 +# define vpiWor 3 +# define vpiTri 4 +# define vpiTri0 5 +# define vpiTri1 6 +# define vpiTriReg 7 +# define vpiTriAnd 8 +# define vpiTriOr 9 +# define vpiSupply1 10 +# define vpiSupply0 11 #define vpiArray 28 #define vpiEdge 36 # define vpiNoEdge 0x00 /* No edge */ From 067fcc07a19433e16ff0aa7278c2ab4400ddf9be Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 25 Jun 2009 12:46:46 -0700 Subject: [PATCH 4/5] More VCD enhancements. Make the code smarter so it can keep fewer items in the lists. Scopes and explicitly given variables are all that is kept. Includes a few other refinements. --- vpi/sys_vcd.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/vpi/sys_vcd.c b/vpi/sys_vcd.c index a9c41196d..c5b5c177f 100644 --- a/vpi/sys_vcd.c +++ b/vpi/sys_vcd.c @@ -495,7 +495,7 @@ static PLI_INT32 sys_dumplimit_calltf(PLI_BYTE8 *name) return 0; } -static void scan_item(unsigned depth, vpiHandle item, int skip, int expl) +static void scan_item(unsigned depth, vpiHandle item, int skip) { struct t_cb_data cb; struct vcd_info* info; @@ -613,17 +613,9 @@ static void scan_item(unsigned depth, vpiHandle item, int skip, int expl) * scope then just return. */ if (skip || vpi_get(vpiAutomatic, item)) return; - /* Skip this signal if it has already been included. */ - if (vcd_names_search(&vcd_var, fullname)) { - /* Only warn when the variable is given explicitly. */ - if (expl) - vpi_printf("VCD warning: skipping signal %s, it was " - "previously included.\n", fullname); - return; - } - - /* Add implicit signals here. */ - if (!expl) vcd_names_add(&vcd_var, fullname); + /* Skip this signal if it has already been included. + * This can only happen for implicitly given signals. */ + if (vcd_names_search(&vcd_var, fullname)) return; /* Declare the variable in the VCD file. */ name = vpi_get_str(vpiName, item); @@ -696,7 +688,10 @@ static void scan_item(unsigned depth, vpiHandle item, int skip, int expl) if (nskip) { vpi_printf("VCD warning: ignoring signals in " "previously scanned scope %s.\n", fullname); - } else vcd_names_add(&vcd_tab, fullname); + } else { + vcd_names_add(&vcd_tab, fullname); + vcd_names_sort(&vcd_tab); + } name = vpi_get_str(vpiName, item); fprintf(dump_file, "$scope %s %s $end\n", type, name); @@ -705,12 +700,11 @@ static void scan_item(unsigned depth, vpiHandle item, int skip, int expl) vpiHandle hand; vpiHandle argv = vpi_iterate(types[i], item); while (argv && (hand = vpi_scan(argv))) { - scan_item(depth-1, hand, nskip, 0); + scan_item(depth-1, hand, nskip); } } /* Sort any signals that we added above. */ - if (!nskip) vcd_names_sort(&vcd_var); fprintf(dump_file, "$upscope $end\n"); } break; @@ -784,12 +778,11 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name) } for ( ; item; item = vpi_scan(argv)) { - const char *scname; + char *scname; + const char *fullname; int add_var = 0; int dep; - vcd_names_sort(&vcd_tab); - /* If this is a signal make sure it has not already * been included. */ switch (vpi_get(vpiType, item)) { @@ -801,20 +794,27 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name) case vpiRealVar: case vpiReg: case vpiTimeVar: - scname = vpi_get_str(vpiFullName, vpi_handle(vpiScope, item)); - if (vcd_names_search(&vcd_var, scname)) { + /* Warn if the variables scope (which includes the + * variable) or the variable itself was already + * included. */ + scname = strdup(vpi_get_str(vpiFullName, + vpi_handle(vpiScope, item))); + fullname = vpi_get_str(vpiFullName, item); + if (vcd_names_search(&vcd_tab, scname) || + vcd_names_search(&vcd_var, fullname)) { vpi_printf("VCD warning: skipping signal %s, " "it was previously included.\n", - vpi_get_str(vpiFullName, item)); + fullname); continue; } else { add_var = 1; } + free(scname); } dep = draw_scope(item, callh); - scan_item(depth, item, 0, 1); + scan_item(depth, item, 0); while (dep--) fprintf(dump_file, "$upscope $end\n"); From c9f6bd68b99a7bdd829d5f2da86fab7b3ad3239f Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 3 Jul 2009 15:37:44 -0700 Subject: [PATCH 5/5] Add compiler warnings for more constant out of bounds array accesses. This patch adds compiler warning messages for all/most constant out of bounds array access. --- elab_expr.cc | 4 ++++ elab_lval.cc | 26 ++++++++++---------------- elab_net.cc | 15 +++++++++++++-- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index b105f8dda..b40044af5 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2610,6 +2610,9 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope, // Special case: The index is out of range, so the value // of this expression is a 'bx vector the width of a word. if (!net->array_index_is_valid(addr)) { + cerr << get_fileline() << ": warning: returning 'bx for out " + "of bounds array access " << net->name() + << "[" << addr << "]." << endl; NetEConst*resx = make_const_x(net->vector_width()); resx->set_line(*this); delete word_index; @@ -2670,6 +2673,7 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope, return elaborate_expr_net_bit_(des, scope, res, found_in); ivl_assert(*this, word_sel == index_component_t::SEL_NONE); + return res; } diff --git a/elab_lval.cc b/elab_lval.cc index 7478eab8c..c421e1243 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -257,13 +257,11 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des, ivl_assert(*this, index_head.msb != 0); ivl_assert(*this, index_head.lsb == 0); + // These are not used, but they need to have a default value. ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE; - // This not used, but it needs to have a default value. bool unsized_flag_tmp = false; - index_head.msb->test_width(des, scope, - reg->vector_width(), reg->vector_width(), - expr_type_tmp, - unsized_flag_tmp); + index_head.msb->test_width(des, scope, integer_width, integer_width, + expr_type_tmp, unsized_flag_tmp); NetExpr*word = elab_and_eval(des, scope, index_head.msb, -1); @@ -338,16 +336,14 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des, NetNet*reg = lv->sig(); + // These are not used, but they need to have a default value. ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE; - // This not used, but it needs to have a default value. bool unsized_flag_tmp = false; - index_tail.msb->test_width(des, scope, - lv->lwidth(), lv->lwidth(), - expr_type_tmp, - unsized_flag_tmp); + index_tail.msb->test_width(des, scope, integer_width, integer_width, + expr_type_tmp, unsized_flag_tmp); - // Bit selects have a single select expression. Evaluate the + // Bit selects have a single select expression. Evaluate the // constant value and treat it as a part select with a bit // width of 1. NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1); @@ -472,13 +468,11 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des, unsigned long wid; calculate_up_do_width_(des, scope, wid); + // These are not used, but they need to have a default value. ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE; - // This not used, but it needs to have a default value. bool unsized_flag_tmp = false; - index_tail.msb->test_width(des, scope, - wid, wid, - expr_type_tmp, - unsized_flag_tmp); + index_tail.msb->test_width(des, scope, integer_width, integer_width, + expr_type_tmp, unsized_flag_tmp); NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1); diff --git a/elab_net.cc b/elab_net.cc index 719173b69..885bd6ae0 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -423,7 +423,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, // Default part select is the entire word. unsigned midx = sig->vector_width()-1, lidx = 0; // The default word select is the first. - unsigned widx = 0; + long widx = 0; const name_component_t&name_tail = path_.back(); @@ -445,6 +445,12 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, } ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT); + // These are not used, but they need to have a default value. + ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE; + bool unsized_flag_tmp = false; + index_head.msb->test_width(des, scope, + integer_width, integer_width, + expr_type_tmp, unsized_flag_tmp); need_constant_expr = true; NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1); need_constant_expr = false; @@ -520,7 +526,12 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, unsigned subnet_wid = midx-lidx+1; if (sig->pin_count() > 1) { - assert(widx < sig->pin_count()); + if (widx < 0 || widx >= (long) sig->pin_count()) { + cerr << get_fileline() << ": warning: ignoring out of " + "bounds l-value array access " + << sig->name() << "[" << widx << "]." << endl; + return 0; + } NetNet*tmp = new NetNet(scope, scope->local_symbol(), sig->type(), sig->vector_width());