Track whether a parameter is overridable

Parameters declared in certain scopes behave like local parameters and can
not be overridden. Rather than making those parameters a localparam track
whether a parameter can be overridden.

This allows to generate better error messages when trying to override the
parameter.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
Lars-Peter Clausen 2022-02-10 10:13:22 +01:00
parent 1207e908b1
commit 9f5ad34e35
5 changed files with 23 additions and 5 deletions

View File

@ -101,7 +101,7 @@ class LexicalScope {
this map. */
struct param_expr_t : public PNamedItem {
inline param_expr_t() : data_type(0), expr(0), range(0),
local_flag(false) { }
local_flag(false), overridable(true) { }
// Type information.
data_type_t*data_type;
// Value expression
@ -110,6 +110,8 @@ class LexicalScope {
range_t*range;
// Whether it is a local parameter
bool local_flag;
// Whether the parameter can be overridden
bool overridable;
SymbolType symbol_type() const;
};

View File

@ -126,7 +126,7 @@ static void collect_parm_item(Design*des, NetScope*scope, perm_string name,
// don't try to elaborate it here, because there may be references to
// other parameters still being located during scope elaboration.
scope->set_parameter(name, is_annotatable, cur.expr, cur.data_type,
cur.local_flag, range_list, cur);
cur.local_flag, cur.overridable, range_list, cur);
}

View File

@ -305,7 +305,7 @@ const netenum_t*NetScope::find_enumeration_for_name(const Design*des, perm_strin
*/
void NetScope::set_parameter(perm_string key, bool is_annotatable,
PExpr*val, data_type_t*val_type,
bool local_flag,
bool local_flag, bool overridable,
NetScope::range_t*range_list,
const LineInfo&file_line)
{
@ -315,6 +315,7 @@ void NetScope::set_parameter(perm_string key, bool is_annotatable,
ref.val_type = val_type;
ref.val_scope = this;
ref.local_flag = local_flag;
ref.overridable = overridable;
ivl_assert(file_line, ref.range == 0);
ref.range = range_list;
ref.val = 0;
@ -400,6 +401,15 @@ void NetScope::replace_parameter(Design *des, perm_string key, PExpr*val, NetSco
des->errors++;
return;
}
if (!ref.overridable) {
cerr << val->get_fileline() << ": error: "
<< "Cannot override parameter `" << key << "` in `"
<< scope_path(this) << "`. Parameter cannot be overriden "
<< "in the scope it has been declared in."
<< endl;
des->errors++;
return;
}
ref.val_expr = val;
ref.val_scope = scope;

View File

@ -968,7 +968,7 @@ class NetScope : public Definitions, public Attrib {
struct range_t;
void set_parameter(perm_string name, bool is_annotatable,
PExpr*val, data_type_t*data_type,
bool local_flag,
bool local_flag, bool overridable,
NetScope::range_t*range_list,
const LineInfo&file_line);
void set_parameter(perm_string name, NetExpr*val,
@ -1227,6 +1227,8 @@ class NetScope : public Definitions, public Attrib {
bool is_annotatable;
// Is this a localparam?
bool local_flag;
// Can it be overriden?
bool overridable;
// range constraints
struct range_t*range;
// Expression value and type (elaborated versoins of val_expr/val_type)

View File

@ -3232,6 +3232,9 @@ void pform_set_parameter(const struct vlltype&loc,
is_local ? "localparam" : "parameter");
return;
}
bool overridable = !is_local;
if (scope == pform_cur_generate && !is_local) {
VLerror("parameter declarations are not permitted in generate blocks");
return;
@ -3247,11 +3250,12 @@ void pform_set_parameter(const struct vlltype&loc,
parm->data_type = data_type;
parm->range = value_range;
parm->local_flag = is_local;
parm->overridable = overridable;
scope->parameters[name] = parm;
// Only a module keeps the position of the parameter.
if (!is_local &&
if (overridable &&
(dynamic_cast<Module*>(scope)) && (scope == pform_cur_module.front()))
pform_cur_module.front()->param_names.push_back(name);
}