Checks for illegal use of automatically allocated variables.
This patch adds a number of compile and run-time checks for illegal uses of variables declared in automatic tasks and functions. It also adds a check for event expressions in automatic tasks that use features not yet supported in VVP.
This commit is contained in:
parent
bbdf622ea5
commit
04377151bc
69
PExpr.cc
69
PExpr.cc
|
|
@ -24,6 +24,7 @@
|
|||
# include "compiler.h"
|
||||
# include "PExpr.h"
|
||||
# include "Module.h"
|
||||
# include "netmisc.h"
|
||||
# include <typeinfo>
|
||||
|
||||
PExpr::PExpr()
|
||||
|
|
@ -35,6 +36,11 @@ PExpr::~PExpr()
|
|||
{
|
||||
}
|
||||
|
||||
bool PExpr::has_aa_term(Design*, NetScope*) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PExpr::is_the_same(const PExpr*that) const
|
||||
{
|
||||
return typeid(this) == typeid(that);
|
||||
|
|
@ -64,6 +70,12 @@ PEBinary::~PEBinary()
|
|||
{
|
||||
}
|
||||
|
||||
bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(left_ && right_);
|
||||
return left_->has_aa_term(des, scope) || right_->has_aa_term(des, scope);
|
||||
}
|
||||
|
||||
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
|
||||
: PEBinary(op, l, r)
|
||||
{
|
||||
|
|
@ -130,6 +142,15 @@ PECallFunction::~PECallFunction()
|
|||
{
|
||||
}
|
||||
|
||||
bool PECallFunction::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = false;
|
||||
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
|
||||
flag = parms_[idx]->has_aa_term(des, scope) || flag;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
PEConcat::PEConcat(const svector<PExpr*>&p, PExpr*r)
|
||||
: parms_(p), repeat_(r)
|
||||
{
|
||||
|
|
@ -140,6 +161,18 @@ PEConcat::~PEConcat()
|
|||
delete repeat_;
|
||||
}
|
||||
|
||||
bool PEConcat::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = false;
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
flag = parms_[idx]->has_aa_term(des, scope) || flag;
|
||||
}
|
||||
if (repeat_)
|
||||
flag = repeat_->has_aa_term(des, scope) || flag;
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
PEEvent::PEEvent(PEEvent::edge_t t, PExpr*e)
|
||||
: type_(t), expr_(e)
|
||||
{
|
||||
|
|
@ -154,6 +187,12 @@ PEEvent::edge_t PEEvent::type() const
|
|||
return type_;
|
||||
}
|
||||
|
||||
bool PEEvent::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(expr_);
|
||||
return expr_->has_aa_term(des, scope);
|
||||
}
|
||||
|
||||
PExpr* PEEvent::expr() const
|
||||
{
|
||||
return expr_;
|
||||
|
|
@ -188,6 +227,22 @@ PEIdent::~PEIdent()
|
|||
{
|
||||
}
|
||||
|
||||
bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetNet* net = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
const NetExpr*ex1, *ex2;
|
||||
|
||||
scope = symbol_search(0, des, scope, path_, net, par, eve, ex1, ex2);
|
||||
|
||||
if (scope)
|
||||
return scope->is_auto();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
PENumber::PENumber(verinum*vp)
|
||||
: value_(vp)
|
||||
{
|
||||
|
|
@ -237,6 +292,14 @@ PETernary::~PETernary()
|
|||
{
|
||||
}
|
||||
|
||||
bool PETernary::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(expr_ && tru_ && fal_);
|
||||
return expr_->has_aa_term(des, scope)
|
||||
|| tru_->has_aa_term(des, scope)
|
||||
|| fal_->has_aa_term(des, scope);
|
||||
}
|
||||
|
||||
PEUnary::PEUnary(char op, PExpr*ex)
|
||||
: op_(op), expr_(ex)
|
||||
{
|
||||
|
|
@ -245,3 +308,9 @@ PEUnary::PEUnary(char op, PExpr*ex)
|
|||
PEUnary::~PEUnary()
|
||||
{
|
||||
}
|
||||
|
||||
bool PEUnary::has_aa_term(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(expr_);
|
||||
return expr_->has_aa_term(des, scope);
|
||||
}
|
||||
|
|
|
|||
22
PExpr.h
22
PExpr.h
|
|
@ -46,6 +46,10 @@ class PExpr : public LineInfo {
|
|||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
// This method tests whether the expression contains any
|
||||
// references to automatically allocated variables.
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
// This method tests the width that the expression wants to
|
||||
// be. It is used by elaboration of assignments to figure out
|
||||
// the width of the expression.
|
||||
|
|
@ -156,6 +160,8 @@ class PEConcat : public PExpr {
|
|||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
|
|
@ -200,6 +206,8 @@ class PEEvent : public PExpr {
|
|||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
edge_t type_;
|
||||
PExpr *expr_;
|
||||
|
|
@ -247,6 +255,9 @@ class PEIdent : public PExpr {
|
|||
void append_name(perm_string);
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
|
|
@ -420,6 +431,8 @@ class PEUnary : public PExpr {
|
|||
|
||||
virtual void dump(ostream&out) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
|
|
@ -448,6 +461,8 @@ class PEBinary : public PExpr {
|
|||
|
||||
virtual void dump(ostream&out) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
|
|
@ -541,6 +556,9 @@ class PETernary : public PExpr {
|
|||
~PETernary();
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
|
|
@ -579,7 +597,9 @@ class PECallFunction : public PExpr {
|
|||
|
||||
virtual void dump(ostream &) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_wid, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -228,6 +228,15 @@ void PEventStatement::set_statement(Statement*st)
|
|||
statement_ = st;
|
||||
}
|
||||
|
||||
bool PEventStatement::has_aa_term(Design*des, NetScope*scope)
|
||||
{
|
||||
bool flag = false;
|
||||
for (unsigned idx = 0 ; idx < expr_.count() ; idx += 1) {
|
||||
flag = expr_[idx]->has_aa_term(des, scope) || flag;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
PForce::PForce(PExpr*l, PExpr*r)
|
||||
: lval_(l), expr_(r)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -347,6 +347,8 @@ class PEventStatement : public Statement {
|
|||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
bool has_aa_term(Design*des, NetScope*scope);
|
||||
|
||||
// This method is used to elaborate, but attach a previously
|
||||
// elaborated statement to the event.
|
||||
NetProc* elaborate_st(Design*des, NetScope*scope, NetProc*st) const;
|
||||
|
|
|
|||
|
|
@ -1123,8 +1123,9 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
|
|||
? NetScope::FORK_JOIN
|
||||
: NetScope::BEGIN_END);
|
||||
my_scope->set_line(get_file(), get_lineno());
|
||||
my_scope->is_auto(scope->is_auto());
|
||||
|
||||
// Scan the parameters in the module, and create stub parameter
|
||||
// Scan the parameters in the scope, and create stub parameter
|
||||
// entries in the scope for the parameter names.
|
||||
|
||||
collect_scope_parameters_(my_scope, parameters);
|
||||
|
|
|
|||
84
elaborate.cc
84
elaborate.cc
|
|
@ -2012,6 +2012,14 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (scope->is_auto() && lval()->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically allocated "
|
||||
"variables may not be assigned values using non-blocking "
|
||||
"assignments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Elaborate the l-value. */
|
||||
NetAssign_*lv = elaborate_lval(des, scope);
|
||||
if (lv == 0) return 0;
|
||||
|
|
@ -2042,6 +2050,15 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
|
|||
NetEvWait*event = 0;
|
||||
if (count_ != 0 || event_ != 0) {
|
||||
if (count_ != 0) {
|
||||
if (scope->is_auto() && count_->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically "
|
||||
"allocated variables may not be referenced "
|
||||
"in intra-assignment event controls of "
|
||||
"non-blocking assignments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(event_ != 0);
|
||||
count = elab_and_eval(des, scope, count_, -1);
|
||||
if (count == 0) {
|
||||
|
|
@ -2052,6 +2069,15 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
|
|||
}
|
||||
}
|
||||
|
||||
if (scope->is_auto() && event_->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically "
|
||||
"allocated variables may not be referenced "
|
||||
"in intra-assignment event controls of "
|
||||
"non-blocking assignments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetProc*st = event_->elaborate(des, scope);
|
||||
if (st == 0) {
|
||||
cerr << get_fileline() << ": unable to elaborate "
|
||||
|
|
@ -2586,6 +2612,22 @@ NetCAssign* PCAssign::elaborate(Design*des, NetScope*scope) const
|
|||
NetCAssign*dev = 0;
|
||||
assert(scope);
|
||||
|
||||
if (scope->is_auto() && lval_->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically allocated "
|
||||
"variables may not be assigned values using procedural "
|
||||
"continuous assignments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (scope->is_auto() && expr_->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically allocated "
|
||||
"variables may not be referenced in procedural "
|
||||
"continuous assignments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope, false);
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
|
@ -2617,6 +2659,14 @@ NetDeassign* PDeassign::elaborate(Design*des, NetScope*scope) const
|
|||
{
|
||||
assert(scope);
|
||||
|
||||
if (scope->is_auto() && lval_->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically allocated "
|
||||
"variables may not be assigned values using procedural "
|
||||
"continuous assignments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope, false);
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
|
@ -2875,6 +2925,16 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
|
|||
the sub-expression as a net and decide how to handle
|
||||
the edge. */
|
||||
|
||||
if (scope->is_auto()) {
|
||||
if (! dynamic_cast<PEIdent*>(expr_[idx]->expr())) {
|
||||
cerr << get_fileline() << ": sorry, complex event "
|
||||
"expressions are not yet supported in "
|
||||
"automatic tasks." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool save_flag = error_implicit;
|
||||
error_implicit = true;
|
||||
NetExpr*tmp = elab_and_eval(des, scope, expr_[idx]->expr(), 0);
|
||||
|
|
@ -3150,6 +3210,22 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
|
|||
NetForce*dev = 0;
|
||||
assert(scope);
|
||||
|
||||
if (scope->is_auto() && lval_->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically allocated "
|
||||
"variables may not be assigned values using procedural "
|
||||
"force statements." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (scope->is_auto() && expr_->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically allocated "
|
||||
"variables may not be referenced in procedural force "
|
||||
"statements." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope, true);
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
|
@ -3355,6 +3431,14 @@ NetProc* PRelease::elaborate(Design*des, NetScope*scope) const
|
|||
{
|
||||
assert(scope);
|
||||
|
||||
if (scope->is_auto() && lval_->has_aa_term(des, scope)) {
|
||||
cerr << get_fileline() << ": error: automatically allocated "
|
||||
"variables may not be assigned values using procedural "
|
||||
"force statements." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetAssign_*lval = lval_->elaborate_lval(des, scope, true);
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -100,7 +100,8 @@ static int vpi_get_dec_size(vpiHandle item)
|
|||
);
|
||||
}
|
||||
|
||||
static void array_from_iterator(struct strobe_cb_info*info, vpiHandle argv)
|
||||
static int array_from_iterator(struct strobe_cb_info*info, vpiHandle argv,
|
||||
int check_no_aa_vars)
|
||||
{
|
||||
if (argv) {
|
||||
vpiHandle item;
|
||||
|
|
@ -111,13 +112,17 @@ static void array_from_iterator(struct strobe_cb_info*info, vpiHandle argv)
|
|||
free(items);
|
||||
info->nitems = 0;
|
||||
info->items = 0;
|
||||
return;
|
||||
return check_no_aa_vars;
|
||||
}
|
||||
if (check_no_aa_vars && vpi_get(vpiAutomatic, items[0]))
|
||||
check_no_aa_vars = 0;
|
||||
|
||||
for (item = vpi_scan(argv) ; item ; item = vpi_scan(argv)) {
|
||||
items = realloc(items, (nitems+1)*sizeof(vpiHandle));
|
||||
items[nitems] = item;
|
||||
nitems += 1;
|
||||
if (check_no_aa_vars && vpi_get(vpiAutomatic, item))
|
||||
check_no_aa_vars = 0;
|
||||
}
|
||||
|
||||
info->nitems = nitems;
|
||||
|
|
@ -127,6 +132,7 @@ static void array_from_iterator(struct strobe_cb_info*info, vpiHandle argv)
|
|||
info->nitems = 0;
|
||||
info->items = 0;
|
||||
}
|
||||
return check_no_aa_vars;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -902,7 +908,7 @@ static PLI_INT32 sys_display_calltf(PLI_BYTE8*name)
|
|||
info = malloc(sizeof (struct strobe_cb_info));
|
||||
info->default_format = get_default_format(name);
|
||||
info->scope = scope;
|
||||
array_from_iterator(info, argv);
|
||||
array_from_iterator(info, argv, 0);
|
||||
|
||||
vpi_put_userdata(sys, info);
|
||||
}
|
||||
|
|
@ -995,7 +1001,13 @@ static PLI_INT32 sys_strobe_calltf(PLI_BYTE8*name)
|
|||
info->mcd = 1;
|
||||
}
|
||||
|
||||
array_from_iterator(info, argv);
|
||||
if (!array_from_iterator(info, argv, 1)) {
|
||||
vpi_printf("ERROR: %s parameters may not include automatically "
|
||||
"allocated variables\n", name);
|
||||
free(info->items);
|
||||
free(info);
|
||||
return 0;
|
||||
}
|
||||
info->name = strdup(name);
|
||||
info->default_format = get_default_format(name);
|
||||
info->scope= scope;
|
||||
|
|
@ -1095,7 +1107,13 @@ static PLI_INT32 sys_monitor_calltf(PLI_BYTE8*name)
|
|||
}
|
||||
|
||||
/* Make an array of handles from the argument list. */
|
||||
array_from_iterator(&monitor_info, argv);
|
||||
if (!array_from_iterator(&monitor_info, argv, 1)) {
|
||||
vpi_printf("ERROR: $monitor parameters may not include "
|
||||
"automatically allocated variables\n");
|
||||
free(monitor_info.items);
|
||||
monitor_info.nitems = 0;
|
||||
return 0;
|
||||
}
|
||||
monitor_info.name = strdup(name);
|
||||
monitor_info.default_format = get_default_format(name);
|
||||
monitor_info.scope = scope;
|
||||
|
|
@ -1211,7 +1229,7 @@ static PLI_INT32 sys_fdisplay_calltf(PLI_BYTE8*name)
|
|||
assert(scope);
|
||||
info.default_format = get_default_format(name);
|
||||
info.scope = scope;
|
||||
array_from_iterator(&info, argv);
|
||||
array_from_iterator(&info, argv, 0);
|
||||
do_display(mcd, &info);
|
||||
free(info.items);
|
||||
|
||||
|
|
@ -1969,7 +1987,7 @@ static PLI_INT32 sys_swrite_calltf(PLI_BYTE8 *name)
|
|||
info.name = name;
|
||||
info.default_format = get_default_format(name);
|
||||
info.scope = scope;
|
||||
array_from_iterator(&info, argv);
|
||||
array_from_iterator(&info, argv, 0);
|
||||
|
||||
/* Because %u and %z may put embedded NULL characters into the returned
|
||||
* string strlen() may not match the real size! */
|
||||
|
|
@ -2049,7 +2067,7 @@ static PLI_INT32 sys_sformat_calltf(PLI_BYTE8 *name)
|
|||
info.name = name;
|
||||
info.default_format = get_default_format(name);
|
||||
info.scope = scope;
|
||||
array_from_iterator(&info, argv);
|
||||
array_from_iterator(&info, argv, 0);
|
||||
idx = -1;
|
||||
size = get_format(&result, fmt, &info, &idx);
|
||||
free(fmt);
|
||||
|
|
|
|||
|
|
@ -454,6 +454,9 @@ static int vpi_array_var_word_get(int code, vpiHandle ref)
|
|||
case vpiRightRange:
|
||||
return parent->lsb.value;
|
||||
|
||||
case vpiAutomatic:
|
||||
return (int) parent->scope->is_automatic;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -634,6 +637,9 @@ static int vpi_array_vthr_A_get(int code, vpiHandle ref)
|
|||
case vpiRightRange:
|
||||
return parent->lsb.value;
|
||||
|
||||
case vpiAutomatic:
|
||||
return (int) parent->scope->is_automatic;
|
||||
|
||||
// For now &A<> is only a constant select. This will need
|
||||
// to be changed when it supports variable selection.
|
||||
case vpiConstantSelect:
|
||||
|
|
|
|||
|
|
@ -119,6 +119,14 @@ void delete_vpi_callback(struct __vpiCallback* ref)
|
|||
*/
|
||||
static struct __vpiCallback* make_value_change(p_cb_data data)
|
||||
{
|
||||
if (vpi_get(vpiAutomatic, data->obj)) {
|
||||
fprintf(stderr, "vpi error: cannot place value change "
|
||||
"callback on automatically allocated "
|
||||
"variable '%s'\n",
|
||||
vpi_get_str(vpiName, data->obj));
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct __vpiCallback*obj = new_vpi_callback();
|
||||
obj->cb_data = *data;
|
||||
if (data->time) {
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@ static int string_get(int code, vpiHandle ref)
|
|||
case vpiConstType:
|
||||
return vpiStringConst;
|
||||
|
||||
case vpiAutomatic:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp error: get %d not supported "
|
||||
"by vpiStringConst\n", code);
|
||||
|
|
@ -343,6 +346,9 @@ static int binary_get(int code, vpiHandle ref)
|
|||
case vpiSize:
|
||||
return rfp->bits.size();
|
||||
|
||||
case vpiAutomatic:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp error: get %d not supported "
|
||||
"by vpiBinaryConst\n", code);
|
||||
|
|
@ -533,6 +539,9 @@ static int dec_get(int code, vpiHandle ref)
|
|||
case vpiSize:
|
||||
return 32;
|
||||
|
||||
case vpiAutomatic:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp error: get %d not supported "
|
||||
"by vpiDecConst\n", code);
|
||||
|
|
@ -636,6 +645,9 @@ static int real_get(int code, vpiHandle ref)
|
|||
case vpiSigned:
|
||||
return 1;
|
||||
|
||||
case vpiAutomatic:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp error: get %d not supported "
|
||||
"by vpiDecConst\n", code);
|
||||
|
|
|
|||
|
|
@ -692,6 +692,14 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
|
|||
if (flags!=vpiNoDelay && flags!=vpiForceFlag && flags!=vpiReleaseFlag) {
|
||||
vvp_time64_t dly;
|
||||
|
||||
if (vpi_get(vpiAutomatic, obj)) {
|
||||
fprintf(stderr, "vpi error: cannot put a value with "
|
||||
"a delay on automatically allocated "
|
||||
"variable '%s'\n",
|
||||
vpi_get_str(vpiName, obj));
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(when != 0);
|
||||
|
||||
switch (when->type) {
|
||||
|
|
|
|||
|
|
@ -223,7 +223,6 @@ struct __vpiSignal {
|
|||
unsigned signed_flag : 1;
|
||||
unsigned isint_ : 1; // original type was integer
|
||||
unsigned is_netarray : 1; // This is word of a net array
|
||||
unsigned is_automatic : 1;
|
||||
/* The represented value is here. */
|
||||
vvp_net_t*node;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -75,6 +75,9 @@ static int scope_get(int code, vpiHandle obj)
|
|||
|
||||
case vpiTopModule:
|
||||
return 0x0 == ref->scope;
|
||||
|
||||
case vpiAutomatic:
|
||||
return (int) ref->is_automatic;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -330,33 +333,29 @@ compile_scope_decl(char*label, char*type, char*name, const char*tname,
|
|||
struct __vpiScope*scope = new struct __vpiScope;
|
||||
count_vpi_scopes += 1;
|
||||
|
||||
if (strcmp(type,"module") == 0) {
|
||||
char*base_type = 0;
|
||||
if (strncmp(type,"auto",4) == 0) {
|
||||
scope->is_automatic = true;
|
||||
base_type = &type[4];
|
||||
} else {
|
||||
scope->is_automatic = false;
|
||||
base_type = &type[0];
|
||||
}
|
||||
|
||||
if (strcmp(base_type,"module") == 0) {
|
||||
scope->base.vpi_type = &vpip_scope_module_rt;
|
||||
scope->is_automatic = false;
|
||||
} else if (strcmp(type,"autofunction") == 0) {
|
||||
} else if (strcmp(base_type,"function") == 0) {
|
||||
scope->base.vpi_type = &vpip_scope_function_rt;
|
||||
scope->is_automatic = true;
|
||||
} else if (strcmp(type,"function") == 0) {
|
||||
scope->base.vpi_type = &vpip_scope_function_rt;
|
||||
scope->is_automatic = false;
|
||||
} else if (strcmp(type,"autotask") == 0) {
|
||||
} else if (strcmp(base_type,"task") == 0) {
|
||||
scope->base.vpi_type = &vpip_scope_task_rt;
|
||||
scope->is_automatic = true;
|
||||
} else if (strcmp(type,"task") == 0) {
|
||||
scope->base.vpi_type = &vpip_scope_task_rt;
|
||||
scope->is_automatic = false;
|
||||
} else if (strcmp(type,"fork") == 0) {
|
||||
} else if (strcmp(base_type,"fork") == 0) {
|
||||
scope->base.vpi_type = &vpip_scope_fork_rt;
|
||||
scope->is_automatic = false;
|
||||
} else if (strcmp(type,"begin") == 0) {
|
||||
} else if (strcmp(base_type,"begin") == 0) {
|
||||
scope->base.vpi_type = &vpip_scope_begin_rt;
|
||||
scope->is_automatic = false;
|
||||
} else if (strcmp(type,"generate") == 0) {
|
||||
} else if (strcmp(base_type,"generate") == 0) {
|
||||
scope->base.vpi_type = &vpip_scope_begin_rt;
|
||||
scope->is_automatic = false;
|
||||
} else {
|
||||
scope->base.vpi_type = &vpip_scope_module_rt;
|
||||
scope->is_automatic = false;
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
|
@ -396,10 +395,6 @@ compile_scope_decl(char*label, char*type, char*name, const char*tname,
|
|||
scope->time_units = sp->time_units;
|
||||
scope->time_precision = sp->time_precision;
|
||||
|
||||
/* Scopes within automatic scopes are themselves automatic. */
|
||||
if (sp->is_automatic)
|
||||
scope->is_automatic = true;
|
||||
|
||||
} else {
|
||||
scope->scope = 0x0;
|
||||
|
||||
|
|
@ -476,5 +471,3 @@ unsigned vpip_add_item_to_context(automatic_hooks_s*item,
|
|||
/* Offset the context index by 2 to leave space for the list links. */
|
||||
return 2 + idx;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -528,10 +528,14 @@ static int signal_get(int code, vpiHandle ref)
|
|||
else
|
||||
return 0;
|
||||
|
||||
case vpiLeftRange: return rfp->msb;
|
||||
case vpiRightRange: return rfp->lsb;
|
||||
case vpiLeftRange:
|
||||
return rfp->msb;
|
||||
|
||||
case vpiAutomatic: return rfp->is_automatic;
|
||||
case vpiRightRange:
|
||||
return rfp->lsb;
|
||||
|
||||
case vpiAutomatic:
|
||||
return (int) vpip_scope(rfp)->is_automatic;
|
||||
|
||||
case _vpiNexusId:
|
||||
if (rfp->msb == rfp->lsb)
|
||||
|
|
@ -863,7 +867,6 @@ vpiHandle vpip_make_int(const char*name, int msb, int lsb, vvp_net_t*vec)
|
|||
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
|
||||
obj->vpi_type = &vpip_reg_rt;
|
||||
rfp->isint_ = true;
|
||||
rfp->is_automatic = vpip_peek_current_scope()->is_automatic;
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
@ -876,7 +879,6 @@ vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
|
|||
vpiHandle obj = vpip_make_net(name, msb,lsb, signed_flag, vec);
|
||||
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
|
||||
obj->vpi_type = &vpip_reg_rt;
|
||||
rfp->is_automatic = vpip_peek_current_scope()->is_automatic;
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
@ -915,7 +917,6 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
|||
obj->signed_flag = signed_flag? 1 : 0;
|
||||
obj->isint_ = 0;
|
||||
obj->is_netarray = 0;
|
||||
obj->is_automatic = vpip_peek_current_scope()->is_automatic;
|
||||
obj->node = node;
|
||||
|
||||
// Place this object within a scope. If this object is
|
||||
|
|
@ -972,11 +973,15 @@ static int PV_get(int code, vpiHandle ref)
|
|||
case vpiConstantSelect:
|
||||
return rfp->twid == 0;
|
||||
|
||||
case vpiLeftRange: rval += rfp->width;
|
||||
case vpiLeftRange:
|
||||
rval += rfp->width;
|
||||
case vpiRightRange:
|
||||
rval += vpi_get(vpiRightRange, rfp->parent) + PV_get_base(rfp);
|
||||
return rval;
|
||||
|
||||
case vpiAutomatic:
|
||||
return vpi_get(vpiAutomatic, rfp->parent);
|
||||
|
||||
default:
|
||||
fprintf(stderr, "PV_get: property %d is unknown\n", code);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,6 +93,9 @@ static int timevar_time_get(int code, vpiHandle ref)
|
|||
case vpiFuncType:
|
||||
return vpiTimeFunc;
|
||||
|
||||
case vpiAutomatic:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Code: %d\n", code);
|
||||
assert(0);
|
||||
|
|
@ -148,6 +151,9 @@ static int timevar_realtime_get(int code, vpiHandle ref)
|
|||
case vpiFuncType:
|
||||
return vpiRealFunc;
|
||||
|
||||
case vpiAutomatic:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Code: %d\n", code);
|
||||
assert(0);
|
||||
|
|
|
|||
Loading…
Reference in New Issue