Merge branch 'master' into vvp-net-out-rework

This commit is contained in:
Stephen Williams 2009-09-22 17:48:33 -07:00
commit 6cc16711db
18 changed files with 137 additions and 72 deletions

View File

@ -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 << "[]";

View File

@ -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);

View File

@ -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:

View File

@ -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_;
};
/*

View File

@ -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();

View File

@ -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;

View File

@ -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),

View File

@ -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);
}

View File

@ -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",

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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; }

View File

@ -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

View File

@ -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;

View File

@ -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:

View File

@ -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);
/*

View File

@ -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;
}