Rework of parameter expression elaboration.

The compiler currently performs parameter expression elaboration before
performing parameter overrides. This means that the information needed
to correctly determine the expression type and width may not be available
at the time elaboration is performed. This patch reworks the code to
delay elaboration until after all overrides have been performed. It
also provides a new -g option that controls how the width of parameter
expressions is calculated when the parameter itself is unsized.
This commit is contained in:
Martin Whitaker 2010-12-05 21:28:17 +00:00 committed by Stephen Williams
parent fd5bc3fe51
commit 275dde7712
17 changed files with 333 additions and 517 deletions

View File

@ -138,7 +138,7 @@ class Module : public PScope, public LineInfo {
void dump(ostream&out) const;
bool elaborate(Design*, NetScope*scope) const;
typedef map<perm_string,NetExpr*> replace_t;
typedef map<perm_string,PExpr*> replace_t;
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep);
bool elaborate_sig(Design*, NetScope*scope) const;

View File

@ -151,6 +151,10 @@ extern bool gn_io_range_error_flag;
re-evaluated. */
extern bool gn_strict_ca_eval_flag;
/* If this flag is true, then force strict conformance to the IEEE
standard expression width rules. */
extern bool gn_strict_expr_width_flag;
/* If variables can be converted to uwires by a continuous assignment
(assuming no procedural assign, then return true. This will be true
for SystemVerilog */

View File

@ -29,6 +29,7 @@
# include "compiler.h"
# include "discipline.h"
# include "ivl_assert.h"
# include "PExpr.h"
static ostream& operator<< (ostream&o, NetBlock::Type t)
{
@ -1128,8 +1129,8 @@ void NetScope::dump(ostream&o) const
<< ":" << *(*pp).second.lsb << "] ";
o << (*pp).first << " = ";
if (pp->second.expr)
o << *(*pp).second.expr;
if (pp->second.val)
o << *(*pp).second.val;
else
o << "<nil>";
@ -1167,13 +1168,13 @@ void NetScope::dump(ostream&o) const
for (pp = localparams.begin()
; pp != localparams.end() ; ++ pp ) {
o << " localparam " << (*pp).first << " = " <<
*(*pp).second.expr << ";" << endl;
*(*pp).second.val << ";" << endl;
}
}
/* Dump the saved defparam assignments here. */
{
list<pair<pform_name_t,NetExpr*> >::const_iterator pp;
list<pair<pform_name_t,PExpr*> >::const_iterator pp;
for (pp = defparams.begin()
; pp != defparams.end() ; ++ pp ) {
o << " defparam " << (*pp).first << " = " <<
@ -1182,7 +1183,7 @@ void NetScope::dump(ostream&o) const
}
{
list<pair<list<hname_t>,NetExpr*> >::const_iterator pp;
list<pair<list<hname_t>,PExpr*> >::const_iterator pp;
for (pp = defparams_later.begin()
; pp != defparams_later.end() ; ++ pp ) {
o << " defparam(later) " << pp->first << " = " <<

View File

@ -121,6 +121,7 @@ const char*gen_xtypes = "xtypes";
const char*gen_icarus = "icarus-misc";
const char*gen_io_range_error = "io-range-error";
const char*gen_strict_ca_eval = "no-strict-ca-eval";
const char*gen_strict_expr_width = "no-strict-expr-width";
const char*gen_verilog_ams = "no-verilog-ams";
/* Boolean: true means use a default include dir, false means don't */
@ -680,6 +681,12 @@ int process_generation(const char*name)
else if (strcmp(name,"no-strict-ca-eval") == 0)
gen_strict_ca_eval = "no-strict-ca-eval";
else if (strcmp(name,"strict-expr-width") == 0)
gen_strict_expr_width = "strict-expr-width";
else if (strcmp(name,"no-strict-expr-width") == 0)
gen_strict_expr_width = "no-strict-expr-width";
else if (strcmp(name,"verilog-ams") == 0)
gen_verilog_ams = "verilog-ams";
@ -702,7 +709,8 @@ int process_generation(const char*name)
" xtypes | no-xtypes\n"
" icarus-misc | no-icarus-misc\n"
" io-range-error | no-io-range-error\n"
" strict-ca-eval | no-strict-ca-eval\n");
" strict-ca-eval | no-strict-ca-eval\n"
" strict-expr-width | no-strict-expr-width\n");
return 1;
}
@ -1043,6 +1051,7 @@ int main(int argc, char **argv)
fprintf(iconfig_file, "generation:%s\n", gen_xtypes);
fprintf(iconfig_file, "generation:%s\n", gen_io_range_error);
fprintf(iconfig_file, "generation:%s\n", gen_strict_ca_eval);
fprintf(iconfig_file, "generation:%s\n", gen_strict_expr_width);
fprintf(iconfig_file, "generation:%s\n", gen_verilog_ams);
fprintf(iconfig_file, "generation:%s\n", gen_icarus);
fprintf(iconfig_file, "warnings:%s\n", warning_flags);

View File

@ -2089,32 +2089,13 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
return expr_width_;
}
// The width of a parameter name is the width of the range for
// the parameter name, if a range is declared. Otherwise, the
// width is undefined.
// The width of a parameter is the width of the parameter value
// (as evaluated earlier).
if (par != 0) {
expr_type_ = par->expr_type();
expr_type__ = expr_type_;
if (ex1) {
ivl_assert(*this, ex2);
const NetEConst*ex1_const = dynamic_cast<const NetEConst*> (ex1);
const NetEConst*ex2_const = dynamic_cast<const NetEConst*> (ex2);
ivl_assert(*this, ex1_const && ex2_const);
long msb = ex1_const->value().as_long();
long lsb = ex2_const->value().as_long();
if (msb >= lsb)
expr_width_ = msb - lsb + 1;
else
expr_width_ = lsb - msb + 1;
return expr_width_;
}
// This is a parameter. If it is sized (meaning it was
// declared with range expressions) then the range
// expressions would have been caught above. So if we
// got here then we know this is an unsized constant.
expr_width_ = par->expr_width();
expr_type__ = expr_type_;
if (!par->has_width())
unsized_flag = true;
return expr_width_;
}
@ -2154,6 +2135,14 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
const NetExpr*ex1, *ex2;
if (is_param_expr && path_.size() > 1) {
cerr << get_fileline() << ": error: parameter r-value expression "
"does not support hierarchical references `" << path_
<< "`." << endl;
des->errors += 1;
return 0;
}
NetScope*found_in = symbol_search(this, des, scope, path_,
net, par, eve,
ex1, ex2);
@ -2163,6 +2152,14 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
if (par != 0)
return elaborate_expr_param_(des, scope, par, found_in, ex1, ex2, expr_wid);
// If this is a parameter expression, no other identifiers are valid.
if (is_param_expr) {
cerr << get_fileline() << ": error: identifier `"
<< path_ << "` is not a parameter in "
<< scope_path(scope) << "." << endl;
des->errors += 1;
return 0;
}
// If the identifier names a signal (a register or wire)
// then create a NetESignal node to handle it.
@ -3461,7 +3458,8 @@ NetEConst* PENumber::elaborate_expr(Design*, NetScope*,
// the self-determined size.
if (expr_width__ > 0) {
tvalue = pad_to_width(tvalue, expr_width__);
if (tvalue.len() > (unsigned)expr_width__) {
if ( (tvalue.len() > (unsigned)expr_width__) ||
(is_param_expr && !tvalue.has_len()) ) {
verinum tmp (tvalue, expr_width__);
tmp.has_sign(tvalue.has_sign());
tvalue = tmp;

View File

@ -229,7 +229,7 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
// name is not found in the pscope, look in containing scopes,
// but do not go outside the containing module instance.
for (;;) {
ex = pscope->get_parameter(name_tail.name, ex_msb, ex_lsb);
ex = pscope->get_parameter(des, name_tail.name, ex_msb, ex_lsb);
if (ex != 0)
break;
if (pscope->type() == NetScope::MODULE)
@ -509,7 +509,7 @@ void NetEParam::resolve_pexpr_type(void)
if (reference_->second.signed_flag) {
cast_signed_base_(true);
} else if (reference_->second.expr) {
cast_signed_base_( reference_->second.expr->has_sign() );
} else if (reference_->second.val) {
cast_signed_base_( reference_->second.val->has_sign() );
}
}

View File

@ -50,63 +50,9 @@
typedef map<perm_string,LexicalScope::param_expr_t>::const_iterator mparm_it_t;
static void collect_scope_parameters_(NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&parameters)
static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
const LexicalScope::param_expr_t&cur)
{
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; ++ cur ) {
NetEParam*tmp = new NetEParam;
tmp->set_line(*((*cur).second.expr));
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
0, 0, false, 0, (*cur).second);
}
}
static void collect_scope_localparams_(NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&localparams)
{
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; ++ cur ) {
NetEParam*tmp = new NetEParam;
tmp->set_line(*((*cur).second.expr));
if ((*cur).second.msb)
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
0, 0, false, 0, (*cur).second);
}
}
static void elaborate_parm_item_(perm_string name,
const LexicalScope::param_expr_t&cur,
Design*des, NetScope*scope)
{
PExpr*ex = cur.expr;
assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope);
NetExpr*msb = 0;
NetExpr*lsb = 0;
bool signed_flag = cur.signed_flag;
/* If the parameter declaration includes msb and lsb,
then use them to calculate a width for the
result. Then make sure the constant expression of the
parameter value is coerced to have the correct
and defined width. */
if (cur.msb) {
assert(cur.lsb);
msb = cur.msb ->elaborate_pexpr(des, scope);
assert(msb);
lsb = cur.lsb ->elaborate_pexpr(des, scope);
assert(lsb);
}
NetScope::range_t*range_list = 0;
for (LexicalScope::range_t*range = cur.range ; range ; range = range->next) {
NetScope::range_t*tmp = new NetScope::range_t;
@ -143,33 +89,11 @@ static void elaborate_parm_item_(perm_string name,
range_list = tmp;
}
/* Set the parameter expression to 0 if the evaluation failed. */
if (val == 0) {
val = scope->set_parameter(name, val, cur.type, msb, lsb,
signed_flag, range_list, cur);
delete val;
return;
scope->set_parameter(name, cur.expr, cur.type, cur.msb, cur.lsb,
cur.signed_flag, range_list, cur);
}
if (signed_flag) {
/* If explicitly signed, then say so. */
val->cast_signed(true);
} else if (cur.msb) {
/* If there is a range, then the signedness comes
from the type and not the expression. */
val->cast_signed(signed_flag);
} else {
/* otherwise, let the expression describe
itself. */
signed_flag = val->has_sign();
}
val = scope->set_parameter(name, val, cur.type, msb, lsb, signed_flag,
range_list, cur);
delete val;
}
static void elaborate_scope_parameters_(Design*des, NetScope*scope,
static void collect_scope_parameters_(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&parameters)
{
for (mparm_it_t cur = parameters.begin()
@ -184,11 +108,11 @@ static void elaborate_scope_parameters_(Design*des, NetScope*scope,
des->errors += 1;
}
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
collect_parm_item_(des, scope, (*cur).first, (*cur).second);
}
}
static void elaborate_scope_localparams_(Design*des, NetScope*scope,
static void collect_scope_localparams_(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&localparams)
{
for (mparm_it_t cur = localparams.begin()
@ -203,7 +127,7 @@ static void elaborate_scope_localparams_(Design*des, NetScope*scope,
des->errors += 1;
}
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
collect_parm_item_(des, scope, (*cur).first, (*cur).second);
}
}
@ -295,7 +219,7 @@ static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
for (Module::replace_t::const_iterator cur = replacements.begin()
; cur != replacements.end() ; ++ cur ) {
NetExpr*val = (*cur).second;
PExpr*val = (*cur).second;
if (val == 0) {
cerr << loc.get_fileline() << ": internal error: "
<< "Missing expression in parameter replacement for "
@ -310,7 +234,8 @@ static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
cerr << loc.get_fileline() << ": : "
<< "Type=" << val->expr_type() << endl;
}
bool flag = scope->replace_parameter((*cur).first, val);
bool flag = scope->replace_parameter((*cur).first, val,
scope->parent());
if (! flag) {
cerr << val->get_fileline() << ": warning: parameter "
<< (*cur).first << " not found in "
@ -360,8 +285,8 @@ static void elaborate_scope_tasks(Design*des, NetScope*scope,
// A task can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter((*cur).first, ex_msb,
ex_lsb);
const NetExpr *parm = scope->get_parameter(des, (*cur).first,
ex_msb, ex_lsb);
if (parm) {
cerr << cur->second->get_fileline()
<< ": error: task and parameter in '"
@ -415,8 +340,8 @@ static void elaborate_scope_funcs(Design*des, NetScope*scope,
// A function can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter((*cur).first, ex_msb,
ex_lsb);
const NetExpr *parm = scope->get_parameter(des, (*cur).first,
ex_msb, ex_lsb);
if (parm) {
cerr << cur->second->get_fileline()
<< ": error: function and parameter in '"
@ -484,60 +409,29 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
scope->add_genvar((*cur).first, (*cur).second);
}
// Generate all the parameters that this instance of this
// module introduces to the design. This loop elaborates the
// parameters, but doesn't evaluate references to
// parameters. This scan practically locates all the
// parameters and puts them in the parameter table in the
// design.
// Scan the parameters in the module, and store the information
// needed to evaluate the parameter expressions. The expressions
// will be evaluated later, once all parameter overrides for this
// module have been done.
// No expressions are evaluated, yet. For now, leave them in
// the pform and just place a NetEParam placeholder in the
// place of the elaborated expression.
collect_scope_parameters_(des, scope, parameters);
// Scan the parameters in the module, and create stub parameter
// entries in the scope for the parameter names.
collect_scope_localparams_(des, scope, localparams);
collect_scope_parameters_(scope, parameters);
// Run parameter replacements that were collected from the
// containing scope and meant for me.
collect_scope_localparams_(scope, localparams);
// Now scan the parameters again, this time elaborating them
// for use as parameter values. This is after the previous
// scan so that local parameter names can be used in the
// r-value expressions.
elaborate_scope_parameters_(des, scope, parameters);
/* run parameter replacements that were collected from the
containing scope and meant for me. */
replace_scope_parameters_(scope, *this, replacements);
elaborate_scope_localparams_(des, scope, localparams);
elaborate_scope_enumerations(des, scope, enum_sets);
// Run through the defparams for this module, elaborate the
// expressions in this context and save the result is a table
// for later final override.
// It is OK to elaborate the expressions of the defparam here
// because Verilog requires that the expressions only use
// local parameter names. It is *not* OK to do the override
// here because the parameter receiving the assignment may be
// in a scope not discovered by this pass.
// Run through the defparams for this module and save the result
// in a table for later final override.
typedef list<Module::named_expr_t>::const_iterator defparms_iter_t;
for (defparms_iter_t cur = defparms.begin()
; cur != defparms.end() ; ++ cur ) {
PExpr*ex = cur->second;
assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope);
if (val == 0) continue;
scope->defparams.push_back(make_pair(cur->first, val));
scope->defparams.push_back(make_pair(cur->first, cur->second));
}
// Evaluate the attributes. Evaluate them in the scope of the
@ -708,7 +602,8 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
// A generate "loop" can not have the same name as a parameter.
const NetExpr*tmsb;
const NetExpr*tlsb;
const NetExpr*texpr = container->get_parameter(scope_name, tmsb, tlsb);
const NetExpr*texpr = container->get_parameter(des, scope_name,
tmsb, tlsb);
if (texpr != 0) {
cerr << get_fileline() << ": error: generate \"loop\" and "
"parameter in '" << container->fullname()
@ -719,7 +614,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
// These have all been checked so we just need to skip the actual
// generation for these name conflicts. Not skipping these two will
// cause the compiler to have problems (assert, inf. loop, etc.).
if (container->get_parameter(loop_index, tmsb, tlsb)) return false;
if (container->get_parameter(des, loop_index, tmsb, tlsb)) return false;
if (container->find_event(loop_index)) return false;
genvar = init->value().as_long();
@ -868,8 +763,8 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
// A generate "if" can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = container->get_parameter(scope_name, ex_msb,
ex_lsb);
const NetExpr *parm = container->get_parameter(des, scope_name,
ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: generate \"if\" and "
"parameter in '" << container->fullname()
@ -1014,8 +909,8 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
// A generate "case" can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = container->get_parameter(item->scope_name, ex_msb,
ex_lsb);
const NetExpr *parm = container->get_parameter(des, item->scope_name,
ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: generate \"case\" and "
"parameter in '" << container->fullname()
@ -1074,8 +969,8 @@ bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
// A generate "block" can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = container->get_parameter(scope_name, ex_msb,
ex_lsb);
const NetExpr *parm = container->get_parameter(des, scope_name,
ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: generate \"block\" and "
"parameter in '" << container->fullname()
@ -1123,13 +1018,11 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
(*cur) -> generate_scope(des, scope);
}
// Scan the localparams in this scope, and create stub parameter
// entries in the scope for the parameter names.
collect_scope_localparams_(scope, localparams);
// Now scan the localparams again, this time elaborating them
// for use as parameter values.
elaborate_scope_localparams_(des, scope, localparams);
// Scan the localparams in this scope, and store the information
// needed to evaluate the parameter expressions. The expressions
// will be evaluated later, once all parameter overrides for this
// module have been done.
collect_scope_localparams_(des, scope, localparams);
// Scan through all the task and function declarations in this
// scope.
@ -1230,7 +1123,7 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
// A module instance can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = sc->get_parameter(get_name(), ex_msb, ex_lsb);
const NetExpr *parm = sc->get_parameter(des, get_name(), ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: module <" << mod->mod_name()
<< "> instance and parameter in '" << sc->fullname()
@ -1391,9 +1284,7 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
// passed. It is built up by the ordered overrides or named
// overrides.
typedef map<perm_string,PExpr*>::const_iterator mparm_local_it_t;
map<perm_string,PExpr*> replace;
Module::replace_t replace;
// Positional parameter overrides are matched to parameter
// names by using the param_names list of parameter
@ -1411,6 +1302,9 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
if (cur == mod->param_names.end())
break;
// No expression means that the parameter is not
// replaced at all.
if (*jdx)
replace[*cur] = *jdx;
++ jdx;
@ -1427,31 +1321,12 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
}
Module::replace_t replace_net;
// And here we scan the replacements we collected. Elaborate
// the expression in my context, then replace the sub-scope
// parameter value with the new expression.
for (mparm_local_it_t cur = replace.begin()
; cur != replace.end() ; ++ cur ) {
PExpr*tmp = (*cur).second;
// No expression means that the parameter is not
// replaced at all.
if (tmp == 0) continue;
NetExpr*val = tmp->elaborate_pexpr(des, sc);
if (val == 0) continue;
replace_net[(*cur).first] = val;
}
// This call actually arranges for the description of the
// module type to process this instance and handle parameters
// and sub-scopes that might occur. Parameters are also
// created in that scope, as they exist. (I'll override them
// later.)
mod->elaborate_scope(des, my_scope, replace_net);
mod->elaborate_scope(des, my_scope, replace);
}
@ -1494,7 +1369,7 @@ void PEvent::elaborate_scope(Design*des, NetScope*scope) const
// A named event can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(name_, ex_msb, ex_lsb);
const NetExpr *parm = scope->get_parameter(des, name_, ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: named event and "
<< "parameter in '" << scope->fullname()
@ -1511,21 +1386,12 @@ void PFunction::elaborate_scope(Design*des, NetScope*scope) const
{
assert(scope->type() == NetScope::FUNC);
// Scan the parameters in the function, and create stub parameter
// entries in the scope for the parameter names.
// Scan the parameters in the function, and store the information
// needed to evaluate the parameter expressions.
collect_scope_parameters_(scope, parameters);
collect_scope_parameters_(des, scope, parameters);
collect_scope_localparams_(scope, localparams);
// Now scan the parameters again, this time elaborating them
// for use as parameter values. This is after the previous
// scan so that local parameter names can be used in the
// r-value expressions.
elaborate_scope_parameters_(des, scope, parameters);
elaborate_scope_localparams_(des, scope, localparams);
collect_scope_localparams_(des, scope, localparams);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
@ -1538,21 +1404,12 @@ void PTask::elaborate_scope(Design*des, NetScope*scope) const
{
assert(scope->type() == NetScope::TASK);
// Scan the parameters in the task, and create stub parameter
// entries in the scope for the parameter names.
// Scan the parameters in the task, and store the information
// needed to evaluate the parameter expressions.
collect_scope_parameters_(scope, parameters);
collect_scope_parameters_(des, scope, parameters);
collect_scope_localparams_(scope, localparams);
// Now scan the parameters again, this time elaborating them
// for use as parameter values. This is after the previous
// scan so that local parameter names can be used in the
// r-value expressions.
elaborate_scope_parameters_(des, scope, parameters);
elaborate_scope_localparams_(des, scope, localparams);
collect_scope_localparams_(des, scope, localparams);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
@ -1604,8 +1461,8 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
// A named block can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(pscope_name(), ex_msb,
ex_lsb);
const NetExpr *parm = scope->get_parameter(des, pscope_name(),
ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: named block and "
"parameter in '" << scope->fullname()
@ -1624,21 +1481,12 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
my_scope->set_line(get_file(), get_lineno());
my_scope->is_auto(scope->is_auto());
// Scan the parameters in the scope, and create stub parameter
// entries in the scope for the parameter names.
// Scan the parameters in the scope, and store the information
// needed to evaluate the parameter expressions.
collect_scope_parameters_(my_scope, parameters);
collect_scope_parameters_(des, my_scope, parameters);
collect_scope_localparams_(my_scope, localparams);
// Now scan the parameters again, this time elaborating them
// for use as parameter values. This is after the previous
// scan so that local parameter names can be used in the
// r-value expressions.
elaborate_scope_parameters_(des, my_scope, parameters);
elaborate_scope_localparams_(des, my_scope, localparams);
collect_scope_localparams_(des, my_scope, localparams);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, my_scope, events);

View File

@ -831,7 +831,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
}
// A signal can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(name_, ex_msb, ex_lsb);
const NetExpr *parm = scope->get_parameter(des, name_, ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: signal and parameter in '"
<< scope->fullname() << "' have the same name '" << name_

View File

@ -4460,8 +4460,7 @@ class elaborate_root_scope_t : public elaborator_work_item_t {
if (tmp_name.size() != 1)
continue;
NetExpr*tmp_expr = cur->second->elaborate_pexpr(des, scope_);
root_repl[peek_head_name(tmp_name)] = tmp_expr;
root_repl[peek_head_name(tmp_name)] = cur->second;
}
if (! rmod_->elaborate_scope(des, scope_, root_repl))

View File

@ -1291,123 +1291,10 @@ NetEConst* NetEConcat::eval_tree(int prune_to_width)
NetExpr* NetEParam::eval_tree(int prune_to_width)
{
// HERE
if (des_ == 0) {
assert(scope_ == 0);
return 0;
}
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: Evaluating expression:"
<< *this << ", prune_to_width=" << prune_to_width << endl;
}
if (solving()) {
cerr << get_fileline() << ": warning: Recursive parameter "
"reference found involving " << *this << "." << endl;
return 0;
}
assert(scope_);
perm_string name = (*reference_).first;
const NetExpr*expr = (*reference_).second.expr;
// Since constant user functions are not supported we can get
// parameters/localparams that are not defined. For now generate
// an appropriate error message.
if (expr == NULL) {
cerr << get_fileline() << ": internal error: parameter/localparam "
<< *this << " cannot be evaluated." << endl;
return 0;
}
// If the parameter that I refer to is already evaluated, then
// return the constant value.
if (const NetEConst*tmp = dynamic_cast<const NetEConst*>(expr)) {
verinum val = tmp->value();
NetEConstParam*ptmp = new NetEConstParam(scope_, name, val);
ptmp->set_line(*this);
return ptmp;
}
if (const NetECReal*tmp = dynamic_cast<const NetECReal*>(expr)) {
verireal val = tmp->value();
NetECRealParam*ptmp = new NetECRealParam(scope_, name, val);
ptmp->set_line(*this);
return ptmp;
}
// Try to evaluate the expression. If I cannot, then the
// expression is not a constant expression and I fail here.
solving(true);
NetExpr*nexpr = expr->dup_expr();
assert(nexpr);
NetExpr*res = nexpr->eval_tree();
solving(false);
if (res == 0) {
cerr << get_fileline() << ": internal error: Unable to evaluate ";
if (expr_type() == IVL_VT_REAL) cerr << "real ";
cerr << "parameter " << name << " expression: "
<< *nexpr << endl;
delete nexpr;
return 0;
}
// The result can be saved as the value of the parameter for
// future reference, and return a copy to the caller.
bool flag = scope_->replace_parameter(name, res);
if (!flag) {
cerr << get_fileline() << ": internal error: Could not "
<< "replace parameter expression for " << name << endl;
return 0;
}
/* Return as a result a NetEConstParam or NetECRealParam
object, depending on the type of the expression. */
switch (res->expr_type()) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
{ NetEConst*tmp = dynamic_cast<NetEConst*>(res);
if (tmp == 0) {
cerr << get_fileline() << ": internal error: parameter "
<< name << " evaluates to incomprehensible "
<< *res << "." << endl;
return 0;
}
assert(tmp);
verinum val = tmp->value();
NetEConstParam*ptmp = new NetEConstParam(scope_, name, val);
return ptmp;
}
case IVL_VT_REAL:
{ NetECReal*tmp = dynamic_cast<NetECReal*>(res);
if (tmp == 0) {
cerr << get_fileline() << ": internal error: parameter "
<< name << " evaluates to incomprehensible "
<< *res << "." << endl;
return 0;
}
assert(tmp);
verireal val = tmp->value();
NetECRealParam*ptmp = new NetECRealParam(scope_, name, val);
return ptmp;
}
default:
// The NetEParam class is now redundant.
assert(0);
return 0;
}
}
NetEConst* NetESelect::eval_tree(int prune_to_width)
{

View File

@ -106,6 +106,7 @@ bool gn_cadence_types_flag = true;
bool gn_specify_blocks_flag = true;
bool gn_io_range_error_flag = true;
bool gn_strict_ca_eval_flag = false;
bool gn_strict_expr_width_flag = false;
bool gn_verilog_ams_flag = false;
/*
@ -295,6 +296,12 @@ static void process_generation_flag(const char*gen)
} else if (strcmp(gen,"no-strict-ca-eval") == 0) {
gn_strict_ca_eval_flag = false;
} else if (strcmp(gen,"strict-expr-width") == 0) {
gn_strict_expr_width_flag = true;
} else if (strcmp(gen,"no-strict-expr-width") == 0) {
gn_strict_expr_width_flag = false;
} else {
}
}

View File

@ -32,6 +32,7 @@
# include "util.h"
# include "compiler.h"
# include "netmisc.h"
# include "PExpr.h"
# include <sstream>
# include "ivl_assert.h"
@ -224,11 +225,11 @@ void NetScope::run_defparams(Design*des)
cur->second->run_defparams(des);
while (! defparams.empty()) {
pair<pform_name_t,NetExpr*> pp = defparams.front();
pair<pform_name_t,PExpr*> pp = defparams.front();
defparams.pop_front();
pform_name_t path = pp.first;
NetExpr*val = pp.second;
PExpr*val = pp.second;
perm_string perm_name = peek_tail_name(path);
path.pop_back();
@ -249,11 +250,7 @@ void NetScope::run_defparams(Design*des)
continue;
}
// Once placed in the parameter map, the expression may
// be deleted when evaluated, so give it a copy of this
// expression, not the original.
val = val->dup_expr();
bool flag = targ_scope->replace_parameter(perm_name, val);
bool flag = targ_scope->replace_parameter(perm_name, val, this);
if (! flag) {
cerr << val->get_fileline() << ": warning: parameter "
<< perm_name << " not found in "
@ -272,17 +269,17 @@ void NetScope::run_defparams(Design*des)
void NetScope::run_defparams_later(Design*des)
{
set<NetScope*> target_scopes;
list<pair<list<hname_t>,NetExpr*> > defparams_even_later;
list<pair<list<hname_t>,PExpr*> > defparams_even_later;
while (! defparams_later.empty()) {
pair<list<hname_t>,NetExpr*> cur = defparams_later.front();
pair<list<hname_t>,PExpr*> cur = defparams_later.front();
defparams_later.pop_front();
list<hname_t>eval_path = cur.first;
perm_string name = eval_path.back().peek_name();
eval_path.pop_back();
NetExpr*val = cur.second;
PExpr*val = cur.second;
NetScope*targ_scope = des->find_scope(this, eval_path);
if (targ_scope == 0) {
@ -294,11 +291,7 @@ void NetScope::run_defparams_later(Design*des)
continue;
}
// Once placed in the parameter map, the expression may
// be deleted when evaluated, so give it a copy of this
// expression, not the original.
val = val->dup_expr();
bool flag = targ_scope->replace_parameter(name, val);
bool flag = targ_scope->replace_parameter(name, val, this);
if (! flag) {
cerr << val->get_fileline() << ": warning: parameter "
<< name << " not found in "
@ -337,10 +330,12 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
bool range_flag = false;
/* Evaluate the msb expression, if it is present. */
if ((*cur).second.msb) {
eval_expr((*cur).second.msb);
PExpr*msb_expr = (*cur).second.msb_expr;
if (msb_expr) {
probe_expr_width(des, this, msb_expr);
(*cur).second.msb = elab_and_eval(des, this, msb_expr, -2);
if (! eval_as_long(msb, (*cur).second.msb)) {
cerr << (*cur).second.expr->get_fileline()
cerr << (*cur).second.val->get_fileline()
<< ": error: Unable to evaluate msb expression "
<< "for parameter " << (*cur).first << ": "
<< *(*cur).second.msb << endl;
@ -352,10 +347,12 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
}
/* Evaluate the lsb expression, if it is present. */
if ((*cur).second.lsb) {
eval_expr((*cur).second.lsb);
PExpr*lsb_expr = (*cur).second.lsb_expr;
if (lsb_expr) {
probe_expr_width(des, this, lsb_expr);
(*cur).second.lsb = elab_and_eval(des, this, lsb_expr, -2);
if (! eval_as_long(lsb, (*cur).second.lsb)) {
cerr << (*cur).second.expr->get_fileline()
cerr << (*cur).second.val->get_fileline()
<< ": error: Unable to evaluate lsb expression "
<< "for parameter " << (*cur).first << ": "
<< *(*cur).second.lsb << endl;
@ -366,17 +363,31 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
range_flag = true;
}
/* Evaluate the parameter expression. */
PExpr*val_expr = (*cur).second.val_expr;
NetScope*val_scope = (*cur).second.val_scope;
/* Evaluate the parameter expression, if necessary. */
NetExpr*expr = (*cur).second.expr;
if (expr == NULL) return; // This is an invalid parameter so return.
unsigned lval_wid = 0;
if (range_flag)
lval_wid = (msb >= lsb) ? 1 + msb - lsb : 1 + lsb - msb;
eval_expr(expr);
bool unsized_flag = false;
ivl_variable_type_t rval_type = IVL_VT_NO_TYPE;
int expr_wid = val_expr->test_width(des, val_scope, lval_wid, lval_wid,
rval_type, unsized_flag);
/* The eval_expr may delete and replace the expr pointer, so the
second.expr value cannot be relied on. Might as well replace
it now with the expression that we evaluated. */
(*cur).second.expr = expr;
if (unsized_flag && !range_flag)
expr_wid = -1;
int prune_wid = -1;
if (gn_strict_expr_width_flag)
prune_wid = 0;
if (range_flag)
prune_wid = lval_wid;
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, expr_wid, prune_wid);
if (! expr)
return;
switch (expr->expr_type()) {
case IVL_VT_REAL:
@ -385,7 +396,6 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
<< ": error: Unable to evaluate real parameter "
<< (*cur).first << " value: " << *expr << endl;
des->errors += 1;
(*cur).second.expr = NULL;
return;
}
break;
@ -397,7 +407,6 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
<< ": error: Unable to evaluate parameter "
<< (*cur).first << " value: " << *expr << endl;
des->errors += 1;
(*cur).second.expr = NULL;
return;
}
break;
@ -407,41 +416,24 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
<< ": internal error: "
<< "Unhandled expression type?" << endl;
des->errors += 1;
(*cur).second.expr = NULL;
return;
}
(*cur).second.val = expr;
/* If the parameter has range information, then make
sure the value is set right. Note that if the
sure the type is set right. Note that if the
parameter doesn't have an explicit range, then it
will get the signedness from the expression itself. */
if (range_flag) {
unsigned long wid = (msb >= lsb)? msb - lsb : lsb - msb;
wid += 1;
/* If we have a real value convert it to an integer. */
if(NetECReal*tmp = dynamic_cast<NetECReal*>(expr)) {
verinum nval(tmp->value().as_long64());
verinum nval(tmp->value().as_long64(), lval_wid);
expr = new NetEConst(nval);
expr->set_line(*((*cur).second.expr));
(*cur).second.expr = expr;
expr->set_line(*((*cur).second.val));
(*cur).second.val = expr;
}
NetEConst*val = dynamic_cast<NetEConst*>(expr);
assert(val);
verinum value = val->value();
if (! (value.has_len()
&& (value.len() == wid)
&& (value.has_sign() == (*cur).second.signed_flag))) {
verinum tmp (value, wid);
tmp.has_sign ( (*cur).second.signed_flag );
delete val;
val = new NetEConst(tmp);
(*cur).second.expr = expr = val;
}
(*cur).second.val->cast_signed((*cur).second.signed_flag);
}
// If there are no value ranges to test the value against,
@ -450,9 +442,9 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
return;
}
NetEConst*val = dynamic_cast<NetEConst*>((*cur).second.expr);
ivl_assert(*(*cur).second.expr, (*cur).second.expr);
ivl_assert(*(*cur).second.expr, val);
NetEConst*val = dynamic_cast<NetEConst*>((*cur).second.val);
ivl_assert(*(*cur).second.val, (*cur).second.val);
ivl_assert(*(*cur).second.val, val);
verinum value = val->value();
@ -509,11 +501,25 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
{
NetExpr*expr = (*cur).second.expr;
if (expr == NULL) return; // This is an invalid parameter so return.
PExpr*val_expr = (*cur).second.val_expr;
NetScope*val_scope = (*cur).second.val_scope;
bool unsized_flag = false;
ivl_variable_type_t rval_type = IVL_VT_NO_TYPE;
int expr_wid = val_expr->test_width(des, val_scope, 0, 0,
rval_type, unsized_flag);
if (unsized_flag)
expr_wid = -1;
int prune_wid = -1;
if (gn_strict_expr_width_flag)
prune_wid = 0;
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, expr_wid, prune_wid);
if (! expr)
return;
NetECReal*res = 0;
eval_expr(expr);
switch (expr->expr_type()) {
case IVL_VT_REAL:
@ -525,7 +531,6 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
<< "Unable to evaluate real parameter "
<< (*cur).first << " value: " << *expr << endl;
des->errors += 1;
(*cur).second.expr = NULL;
return;
}
break;
@ -542,7 +547,6 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
<< "Unable to evaluate parameter "
<< (*cur).first << " value: " << *expr << endl;
des->errors += 1;
(*cur).second.expr = NULL;
return;
}
break;
@ -552,12 +556,11 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
<< ": internal error: "
<< "Unhandled expression type?" << endl;
des->errors += 1;
(*cur).second.expr = NULL;
return;
break;
}
(*cur).second.expr = res;
(*cur).second.val = res;
double value = res->value().as_double();
bool from_flag = (*cur).second.range == 0? true : false;
@ -607,31 +610,20 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
}
}
void NetScope::evaluate_parameters(Design*des)
void NetScope::evaluate_parameter_(Design*des, param_ref_t cur)
{
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
; cur != children_.end() ; ++ cur )
cur->second->evaluate_parameters(des);
// If the parameter has already been evaluated, quietly return.
if (cur->second.val_expr == 0)
return;
if (debug_scopes)
cerr << ":0" << ": debug: "
<< "Evaluate parameters in " << scope_path(this) << endl;
// Evaluate the parameter values. The parameter expressions
// have already been elaborated and replaced by the scope
// scanning code. Now the parameter expression can be fully
// evaluated, or it cannot be evaluated at all.
for (param_ref_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
// Resolve the expression type (signed/unsigned) if the
// expression is present. It is possible to not be
// present if there are earlier errors in elaboration.
if (cur->second.expr)
cur->second.expr->resolve_pexpr_type();
switch ((*cur).second.type) {
if (cur->second.solving) {
cerr << cur->second.get_fileline() << ": error: "
<< "Recursive parameter reference found involving "
<< cur->first << "." << endl;
des->errors += 1;
} else {
cur->second.solving = true;
switch (cur->second.type) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
evaluate_parameter_logic_(des, cur);
@ -642,18 +634,55 @@ void NetScope::evaluate_parameters(Design*des)
break;
default:
cerr << (*cur).second.get_fileline() << ": internal error: "
<< "Unexpected expression type " << (*cur).second.type
cerr << cur->second.get_fileline() << ": internal error: "
<< "Unexpected expression type " << cur->second.type
<< "." << endl;
cerr << (*cur).second.get_fileline() << ": : "
<< "Parameter name: " << (*cur).first << endl;
cerr << (*cur).second.get_fileline() << ": : "
<< "Expression is: " << *(*cur).second.expr << endl;
ivl_assert((*cur).second, 0);
cerr << cur->second.get_fileline() << ": : "
<< "Parameter name: " << cur->first << endl;
cerr << cur->second.get_fileline() << ": : "
<< "Expression is: " << *cur->second.val_expr << endl;
ivl_assert(cur->second, 0);
break;
}
cur->second.solving = false;
}
// If we have failed to evaluate the expression, create a dummy
// value. This prevents spurious error messages being output.
if (cur->second.val == 0) {
verinum val(verinum::Vx);
cur->second.val = new NetEConst(val);
}
// Flag that the expression has been evaluated.
cur->second.val_expr = 0;
}
/*
* Set the following to true when evaluating the parameter expressions.
* This causes PEIdent::elaborate_expr() to report an error if an
* identifier in an expression is anything other than a non-hierarchical
* parameter name.
*/
bool is_param_expr = false;
void NetScope::evaluate_parameters(Design*des)
{
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
; cur != children_.end() ; ++ cur )
cur->second->evaluate_parameters(des);
if (debug_scopes)
cerr << ":0" << ": debug: "
<< "Evaluate parameters in " << scope_path(this) << endl;
is_param_expr = true;
for (param_ref_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
evaluate_parameter_(des, cur);
}
is_param_expr = false;
}
void Design::residual_defparams()
@ -668,7 +697,7 @@ void NetScope::residual_defparams(Design*des)
// Clean out the list of defparams that never managed to match
// a scope. Print a warning for each.
while (! defparams_later.empty()) {
pair<list<hname_t>,NetExpr*> cur = defparams_later.front();
pair<list<hname_t>,PExpr*> cur = defparams_later.front();
defparams_later.pop_front();
cerr << cur.second->get_fileline() << ": warning: "

View File

@ -27,6 +27,8 @@
# include <sstream>
# include "ivl_assert.h"
class PExpr;
/*
* The NetScope class keeps a scope tree organized. Each node of the
* scope tree points to its parent, its right sibling and its leftmost
@ -107,26 +109,27 @@ void NetScope::set_line(perm_string file, perm_string def_file,
def_lineno_ = def_lineno;
}
NetExpr* NetScope::set_parameter(perm_string key, NetExpr*expr,
void NetScope::set_parameter(perm_string key, PExpr*val,
ivl_variable_type_t type__,
NetExpr*msb, NetExpr*lsb, bool signed_flag,
PExpr*msb, PExpr*lsb, bool signed_flag,
NetScope::range_t*range_list,
const LineInfo&file_line)
{
param_expr_t&ref = parameters[key];
NetExpr* res = ref.expr;
ref.expr = expr;
ref.msb_expr = msb;
ref.lsb_expr = lsb;
ref.val_expr = val;
ref.val_scope = this;
ref.type = type__;
ref.msb = msb;
ref.lsb = lsb;
ref.msb = 0;
ref.lsb = 0;
ref.signed_flag = signed_flag;
ivl_assert(file_line, ref.range == 0);
ref.range = range_list;
ref.val = 0;
ref.set_line(file_line);
ivl_assert(file_line, type__ != IVL_VT_NO_TYPE);
return res;
}
bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
@ -166,15 +169,14 @@ bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
* Return false if the parameter does not already exist.
* A parameter is not automatically created.
*/
bool NetScope::replace_parameter(perm_string key, NetExpr*expr)
bool NetScope::replace_parameter(perm_string key, PExpr*val, NetScope*scope)
{
bool flag = false;
if (parameters.find(key) != parameters.end()) {
param_expr_t&ref = parameters[key];
delete ref.expr;
ref.expr = expr;
ref.val_expr = val;
ref.val_scope = scope;
flag = true;
}
@ -185,15 +187,20 @@ bool NetScope::replace_parameter(perm_string key, NetExpr*expr)
* This is not really complete (msb, lsb, sign). It is currently only
* used to add a genvar to the local parameter list.
*/
NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr,
NetExpr* NetScope::set_localparam(perm_string key, NetExpr*val,
const LineInfo&file_line)
{
param_expr_t&ref = localparams[key];
NetExpr* res = ref.expr;
ref.expr = expr;
NetExpr* res = ref.val;
ref.msb_expr = 0;
ref.lsb_expr = 0;
ref.val_expr = 0;
ref.val_scope = this;
ref.type = IVL_VT_BOOL;
ref.msb = 0;
ref.lsb = 0;
ref.signed_flag = false;
ref.val = val;
ref.set_line(file_line);
return res;
}
@ -205,31 +212,39 @@ NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr,
* perm_string::literal method to fake the compiler into doing the
* compare without actually creating a perm_string.
*/
const NetExpr* NetScope::get_parameter(const char* key,
const NetExpr* NetScope::get_parameter(Design*des,
const char* key,
const NetExpr*&msb,
const NetExpr*&lsb) const
const NetExpr*&lsb)
{
return get_parameter(perm_string::literal(key), msb, lsb);
return get_parameter(des, perm_string::literal(key), msb, lsb);
}
const NetExpr* NetScope::get_parameter(perm_string key,
const NetExpr* NetScope::get_parameter(Design*des,
perm_string key,
const NetExpr*&msb,
const NetExpr*&lsb) const
const NetExpr*&lsb)
{
map<perm_string,param_expr_t>::const_iterator idx;
map<perm_string,param_expr_t>::iterator idx;
idx = parameters.find(key);
if (idx != parameters.end()) {
msb = (*idx).second.msb;
lsb = (*idx).second.lsb;
return (*idx).second.expr;
if (idx->second.val_expr)
evaluate_parameter_(des, idx);
msb = idx->second.msb;
lsb = idx->second.lsb;
return idx->second.val;
}
idx = localparams.find(key);
if (idx != localparams.end()) {
msb = (*idx).second.msb;
lsb = (*idx).second.lsb;
return (*idx).second.expr;
if (idx->second.val_expr)
evaluate_parameter_(des, idx);
msb = idx->second.msb;
lsb = idx->second.lsb;
return idx->second.val;
}
map<perm_string,NetEConstEnum*>::const_iterator eidx;
@ -244,7 +259,7 @@ const NetExpr* NetScope::get_parameter(perm_string key,
return 0;
}
map<perm_string,NetScope::param_expr_t>::iterator NetScope::find_parameter(perm_string key)
NetScope::param_ref_t NetScope::find_parameter(perm_string key)
{
map<perm_string,param_expr_t>::iterator idx;

View File

@ -71,6 +71,7 @@ class NetRamDq;
class NetTaskDef;
class NetEvTrig;
class NetEvWait;
class PExpr;
class netenum_t;
struct target;
@ -713,26 +714,28 @@ class NetScope : public Attrib {
previous expression, if there was one. */
struct range_t;
NetExpr* set_parameter(perm_string name, NetExpr*val,
void set_parameter(perm_string name, PExpr*val,
ivl_variable_type_t type,
NetExpr*msb, NetExpr*lsb, bool signed_flag,
PExpr*msb, PExpr*lsb, bool signed_flag,
NetScope::range_t*range_list,
const LineInfo&file_line);
NetExpr* set_localparam(perm_string name, NetExpr*val,
const LineInfo&file_line);
const NetExpr*get_parameter(const char* name,
const NetExpr*get_parameter(Design*des,
const char* name,
const NetExpr*&msb,
const NetExpr*&lsb) const;
const NetExpr*get_parameter(perm_string name,
const NetExpr*&lsb);
const NetExpr*get_parameter(Design*des,
perm_string name,
const NetExpr*&msb,
const NetExpr*&lsb) const;
const NetExpr*&lsb);
/* These are used by defparam elaboration to replace the
expression with a new expression, without affecting the
range or signed_flag. Return false if the name does not
exist. */
bool replace_parameter(perm_string name, NetExpr*val);
bool replace_parameter(perm_string name, PExpr*val, NetScope*scope);
/* These methods set or access events that live in this
scope. */
@ -848,8 +851,8 @@ class NetScope : public Attrib {
assignments from the scope pass to the parameter evaluation
step. After that, it is not used. */
list<pair<pform_name_t,NetExpr*> > defparams;
list<pair<list<hname_t>,NetExpr*> > defparams_later;
list<pair<pform_name_t,PExpr*> > defparams;
list<pair<list<hname_t>,PExpr*> > defparams_later;
public:
struct range_t {
@ -867,7 +870,17 @@ class NetScope : public Attrib {
/* After everything is all set up, the code generators like
access to these things to make up the parameter lists. */
struct param_expr_t : public LineInfo {
param_expr_t() : type(IVL_VT_NO_TYPE), signed_flag(false), msb(0), lsb(0), range(0), expr(0) { }
param_expr_t() : msb_expr(0), lsb_expr(0), val_expr(0), val_scope(0),
solving(false), type(IVL_VT_NO_TYPE), signed_flag(false),
msb(0), lsb(0), range(0), val(0) { }
// Source expressions
PExpr*msb_expr;
PExpr*lsb_expr;
PExpr*val_expr;
// Scope information
NetScope*val_scope;
// Evaluation status
bool solving;
// Type information
ivl_variable_type_t type;
bool signed_flag;
@ -876,7 +889,7 @@ class NetScope : public Attrib {
// range constraints
struct range_t*range;
// Expression value
NetExpr*expr;
NetExpr*val;
};
map<perm_string,param_expr_t>parameters;
map<perm_string,param_expr_t>localparams;
@ -909,6 +922,7 @@ class NetScope : public Attrib {
private:
void evaluate_parameter_logic_(Design*des, param_ref_t cur);
void evaluate_parameter_real_(Design*des, param_ref_t cur);
void evaluate_parameter_(Design*des, param_ref_t cur);
private:
TYPE type_;

View File

@ -140,6 +140,11 @@ extern unsigned count_lval_width(const class NetAssign_*first);
*/
extern bool need_constant_expr;
/*
* This is used to indicate that we are evaluating a parameter expression.
*/
extern bool is_param_expr;
/*
* This function elaborates an expression, and tries to evaluate it
* right away. If the expression can be evaluated, this returns a

View File

@ -74,7 +74,7 @@ NetScope*symbol_search(const LineInfo*li, Design*des, NetScope*scope,
if ( (eve = scope->find_event(key)) )
return scope;
if ( (par = scope->get_parameter(key, ex1, ex2)) )
if ( (par = scope->get_parameter(des, key, ex1, ex2)) )
return scope;
/* We can't look up if we are at the enclosing module scope

View File

@ -482,7 +482,7 @@ void dll_target::make_scope_parameters(ivl_scope_t scop, const NetScope*net)
cur_par->file = (*cur_pit).second.get_file();
cur_par->lineno = (*cur_pit).second.get_lineno();
NetExpr*etmp = (*cur_pit).second.expr;
NetExpr*etmp = (*cur_pit).second.val;
make_scope_param_expr(cur_par, etmp);
idx += 1;
}
@ -496,7 +496,7 @@ void dll_target::make_scope_parameters(ivl_scope_t scop, const NetScope*net)
cur_par->file = (*cur_pit).second.get_file();
cur_par->lineno = (*cur_pit).second.get_lineno();
NetExpr*etmp = (*cur_pit).second.expr;
NetExpr*etmp = (*cur_pit).second.val;
make_scope_param_expr(cur_par, etmp);
idx += 1;
}