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 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()); 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) diff --git a/vpi/sys_vcd.c b/vpi/sys_vcd.c index 6fbbfd95c..c5b5c177f 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 { @@ -496,15 +502,20 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) 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,105 @@ 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. + * 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); 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 +633,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 +655,59 @@ 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) + /* 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); - else - vpi_printf("VCD warning: ignoring signals in " - "previously scanned scope %s\n", fullname); + vcd_names_sort(&vcd_tab); + } 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); } } + /* Sort any signals that we added above. */ fprintf(dump_file, "$upscope $end\n"); } break; - - default: - vpi_printf("VCD warning: $dumpvars: Unsupported parameter " - "type (%s)\n", vpi_get_str(vpiType, item)); } } @@ -759,30 +778,38 @@ 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)) { 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)) { + /* 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); 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 */