diff --git a/tgt-vvp/draw_vpi.c b/tgt-vvp/draw_vpi.c index 2695f56db..0cc66d9e6 100644 --- a/tgt-vvp/draw_vpi.c +++ b/tgt-vvp/draw_vpi.c @@ -212,19 +212,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/vvp/README.txt b/vvp/README.txt index d13fdcc42..c848c7041 100644 --- a/vvp/README.txt +++ b/vvp/README.txt @@ -824,12 +824,15 @@ retrieves the index from thread space ( bits starting at ). The &PV<> argument is a reference to part of a signal. The syntax is: &PV '<' , , '>' - &PV '<' , , '>' + &PV '<' , , '>' + &PV '<' , <"s" or "u"> , '>' The is the label for a signal, the is the canonical starting bit of the part select and is the number of bits in -the select. The second form retrieves the from thread space -using bits starting at . +the select. The second form retrieves the from the given signal +or &A<>/&PV<> select. The third form retrieves the from thread +space using bits starting at . The base value may be +signed or unsigned. * The T<> argument diff --git a/vvp/parse.y b/vvp/parse.y index 47e0d5e5b..cd23a7e89 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -887,8 +887,8 @@ symbol_access { $$ = vpip_make_PV($3, $5, $7); } | K_PV '<' T_SYMBOL ',' symbol_access ',' T_NUMBER '>' { $$ = vpip_make_PV($3, $5, $7); } - | K_PV '<' T_SYMBOL ',' T_NUMBER T_NUMBER ',' T_NUMBER '>' - { $$ = vpip_make_PV($3, $5, $6, $8); } + | K_PV '<' T_SYMBOL ',' T_NUMBER T_NUMBER T_STRING ',' T_NUMBER '>' + { $$ = vpip_make_PV($3, $5, $6, $7, $9); } /* functor operands can only be a list of symbols. */ symbols diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index a1d0ba6e8..4d0eba18c 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -264,11 +264,13 @@ struct __vpiPV { vpiHandle sbase; int tbase; unsigned twid, width; + bool is_signed; }; extern vpiHandle vpip_make_PV(char*name, int base, int width); extern vpiHandle vpip_make_PV(char*name, char*symbol, int width); extern vpiHandle vpip_make_PV(char*name, vpiHandle handle, int width); -extern vpiHandle vpip_make_PV(char*name, int tbase, int twid, int width); +extern vpiHandle vpip_make_PV(char*name, int tbase, int twid, char*is_signed, + int width); extern struct __vpiPV* vpip_PV_from_handle(vpiHandle obj); extern void vpip_part_select_value_change(struct __vpiCallback*cbh, vpiHandle obj); diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index 5e33f2846..4a809bd02 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -1027,6 +1027,15 @@ static int PV_get_base(struct __vpiPV*rfp) } } + /* Check to see if we need to sign extend the result. */ + if (rfp->is_signed && (rfp->twid < 8*sizeof(tval))) { + vvp_bit4_t msb = vthread_get_bit(vpip_current_vthread, + rfp->tbase + rfp->twid - 1); + if (msb == BIT4_1) { + tval |= ~((1 << rfp->twid) - 1); + } + } + return tval; } @@ -1281,7 +1290,7 @@ vpiHandle vpip_make_PV(char*var, vpiHandle handle, int width) return &obj->base; } -vpiHandle vpip_make_PV(char*var, int tbase, int twid, int width) +vpiHandle vpip_make_PV(char*var, int tbase, int twid, char*is_signed, int width) { struct __vpiPV*obj = (struct __vpiPV*) malloc(sizeof(struct __vpiPV)); obj->base.vpi_type = &vpip_PV_rt; @@ -1289,10 +1298,13 @@ vpiHandle vpip_make_PV(char*var, int tbase, int twid, int width) obj->sbase = 0; obj->tbase = tbase; obj->twid = (unsigned) twid; + obj->is_signed = strcmp(is_signed, "s") == 0; obj->width = (unsigned) width; obj->net = 0; functor_ref_lookup(&obj->net, var); + delete [] is_signed; + return &obj->base; }