Merge pull request #598 from larsclausen/fix-implicit-localparam

Handle implicit `localparam`
This commit is contained in:
Stephen Williams 2022-02-01 15:24:57 -08:00 committed by GitHub
commit dd0a4c9a5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 67 additions and 61 deletions

View File

@ -0,0 +1,30 @@
// Check that all parameters in a parameter port list after a `localparam` get
// elaborated as localparams, until the next `parameter`.
module a #(
parameter A = 1, B = 2,
localparam C = 3, D = 4,
parameter E = 5
);
initial begin
if (A == 10 && B == 20 && C == 3 && D == 4 && E == 50) begin
$display("PASSED");
end else begin
$display("FAILED");
end
end
endmodule
module b;
a #(
.A(10),
.B(20),
.C(30),
.D(40),
.E(50)
) i_a();
endmodule

View File

@ -300,6 +300,7 @@ l_equiv normal,-g2005-sv ivltests
l_equiv_ca normal,-g2005-sv ivltests
l_equiv_const normal,-g2005-sv ivltests
line_directive normal,-g2009,-I./ivltests ivltests gold=line_directive.gold
localparam_implicit normal,-g2005-sv ivltests
localparam_query normal,-g2005-sv ivltests
localparam_type2 normal,-g2009 ivltests
logical_short_circuit normal,-g2012 ivltests

55
parse.y
View File

@ -38,6 +38,7 @@ class PSpecPath;
extern void lex_end_table();
static data_type_t* param_data_type = 0;
static bool param_is_local = false;
static std::list<pform_range_t>* specparam_active_range = 0;
/* Port declaration lists use this structure for context. */
@ -2040,8 +2041,7 @@ package_import_item_list
package_item /* IEEE1800-2005 A.1.10 */
: timeunits_declaration
| K_parameter param_type parameter_assign_list ';'
| K_localparam param_type localparam_assign_list ';'
| parameter_or_localparam param_type parameter_assign_list ';'
| type_declaration
| function_declaration
| task_declaration
@ -2773,8 +2773,7 @@ block_item_decl
{ if ($2) pform_make_events($2, @1.text, @1.first_line);
}
| K_parameter param_type parameter_assign_list ';'
| K_localparam param_type localparam_assign_list ';'
| parameter_or_localparam param_type parameter_assign_list ';'
/* Blocks can have type declarations. */
@ -2797,11 +2796,11 @@ block_item_decl
yyerrok;
}
| K_parameter error ';'
| parameter error ';'
{ yyerror(@1, "error: syntax error in parameter list.");
yyerrok;
}
| K_localparam error ';'
| localparam error ';'
{ yyerror(@1, "error: syntax error localparam list.");
yyerrok;
}
@ -5003,22 +5002,20 @@ module_parameter_port_list_opt
| '#' '(' module_parameter_port_list ')'
;
module_parameter_port_list
: K_parameter param_type parameter_assign
| K_localparam param_type localparam_assign
module_parameter
: parameter param_type parameter_assign
| localparam param_type parameter_assign
{ if (!gn_system_verilog()) {
yyerror(@1, "error: Local parameters in module parameter "
"port lists requires SystemVerilog.");
}
}
| module_parameter_port_list ',' parameter_assign
| module_parameter_port_list ',' K_parameter param_type parameter_assign
| module_parameter_port_list ',' K_localparam param_type localparam_assign
{ if (!gn_system_verilog()) {
yyerror(@3, "error: Local parameters in module parameter "
"port lists requires SystemVerilog.");
}
}
;
module_parameter_port_list
: module_parameter
| module_parameter_port_list ',' module_parameter
| module_parameter_port_list ',' parameter_assign
;
module_item
@ -5663,6 +5660,14 @@ net_type
param_type : data_type_or_implicit { param_data_type = $1; }
parameter : K_parameter { param_is_local = false; };
localparam : K_localparam { param_is_local = true; };
parameter_or_localparam
: parameter
| localparam
;
/* parameter and localparam assignment lists are broken into
separate BNF so that I can call slightly different parameter
handling code. localparams parse the same as parameters, they
@ -5673,23 +5678,11 @@ parameter_assign_list
| parameter_assign_list ',' parameter_assign
;
localparam_assign_list
: localparam_assign
| localparam_assign_list ',' localparam_assign
;
parameter_assign
: IDENTIFIER '=' expression parameter_value_ranges_opt
{ PExpr*tmp = $3;
pform_set_parameter(@1, lex_strings.make($1), param_data_type, tmp, $4);
delete[]$1;
}
;
localparam_assign
: IDENTIFIER '=' expression
{ PExpr*tmp = $3;
pform_set_localparam(@1, lex_strings.make($1), param_data_type, tmp);
pform_set_parameter(@1, lex_strings.make($1), param_is_local,
param_data_type, tmp, $4);
delete[]$1;
}
;

View File

@ -3223,15 +3223,16 @@ LexicalScope::range_t* pform_parameter_value_range(bool exclude_flag,
}
void pform_set_parameter(const struct vlltype&loc,
perm_string name, data_type_t*data_type, PExpr*expr,
perm_string name, bool is_local, data_type_t*data_type, PExpr*expr,
LexicalScope::range_t*value_range)
{
LexicalScope*scope = lexical_scope;
if (is_compilation_unit(scope) && !gn_system_verilog()) {
VLerror(loc, "error: parameter declarations must be contained within a module.");
VLerror(loc, "error: %s declarations must be contained within a module.",
is_local ? "localparam" : "parameter");
return;
}
if (scope == pform_cur_generate) {
if (scope == pform_cur_generate && !is_local) {
VLerror("parameter declarations are not permitted in generate blocks");
return;
}
@ -3241,36 +3242,20 @@ void pform_set_parameter(const struct vlltype&loc,
FILE_NAME(parm, loc);
add_local_symbol(scope, name, parm);
scope->parameters[name] = parm;
parm->expr = expr;
parm->data_type = data_type;
parm->range = value_range;
// Only a Module keeps the position of the parameter.
if ((dynamic_cast<Module*>(scope)) && (scope == pform_cur_module.front()))
pform_cur_module.front()->param_names.push_back(name);
}
if (is_local) {
scope->localparams[name] = parm;
} else {
scope->parameters[name] = parm;
void pform_set_localparam(const struct vlltype&loc,
perm_string name, data_type_t*data_type, PExpr*expr)
{
LexicalScope*scope = lexical_scope;
if (is_compilation_unit(scope) && !gn_system_verilog()) {
VLerror(loc, "error: localparam declarations must be contained within a module.");
return;
// Only a Module keeps the position of the parameter.
if ((dynamic_cast<Module*>(scope)) && (scope == pform_cur_module.front()))
pform_cur_module.front()->param_names.push_back(name);
}
assert(expr);
Module::param_expr_t*parm = new Module::param_expr_t();
FILE_NAME(parm, loc);
add_local_symbol(scope, name, parm);
scope->localparams[name] = parm;
parm->expr = expr;
parm->data_type = data_type;
parm->range = 0;
}
void pform_set_specparam(const struct vlltype&loc, perm_string name,

View File

@ -432,12 +432,9 @@ extern LexicalScope::range_t* pform_parameter_value_range(bool exclude_flag,
extern void pform_set_parameter(const struct vlltype&loc,
perm_string name,
bool is_local,
data_type_t*data_type,
PExpr*expr, LexicalScope::range_t*value_range);
extern void pform_set_localparam(const struct vlltype&loc,
perm_string name,
data_type_t*data_type,
PExpr*expr);
extern void pform_set_specparam(const struct vlltype&loc,
perm_string name,
std::list<pform_range_t>*range,