diff --git a/elab_lval.cc b/elab_lval.cc index 95808a208..f3ca7d083 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -491,9 +491,11 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des, offset = -wid + 1; } delete base; - base = new NetEConst(verinum(reg->sb_to_idx(lsv) + offset)); + long rel_base = reg->sb_to_idx(lsv) + offset; + /* If we cover the entire lvalue just skip the select. */ + if (rel_base == 0 && wid == reg->vector_width()) return true; + base = new NetEConst(verinum(rel_base)); if (warn_ob_select) { - long rel_base = reg->sb_to_idx(lsv) + offset; if (rel_base < 0) { cerr << get_fileline() << ": warning: " << reg->name(); if (reg->array_dimensions() > 0) cerr << "[]"; diff --git a/expr_synth.cc b/expr_synth.cc index 444c00bb3..005617959 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -1089,7 +1089,8 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root) if (base_ != 0) { off = base_->synthesize(des, scope, root); - NetPartSelect*sel = new NetPartSelect(sub, off, expr_width()); + NetPartSelect*sel = new NetPartSelect(sub, off, expr_width(), + base_->has_sign()); sel->set_line(*this); des->add_node(sel); diff --git a/netlist.cc b/netlist.cc index 095338ff3..add9690f0 100644 --- a/netlist.cc +++ b/netlist.cc @@ -885,7 +885,7 @@ const NetDelaySrc* NetNet::delay_path(unsigned idx) const NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid, NetPartSelect::dir_t dir__) : NetNode(sig->scope(), sig->scope()->local_symbol(), 2), - off_(off), wid_(wid), dir_(dir__) + off_(off), wid_(wid), dir_(dir__), signed_flag_(false) { set_line(*sig); @@ -904,9 +904,9 @@ NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid, } NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel, - unsigned wid) + unsigned wid, bool signed_flag) : NetNode(sig->scope(), sig->scope()->local_symbol(), 3), - off_(0), wid_(wid), dir_(VP) + off_(0), wid_(wid), dir_(VP), signed_flag_(signed_flag) { switch (dir_) { case NetPartSelect::VP: diff --git a/netlist.h b/netlist.h index 9162e7b71..40efe0b47 100644 --- a/netlist.h +++ b/netlist.h @@ -1795,12 +1795,14 @@ class NetPartSelect : public NetNode { explicit NetPartSelect(NetNet*sig, unsigned off, unsigned wid, dir_t dir); explicit NetPartSelect(NetNet*sig, NetNet*sel, - unsigned wid); + unsigned wid, bool signed_flag = false); ~NetPartSelect(); unsigned base() const; unsigned width() const; dir_t dir() const; + /* Is the select signal signed? */ + bool signed_flag() const { return signed_flag_; } virtual void dump_node(ostream&, unsigned ind) const; bool emit_node(struct target_t*tgt) const; @@ -1809,6 +1811,7 @@ class NetPartSelect : public NetNode { unsigned off_; unsigned wid_; dir_t dir_; + bool signed_flag_; }; /* diff --git a/t-dll.cc b/t-dll.cc index 45d7851d7..d89bc58d0 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -2153,8 +2153,12 @@ bool dll_target::part_select(const NetPartSelect*net) obj->scope = find_scope(des_, net->scope()); assert(obj->scope); - /* Part selects are always unsigned. */ - obj->u_.part.signed_flag = 0; + /* Part selects are always unsigned, so we use this to indicate + * if the part select base signal is signed or not. */ + if (net->signed_flag()) + obj->u_.part.signed_flag = 1; + else + obj->u_.part.signed_flag = 0; /* Choose the width of the part select. */ obj->width = net->width(); diff --git a/tgt-vvp/draw_vpi.c b/tgt-vvp/draw_vpi.c index 2695f56db..02159e839 100644 --- a/tgt-vvp/draw_vpi.c +++ b/tgt-vvp/draw_vpi.c @@ -155,8 +155,9 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result, /* Fallback case: evaluate expression. */ struct vector_info av; av = draw_eval_expr(word_ex, STUFF_OK_XZ); - snprintf(buffer, sizeof buffer, "&A", - sig, av.base, av.wid); + snprintf(buffer, sizeof buffer, "&A", + sig, av.base, av.wid, + (ivl_expr_signed(word_ex) ? "s" : "u")); result->vec = av; result->vec_flag = 1; } else { @@ -212,19 +213,11 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result, /* Fallback case: evaluate the expression. */ struct vector_info rv; rv = draw_eval_expr(bexpr, STUFF_OK_XZ); - /* We need to enhance &PV<> to support a signed index. */ - if (ivl_expr_signed(bexpr) && - (ivl_expr_width(bexpr) < 8*sizeof(int))) { - fprintf(stderr, "%s:%u: tgt-vvp warning: V0.9 may give " - "incorrect results for a select with a " - "signed index less than %zu bits.\n", - ivl_expr_file(expr), - ivl_expr_lineno(expr), - 8*sizeof(int)); - } - snprintf(buffer, sizeof buffer, "&PV", + snprintf(buffer, sizeof buffer, + "&PV", ivl_expr_signal(vexpr), rv.base, rv.wid, + (ivl_expr_signed(bexpr) ? "s" : "u"), ivl_expr_width(expr)); result->vec = rv; result->vec_flag = 1; diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 37d87ec69..ed00cf696 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -1189,7 +1189,6 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec) } else { /* Do not support bit or part selects of l-values yet. */ assert(ivl_lval_mux(lval) == 0); - assert(ivl_lval_part_off(lval) == 0); assert(ivl_lval_width(lval) == ivl_signal_width(lsig)); assert((roff + use_wid) <= rvec.wid); @@ -1238,8 +1237,13 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval) /* We do not currently support driving a signal to a bit or * part select (this could give us multiple drivers). */ part_off_ex = ivl_lval_part_off(lval); + /* This should be verified in force_vector_to_lval() which is called + * before this procedure. */ + if (part_off_ex) { + assert(number_is_immediate(part_off_ex, IMM_WID, 0)); + assert(! number_is_unknown(part_off_ex)); + } if (ivl_signal_width(lsig) > ivl_signal_width(rsig) || - // Do we need checks for number_is{immediate,unknown} of part_of_ex? (part_off_ex && get_number_immediate(part_off_ex) != 0)) { fprintf(stderr, "%s:%u: vvp-tgt sorry: cannot %s signal to " "a bit/part select.\n", ivl_expr_file(rval), diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index f02edcf1c..325f171e6 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -1660,8 +1660,9 @@ static void draw_lpm_part(ivl_lpm_t net) fprintf(vvp_out, ", %u, %u;\n", base, width); } else { const char*sel_symbol = draw_net_input(sel); - fprintf(vvp_out, "L_%p%s .part/v %s", - net, dly, draw_net_input(ivl_lpm_data(net,0))); + fprintf(vvp_out, "L_%p%s .part/v%s %s", net, dly, + (ivl_lpm_signed(net) ? ".s" : ""), + draw_net_input(ivl_lpm_data(net,0))); fprintf(vvp_out, ", %s", sel_symbol); fprintf(vvp_out, ", %u;\n", width); } diff --git a/vpi/sys_vcd.c b/vpi/sys_vcd.c index 904a80056..53f24e48c 100644 --- a/vpi/sys_vcd.c +++ b/vpi/sys_vcd.c @@ -782,10 +782,11 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name) const char *fullname; int add_var = 0; int dep; + PLI_INT32 item_type = vpi_get(vpiType, item); /* If this is a signal make sure it has not already * been included. */ - switch (vpi_get(vpiType, item)) { + switch (item_type) { case vpiIntegerVar: case vpiMemoryWord: case vpiNamedEvent: @@ -796,11 +797,13 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name) case vpiTimeVar: /* Warn if the variables scope (which includes the * variable) or the variable itself was already - * included. */ + * included. A scope does not automatically include + * memory words so do not check the scope for them. */ scname = strdup(vpi_get_str(vpiFullName, vpi_handle(vpiScope, item))); fullname = vpi_get_str(vpiFullName, item); - if (vcd_names_search(&vcd_tab, scname) || + if (((item_type != vpiMemoryWord) && + vcd_names_search(&vcd_tab, scname)) || vcd_names_search(&vcd_var, fullname)) { vpi_printf("VCD warning: skipping signal %s, " "it was previously included.\n", diff --git a/vvp/README.txt b/vvp/README.txt index d13fdcc42..abb57e775 100644 --- a/vvp/README.txt +++ b/vvp/README.txt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com) * */ @@ -473,6 +473,7 @@ bit number, and a width. Normally, those bits are constant values.