Merge branch 'master' into vvp-net-out-rework
This commit is contained in:
commit
6cc16711db
|
|
@ -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 << "[]";
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
8
t-dll.cc
8
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();
|
||||
|
|
|
|||
|
|
@ -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<v%p, %u %u>",
|
||||
sig, av.base, av.wid);
|
||||
snprintf(buffer, sizeof buffer, "&A<v%p, %u %u \"%s\">",
|
||||
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<v%p_0, %u %u, %u>",
|
||||
snprintf(buffer, sizeof buffer,
|
||||
"&PV<v%p_0, %u %u \"%s\", %u>",
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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.
|
|||
<label> .part <symbol>, <base>, <wid>;
|
||||
<label> .part/pv <symbol>, <base>, <wid>, <vector_wid>;
|
||||
<label> .part/v <symbol>, <symbol>, <wid>;
|
||||
<label> .part/v.s <symbol>, <symbol>, <wid>;
|
||||
|
||||
The input is typically a .reg or .net, but can be any vector node in
|
||||
the netlist.
|
||||
|
|
@ -485,7 +486,8 @@ that part is written to. Destination nodes use this value to check
|
|||
further output widths.
|
||||
|
||||
The .part/v variation takes a vector (or long) input on port-1 as the
|
||||
base of the part select. Thus, the part select can move around.
|
||||
base of the part select. Thus, the part select can move around. The
|
||||
.part/v.s variation treats the vector as a signed value.
|
||||
|
||||
PART CONCATENATION STATEMENTS:
|
||||
|
||||
|
|
@ -813,23 +815,29 @@ The &A<> argument is a reference to the word of a variable array. The
|
|||
syntax is:
|
||||
|
||||
&A '<' <symbol> , <number> '>'
|
||||
&A '<' <symbol> , <base> <width> '>'
|
||||
&A '<' <symbol> , <base_symbol> '>'
|
||||
&A '<' <symbol> , <base> <width> <"s" or "u"> '>'
|
||||
|
||||
The <symbol> is the label for a variable array, and the <number> is
|
||||
the canonical word index as an unsigned integer. The second form
|
||||
retrieves the index from thread space (<width> bits starting at <base>).
|
||||
retrieves the <base> from the given signal or &A<>/&PV<> select.
|
||||
The third form retrieves the index from thread space (<width> bits
|
||||
starting at <base>). The base value may be signed or unsigned.
|
||||
|
||||
* The &PV<> argument
|
||||
|
||||
The &PV<> argument is a reference to part of a signal. The syntax is:
|
||||
|
||||
&PV '<' <symbol> , <base> , <width> '>'
|
||||
&PV '<' <symbol> , <tbase> <twid> , <width> '>'
|
||||
&PV '<' <symbol> , <base_symbol> , <width> '>'
|
||||
&PV '<' <symbol> , <tbase> <twid> <"s" or "u"> , <width> '>'
|
||||
|
||||
The <symbol> is the label for a signal, the <base> is the canonical
|
||||
starting bit of the part select and <width> is the number of bits in
|
||||
the select. The second form retrieves the <base> from thread space
|
||||
using <twid> bits starting at <tbase>.
|
||||
the select. The second form retrieves the <base> from the given signal
|
||||
or &A<>/&PV<> select. The third form retrieves the <base> from thread
|
||||
space using <twid> bits starting at <tbase>. The base value may be
|
||||
signed or unsigned.
|
||||
|
||||
* The T<> argument
|
||||
|
||||
|
|
@ -1105,7 +1113,7 @@ current read or write context of the running thread, using its
|
|||
stored context index.
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
|
|||
46
vvp/array.cc
46
vvp/array.cc
|
|
@ -129,6 +129,7 @@ struct __vpiArrayVthrA {
|
|||
// If wid >0, then the address is the base and wid the vector
|
||||
// width of the index to pull from the thread.
|
||||
unsigned wid;
|
||||
bool is_signed;
|
||||
|
||||
unsigned get_address() const
|
||||
{
|
||||
|
|
@ -151,14 +152,37 @@ struct __vpiArrayVthrA {
|
|||
if (wid == 0)
|
||||
return address;
|
||||
|
||||
vvp_vector4_t tmp (wid);
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
vvp_bit4_t bit = vthread_get_bit(vpip_current_vthread, address+idx);
|
||||
tmp.set_bit(idx, bit);
|
||||
/* Get the value from thread space. */
|
||||
int tval = 0;
|
||||
for (unsigned idx = 0 ; (idx < wid) && (idx < 8*sizeof(tval));
|
||||
idx += 1) {
|
||||
vvp_bit4_t bit = vthread_get_bit(vpip_current_vthread,
|
||||
address + idx);
|
||||
switch (bit) {
|
||||
case BIT4_X:
|
||||
case BIT4_Z:
|
||||
/* Return UINT_MAX to indicate an X base. */
|
||||
return UINT_MAX;
|
||||
break;
|
||||
|
||||
case BIT4_1:
|
||||
tval |= 1<<idx;
|
||||
break;
|
||||
|
||||
case BIT4_0:
|
||||
break; // Do nothing!
|
||||
}
|
||||
}
|
||||
unsigned long val = ULONG_MAX;
|
||||
vector4_to_value(tmp, val);
|
||||
return val;
|
||||
|
||||
if (is_signed && (wid < 8*sizeof(tval))) {
|
||||
vvp_bit4_t msb = vthread_get_bit(vpip_current_vthread,
|
||||
address + wid - 1);
|
||||
if (msb == BIT4_1) {
|
||||
tval |= ~((1 << wid) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return tval;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1547,7 +1571,8 @@ vpiHandle vpip_make_vthr_A(char*label, unsigned addr)
|
|||
return &(obj->base);
|
||||
}
|
||||
|
||||
vpiHandle vpip_make_vthr_A(char*label, unsigned tbase, unsigned twid)
|
||||
vpiHandle vpip_make_vthr_A(char*label, unsigned tbase, unsigned twid,
|
||||
char*is_signed)
|
||||
{
|
||||
struct __vpiArrayVthrA*obj = (struct __vpiArrayVthrA*)
|
||||
malloc(sizeof (struct __vpiArrayVthrA));
|
||||
|
|
@ -1562,7 +1587,10 @@ vpiHandle vpip_make_vthr_A(char*label, unsigned tbase, unsigned twid)
|
|||
|
||||
obj->address_handle = 0;
|
||||
obj->address = tbase;
|
||||
obj->wid = twid;
|
||||
obj->wid = twid;
|
||||
obj->is_signed = strcmp(is_signed, "s") == 0;
|
||||
|
||||
delete [] is_signed;
|
||||
|
||||
return &(obj->base);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ extern void compile_part_select_pv(char*label, char*src,
|
|||
unsigned base, unsigned wid,
|
||||
unsigned vec_wid);
|
||||
extern void compile_part_select_var(char*label, char*src,
|
||||
char*var, unsigned wid);
|
||||
char*var, unsigned wid, bool is_signed);
|
||||
|
||||
/*
|
||||
* This is called by the parser to make the various arithmetic and
|
||||
|
|
|
|||
|
|
@ -160,6 +160,7 @@ static char* strdupnew(char const *str)
|
|||
".part" { return K_PART; }
|
||||
".part/pv" { return K_PART_PV; }
|
||||
".part/v" { return K_PART_V; }
|
||||
".part/v.s" { return K_PART_V_S; }
|
||||
".port" { return K_PORT; }
|
||||
".reduce/and" { return K_REDUCE_AND; }
|
||||
".reduce/or" { return K_REDUCE_OR; }
|
||||
|
|
|
|||
14
vvp/parse.y
14
vvp/parse.y
|
|
@ -79,7 +79,7 @@ static struct __vpiModPath*modpath_dst = 0;
|
|||
%token K_MODPATH K_NET K_NET_S K_NET_R
|
||||
%token K_NET8 K_NET8_S
|
||||
%token K_PARAM_STR K_PARAM_L K_PARAM_REAL K_PART K_PART_PV
|
||||
%token K_PART_V K_PORT K_PV K_REDUCE_AND K_REDUCE_OR K_REDUCE_XOR
|
||||
%token K_PART_V K_PART_V_S K_PORT K_PV K_REDUCE_AND K_REDUCE_OR K_REDUCE_XOR
|
||||
%token K_REDUCE_NAND K_REDUCE_NOR K_REDUCE_XNOR K_REPEAT
|
||||
%token K_RESOLV K_SCOPE K_SFUNC K_SFUNC_E K_SHIFTL K_SHIFTR K_SHIFTRS
|
||||
%token K_THREAD K_TIMESCALE K_TRAN K_TRANIF0 K_TRANIF1 K_TRANVP
|
||||
|
|
@ -250,7 +250,9 @@ statement
|
|||
{ compile_part_select_pv($1, $3, $5, $7, $9); }
|
||||
|
||||
| T_LABEL K_PART_V T_SYMBOL ',' T_SYMBOL ',' T_NUMBER ';'
|
||||
{ compile_part_select_var($1, $3, $5, $7); }
|
||||
{ compile_part_select_var($1, $3, $5, $7, false); }
|
||||
| T_LABEL K_PART_V_S T_SYMBOL ',' T_SYMBOL ',' T_NUMBER ';'
|
||||
{ compile_part_select_var($1, $3, $5, $7, true); }
|
||||
|
||||
| T_LABEL K_CONCAT '[' T_NUMBER T_NUMBER T_NUMBER T_NUMBER ']' ','
|
||||
symbols ';'
|
||||
|
|
@ -873,8 +875,8 @@ argument
|
|||
symbol_access
|
||||
: K_A '<' T_SYMBOL ',' T_NUMBER '>'
|
||||
{ $$ = vpip_make_vthr_A($3, $5); }
|
||||
| K_A '<' T_SYMBOL ',' T_NUMBER T_NUMBER '>'
|
||||
{ $$ = vpip_make_vthr_A($3, $5, $6); }
|
||||
| K_A '<' T_SYMBOL ',' T_NUMBER T_NUMBER T_STRING '>'
|
||||
{ $$ = vpip_make_vthr_A($3, $5, $6, $7); }
|
||||
| K_A '<' T_SYMBOL ',' T_SYMBOL '>'
|
||||
{ $$ = vpip_make_vthr_A($3, $5); }
|
||||
| K_A '<' T_SYMBOL ',' symbol_access '>'
|
||||
|
|
@ -887,8 +889,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
|
||||
|
|
|
|||
22
vvp/part.cc
22
vvp/part.cc
|
|
@ -228,8 +228,8 @@ void vvp_fun_part_pv::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
|||
port.ptr()->send_vec8_pv(bit, base_, wid_, vwid_);
|
||||
}
|
||||
|
||||
vvp_fun_part_var::vvp_fun_part_var(unsigned w)
|
||||
: wid_(w)
|
||||
vvp_fun_part_var::vvp_fun_part_var(unsigned w, bool is_signed)
|
||||
: wid_(w), is_signed_(is_signed)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -250,9 +250,7 @@ bool vvp_fun_part_var::recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
// INT_MIN is before the vector and is used to
|
||||
// represent a 'bx value on the select input.
|
||||
tmp = INT_MIN;
|
||||
// We need a new .part/v that knows if the index is signed.
|
||||
// For now this will work for a normal integer value.
|
||||
vector4_to_value(bit, tmp, false);
|
||||
vector4_to_value(bit, tmp, is_signed_);
|
||||
if ((int)tmp == base) return false;
|
||||
base = tmp;
|
||||
break;
|
||||
|
|
@ -279,8 +277,8 @@ bool vvp_fun_part_var::recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
return false;
|
||||
}
|
||||
|
||||
vvp_fun_part_var_sa::vvp_fun_part_var_sa(unsigned w)
|
||||
: vvp_fun_part_var(w), base_(0)
|
||||
vvp_fun_part_var_sa::vvp_fun_part_var_sa(unsigned w, bool is_signed)
|
||||
: vvp_fun_part_var(w, is_signed), base_(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -319,8 +317,8 @@ struct vvp_fun_part_var_state_s {
|
|||
vvp_vector4_t ref;
|
||||
};
|
||||
|
||||
vvp_fun_part_var_aa::vvp_fun_part_var_aa(unsigned w)
|
||||
: vvp_fun_part_var(w)
|
||||
vvp_fun_part_var_aa::vvp_fun_part_var_aa(unsigned w, bool is_signed)
|
||||
: vvp_fun_part_var(w, is_signed)
|
||||
{
|
||||
context_scope_ = vpip_peek_context_scope();
|
||||
context_idx_ = vpip_add_item_to_context(this, context_scope_);
|
||||
|
|
@ -435,13 +433,13 @@ void compile_part_select_pv(char*label, char*source,
|
|||
}
|
||||
|
||||
void compile_part_select_var(char*label, char*source, char*var,
|
||||
unsigned wid)
|
||||
unsigned wid, bool is_signed)
|
||||
{
|
||||
vvp_fun_part_var*fun = 0;
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
fun = new vvp_fun_part_var_aa(wid);
|
||||
fun = new vvp_fun_part_var_aa(wid, is_signed);
|
||||
} else {
|
||||
fun = new vvp_fun_part_var_sa(wid);
|
||||
fun = new vvp_fun_part_var_sa(wid, is_signed);
|
||||
}
|
||||
vvp_net_t*net = new vvp_net_t;
|
||||
net->fun = fun;
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ class vvp_fun_part_pv : public vvp_net_fun_t {
|
|||
class vvp_fun_part_var : public vvp_net_fun_t {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_part_var(unsigned wid);
|
||||
explicit vvp_fun_part_var(unsigned wid, bool is_signed);
|
||||
~vvp_fun_part_var();
|
||||
|
||||
protected:
|
||||
|
|
@ -134,6 +134,7 @@ class vvp_fun_part_var : public vvp_net_fun_t {
|
|||
vvp_vector4_t&ref);
|
||||
|
||||
unsigned wid_;
|
||||
bool is_signed_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -142,7 +143,7 @@ class vvp_fun_part_var : public vvp_net_fun_t {
|
|||
class vvp_fun_part_var_sa : public vvp_fun_part_var {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_part_var_sa(unsigned wid);
|
||||
explicit vvp_fun_part_var_sa(unsigned wid, bool is_signed);
|
||||
~vvp_fun_part_var_sa();
|
||||
|
||||
public:
|
||||
|
|
@ -166,7 +167,7 @@ class vvp_fun_part_var_sa : public vvp_fun_part_var {
|
|||
class vvp_fun_part_var_aa : public vvp_fun_part_var, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_part_var_aa(unsigned wid);
|
||||
explicit vvp_fun_part_var_aa(unsigned wid, bool is_signed);
|
||||
~vvp_fun_part_var_aa();
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -494,7 +496,8 @@ vpiHandle vpip_make_vthr_word(unsigned base, const char*type);
|
|||
|
||||
vpiHandle vpip_make_vthr_A(char*label, unsigned index);
|
||||
vpiHandle vpip_make_vthr_A(char*label, char*symbol);
|
||||
vpiHandle vpip_make_vthr_A(char*label, unsigned tbase, unsigned twid);
|
||||
vpiHandle vpip_make_vthr_A(char*label, unsigned tbase, unsigned twid,
|
||||
char*is_signed);
|
||||
vpiHandle vpip_make_vthr_A(char*label, vpiHandle handle);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1012,7 +1012,8 @@ static int PV_get_base(struct __vpiPV*rfp)
|
|||
|
||||
/* Get the value from thread space. */
|
||||
int tval = 0;
|
||||
for (unsigned idx = 0 ; idx < rfp->twid ; idx += 1) {
|
||||
for (unsigned idx = 0 ; (idx < rfp->twid) && (idx < 8*sizeof(tval));
|
||||
idx += 1) {
|
||||
vvp_bit4_t bit = vthread_get_bit(vpip_current_vthread,
|
||||
rfp->tbase + idx);
|
||||
switch (bit) {
|
||||
|
|
@ -1031,6 +1032,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;
|
||||
}
|
||||
|
||||
|
|
@ -1285,7 +1295,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;
|
||||
|
|
@ -1293,10 +1303,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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue