Merge pull request #598 from larsclausen/fix-implicit-localparam
Handle implicit `localparam`
This commit is contained in:
commit
dd0a4c9a5e
|
|
@ -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
|
||||
|
|
@ -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
55
parse.y
|
|
@ -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;
|
||||
}
|
||||
;
|
||||
|
|
|
|||
37
pform.cc
37
pform.cc
|
|
@ -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,
|
||||
|
|
|
|||
5
pform.h
5
pform.h
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue