Merge branch 'master' into vvp-net-out-rework
Conflicts: vvp/vpi_signal.cc
This commit is contained in:
commit
3d5d312786
|
|
@ -88,6 +88,11 @@ extern bool warn_ob_select;
|
|||
/* Warn about structures that may have infinite loops. */
|
||||
extern bool warn_inf_loop;
|
||||
|
||||
/* Warn about always @* statements where a part or word select causes
|
||||
sensitivity to an entire vector or array. */
|
||||
extern bool warn_sens_entire_vec;
|
||||
extern bool warn_sens_entire_arr;
|
||||
|
||||
/* This is true if verbose output is requested. */
|
||||
extern bool verbose_flag;
|
||||
|
||||
|
|
|
|||
|
|
@ -259,8 +259,8 @@ after a \fB-Wall\fP argument to suppress isolated warning types.
|
|||
|
||||
.TP 8
|
||||
.B all
|
||||
This enables the implicit, portbind, select-range and timescale warning
|
||||
categories.
|
||||
This enables the implicit, portbind, select-range, timescale, and
|
||||
sensitivity-entire-array warning categories.
|
||||
|
||||
.TP 8
|
||||
.B implicit
|
||||
|
|
@ -303,6 +303,22 @@ verified. It is expected that many of the warnings will be false
|
|||
positives, since the code treats the value of all variables and signals
|
||||
as indeterminate.
|
||||
|
||||
.TP 8
|
||||
.B sensitivity-entire-vector
|
||||
This enables warnings for when a part select within an "always @*"
|
||||
statement results in the entire vector being added to the implicit
|
||||
sensitivity list. Although this behaviour is prescribed by the IEEE
|
||||
standard, it is not what might be expected and can have performance
|
||||
implications if the vector is large.
|
||||
|
||||
.TP 8
|
||||
.B sensitivity-entire-array
|
||||
This enables warnings for when a word select within an "always @*"
|
||||
statement results in the entire array being added to the implicit
|
||||
sensitivity list. Although this behaviour is prescribed by the IEEE
|
||||
standard, it is not what might be expected and can have performance
|
||||
implications if the array is large.
|
||||
|
||||
.SH "SYSTEM FUNCTION TABLE FILES"
|
||||
If the source file name as a \fB.sft\fP suffix, then it is taken to be
|
||||
a system function table file. A System function table file is used to
|
||||
|
|
|
|||
|
|
@ -477,6 +477,7 @@ static void process_warning_switch(const char*name)
|
|||
process_warning_switch("portbind");
|
||||
process_warning_switch("select-range");
|
||||
process_warning_switch("timescale");
|
||||
process_warning_switch("sensitivity-entire-array");
|
||||
} else if (strcmp(name,"implicit") == 0) {
|
||||
if (! strchr(warning_flags, 'i'))
|
||||
strcat(warning_flags, "i");
|
||||
|
|
@ -494,6 +495,12 @@ static void process_warning_switch(const char*name)
|
|||
} else if (strcmp(name,"infloop") == 0) {
|
||||
if (! strchr(warning_flags, 'l'))
|
||||
strcat(warning_flags, "l");
|
||||
} else if (strcmp(name,"sensitivity-entire-vector") == 0) {
|
||||
if (! strchr(warning_flags, 'v'))
|
||||
strcat(warning_flags, "v");
|
||||
} else if (strcmp(name,"sensitivity-entire-array") == 0) {
|
||||
if (! strchr(warning_flags, 'a'))
|
||||
strcat(warning_flags, "a");
|
||||
} else if (strcmp(name,"no-implicit") == 0) {
|
||||
char*cp = strchr(warning_flags, 'i');
|
||||
if (cp) while (*cp) {
|
||||
|
|
@ -518,6 +525,18 @@ static void process_warning_switch(const char*name)
|
|||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else if (strcmp(name,"no-sensitivity-entire-vector") == 0) {
|
||||
char*cp = strchr(warning_flags, 'v');
|
||||
if (cp) while (*cp) {
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else if (strcmp(name,"no-sensitivity-entire-array") == 0) {
|
||||
char*cp = strchr(warning_flags, 'a');
|
||||
if (cp) while (*cp) {
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1488,6 +1488,12 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
|||
def->port(idx)->data_type(),
|
||||
def->port(idx)->vector_width(),
|
||||
tmp);
|
||||
if (NetEEvent*evt = dynamic_cast<NetEEvent*> (parms[idx])) {
|
||||
cerr << evt->get_fileline() << ": error: An event '"
|
||||
<< evt->event()->name() << "' can not be a user "
|
||||
"function argument." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug:"
|
||||
<< " function " << path_
|
||||
|
|
|
|||
|
|
@ -2644,6 +2644,13 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
|||
ivl_variable_type_t lv_type = lv->expr_type();
|
||||
|
||||
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, wid, parms_[idx]);
|
||||
if (NetEEvent*evt = dynamic_cast<NetEEvent*> (rv)) {
|
||||
cerr << evt->get_fileline() << ": error: An event '"
|
||||
<< evt->event()->name() << "' can not be a user "
|
||||
"task argument." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
if (wid > rv->expr_width()) {
|
||||
rv->set_width(wid);
|
||||
rv = pad_to_width(rv, wid, *this);
|
||||
|
|
|
|||
|
|
@ -1369,6 +1369,10 @@ NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
|||
/* Synthesize the arguments. */
|
||||
bool errors = false;
|
||||
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
|
||||
if (dynamic_cast<NetEEvent*> (parms_[idx])) {
|
||||
errors = true;
|
||||
continue;
|
||||
}
|
||||
NetNet*tmp = parms_[idx]->synthesize(des, scope, root);
|
||||
if (tmp == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to synthesize "
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ PLI_INT32 tf_igetp(PLI_INT32 n, void *obj)
|
|||
{
|
||||
value.format = vpiStringVal;
|
||||
vpi_get_value(arg_h, &value);
|
||||
/* The following may generate a compilation warning, but this
|
||||
* functionality is required by some versions of the standard. */
|
||||
rtn = (int) value.value.str; /* Oh my */
|
||||
} else {
|
||||
value.format = vpiIntVal;
|
||||
|
|
|
|||
8
main.cc
8
main.cc
|
|
@ -116,6 +116,8 @@ bool warn_timescale = false;
|
|||
bool warn_portbinding = false;
|
||||
bool warn_inf_loop = false;
|
||||
bool warn_ob_select = false;
|
||||
bool warn_sens_entire_vec = false;
|
||||
bool warn_sens_entire_arr = false;
|
||||
|
||||
bool error_implicit = false;
|
||||
|
||||
|
|
@ -501,6 +503,12 @@ static void read_iconfig_file(const char*ipath)
|
|||
case 't':
|
||||
warn_timescale = true;
|
||||
break;
|
||||
case 'v':
|
||||
warn_sens_entire_vec = true;
|
||||
break;
|
||||
case 'a':
|
||||
warn_sens_entire_arr = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
# include <cassert>
|
||||
# include <typeinfo>
|
||||
# include "compiler.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
|
||||
|
|
@ -115,7 +116,7 @@ NexusSet* NetESelect::nex_input(bool rem_out)
|
|||
result->add(*tmp);
|
||||
delete tmp;
|
||||
/* See the comment for NetESignal below. */
|
||||
if (base_) {
|
||||
if (base_ && warn_sens_entire_vec) {
|
||||
cerr << get_fileline() << ": warning: @* is sensitive to all "
|
||||
"bits in '" << *expr_ << "'." << endl;
|
||||
}
|
||||
|
|
@ -151,9 +152,11 @@ NexusSet* NetESignal::nex_input(bool rem_out)
|
|||
tmp = word_->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
cerr << get_fileline() << ": warning: @* is sensitive to all "
|
||||
<< net_->array_count() << " words in array '"
|
||||
<< name() << "'." << endl;
|
||||
if (warn_sens_entire_arr) {
|
||||
cerr << get_fileline() << ": warning: @* is sensitive to all "
|
||||
<< net_->array_count() << " words in array '"
|
||||
<< name() << "'." << endl;
|
||||
}
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1)
|
||||
result->add(net_->pin(idx).nexus());
|
||||
|
|
|
|||
|
|
@ -308,6 +308,7 @@ void dll_target::expr_event(const NetEEvent*net)
|
|||
assert(expr_);
|
||||
|
||||
expr_->type_ = IVL_EX_EVENT;
|
||||
FILE_NAME(expr_, net);
|
||||
expr_->value_= IVL_VT_VOID;
|
||||
|
||||
/* Locate the event by name. Save the ivl_event_t in the
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
|
|||
(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 %d bits.\n",
|
||||
"signed index less than %zu bits.\n",
|
||||
ivl_expr_file(expr),
|
||||
ivl_expr_lineno(expr),
|
||||
8*sizeof(int));
|
||||
|
|
|
|||
|
|
@ -2983,6 +2983,12 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
|
|||
res.base = 0;
|
||||
res.wid = 0;
|
||||
break;
|
||||
case IVL_EX_EVENT:
|
||||
fprintf(stderr, "%s:%u: vvp-tgt error: A named event is not "
|
||||
"handled in this context (expression).\n",
|
||||
ivl_expr_file(exp), ivl_expr_lineno(exp));
|
||||
exit(1);
|
||||
break;
|
||||
|
||||
case IVL_EX_STRING:
|
||||
res = draw_string_expr(exp, wid);
|
||||
|
|
|
|||
|
|
@ -214,7 +214,6 @@ static PLI_INT32 sys_fclose_calltf(PLI_BYTE8*name)
|
|||
vpiHandle fd = vpi_scan(argv);
|
||||
s_vpi_value val;
|
||||
PLI_UINT32 fd_mcd;
|
||||
char *str = ""; /* This prevents the compiler from complaining. */
|
||||
errno = 0;
|
||||
|
||||
vpi_free_object(argv);
|
||||
|
|
@ -225,7 +224,7 @@ static PLI_INT32 sys_fclose_calltf(PLI_BYTE8*name)
|
|||
fd_mcd = val.value.integer;
|
||||
|
||||
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
|
||||
( IS_MCD(fd_mcd) && vpi_mcd_printf(fd_mcd, str) == EOF) ||
|
||||
( IS_MCD(fd_mcd) && vpi_mcd_printf(fd_mcd, "%s", "") == EOF) ||
|
||||
(! fd_mcd)) {
|
||||
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
|
|
@ -254,7 +253,6 @@ static PLI_INT32 sys_fflush_calltf(PLI_BYTE8*name)
|
|||
s_vpi_value val;
|
||||
PLI_UINT32 fd_mcd;
|
||||
FILE *fp;
|
||||
char *str = ""; /* This prevents the compiler from complaining. */
|
||||
errno = 0;
|
||||
|
||||
/* If we have no argument then flush all the streams. */
|
||||
|
|
@ -274,7 +272,7 @@ static PLI_INT32 sys_fflush_calltf(PLI_BYTE8*name)
|
|||
if (fd_mcd == 0) return 0;
|
||||
|
||||
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
|
||||
( IS_MCD(fd_mcd) && vpi_mcd_printf(fd_mcd, str) == EOF) ||
|
||||
( IS_MCD(fd_mcd) && vpi_mcd_printf(fd_mcd, "%s", "") == EOF) ||
|
||||
(! fd_mcd)) {
|
||||
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
|
|
|
|||
12
vvp/array.cc
12
vvp/array.cc
|
|
@ -31,6 +31,7 @@
|
|||
#endif
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <limits.h>
|
||||
# include <iostream>
|
||||
# include "compile.h"
|
||||
# include <assert.h>
|
||||
|
|
@ -133,6 +134,15 @@ struct __vpiArrayVthrA {
|
|||
{
|
||||
if (address_handle) {
|
||||
s_vpi_value vp;
|
||||
/* Check to see if the value is defined. */
|
||||
vp.format = vpiVectorVal;
|
||||
vpi_get_value(address_handle, &vp);
|
||||
int words = (vpi_get(vpiSize, address_handle)-1)/32 + 1;
|
||||
for(int idx = 0; idx < words; idx += 1) {
|
||||
/* Return UINT_MAX to indicate an X base. */
|
||||
if (vp.value.vector[idx].bval != 0) return UINT_MAX;
|
||||
}
|
||||
/* The value is defined so get and return it. */
|
||||
vp.format = vpiIntVal;
|
||||
vpi_get_value(address_handle, &vp);
|
||||
return vp.value.integer;
|
||||
|
|
@ -146,7 +156,7 @@ struct __vpiArrayVthrA {
|
|||
vvp_bit4_t bit = vthread_get_bit(vpip_current_vthread, address+idx);
|
||||
tmp.set_bit(idx, bit);
|
||||
}
|
||||
unsigned long val;
|
||||
unsigned long val = ULONG_MAX;
|
||||
vector4_to_value(tmp, val);
|
||||
return val;
|
||||
}
|
||||
|
|
|
|||
15
vvp/part.cc
15
vvp/part.cc
|
|
@ -238,7 +238,7 @@ vvp_fun_part_var::~vvp_fun_part_var()
|
|||
}
|
||||
|
||||
bool vvp_fun_part_var::recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
long&base, vvp_vector4_t&source,
|
||||
int&base, vvp_vector4_t&source,
|
||||
vvp_vector4_t&ref)
|
||||
{
|
||||
long tmp;
|
||||
|
|
@ -247,12 +247,13 @@ bool vvp_fun_part_var::recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
source = bit;
|
||||
break;
|
||||
case 1:
|
||||
// LONG_MIN is before the vector and is used to
|
||||
// INT_MIN is before the vector and is used to
|
||||
// represent a 'bx value on the select input.
|
||||
tmp = LONG_MIN;
|
||||
// We need a new &PV<> that knows if the index is signed.
|
||||
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);
|
||||
if (tmp == base) return false;
|
||||
if ((int)tmp == base) return false;
|
||||
base = tmp;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -264,7 +265,7 @@ bool vvp_fun_part_var::recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
vvp_vector4_t res (wid_);
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
|
||||
long adr = base+idx;
|
||||
int adr = base+idx;
|
||||
if (adr < 0) continue;
|
||||
if ((unsigned)adr >= source.size()) break;
|
||||
|
||||
|
|
@ -313,7 +314,7 @@ void vvp_fun_part_var_sa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&b
|
|||
struct vvp_fun_part_var_state_s {
|
||||
vvp_fun_part_var_state_s() : base(0) { }
|
||||
|
||||
long base;
|
||||
int base;
|
||||
vvp_vector4_t source;
|
||||
vvp_vector4_t ref;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ class vvp_fun_part_var : public vvp_net_fun_t {
|
|||
|
||||
protected:
|
||||
bool recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
long&base, vvp_vector4_t&source,
|
||||
int&base, vvp_vector4_t&source,
|
||||
vvp_vector4_t&ref);
|
||||
|
||||
unsigned wid_;
|
||||
|
|
@ -154,7 +154,7 @@ class vvp_fun_part_var_sa : public vvp_fun_part_var {
|
|||
vvp_context_t);
|
||||
|
||||
private:
|
||||
long base_;
|
||||
int base_;
|
||||
vvp_vector4_t source_;
|
||||
// Save the last output, for detecting change.
|
||||
vvp_vector4_t ref_;
|
||||
|
|
|
|||
|
|
@ -139,8 +139,8 @@ static void format_vpiBinStrVal(vvp_signal_value*sig, int base, unsigned wid,
|
|||
s_vpi_value*vp)
|
||||
{
|
||||
char *rbuf = need_result_buf(wid+1, RBUF_VAL);
|
||||
long offset = wid - 1 + base;
|
||||
long end = base + (signed)wid;
|
||||
long offset = end - 1;
|
||||
long ssize = (signed)sig->value_size();
|
||||
|
||||
for (long idx = base ; idx < end ; idx += 1) {
|
||||
|
|
@ -993,6 +993,15 @@ static int PV_get_base(struct __vpiPV*rfp)
|
|||
/* We return from the symbol base if it is defined. */
|
||||
if (rfp->sbase != 0) {
|
||||
s_vpi_value val;
|
||||
/* Check to see if the value is defined. */
|
||||
val.format = vpiVectorVal;
|
||||
vpi_get_value(rfp->sbase, &val);
|
||||
int words = (vpi_get(vpiSize, rfp->sbase)-1)/32 + 1;
|
||||
for(int idx = 0; idx < words; idx += 1) {
|
||||
/* Return INT_MIN to indicate an X base. */
|
||||
if (val.value.vector[idx].bval != 0) return INT_MIN;
|
||||
}
|
||||
/* The value is defined so get and return it. */
|
||||
val.format = vpiIntVal;
|
||||
vpi_get_value(rfp->sbase, &val);
|
||||
return val.value.integer;
|
||||
|
|
|
|||
|
|
@ -1300,8 +1300,8 @@ vvp_vector4_t& vvp_vector4_t::operator |= (const vvp_vector4_t&that)
|
|||
if (size_ <= BITS_PER_WORD) {
|
||||
unsigned long tmp = abits_val_ | bbits_val_ |
|
||||
that.abits_val_ | that.bbits_val_;
|
||||
bbits_val_ = (~abits_val_ | bbits_val_) & that.bbits_val_ |
|
||||
(~that.abits_val_ | that.bbits_val_) & bbits_val_;
|
||||
bbits_val_ = ((~abits_val_ | bbits_val_) & that.bbits_val_) |
|
||||
((~that.abits_val_ | that.bbits_val_) & bbits_val_);
|
||||
abits_val_ = tmp;
|
||||
|
||||
} else {
|
||||
|
|
@ -1309,10 +1309,10 @@ vvp_vector4_t& vvp_vector4_t::operator |= (const vvp_vector4_t&that)
|
|||
for (unsigned idx = 0; idx < words ; idx += 1) {
|
||||
unsigned long tmp = abits_ptr_[idx] | bbits_ptr_[idx] |
|
||||
that.abits_ptr_[idx] | that.bbits_ptr_[idx];
|
||||
bbits_ptr_[idx] = (~abits_ptr_[idx] | bbits_ptr_[idx]) &
|
||||
that.bbits_ptr_[idx] |
|
||||
(~that.abits_ptr_[idx] |
|
||||
that.bbits_ptr_[idx]) & bbits_ptr_[idx];
|
||||
bbits_ptr_[idx] = ((~abits_ptr_[idx] | bbits_ptr_[idx]) &
|
||||
that.bbits_ptr_[idx]) |
|
||||
((~that.abits_ptr_[idx] |
|
||||
that.bbits_ptr_[idx]) & bbits_ptr_[idx]);
|
||||
abits_ptr_[idx] = tmp;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue