From 618959d1478fef89b724e8d71bc0a7daf6126e0f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 5 Feb 2022 10:49:34 +0100 Subject: [PATCH] Add helper function to emit error when SystemVerilog is requried When encountering a construct that requires SystemVerilog in most cases an error message is generated when SystemVerilog is not enabled and parsing simply continues. Factor the checking and generating of the error message into a helper function. This slightly reduces boiler plate code and gives consistent error messages. Signed-off-by: Lars-Peter Clausen --- parse.y | 107 +++++++++++++++------------------------------------ parse_misc.h | 1 + pform.cc | 22 ++++++----- pform.h | 2 + 4 files changed, 48 insertions(+), 84 deletions(-) diff --git a/parse.y b/parse.y index 4850a0611..20e3b14d2 100644 --- a/parse.y +++ b/parse.y @@ -309,9 +309,8 @@ static void current_task_set_statement(const YYLTYPE&loc, std::vectorset_statement(tmp); @@ -330,9 +329,7 @@ static void current_task_set_statement(const YYLTYPE&loc, std::vectorset_statement(tmp); @@ -368,9 +364,7 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vectorsize() > 1 && !gn_system_verilog()) { - yyerror(@7, "error: Task body with multiple statements requires SystemVerilog."); + if ($7 && $7->size() > 1) { + pform_requires_sv(@7, "Task body with multiple statements"); } delete $7; } @@ -2452,10 +2445,8 @@ tf_port_item /* IEEE1800-2005: A.2.7 */ tmp = pform_make_task_ports(@3, use_port_type, $2, ilist); } if ($4 != 0) { - if (gn_system_verilog()) { + if (pform_requires_sv(@4, "Task/function port with unpacked dimensions")) { pform_set_reg_idx(name, $4); - } else { - yyerror(@4, "error: Task/function port with unpacked dimensions requires SystemVerilog."); } } @@ -2479,10 +2470,7 @@ tf_port_item /* IEEE1800-2005: A.2.7 */ tf_port_item_expr_opt : '=' expression - { if (! gn_system_verilog()) { - yyerror(@1, "error: Task/function default arguments require " - "SystemVerilog."); - } + { pform_requires_sv(@$, "Task/function default argument"); $$ = $2; } | { $$ = 0; } @@ -2582,9 +2570,7 @@ variable_dimension /* IEEE1800-2005: A.2.5 */ | '[' ']' { std::list *tmp = new std::list; pform_range_t index (0,0); - if (!gn_system_verilog()) { - yyerror("error: Dynamic array declaration require SystemVerilog."); - } + pform_requires_sv(@$, "Dynamic array declaration"); tmp->push_back(index); $$ = tmp; } @@ -2592,9 +2578,7 @@ variable_dimension /* IEEE1800-2005: A.2.5 */ { // SystemVerilog queue list *tmp = new std::list; pform_range_t index (new PENull,0); - if (!gn_system_verilog()) { - yyerror("error: Queue declaration require SystemVerilog."); - } + pform_requires_sv(@$, "Queue declaration"); tmp->push_back(index); $$ = tmp; } @@ -2602,9 +2586,7 @@ variable_dimension /* IEEE1800-2005: A.2.5 */ { // SystemVerilog queue with a max size list *tmp = new std::list; pform_range_t index (new PENull,$4); - if (!gn_system_verilog()) { - yyerror("error: Queue declarations require SystemVerilog."); - } + pform_requires_sv(@$, "Queue declaration"); tmp->push_back(index); $$ = tmp; } @@ -2612,10 +2594,8 @@ variable_dimension /* IEEE1800-2005: A.2.5 */ variable_lifetime : lifetime - { if (!gn_system_verilog()) { - yyerror(@1, "error: overriding the default variable lifetime " - "requires SystemVerilog."); - } else if ($1 != pform_peek_scope()->default_lifetime) { + { if (pform_requires_sv(@1, "Overriding default variable lifetime") && + $1 != pform_peek_scope()->default_lifetime) { yyerror(@1, "sorry: overriding the default variable lifetime " "is not yet supported."); } @@ -3913,9 +3893,7 @@ expr_primary FILE_NAME(tmp, @1); delete[]$1; $$ = tmp; - if (!gn_system_verilog()) { - yyerror(@1, "error: Empty function argument list requires SystemVerilog."); - } + pform_requires_sv(@1, "Empty function argument list"); } | implicit_class_handle @@ -4158,24 +4136,22 @@ expr_primary | expr_primary '\'' '(' expression ')' { PExpr*base = $4; - if (gn_system_verilog()) { + if (pform_requires_sv(@1, "Size cast")) { PECastSize*tmp = new PECastSize($1, base); FILE_NAME(tmp, @1); $$ = tmp; } else { - yyerror(@1, "error: Size cast requires SystemVerilog."); $$ = base; } } | simple_type_or_string '\'' '(' expression ')' { PExpr*base = $4; - if (gn_system_verilog()) { + if (pform_requires_sv(@1, "Type cast")) { PECastType*tmp = new PECastType($1, base); FILE_NAME(tmp, @1); $$ = tmp; } else { - yyerror(@1, "error: Type cast requires SystemVerilog."); $$ = base; } } @@ -4409,12 +4385,9 @@ hierarchy_identifier $$ = tmp; } | hierarchy_identifier '[' '$' ']' - { pform_name_t * tmp = $1; + { pform_requires_sv(@3, "Last element expression ($)"); + pform_name_t * tmp = $1; name_component_t&tail = tmp->back(); - if (! gn_system_verilog()) { - yyerror(@3, "error: Last element expression ($) " - "requires SystemVerilog. Try enabling SystemVerilog."); - } index_component_t itmp; itmp.sel = index_component_t::SEL_BIT_LAST; itmp.msb = 0; @@ -4585,9 +4558,7 @@ port_declaration $$ = ptmp; } | attribute_list_opt K_input net_type_opt data_type_or_implicit IDENTIFIER '=' expression - { if (!gn_system_verilog()) { - yyerror("error: Default port values require SystemVerilog."); - } + { pform_requires_sv(@6, "Default port value"); Module::port_t*ptmp; perm_string name = lex_strings.make($5); data_type_t*use_type = $4; @@ -4935,11 +4906,8 @@ module_parameter_port_list_opt 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."); - } - } + { pform_requires_sv(@1, "Local parameter in module parameter port list"); + } ; module_parameter_port_list @@ -5379,10 +5347,7 @@ module_item | K_function error K_endfunction label_opt { yyerror(@1, "error: I give up on this function definition."); if ($4) { - if (!gn_system_verilog()) { - yyerror(@4, "error: Function end names require " - "SystemVerilog."); - } + pform_requires_sv(@4, "Function end label"); delete[]$4; } yyerrok; @@ -6514,10 +6479,7 @@ statement_item /* This is roughly statement_item in the LRM */ block_item_decls_opt { if (!$2) { if ($4) { - if (! gn_system_verilog()) { - yyerror("error: Variable declaration in unnamed block " - "requires SystemVerilog."); - } + pform_requires_sv(@4, "Variable declaration in unnamed block"); } else { /* If there are no declarations in the scope then just delete it. */ pform_pop_scope(); @@ -6560,10 +6522,7 @@ statement_item /* This is roughly statement_item in the LRM */ { if (!$2) { if ($4) { - if (! gn_system_verilog()) { - yyerror("error: Variable declaration in unnamed block " - "requires SystemVerilog."); - } + pform_requires_sv(@4, "Variable declaration in unnamed block"); } else { /* If there are no declarations in the scope then just delete it. */ pform_pop_scope(); @@ -6847,9 +6806,7 @@ statement_item /* This is roughly statement_item in the LRM */ | hierarchy_identifier K_with '{' constraint_block_item_list_opt '}' ';' { /* ....randomize with { } */ if ($1 && peek_tail_name(*$1) == "randomize") { - if (!gn_system_verilog()) - yyerror(@2, "error: Randomize with constraint requires SystemVerilog."); - else + if (pform_requires_sv(@2, "Randomize with constraint")) yyerror(@2, "sorry: Randomize with constraint not supported."); } else { yyerror(@2, "error: Constraint block can only be applied to randomize method."); diff --git a/parse_misc.h b/parse_misc.h index c7a6faa2e..c20cc0e4e 100644 --- a/parse_misc.h +++ b/parse_misc.h @@ -57,6 +57,7 @@ extern YYLTYPE yylloc; */ extern int VLlex(); extern void VLerror(const char*msg); +extern void VLerror(const YYLTYPE&loc, va_list ap); extern void VLerror(const YYLTYPE&loc, const char*msg, ...) __attribute__((format(printf,2,3))); #define yywarn VLwarn extern void VLwarn(const char*msg); diff --git a/pform.cc b/pform.cc index 4de09e481..4ab111ea0 100644 --- a/pform.cc +++ b/pform.cc @@ -1334,10 +1334,9 @@ void pform_startmodule(const struct vlltype&loc, const char*name, error_count += 1; } - if (lifetime != LexicalScope::INHERITED && !gn_system_verilog()) { - cerr << loc << ": error: Default subroutine lifetimes " - "require SystemVerilog." << endl; - error_count += 1; + + if (lifetime != LexicalScope::INHERITED) { + pform_requires_sv(loc, "Default subroutine lifetime"); } if (gn_system_verilog() && ! pform_cur_module.empty()) { @@ -3138,11 +3137,7 @@ PAssign* pform_compressed_assign_from_inc_dec(const struct vlltype&loc, PExpr*ex PExpr* pform_genvar_inc_dec(const struct vlltype&loc, const char*name, bool inc_flag) { - if (!gn_system_verilog()) { - cerr << loc << ": error: Increment/decrement operators " - "require SystemVerilog." << endl; - error_count += 1; - } + pform_requires_sv(loc, "Increment/decrement operator"); PExpr*lval = new PEIdent(lex_strings.make(name)); PExpr*rval = new PENumber(new verinum(1)); @@ -3760,6 +3755,15 @@ void pform_add_modport_port(const struct vlltype&loc, pform_cur_modport->simple_ports[name] = make_pair(port_type, expr); } +bool pform_requires_sv(const struct vlltype&loc, const char *feature) +{ + if (gn_system_verilog()) + return true; + + VLerror(loc, "error: %s requires SystemVerilog.", feature); + + return false; +} FILE*vl_input = 0; extern void reset_lexor(); diff --git a/pform.h b/pform.h index cfefa09b3..b1b5e7a1d 100644 --- a/pform.h +++ b/pform.h @@ -612,4 +612,6 @@ extern bool allow_timeprec_decl; void pform_put_enum_type_in_scope(enum_type_t*enum_set); +bool pform_requires_sv(const struct vlltype&loc, const char *feature); + #endif /* IVL_pform_H */