Merge branch 'master' into vvp-net-out-rework
This commit is contained in:
commit
9fe28e09a6
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
24
elab_lval.cc
24
elab_lval.cc
|
|
@ -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,13 +336,11 @@ 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
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
15
elab_net.cc
15
elab_net.cc
|
|
@ -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());
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
241
vpi/sys_vcd.c
241
vpi/sys_vcd.c
|
|
@ -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 = find_nexus_ident(nexus_id);
|
|
||||||
} else {
|
|
||||||
ident = 0;
|
ident = 0;
|
||||||
}
|
if (nexus_id) ident = find_nexus_ident(nexus_id);
|
||||||
|
|
||||||
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 info: scanning scope %s, %u levels\n",
|
|
||||||
fullname, depth);
|
|
||||||
#endif
|
|
||||||
nskip = 0 != vcd_names_search(&vcd_tab, fullname);
|
|
||||||
|
|
||||||
if (!nskip)
|
|
||||||
vcd_names_add(&vcd_tab, fullname);
|
|
||||||
else
|
|
||||||
vpi_printf("VCD warning: ignoring signals in "
|
vpi_printf("VCD warning: ignoring signals in "
|
||||||
"previously scanned scope %s\n", fullname);
|
"previously scanned scope %s.\n", fullname);
|
||||||
|
} else {
|
||||||
|
vcd_names_add(&vcd_tab, fullname);
|
||||||
|
vcd_names_sort(&vcd_tab);
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
|
||||||
10
vpi_user.h
10
vpi_user.h
|
|
@ -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 */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue