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

This commit is contained in:
Stephen Williams 2009-07-03 19:53:03 -07:00
commit 9fe28e09a6
8 changed files with 186 additions and 129 deletions

2
aclocal.m4 vendored
View File

@ -8,7 +8,7 @@
AC_DEFUN([AX_ENABLE_SUFFIX], AC_DEFUN([AX_ENABLE_SUFFIX],
[AC_ARG_ENABLE([suffix],[Set the installation command suffix],[true],[enable_suffix=no]) [AC_ARG_ENABLE([suffix],[Set the installation command suffix],[true],[enable_suffix=no])
if test X$enable_suffix = Xyes; then if test X$enable_suffix = Xyes; then
install_suffix='-0.9' install_suffix='-0.10'
elif test X$enable_suffix = Xno; then elif test X$enable_suffix = Xno; then
install_suffix='' install_suffix=''
else else

View File

@ -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 // Special case: The index is out of range, so the value
// of this expression is a 'bx vector the width of a word. // of this expression is a 'bx vector the width of a word.
if (!net->array_index_is_valid(addr)) { 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()); NetEConst*resx = make_const_x(net->vector_width());
resx->set_line(*this); resx->set_line(*this);
delete word_index; 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); return elaborate_expr_net_bit_(des, scope, res, found_in);
ivl_assert(*this, word_sel == index_component_t::SEL_NONE); ivl_assert(*this, word_sel == index_component_t::SEL_NONE);
return res; return res;
} }

View File

@ -257,13 +257,11 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
ivl_assert(*this, index_head.msb != 0); ivl_assert(*this, index_head.msb != 0);
ivl_assert(*this, index_head.lsb == 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; 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; bool unsized_flag_tmp = false;
index_head.msb->test_width(des, scope, index_head.msb->test_width(des, scope, integer_width, integer_width,
reg->vector_width(), reg->vector_width(), expr_type_tmp, unsized_flag_tmp);
expr_type_tmp,
unsized_flag_tmp);
NetExpr*word = elab_and_eval(des, scope, index_head.msb, -1); 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(); 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; 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; bool unsized_flag_tmp = false;
index_tail.msb->test_width(des, scope, index_tail.msb->test_width(des, scope, integer_width, integer_width,
lv->lwidth(), lv->lwidth(), expr_type_tmp, unsized_flag_tmp);
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 // constant value and treat it as a part select with a bit
// width of 1. // width of 1.
NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -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; unsigned long wid;
calculate_up_do_width_(des, scope, 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; 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; bool unsized_flag_tmp = false;
index_tail.msb->test_width(des, scope, index_tail.msb->test_width(des, scope, integer_width, integer_width,
wid, wid, expr_type_tmp, unsized_flag_tmp);
expr_type_tmp,
unsized_flag_tmp);
NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1); NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);

View File

@ -423,7 +423,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
// Default part select is the entire word. // Default part select is the entire word.
unsigned midx = sig->vector_width()-1, lidx = 0; unsigned midx = sig->vector_width()-1, lidx = 0;
// The default word select is the first. // The default word select is the first.
unsigned widx = 0; long widx = 0;
const name_component_t&name_tail = path_.back(); 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); 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; need_constant_expr = true;
NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1); NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1);
need_constant_expr = false; need_constant_expr = false;
@ -520,7 +526,12 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
unsigned subnet_wid = midx-lidx+1; unsigned subnet_wid = midx-lidx+1;
if (sig->pin_count() > 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(), NetNet*tmp = new NetNet(scope, scope->local_symbol(),
sig->type(), sig->vector_width()); sig->type(), sig->vector_width());

View File

@ -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 lv;
struct vector_info rv; 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) == '+') if ((ivl_expr_opcode(exp) == '+')
&& (ivl_expr_type(le) == IVL_EX_SIGNAL) && (ivl_expr_type(le) == IVL_EX_SIGNAL)

View File

@ -103,12 +103,14 @@ static char *truncate_bitvec(char *s)
static void show_this_item(struct vcd_info*info) static void show_this_item(struct vcd_info*info)
{ {
s_vpi_value value; 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; value.format = vpiRealVal;
vpi_get_value(info->item, &value); vpi_get_value(info->item, &value);
fprintf(dump_file, "r%.16g %s\n", value.value.real, info->ident); 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) { } else if (vpi_get(vpiSize, info->item) == 1) {
value.format = vpiBinStrVal; value.format = vpiBinStrVal;
vpi_get_value(info->item, &value); 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) 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...? */ /* Some tools dump nothing here...? */
fprintf(dump_file, "rNaN %s\n", info->ident); 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) { } else if (vpi_get(vpiSize, info->item) == 1) {
fprintf(dump_file, "x%s\n", info->ident); fprintf(dump_file, "x%s\n", info->ident);
} else { } else {
@ -496,15 +502,20 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
const char* type; const char* type;
const char* name; const char* name;
const char* fullname;
const char* prefix; const char* prefix;
const char* ident; const char* ident;
int nexus_id; int nexus_id;
unsigned size;
PLI_INT32 item_type;
/* list of types to iterate upon */ /* list of types to iterate upon */
int i; int i;
static int types[] = { static int types[] = {
/* Value */ /* Value */
vpiNamedEvent,
vpiNet, vpiNet,
// vpiParameter,
vpiReg, vpiReg,
vpiVariables, vpiVariables,
/* Scope */ /* Scope */
@ -516,50 +527,105 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
-1 -1
}; };
switch (vpi_get(vpiType, item)) { /* Get the displayed type for the various $var and $scope types. */
/* Not all of these are supported now, but they should be in a
case vpiNet: type = "wire"; if(0){ * 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 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) { if (vpi_get(vpiConstantSelect, item) == 0) {
/* Turn a non-constant array word select into a
* constant word select. */
vpiHandle array = vpi_handle(vpiParent, item); vpiHandle array = vpi_handle(vpiParent, item);
PLI_INT32 index = vpi_get(vpiIndex, item); PLI_INT32 index = vpi_get(vpiIndex, item);
item = vpi_handle_by_index(array, index); 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 /* An array word is implicitly escaped so look for an
* escaped identifier that this could conflict with. */ * 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 && if (vpi_get(vpiType, item) == vpiMemoryWord &&
vpi_handle_by_name(vpi_get_str(vpiFullName, item), 0)) { vpi_handle_by_name(vpi_get_str(vpiFullName, item), 0)) {
vpi_printf("VCD warning: dumping array word %s will " vpi_printf("VCD warning: array word %s will conflict "
"conflict with an escaped identifier.\n", "with an escaped identifier.\n",
vpi_get_str(vpiFullName, item)); 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); name = vpi_get_str(vpiName, item);
prefix = is_escaped_id(name) ? "\\" : ""; prefix = is_escaped_id(name) ? "\\" : "";
/* Some signals can have an alias so handle that. */
nexus_id = vpi_get(_vpiNexusId, item); nexus_id = vpi_get(_vpiNexusId, item);
if (nexus_id) { ident = 0;
ident = find_nexus_ident(nexus_id); if (nexus_id) ident = find_nexus_ident(nexus_id);
} else {
ident = 0;
}
if (!ident) { if (!ident) {
ident = strdup(vcdid); 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); if (nexus_id) set_nexus_ident(nexus_id, ident);
/* Add a callback for the signal. */
info = malloc(sizeof(*info)); info = malloc(sizeof(*info));
info->time.type = vpiSimTime; info->time.type = vpiSimTime;
@ -588,107 +655,59 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
info->cb = vpi_register_cb(&cb); 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", fprintf(dump_file, "$var %s %u %s %s%s",
type, vpi_get(vpiSize, item), ident, type, size, ident, prefix, name);
prefix, name);
/* FIXME /* Add a range for vectored values. */
if (vpi_get(vpiVector, item)
*/
if (vpi_get(vpiSize, item) > 1 if (vpi_get(vpiSize, item) > 1
|| vpi_get(vpiLeftRange, item) != 0) { || vpi_get(vpiLeftRange, item) != 0) {
fprintf(dump_file, " [%i:%i]", vpi_get(vpiLeftRange, item), fprintf(dump_file, " [%i:%i]", vpi_get(vpiLeftRange, item),
vpi_get(vpiRightRange, item)); vpi_get(vpiRightRange, item));
} }
fprintf(dump_file, " $end\n"); fprintf(dump_file, " $end\n");
break; break;
case vpiRealVar: case vpiModule:
case vpiNamedBegin:
/* Skip this signal if it has already been included. */ case vpiTask:
if (vcd_names_search(&vcd_var, vpi_get_str(vpiFullName, item))) { case vpiFunction:
vpi_printf("VCD warning: skipping signal %s, it was " case vpiNamedFork:
"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"; }
if (depth > 0) { if (depth > 0) {
int nskip; int nskip = (vcd_names_search(&vcd_tab, fullname) != 0);
vpiHandle argv;
const char* fullname = /* We have to always scan the scope because the
vpi_get_str(vpiFullName, item); * depth could be different for this call. */
if (nskip) {
#if 0 vpi_printf("VCD warning: ignoring signals in "
vpi_printf("VCD info: scanning scope %s, %u levels\n", "previously scanned scope %s.\n", fullname);
fullname, depth); } else {
#endif
nskip = 0 != vcd_names_search(&vcd_tab, fullname);
if (!nskip)
vcd_names_add(&vcd_tab, fullname); vcd_names_add(&vcd_tab, fullname);
else vcd_names_sort(&vcd_tab);
vpi_printf("VCD warning: ignoring signals in " }
"previously scanned scope %s\n", fullname);
name = vpi_get_str(vpiName, item); name = vpi_get_str(vpiName, item);
fprintf(dump_file, "$scope %s %s $end\n", type, name); fprintf(dump_file, "$scope %s %s $end\n", type, name);
for (i=0; types[i]>0; i++) { for (i=0; types[i]>0; i++) {
vpiHandle hand; vpiHandle hand;
argv = vpi_iterate(types[i], item); vpiHandle argv = vpi_iterate(types[i], item);
while (argv && (hand = vpi_scan(argv))) { while (argv && (hand = vpi_scan(argv))) {
scan_item(depth-1, hand, nskip); scan_item(depth-1, hand, nskip);
} }
} }
/* Sort any signals that we added above. */
fprintf(dump_file, "$upscope $end\n"); fprintf(dump_file, "$upscope $end\n");
} }
break; 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)) { for ( ; item; item = vpi_scan(argv)) {
const char *scname; char *scname;
const char *fullname;
int add_var = 0; int add_var = 0;
int dep; int dep;
vcd_names_sort(&vcd_tab);
/* If this is a signal make sure it has not already /* If this is a signal make sure it has not already
* been included. */ * been included. */
switch (vpi_get(vpiType, item)) { switch (vpi_get(vpiType, item)) {
case vpiIntegerVar: case vpiIntegerVar:
case vpiMemoryWord: case vpiMemoryWord:
case vpiNamedEvent:
case vpiNet: case vpiNet:
case vpiParameter:
case vpiRealVar: case vpiRealVar:
case vpiReg: case vpiReg:
case vpiTimeVar: case vpiTimeVar:
scname = vpi_get_str(vpiFullName, vpi_handle(vpiScope, item)); /* Warn if the variables scope (which includes the
if (vcd_names_search(&vcd_tab, scname)) { * 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, " vpi_printf("VCD warning: skipping signal %s, "
"it was previously included.\n", "it was previously included.\n",
vpi_get_str(vpiFullName, item)); fullname);
continue; continue;
} else { } else {
add_var = 1; add_var = 1;
} }
free(scname);
} }
dep = draw_scope(item, callh); dep = draw_scope(item, callh);

View File

@ -271,12 +271,23 @@ PLI_INT32 sys_dumpvars_compiletf(PLI_BYTE8 *name)
case vpiNamedBegin: case vpiNamedBegin:
case vpiNamedFork: case vpiNamedFork:
/* The variable types. */ /* The variable types. */
#if 0
case vpiParameter: /* A constant! */
#endif
case vpiNet: case vpiNet:
case vpiReg: case vpiReg:
case vpiIntegerVar: case vpiIntegerVar:
case vpiTimeVar: case vpiTimeVar:
case vpiRealVar: case vpiRealVar:
case vpiNamedEvent:
break; 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: default:
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));

View File

@ -320,6 +320,16 @@ typedef struct t_vpi_delay {
#define vpiDefLineNo 16 #define vpiDefLineNo 16
#define vpiNetType 22 #define vpiNetType 22
# define vpiWire 1 # 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 vpiArray 28
#define vpiEdge 36 #define vpiEdge 36
# define vpiNoEdge 0x00 /* No edge */ # define vpiNoEdge 0x00 /* No edge */