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. */ this map. */
struct param_expr_t : public PNamedItem { struct param_expr_t : public PNamedItem {
inline param_expr_t() : data_type(0), expr(0), range(0), inline param_expr_t() : data_type(0), expr(0), range(0),
local_flag(false) { } local_flag(false), overridable(true) { }
// Type information. // Type information.
data_type_t*data_type; data_type_t*data_type;
// Value expression // Value expression
@ -110,6 +110,8 @@ class LexicalScope {
range_t*range; range_t*range;
// Whether it is a local parameter // Whether it is a local parameter
bool local_flag; bool local_flag;
// Whether the parameter can be overridden
bool overridable;
SymbolType symbol_type() const; 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 // don't try to elaborate it here, because there may be references to
// other parameters still being located during scope elaboration. // other parameters still being located during scope elaboration.
scope->set_parameter(name, is_annotatable, cur.expr, cur.data_type, 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, void NetScope::set_parameter(perm_string key, bool is_annotatable,
PExpr*val, data_type_t*val_type, PExpr*val, data_type_t*val_type,
bool local_flag, bool local_flag, bool overridable,
NetScope::range_t*range_list, NetScope::range_t*range_list,
const LineInfo&file_line) 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_type = val_type;
ref.val_scope = this; ref.val_scope = this;
ref.local_flag = local_flag; ref.local_flag = local_flag;
ref.overridable = overridable;
ivl_assert(file_line, ref.range == 0); ivl_assert(file_line, ref.range == 0);
ref.range = range_list; ref.range = range_list;
ref.val = 0; ref.val = 0;
@ -400,6 +401,15 @@ void NetScope::replace_parameter(Design *des, perm_string key, PExpr*val, NetSco
des->errors++; des->errors++;
return; 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_expr = val;
ref.val_scope = scope; ref.val_scope = scope;

View File

@ -968,7 +968,7 @@ class NetScope : public Definitions, public Attrib {
struct range_t; struct range_t;
void set_parameter(perm_string name, bool is_annotatable, void set_parameter(perm_string name, bool is_annotatable,
PExpr*val, data_type_t*data_type, PExpr*val, data_type_t*data_type,
bool local_flag, bool local_flag, bool overridable,
NetScope::range_t*range_list, NetScope::range_t*range_list,
const LineInfo&file_line); const LineInfo&file_line);
void set_parameter(perm_string name, NetExpr*val, void set_parameter(perm_string name, NetExpr*val,
@ -1227,6 +1227,8 @@ class NetScope : public Definitions, public Attrib {
bool is_annotatable; bool is_annotatable;
// Is this a localparam? // Is this a localparam?
bool local_flag; bool local_flag;
// Can it be overriden?
bool overridable;
// range constraints // range constraints
struct range_t*range; struct range_t*range;
// Expression value and type (elaborated versoins of val_expr/val_type) // 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"); is_local ? "localparam" : "parameter");
return; return;
} }
bool overridable = !is_local;
if (scope == pform_cur_generate && !is_local) { if (scope == pform_cur_generate && !is_local) {
VLerror("parameter declarations are not permitted in generate blocks"); VLerror("parameter declarations are not permitted in generate blocks");
return; return;
@ -3247,11 +3250,12 @@ void pform_set_parameter(const struct vlltype&loc,
parm->data_type = data_type; parm->data_type = data_type;
parm->range = value_range; parm->range = value_range;
parm->local_flag = is_local; parm->local_flag = is_local;
parm->overridable = overridable;
scope->parameters[name] = parm; scope->parameters[name] = parm;
// Only a module keeps the position of the parameter. // Only a module keeps the position of the parameter.
if (!is_local && if (overridable &&
(dynamic_cast<Module*>(scope)) && (scope == pform_cur_module.front())) (dynamic_cast<Module*>(scope)) && (scope == pform_cur_module.front()))
pform_cur_module.front()->param_names.push_back(name); pform_cur_module.front()->param_names.push_back(name);
} }