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 6ac0eda0a..716582999 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 e49a9afd4..fd744f42d 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 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 10b8d9f37..4ee97ccda 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; @@ -3295,7 +3306,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);