From 6730ead11942917cb898bde2ed317f42132b9941 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 3 Feb 2022 10:48:42 +0100 Subject: [PATCH 1/2] Generate error for invalid declarations within generate block Most things that can be declared in a module can also be declared in a generate block. But there are a few exceptions that can not be declared in generate block * module, program or interface declaration * specify block or specparam * timeunit Some of these currently work while some of them trigger an assertion and cause and application crash. Add checks to make sure that all of them these are reported as an error and do not cause a crash. Signed-off-by: Lars-Peter Clausen --- parse.y | 26 +++++++++++++++++++++----- pform.cc | 21 ++++++++++++++++++--- pform.h | 2 ++ 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/parse.y b/parse.y index 64fe44da7..8af33f0b9 100644 --- a/parse.y +++ b/parse.y @@ -4868,10 +4868,22 @@ module keyword. The syntax for modules programs, and interfaces is almost identical, so let semantics sort out the differences. */ module_start - : K_module { $$ = K_module; } - | K_macromodule { $$ = K_module; } - | K_program { $$ = K_program; } - | K_interface { $$ = K_interface; } + : K_module + { pform_error_in_generate(@1, "module declaration"); + $$ = K_module; + } + | K_macromodule + { pform_error_in_generate(@1, "module declaration"); + $$ = K_module; + } + | K_program + { pform_error_in_generate(@1, "program declaration"); + $$ = K_program; + } + | K_interface + { pform_error_in_generate(@1, "interface declaration"); + $$ = K_interface; + } ; module_end @@ -5262,6 +5274,7 @@ module_item | attribute_list_opt assertion_item | timeunits_declaration + { pform_error_in_generate(@1, "timeunit declaration"); } | class_declaration @@ -5330,8 +5343,9 @@ module_item | attribute_list_opt K_specparam { if (pform_in_interface()) - yyerror(@1, "error: specparam declarations are not allowed " + yyerror(@2, "error: specparam declarations are not allowed " "in interfaces."); + pform_error_in_generate(@2, "specparam declaration"); } specparam_decl ';' @@ -5341,7 +5355,9 @@ module_item { if (pform_in_interface()) yyerror(@1, "error: specify blocks are not allowed " "in interfaces."); + pform_error_in_generate(@1, "specify block"); } + specify_item_list_opt K_endspecify | K_specify error K_endspecify diff --git a/pform.cc b/pform.cc index dd171773c..157231a69 100644 --- a/pform.cc +++ b/pform.cc @@ -780,6 +780,15 @@ PGenerate* pform_parent_generate(void) return pform_cur_generate; } +bool pform_error_in_generate(const vlltype&loc, const char *type) +{ + if (!pform_parent_generate()) + return false; + + VLerror(loc, "error: %s is not allowed in generate block.", type); + return true; +} + void pform_bind_attributes(map&attributes, list*attr, bool keep_attrs) { @@ -1212,7 +1221,8 @@ void pform_set_timeunit(const char*txt, bool initial_decl) if (get_time_unit_prec(txt, val, true)) return; PScopeExtra*scope = dynamic_cast(lexical_scope); - assert(scope); + if (!scope) + return; if (initial_decl) { scope->time_unit = val; @@ -1249,7 +1259,8 @@ void pform_set_timeprec(const char*txt, bool initial_decl) if (get_time_unit_prec(txt, val, false)) return; PScopeExtra*scope = dynamic_cast(lexical_scope); - assert(scope); + if (!scope) + return; if (initial_decl) { scope->time_precision = val; @@ -3288,7 +3299,11 @@ void pform_set_specparam(const struct vlltype&loc, perm_string name, { assert(! pform_cur_module.empty()); Module*scope = pform_cur_module.front(); - assert(scope == lexical_scope); + if (scope != lexical_scope) { + delete range; + delete expr; + return; + } assert(expr); Module::param_expr_t*parm = new Module::param_expr_t(); diff --git a/pform.h b/pform.h index 52199eaad..861d59e67 100644 --- a/pform.h +++ b/pform.h @@ -323,6 +323,8 @@ extern void pform_endgenerate(bool end_conditional); */ extern PGenerate* pform_parent_generate(void); +bool pform_error_in_generate(const vlltype&loc, const char *type); + extern void pform_make_elab_task(const struct vlltype&li, perm_string name, const std::list¶ms); From b37636e4fcda093951864e35944ddd6b6e214335 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 15 Feb 2022 15:26:34 +0100 Subject: [PATCH 2/2] Add regression test for invalid declarations in generate blocks Check that the following declarations inside a generate block generate an error: * module, program or interface * specparam * specify block * timeunit Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/generate_module.v | 16 ++++++++++++++++ ivtest/ivltests/generate_specify.v | 18 ++++++++++++++++++ ivtest/ivltests/generate_specparam.v | 17 +++++++++++++++++ ivtest/ivltests/generate_timeunit.v | 17 +++++++++++++++++ ivtest/regress-sv.list | 2 ++ ivtest/regress-vlg.list | 2 ++ 6 files changed, 72 insertions(+) create mode 100644 ivtest/ivltests/generate_module.v create mode 100644 ivtest/ivltests/generate_specify.v create mode 100644 ivtest/ivltests/generate_specparam.v create mode 100644 ivtest/ivltests/generate_timeunit.v diff --git a/ivtest/ivltests/generate_module.v b/ivtest/ivltests/generate_module.v new file mode 100644 index 000000000..9a0be9b49 --- /dev/null +++ b/ivtest/ivltests/generate_module.v @@ -0,0 +1,16 @@ +// Check that declaring a module inside a generate block is an error + +module test #( + parameter A = 1 +); + +generate + if (A) begin + // Error + module inner; + initial $display("FAILED"); + endmodule + end +endgenerate + +endmodule diff --git a/ivtest/ivltests/generate_specify.v b/ivtest/ivltests/generate_specify.v new file mode 100644 index 000000000..c99a6421b --- /dev/null +++ b/ivtest/ivltests/generate_specify.v @@ -0,0 +1,18 @@ +// Check that a specify block inside a generate block is an error + +module test #( + parameter A = 1 +); + +generate + if (A) begin + specify // Error + endspecify + end +endgenerate + +initial begin + $display("FAILED"); +end + +endmodule diff --git a/ivtest/ivltests/generate_specparam.v b/ivtest/ivltests/generate_specparam.v new file mode 100644 index 000000000..cd9c9629f --- /dev/null +++ b/ivtest/ivltests/generate_specparam.v @@ -0,0 +1,17 @@ +// Check that declaring a specparam inside a generate block is an error + +module test #( + parameter A = 1 +); + +generate + if (A) begin + specparam x = 10; // Error + end +endgenerate + +initial begin + $display("FAILED"); +end + +endmodule diff --git a/ivtest/ivltests/generate_timeunit.v b/ivtest/ivltests/generate_timeunit.v new file mode 100644 index 000000000..658eb4173 --- /dev/null +++ b/ivtest/ivltests/generate_timeunit.v @@ -0,0 +1,17 @@ +// Check that declaring a timeunit inside a generate block is an error + +module test #( + parameter A = 1 +); + +generate + if (A) begin + timeunit 10ns/1ns; // Error + end +endgenerate + +initial begin + $display("FAILED"); +end + +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index b0e865eb5..9467635ad 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -269,6 +269,8 @@ function10 CO,-g2005-sv ivltests function11 CE,-g2005-sv ivltests function12 normal,-g2005-sv ivltests gold=function12.gold genvar_inc_dec normal,-g2009 ivltests +generate_module CE,-g2005-sv ivltests +generate_timeunit CE,-g2005-sv ivltests ibit_test normal,-g2005-sv ivltests ibyte_test normal,-g2005-sv ivltests iint_test normal,-g2005-sv ivltests diff --git a/ivtest/regress-vlg.list b/ivtest/regress-vlg.list index 127c60b07..6aad76074 100644 --- a/ivtest/regress-vlg.list +++ b/ivtest/regress-vlg.list @@ -570,6 +570,8 @@ generate_case normal ivltests generate_case2 normal ivltests generate_case3 normal ivltests generate_multi_loop normal ivltests gold=generate_multi_loop.gold +generate_specify CE,-g2005-sv ivltests +generate_specparam CE,-g2005-sv ivltests genloop normal ivltests genvar_scopes normal ivltests hello1 normal ivltests