From d104e28dbf1aad5c65c7d532bb8d275238782566 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 5 Feb 2022 11:29:27 +0100 Subject: [PATCH] Support non-overridable parameters in classes SystemVerilog allows `parameter` and `localparam` to declare constants within a class scope. E.g. ```SystemVerilog class C; localparam A = 10; endclass ``` In this context both declare a local parameter that can not be overwritten. Supporting this can be achieved for the most part by adding a parser sub-rule in class declaration rule. In addition some extra support code is needed to mark the parameter as non-overridable. Signed-off-by: Lars-Peter Clausen --- elab_scope.cc | 2 ++ parse.y | 9 +++++++-- pform.cc | 3 +++ pform.h | 1 + pform_pclass.cc | 5 +++++ 5 files changed, 18 insertions(+), 2 deletions(-) diff --git a/elab_scope.cc b/elab_scope.cc index 36125fffd..23a9a8ef4 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -524,6 +524,8 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass) class_scope->add_typedefs(&pclass->typedefs); + collect_scope_parameters(des, class_scope, pclass->parameters); + // Elaborate enum types declared in the class. We need these // now because enumeration constants can be used during scope // elaboration. diff --git a/parse.y b/parse.y index 4ddf96132..5cd9cea38 100644 --- a/parse.y +++ b/parse.y @@ -978,6 +978,8 @@ class_item /* IEEE1800-2005: A.1.8 */ yyerrok; } + | parameter_declaration + | error ';' { yyerror(@2, "error: invalid class item."); yyerrok; @@ -2016,7 +2018,7 @@ package_import_item_list package_item /* IEEE1800-2005 A.1.10 */ : timeunits_declaration - | parameter_or_localparam param_type parameter_assign_list ';' + | parameter_declaration | type_declaration | function_declaration | task_declaration @@ -2697,7 +2699,7 @@ block_item_decl { if ($2) pform_make_events($2, @1.text, @1.first_line); } - | parameter_or_localparam param_type parameter_assign_list ';' + | parameter_declaration /* Blocks can have type declarations. */ @@ -5570,6 +5572,9 @@ 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_declaration + : parameter_or_localparam param_type parameter_assign_list ';' + parameter_or_localparam : parameter | localparam diff --git a/pform.cc b/pform.cc index f9f7a3237..0d3f97c4f 100644 --- a/pform.cc +++ b/pform.cc @@ -3213,6 +3213,9 @@ void pform_set_parameter(const struct vlltype&loc, scope->has_parameter_port_list) overridable = false; + if (pform_in_class()) + overridable = false; + Module::param_expr_t*parm = new Module::param_expr_t(); FILE_NAME(parm, loc); diff --git a/pform.h b/pform.h index 687dee9bd..69e5e9c1e 100644 --- a/pform.h +++ b/pform.h @@ -202,6 +202,7 @@ extern void pform_set_this_class(const struct vlltype&loc, PTaskFunc*net); extern void pform_set_constructor_return(PFunction*net); extern void pform_end_class_declaration(const struct vlltype&loc); +extern bool pform_in_class(); extern void pform_make_udp(perm_string name, std::list*parms, std::vector*decl, std::list*table, diff --git a/pform_pclass.cc b/pform_pclass.cc index e9facc013..fdef299dc 100644 --- a/pform_pclass.cc +++ b/pform_pclass.cc @@ -164,3 +164,8 @@ void pform_end_class_declaration(const struct vlltype&loc) pform_cur_class = 0; pform_pop_scope(); } + +bool pform_in_class() +{ + return pform_cur_class != 0; +}