From 4f48a7ed412ba82fab206c40e71cbbb56b37710a Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 2 Oct 2019 19:30:47 -0700 Subject: [PATCH 01/11] Fix assertion in error recovery. --- PExpr.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/PExpr.cc b/PExpr.cc index bce998419..b358542b5 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -126,9 +126,8 @@ PEBinary::~PEBinary() void PEBinary::declare_implicit_nets(LexicalScope*scope, NetNet::Type type) { - assert(left_ && right_); - left_->declare_implicit_nets(scope, type); - right_->declare_implicit_nets(scope, type); + if (left_) left_->declare_implicit_nets(scope, type); + if (right_) right_->declare_implicit_nets(scope, type); } bool PEBinary::has_aa_term(Design*des, NetScope*scope) const From 2ced291d330361cf3cb2c8a60a05d9f660310d4a Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 3 Oct 2019 08:38:36 -0700 Subject: [PATCH 02/11] Replace an assert with an internal error message. --- pform.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pform.cc b/pform.cc index c8a42bb17..d9772dd70 100644 --- a/pform.cc +++ b/pform.cc @@ -2356,7 +2356,22 @@ void pform_make_modgates(const struct vlltype&loc, svector*gates, std::list*attr) { + // The grammer should not allow module gates to happen outside + // an active module. But if really bad input errors combine in + // an ugly way with error recovery, then catch this + // implausible situation and return an error. + if (pform_cur_module.empty()) { + cerr << loc << ": internal error: " + << "Module instantiations outside module scope are not possible." + << endl; + error_count += 1; + delete gates; + return; + } assert(! pform_cur_module.empty()); + + // Detect some more realistic errors. + if (pform_cur_module.front()->program_block) { cerr << loc << ": error: Module instantiations are not allowed in " << "program blocks." << endl; From 9167a236d89bc14271643672c5cfb07fbd59a611 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Thu, 3 Oct 2019 19:44:44 +0100 Subject: [PATCH 03/11] Support import statements in packages and in the unit scope. --- parse.y | 1 + 1 file changed, 1 insertion(+) diff --git a/parse.y b/parse.y index eb10d6b72..9a0a5df2d 100644 --- a/parse.y +++ b/parse.y @@ -1061,6 +1061,7 @@ data_declaration /* IEEE1800-2005: A.2.1.3 */ | attribute_list_opt K_event event_variable_list ';' { if ($3) pform_make_events($3, @2.text, @2.first_line); } + | attribute_list_opt package_import_declaration ; data_type /* IEEE1800-2005: A.2.2.1 */ From 455702810ec0a0524914a0bf9b30cad164e1015f Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 5 Oct 2019 08:55:11 +0100 Subject: [PATCH 04/11] Add support for parsing (and ignoring) the other unsupported SV assertions. --- parse.y | 295 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 236 insertions(+), 59 deletions(-) diff --git a/parse.y b/parse.y index 9a0a5df2d..c4c3b5585 100644 --- a/parse.y +++ b/parse.y @@ -575,6 +575,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %type udp_initial_expr_opt %type register_variable net_variable event_variable endlabel_opt class_declaration_endlabel_opt +%type block_identifier_opt %type register_variable_list net_variable_list event_variable_list %type list_of_identifiers loop_variables %type list_of_port_identifiers list_of_variable_port_identifiers @@ -652,6 +653,9 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %type statement statement_item statement_or_null %type compressed_statement %type loop_statement for_step jump_statement +%type concurrent_assertion_statement +%type deferred_immediate_assertion_statement +%type simple_immediate_assertion_statement %type procedural_assertion_statement %type statement_or_null_list statement_or_null_list_opt @@ -667,6 +671,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %type non_integer_type %type assert_or_assume +%type deferred_mode %type atom2_type %type module_start module_end @@ -724,6 +729,7 @@ assert_or_assume assertion_item /* IEEE1800-2012: A.6.10 */ : concurrent_assertion_item + | deferred_immediate_assertion_item ; assignment_pattern /* IEEE1800-2005: A.6.7.1 */ @@ -744,7 +750,9 @@ assignment_pattern /* IEEE1800-2005: A.6.7.1 */ implements it in a LALR way. */ block_identifier_opt /* */ : IDENTIFIER ':' + { $$ = $1; } | + { $$ = 0; } ; class_declaration /* IEEE1800-2005: A.1.2 */ @@ -988,16 +996,92 @@ class_new /* IEEE1800-2005 A.2.4 */ concurrent_assertion_statement and checker_instantiation rules. */ concurrent_assertion_item /* IEEE1800-2012 A.2.10 */ - : block_identifier_opt K_assert K_property '(' property_spec ')' statement_or_null + : block_identifier_opt concurrent_assertion_statement + { delete $1; + delete $2; + } + ; + +concurrent_assertion_statement /* IEEE1800-2012 A.2.10 */ + : assert_or_assume K_property '(' property_spec ')' statement_or_null %prec less_than_K_else + { /* */ + if (gn_assertions_flag) { + yyerror(@1, "sorry: concurrent_assertion_item not supported." + " Try -gno-assertion to turn this message off."); + } + $$ = 0; + } + | assert_or_assume K_property '(' property_spec ')' K_else statement_or_null + { /* */ + if (gn_assertions_flag) { + yyerror(@1, "sorry: concurrent_assertion_item not supported." + " Try -gno-assertion to turn this message off."); + } + $$ = 0; + } + | assert_or_assume K_property '(' property_spec ')' statement_or_null K_else statement_or_null + { /* */ + if (gn_assertions_flag) { + yyerror(@1, "sorry: concurrent_assertion_item not supported." + " Try -gno-assertion to turn this message off."); + } + $$ = 0; + } + | K_cover K_property '(' property_spec ')' statement_or_null + { /* */ + if (gn_assertions_flag) { + yyerror(@1, "sorry: concurrent_assertion_item not supported." + " Try -gno-assertion to turn this message off."); + } + $$ = 0; + } + /* For now, cheat, and use property_spec for the sequence specification. + They are syntactically identical. */ + | K_cover K_sequence '(' property_spec ')' statement_or_null + { /* */ + if (gn_assertions_flag) { + yyerror(@1, "sorry: concurrent_assertion_item not supported." + " Try -gno-assertion to turn this message off."); + } + $$ = 0; + } + | K_restrict K_property '(' property_spec ')' ';' { /* */ if (gn_assertions_flag) { yyerror(@2, "sorry: concurrent_assertion_item not supported." " Try -gno-assertion to turn this message off."); } + $$ = 0; } - | block_identifier_opt K_assert K_property '(' error ')' statement_or_null + | assert_or_assume K_property '(' error ')' statement_or_null %prec less_than_K_else { yyerrok; yyerror(@2, "error: Error in property_spec of concurrent assertion item."); + $$ = 0; + } + | assert_or_assume K_property '(' error ')' K_else statement_or_null + { yyerrok; + yyerror(@2, "error: Error in property_spec of concurrent assertion item."); + $$ = 0; + } + | assert_or_assume K_property '(' error ')' statement_or_null K_else statement_or_null + { yyerrok; + yyerror(@2, "error: Error in property_spec of concurrent assertion item."); + $$ = 0; + } + | K_cover K_property '(' error ')' statement_or_null + { yyerrok; + yyerror(@2, "error: Error in property_spec of concurrent assertion item."); + $$ = 0; + } + | K_cover K_sequence '(' error ')' statement_or_null + { yyerrok; + yyerror(@2, "error: Error in property_spec of concurrent assertion item."); + $$ = 0; + } + | K_restrict K_property '(' error ')' ';' + { yyerrok; + yyerror(@2, "error: Error in property_spec of concurrent assertion item."); + $$ = 0; } ; @@ -1167,6 +1251,81 @@ data_type_or_implicit_or_void } ; +deferred_immediate_assertion_item /* IEEE1800-2012: A.6.10 */ + : block_identifier_opt deferred_immediate_assertion_statement + { delete $1; + delete $2; + } + ; + +deferred_immediate_assertion_statement /* IEEE1800-2012 A.6.10 */ + : assert_or_assume deferred_mode '(' expression ')' statement_or_null %prec less_than_K_else + { + if (gn_assertions_flag) { + yyerror(@1, "sorry: Deferred assertions are not supported." + " Try -gno-assertion to turn this message off."); + } + delete $4; + delete $6; + $$ = 0; + } + | assert_or_assume deferred_mode '(' expression ')' K_else statement_or_null + { + if (gn_assertions_flag) { + yyerror(@1, "sorry: Deferred assertions are not supported." + " Try -gno-assertion to turn this message off."); + } + delete $4; + delete $7; + $$ = 0; + } + | assert_or_assume deferred_mode '(' expression ')' statement_or_null K_else statement_or_null + { + if (gn_assertions_flag) { + yyerror(@1, "sorry: Deferred assertions are not supported." + " Try -gno-assertion to turn this message off."); + } + delete $4; + delete $6; + delete $8; + $$ = 0; + } + | K_cover deferred_mode '(' expression ')' statement_or_null + { + /* Coverage collection is not currently supported. */ + delete $4; + delete $6; + $$ = 0; + } + | assert_or_assume deferred_mode '(' error ')' statement_or_null %prec less_than_K_else + { yyerror(@1, "error: Malformed conditional expression."); + $$ = $6; + } + | assert_or_assume deferred_mode '(' error ')' K_else statement_or_null + { yyerror(@1, "error: Malformed conditional expression."); + $$ = $7; + } + | assert_or_assume deferred_mode '(' error ')' statement_or_null K_else statement_or_null + { yyerror(@1, "error: Malformed conditional expression."); + $$ = $6; + } + | K_cover deferred_mode '(' error ')' statement_or_null + { yyerror(@1, "error: Malformed conditional expression."); + $$ = $6; + } + ; + +deferred_mode + : '#' DEC_NUMBER + { if (!$2->is_zero()) { + yyerror(@2, "error: Delay value must be zero for deferred assertion."); + } + delete $2; + $$ = 0; } + | K_final + { $$ = 1; } + ; + /* NOTE: The "module" rule of the description combines the module_declaration, program_declaration, and interface_declaration rules from the standard description. */ @@ -1846,65 +2005,17 @@ port_direction_opt | { $$ = NetNet::PIMPLICIT; } ; -property_expr /* IEEE1800-2012 A.2.10 */ - : expression +procedural_assertion_statement /* IEEE1800-2012 A.6.10 */ + : concurrent_assertion_statement + { $$ = $1; } + | simple_immediate_assertion_statement + { $$ = $1; } + | deferred_immediate_assertion_statement + { $$ = $1; } ; -procedural_assertion_statement /* IEEE1800-2012 A.6.10 */ - // $assertcontrol is not yet supported. - : assert_or_assume '(' expression ')' statement_or_null %prec less_than_K_else - { - if (gn_assertions_flag) { - listarg_list; - PCallTask*tmp1 = new PCallTask(lex_strings.make("$error"), arg_list); - FILE_NAME(tmp1, @1); - PCondit*tmp2 = new PCondit($3, $5, tmp1); - FILE_NAME(tmp2, @1); - $$ = tmp2; - } else { - $$ = 0; - } - } - | assert_or_assume '(' expression ')' K_else statement_or_null - { - if (gn_assertions_flag) { - PCondit*tmp = new PCondit($3, 0, $6); - FILE_NAME(tmp, @1); - $$ = tmp; - } else { - $$ = 0; - } - } - | assert_or_assume '(' expression ')' statement_or_null K_else statement_or_null - { - if (gn_assertions_flag) { - PCondit*tmp = new PCondit($3, $5, $7); - FILE_NAME(tmp, @1); - $$ = tmp; - } else { - $$ = 0; - } - } - | K_cover '(' expression ')' statement_or_null - // Coverage collection is not currently supported. - { $$ = 0; } - - | assert_or_assume '(' error ')' statement_or_null %prec less_than_K_else - { yyerror(@1, "error: Malformed conditional expression."); - $$ = $5; - } - | assert_or_assume '(' error ')' K_else statement_or_null - { yyerror(@1, "error: Malformed conditional expression."); - $$ = $6; - } - | assert_or_assume '(' error ')' statement_or_null K_else statement_or_null - { yyerror(@1, "error: Malformed conditional expression."); - $$ = $5; - } - | K_cover '(' error ')' statement_or_null - { yyerror(@1, "error: Malformed conditional expression."); - $$ = $5; - } +property_expr /* IEEE1800-2012 A.2.10 */ + : expression ; /* The property_qualifier rule is as literally described in the LRM, @@ -1957,6 +2068,72 @@ signing /* IEEE1800-2005: A.2.2.1 */ | K_unsigned { $$ = false; } ; +simple_immediate_assertion_statement /* IEEE1800-2012 A.6.10 */ + : assert_or_assume '(' expression ')' statement_or_null %prec less_than_K_else + { + if (gn_assertions_flag) { + listarg_list; + PCallTask*tmp1 = new PCallTask(lex_strings.make("$error"), arg_list); + FILE_NAME(tmp1, @1); + PCondit*tmp2 = new PCondit($3, $5, tmp1); + FILE_NAME(tmp2, @1); + $$ = tmp2; + } else { + delete $3; + delete $5; + $$ = 0; + } + } + | assert_or_assume '(' expression ')' K_else statement_or_null + { + if (gn_assertions_flag) { + PCondit*tmp = new PCondit($3, 0, $6); + FILE_NAME(tmp, @1); + $$ = tmp; + } else { + delete $3; + delete $6; + $$ = 0; + } + } + | assert_or_assume '(' expression ')' statement_or_null K_else statement_or_null + { + if (gn_assertions_flag) { + PCondit*tmp = new PCondit($3, $5, $7); + FILE_NAME(tmp, @1); + $$ = tmp; + } else { + delete $3; + delete $5; + delete $7; + $$ = 0; + } + } + | K_cover '(' expression ')' statement_or_null + { + /* Coverage collection is not currently supported. */ + delete $3; + delete $5; + $$ = 0; + } + | assert_or_assume '(' error ')' statement_or_null %prec less_than_K_else + { yyerror(@1, "error: Malformed conditional expression."); + $$ = $5; + } + | assert_or_assume '(' error ')' K_else statement_or_null + { yyerror(@1, "error: Malformed conditional expression."); + $$ = $6; + } + | assert_or_assume '(' error ')' statement_or_null K_else statement_or_null + { yyerror(@1, "error: Malformed conditional expression."); + $$ = $5; + } + | K_cover '(' error ')' statement_or_null + { yyerror(@1, "error: Malformed conditional expression."); + $$ = $5; + } + ; + simple_type_or_string /* IEEE1800-2005: A.2.2.1 */ : integer_vector_type { ivl_variable_type_t use_vtype = $1; From 05641f386fde245c3d4696ba436ebb38fadf76c8 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 5 Oct 2019 13:37:03 +0100 Subject: [PATCH 05/11] Add -g option to only enable supported assertion statements. --- compiler.h | 11 +++++---- driver/iverilog.man.in | 7 +++--- driver/main.c | 8 +++++-- main.cc | 15 +++++++++---- parse.y | 51 +++++++++++++++++++++++++----------------- 5 files changed, 58 insertions(+), 34 deletions(-) diff --git a/compiler.h b/compiler.h index 6eccc8743..fd50cd52f 100644 --- a/compiler.h +++ b/compiler.h @@ -1,7 +1,7 @@ #ifndef IVL_compiler_H #define IVL_compiler_H /* - * Copyright (c) 1999-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2019 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -177,9 +177,12 @@ extern bool gn_icarus_misc_flag; is false, then skip elaboration of specify behavior. */ extern bool gn_specify_blocks_flag; -/* If this flag is true, then elaborate assertions. If this flag is - false, then stub out assertion statements. */ -extern bool gn_assertions_flag; +/* If this flag is true, then elaborate supported assertion statements. If + this flag is false, then stub out supported assertion statements. */ +extern bool gn_supported_assertions_flag; +/* If this flag is true, then error on unsupported assertion statements. If + this flag is false, then stub out unsupported assertion statements. */ +extern bool gn_unsupported_assertions_flag; /* If this flag is true, then support/elaborate Verilog-AMS. */ extern bool gn_verilog_ams_flag; diff --git a/driver/iverilog.man.in b/driver/iverilog.man.in index 2578969da..8cad315f3 100644 --- a/driver/iverilog.man.in +++ b/driver/iverilog.man.in @@ -1,4 +1,4 @@ -.TH iverilog 1 "Sep 20th, 2019" "" "Version %M.%n%E" +.TH iverilog 1 "Oct 5th, 2019" "" "Version %M.%n%E" .SH NAME iverilog - Icarus Verilog compiler @@ -80,10 +80,11 @@ use any of the new \fIIEEE1800\fP keywords. Enable or disable (default) support for Verilog\-AMS. Very little Verilog\-AMS specific functionality is currently supported. .TP 8 -.B -gassertions\fI|\fP-gno-assertions +.B -gassertions\fI|\fP-gsupported-assertions\fI|\fP-gno-assertions Enable (default) or disable SystemVerilog assertions. When enabled, assertion statements are elaborated. When disabled, assertion statements -are parsed but ignored. +are parsed but ignored. The \fB\-gsupported-assertions\fP option only +enables assertions that are currently supported by the compiler. .TP 8 .B -gspecify\fI|\fP-gno-specify Enable or disable (default) specify block support. When enabled, diff --git a/driver/main.c b/driver/main.c index b723d7ff3..56228637a 100644 --- a/driver/main.c +++ b/driver/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -748,6 +748,9 @@ static int process_generation(const char*name) else if (strcmp(name,"assertions") == 0) gen_assertions = "assertions"; + else if (strcmp(name,"supported-assertions") == 0) + gen_assertions = "supported-assertions"; + else if (strcmp(name,"no-assertions") == 0) gen_assertions = "no-assertions"; @@ -804,6 +807,7 @@ static int process_generation(const char*name) " 2009 -- IEEE1800-2009\n" " 2012 -- IEEE1800-2012\n" "Other generation flags:\n" + " assertions | supported-assertions | no-assertions\n" " specify | no-specify\n" " verilog-ams | no-verilog-ams\n" " std-include | no-std-include\n" @@ -1176,7 +1180,7 @@ int main(int argc, char **argv) if (version_flag || verbose_flag) { printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n"); - printf("Copyright 1998-2017 Stephen Williams\n\n"); + printf("Copyright 1998-2019 Stephen Williams\n\n"); puts(NOTICE); } diff --git a/main.cc b/main.cc index 938100cca..60ec62e7e 100644 --- a/main.cc +++ b/main.cc @@ -1,5 +1,5 @@ const char COPYRIGHT[] = - "Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)"; + "Copyright (c) 1998-2019 Stephen Williams (steve@icarus.com)"; /* * This source code is free software; you can redistribute it @@ -104,7 +104,8 @@ generation_t generation_flag = GN_DEFAULT; bool gn_icarus_misc_flag = true; bool gn_cadence_types_flag = true; bool gn_specify_blocks_flag = true; -bool gn_assertions_flag = true; +bool gn_supported_assertions_flag = true; +bool gn_unsupported_assertions_flag = true; bool gn_io_range_error_flag = true; bool gn_strict_ca_eval_flag = false; bool gn_strict_expr_width_flag = false; @@ -331,10 +332,16 @@ static void process_generation_flag(const char*gen) gn_specify_blocks_flag = false; } else if (strcmp(gen,"assertions") == 0) { - gn_assertions_flag = true; + gn_supported_assertions_flag = true; + gn_unsupported_assertions_flag = true; + + } else if (strcmp(gen,"supported-assertions") == 0) { + gn_supported_assertions_flag = true; + gn_unsupported_assertions_flag = false; } else if (strcmp(gen,"no-assertions") == 0) { - gn_assertions_flag = false; + gn_supported_assertions_flag = false; + gn_unsupported_assertions_flag = false; } else if (strcmp(gen,"verilog-ams") == 0) { gn_verilog_ams_flag = true; diff --git a/parse.y b/parse.y index c4c3b5585..0ff641c83 100644 --- a/parse.y +++ b/parse.y @@ -1005,33 +1005,37 @@ concurrent_assertion_item /* IEEE1800-2012 A.2.10 */ concurrent_assertion_statement /* IEEE1800-2012 A.2.10 */ : assert_or_assume K_property '(' property_spec ')' statement_or_null %prec less_than_K_else { /* */ - if (gn_assertions_flag) { + if (gn_unsupported_assertions_flag) { yyerror(@1, "sorry: concurrent_assertion_item not supported." - " Try -gno-assertion to turn this message off."); + " Try -gno-assertions or -gsupported-assertions" + " to turn this message off."); } $$ = 0; } | assert_or_assume K_property '(' property_spec ')' K_else statement_or_null { /* */ - if (gn_assertions_flag) { + if (gn_unsupported_assertions_flag) { yyerror(@1, "sorry: concurrent_assertion_item not supported." - " Try -gno-assertion to turn this message off."); + " Try -gno-assertions or -gsupported-assertions" + " to turn this message off."); } $$ = 0; } | assert_or_assume K_property '(' property_spec ')' statement_or_null K_else statement_or_null { /* */ - if (gn_assertions_flag) { + if (gn_unsupported_assertions_flag) { yyerror(@1, "sorry: concurrent_assertion_item not supported." - " Try -gno-assertion to turn this message off."); + " Try -gno-assertions or -gsupported-assertions" + " to turn this message off."); } $$ = 0; } | K_cover K_property '(' property_spec ')' statement_or_null { /* */ - if (gn_assertions_flag) { + if (gn_unsupported_assertions_flag) { yyerror(@1, "sorry: concurrent_assertion_item not supported." - " Try -gno-assertion to turn this message off."); + " Try -gno-assertions or -gsupported-assertions" + " to turn this message off."); } $$ = 0; } @@ -1039,17 +1043,19 @@ concurrent_assertion_statement /* IEEE1800-2012 A.2.10 */ They are syntactically identical. */ | K_cover K_sequence '(' property_spec ')' statement_or_null { /* */ - if (gn_assertions_flag) { + if (gn_unsupported_assertions_flag) { yyerror(@1, "sorry: concurrent_assertion_item not supported." - " Try -gno-assertion to turn this message off."); + " Try -gno-assertions or -gsupported-assertions" + " to turn this message off."); } $$ = 0; } | K_restrict K_property '(' property_spec ')' ';' { /* */ - if (gn_assertions_flag) { + if (gn_unsupported_assertions_flag) { yyerror(@2, "sorry: concurrent_assertion_item not supported." - " Try -gno-assertion to turn this message off."); + " Try -gno-assertions or -gsupported-assertions" + " to turn this message off."); } $$ = 0; } @@ -1261,9 +1267,10 @@ deferred_immediate_assertion_item /* IEEE1800-2012: A.6.10 */ deferred_immediate_assertion_statement /* IEEE1800-2012 A.6.10 */ : assert_or_assume deferred_mode '(' expression ')' statement_or_null %prec less_than_K_else { - if (gn_assertions_flag) { + if (gn_unsupported_assertions_flag) { yyerror(@1, "sorry: Deferred assertions are not supported." - " Try -gno-assertion to turn this message off."); + " Try -gno-assertions or -gsupported-assertions" + " to turn this message off."); } delete $4; delete $6; @@ -1271,9 +1278,10 @@ deferred_immediate_assertion_statement /* IEEE1800-2012 A.6.10 */ } | assert_or_assume deferred_mode '(' expression ')' K_else statement_or_null { - if (gn_assertions_flag) { + if (gn_unsupported_assertions_flag) { yyerror(@1, "sorry: Deferred assertions are not supported." - " Try -gno-assertion to turn this message off."); + " Try -gno-assertions or -gsupported-assertions" + " to turn this message off."); } delete $4; delete $7; @@ -1281,9 +1289,10 @@ deferred_immediate_assertion_statement /* IEEE1800-2012 A.6.10 */ } | assert_or_assume deferred_mode '(' expression ')' statement_or_null K_else statement_or_null { - if (gn_assertions_flag) { + if (gn_unsupported_assertions_flag) { yyerror(@1, "sorry: Deferred assertions are not supported." - " Try -gno-assertion to turn this message off."); + " Try -gno-assertions or -gsupported-assertions" + " to turn this message off."); } delete $4; delete $6; @@ -2071,7 +2080,7 @@ signing /* IEEE1800-2005: A.2.2.1 */ simple_immediate_assertion_statement /* IEEE1800-2012 A.6.10 */ : assert_or_assume '(' expression ')' statement_or_null %prec less_than_K_else { - if (gn_assertions_flag) { + if (gn_supported_assertions_flag) { listarg_list; PCallTask*tmp1 = new PCallTask(lex_strings.make("$error"), arg_list); FILE_NAME(tmp1, @1); @@ -2086,7 +2095,7 @@ simple_immediate_assertion_statement /* IEEE1800-2012 A.6.10 */ } | assert_or_assume '(' expression ')' K_else statement_or_null { - if (gn_assertions_flag) { + if (gn_supported_assertions_flag) { PCondit*tmp = new PCondit($3, 0, $6); FILE_NAME(tmp, @1); $$ = tmp; @@ -2098,7 +2107,7 @@ simple_immediate_assertion_statement /* IEEE1800-2012 A.6.10 */ } | assert_or_assume '(' expression ')' statement_or_null K_else statement_or_null { - if (gn_assertions_flag) { + if (gn_supported_assertions_flag) { PCondit*tmp = new PCondit($3, $5, $7); FILE_NAME(tmp, @1); $$ = tmp; From c9d849ed7b48ad908a1f09c3e663cbd3dba8432d Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 5 Oct 2019 13:41:50 +0100 Subject: [PATCH 06/11] Fix style in iverilog man page. --- driver/iverilog.man.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver/iverilog.man.in b/driver/iverilog.man.in index 8cad315f3..0f49fea4f 100644 --- a/driver/iverilog.man.in +++ b/driver/iverilog.man.in @@ -130,7 +130,7 @@ default, parts of the expression that do not depend on the changed input value(s) are not re-evaluated. If an expression contains a call to a function that doesn't depend solely on its input values or that has side effects, the resulting behavior will differ from that -required by the standard. Using \fI\-gstrict\-ca\-eval\fP will force +required by the standard. Using \fB\-gstrict\-ca\-eval\fP will force standard compliant behavior (with some loss in performance). .TP 8 .B -gstrict-expr-width\fI|\fP-gno-strict-expr-width From c86dc285cca1d60a183f6ea97ee43e7aff8da693 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 5 Oct 2019 20:10:11 +0100 Subject: [PATCH 07/11] Fix for br1004 - fully support class construction in variable initialisation. --- parse.y | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/parse.y b/parse.y index 0ff641c83..6f1165a2a 100644 --- a/parse.y +++ b/parse.y @@ -1743,12 +1743,10 @@ variable_decl_assignment /* IEEE1800-2005 A.2.3 */ delete[]$1; $$ = tmp; } - | IDENTIFIER '=' K_new '(' ')' + | IDENTIFIER '=' class_new { decl_assignment_t*tmp = new decl_assignment_t; tmp->name = lex_strings.make($1); - PENewClass*expr = new PENewClass; - FILE_NAME(expr, @3); - tmp->expr .reset(expr); + tmp->expr .reset($3); delete[]$1; $$ = tmp; } From 862010ac190652c0257a4cd5151accf4b7b93a0d Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 5 Oct 2019 20:11:38 +0100 Subject: [PATCH 08/11] SV does not require constant expression in variable initialisation. --- elaborate.cc | 2 -- pform.cc | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/elaborate.cc b/elaborate.cc index 0875929f3..4781893dc 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2321,8 +2321,6 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope, if (!is_constant_ || !rv) return rv; - if (dynamic_cast(rv)) return rv; - cerr << get_fileline() << ": error: " "The RHS expression must be constant." << endl; cerr << get_fileline() << " : " diff --git a/pform.cc b/pform.cc index d9772dd70..18b391f50 100644 --- a/pform.cc +++ b/pform.cc @@ -2507,7 +2507,7 @@ void pform_make_var_init(const struct vlltype&li, PEIdent*lval = new PEIdent(name); FILE_NAME(lval, li); - PAssign*ass = new PAssign(lval, expr, true); + PAssign*ass = new PAssign(lval, expr, !gn_system_verilog()); FILE_NAME(ass, li); lexical_scope->var_inits.push_back(ass); From 70da8db6b5d27934aa89ea0eff6c5e3339160633 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 5 Oct 2019 20:12:52 +0100 Subject: [PATCH 09/11] Fix assignment to scalar class property in tgt-vvp. --- tgt-vvp/stmt_assign.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 889371ee7..306530994 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -1084,8 +1084,8 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net) ivl_type_t prop_type = ivl_type_prop_type(sig_type, prop_idx); if (ivl_type_base(prop_type) == IVL_VT_BOOL) { - assert(ivl_type_packed_dimensions(prop_type) == 1); - assert(ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)); + assert(ivl_type_packed_dimensions(prop_type) == 0 + || ivl_type_packed_dimensions(prop_type) == 1 && ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)); draw_eval_vec4(rval); if (ivl_expr_value(rval)!=IVL_VT_BOOL) @@ -1097,8 +1097,8 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net) fprintf(vvp_out, " %%pop/obj 1, 0;\n"); } else if (ivl_type_base(prop_type) == IVL_VT_LOGIC) { - assert(ivl_type_packed_dimensions(prop_type) == 1); - assert(ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)); + assert(ivl_type_packed_dimensions(prop_type) == 0 + || ivl_type_packed_dimensions(prop_type) == 1 && ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)); draw_eval_vec4(rval); From b1699a27815e9f3742c4fb2c7f77e3facb2c61f5 Mon Sep 17 00:00:00 2001 From: Cary R Date: Sat, 5 Oct 2019 15:27:20 -0700 Subject: [PATCH 10/11] Fix two compiler warnings --- tgt-vvp/stmt_assign.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 306530994..b99bd6797 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -1084,8 +1084,9 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net) ivl_type_t prop_type = ivl_type_prop_type(sig_type, prop_idx); if (ivl_type_base(prop_type) == IVL_VT_BOOL) { - assert(ivl_type_packed_dimensions(prop_type) == 0 - || ivl_type_packed_dimensions(prop_type) == 1 && ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)); + assert(ivl_type_packed_dimensions(prop_type) == 0 || + (ivl_type_packed_dimensions(prop_type) == 1 && + ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0))); draw_eval_vec4(rval); if (ivl_expr_value(rval)!=IVL_VT_BOOL) @@ -1097,8 +1098,9 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net) fprintf(vvp_out, " %%pop/obj 1, 0;\n"); } else if (ivl_type_base(prop_type) == IVL_VT_LOGIC) { - assert(ivl_type_packed_dimensions(prop_type) == 0 - || ivl_type_packed_dimensions(prop_type) == 1 && ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)); + assert(ivl_type_packed_dimensions(prop_type) == 0 || + (ivl_type_packed_dimensions(prop_type) == 1 && + ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0))); draw_eval_vec4(rval); From befc91340c17e009acbe7b2b6f02888e2bbc5e31 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sat, 5 Oct 2019 16:23:04 -0700 Subject: [PATCH 11/11] Parse and elaborate unique and priority case statements The unique, unique0, and priority keywords can decorate case statements to tell the run time (or synthesis) to do extra tests (or make extra assumptions). These tests are not implemented in the vvp run time, but now the decorations make it to the code generators. --- Statement.cc | 4 ++-- Statement.h | 3 ++- design_dump.cc | 20 +++++++++++++--- elaborate.cc | 2 +- ivl_target.h | 10 ++++++++ net_proc.cc | 4 ++-- netlist.h | 8 ++++++- parse.y | 53 ++++++++++++++++++++++++++----------------- pform_dump.cc | 13 +++++++++++ t-dll-api.cc | 16 +++++++++++++ t-dll-proc.cc | 1 + t-dll.h | 1 + tgt-stub/statement.c | 18 ++++++++++++++- tgt-vvp/vvp_process.c | 7 ++++++ 14 files changed, 128 insertions(+), 32 deletions(-) diff --git a/Statement.cc b/Statement.cc index e5f5f169e..e200f7734 100644 --- a/Statement.cc +++ b/Statement.cc @@ -206,8 +206,8 @@ const pform_name_t& PCallTask::path() const return path_; } -PCase::PCase(NetCase::TYPE t, PExpr*ex, svector*l) -: type_(t), expr_(ex), items_(l) +PCase::PCase(ivl_case_quality_t q, NetCase::TYPE t, PExpr*ex, svector*l) +: quality_(q), type_(t), expr_(ex), items_(l) { } diff --git a/Statement.h b/Statement.h index ae5e162b6..92791d9d2 100644 --- a/Statement.h +++ b/Statement.h @@ -254,7 +254,7 @@ class PCase : public Statement { Statement*stat; }; - PCase(NetCase::TYPE, PExpr*ex, svector*); + PCase(ivl_case_quality_t, NetCase::TYPE, PExpr*ex, svector*); ~PCase(); virtual NetProc* elaborate(Design*des, NetScope*scope) const; @@ -263,6 +263,7 @@ class PCase : public Statement { virtual void dump(ostream&out, unsigned ind) const; private: + ivl_case_quality_t quality_; NetCase::TYPE type_; PExpr*expr_; diff --git a/design_dump.cc b/design_dump.cc index 88cf88bea..cf8c1d4f3 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -1150,15 +1150,29 @@ void NetBlock::dump(ostream&o, unsigned ind) const void NetCase::dump(ostream&o, unsigned ind) const { + o << setw(ind) << ""; + switch (quality_) { + case IVL_CASE_QUALITY_BASIC: + break; + case IVL_CASE_QUALITY_UNIQUE: + o << "unique "; + break; + case IVL_CASE_QUALITY_UNIQUE0: + o << "unique0 "; + break; + case IVL_CASE_QUALITY_PRIORITY: + o << "priority "; + break; + } switch (type_) { case EQ: - o << setw(ind) << "" << "case (" << *expr_ << ")" << endl; + o << "case (" << *expr_ << ")" << endl; break; case EQX: - o << setw(ind) << "" << "casex (" << *expr_ << ")" << endl; + o << "casex (" << *expr_ << ")" << endl; break; case EQZ: - o << setw(ind) << "" << "casez (" << *expr_ << ")" << endl; + o << "casez (" << *expr_ << ")" << endl; break; } diff --git a/elaborate.cc b/elaborate.cc index 4781893dc..5af51cc64 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -3127,7 +3127,7 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const icount += cur->expr.size(); } - NetCase*res = new NetCase(type_, expr, icount); + NetCase*res = new NetCase(quality_, type_, expr, icount); res->set_line(*this); /* Iterate over all the case items (guard/statement pairs) diff --git a/ivl_target.h b/ivl_target.h index 30ae0194f..f0ee992e9 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -434,6 +434,14 @@ typedef enum ivl_statement_type_e { IVL_ST_WHILE = 23 } ivl_statement_type_t; +/* Case statements can be tagged as unique/unique0/priority. */ +typedef enum ivl_case_quality_t { + IVL_CASE_QUALITY_BASIC = 0, /* no quality flags */ + IVL_CASE_QUALITY_UNIQUE = 1, + IVL_CASE_QUALITY_UNIQUE0 = 2, + IVL_CASE_QUALITY_PRIORITY = 3 +} ivl_case_quality_t; + /* SystemVerilog allows a system function to be called as a task. */ typedef enum ivl_sfunc_as_task_e { IVL_SFUNC_AS_TASK_ERROR = 0, @@ -2222,6 +2230,8 @@ extern ivl_scope_t ivl_stmt_call(ivl_statement_t net); extern unsigned ivl_stmt_case_count(ivl_statement_t net); /* IVL_ST_CASE,IVL_ST_CASER,IVL_ST_CASEX,IVL_ST_CASEZ */ extern ivl_expr_t ivl_stmt_case_expr(ivl_statement_t net, unsigned i); + /* IVL+ST_CASE,IVL_ST_CASER,IVL_ST_CASEX,IVL_ST_CASEZ */ +extern ivl_case_quality_t ivl_stmt_case_quality(ivl_statement_t net); /* IVL_ST_CASE,IVL_ST_CASER,IVL_ST_CASEX,IVL_ST_CASEZ */ extern ivl_statement_t ivl_stmt_case_stmt(ivl_statement_t net, unsigned i); /* IVL_ST_CONDIT IVL_ST_CASE IVL_ST_REPEAT IVL_ST_WHILE */ diff --git a/net_proc.cc b/net_proc.cc index 68127445f..b82abe8f1 100644 --- a/net_proc.cc +++ b/net_proc.cc @@ -83,8 +83,8 @@ const NetProc* NetBlock::proc_next(const NetProc*cur) const return cur->next_; } -NetCase::NetCase(NetCase::TYPE c, NetExpr*ex, unsigned cnt) -: type_(c), expr_(ex), items_(cnt) +NetCase::NetCase(ivl_case_quality_t q, NetCase::TYPE c, NetExpr*ex, unsigned cnt) +: quality_(q), type_(c), expr_(ex), items_(cnt) { ivl_assert(*this, expr_); } diff --git a/netlist.h b/netlist.h index 6b85a5a2a..37ed539b7 100644 --- a/netlist.h +++ b/netlist.h @@ -3050,6 +3050,9 @@ class NetBlock : public NetProc { * way the comparisons are performed. Also, it is likely that the * target may be able to optimize differently. * + * Case statements can have unique, unique0, or priority attached to + * them. If not otherwise adorned, it is QBASIC. + * * Case can be one of three types: * EQ -- All bits must exactly match * EQZ -- z bits are don't care @@ -3059,13 +3062,15 @@ class NetCase : public NetProc { public: enum TYPE { EQ, EQX, EQZ }; - NetCase(TYPE c, NetExpr*ex, unsigned cnt); + + NetCase(ivl_case_quality_t q, TYPE c, NetExpr*ex, unsigned cnt); ~NetCase(); void set_case(unsigned idx, NetExpr*ex, NetProc*st); void prune(); + inline ivl_case_quality_t case_quality() const { return quality_; } TYPE type() const; const NetExpr*expr() const { return expr_; } inline unsigned nitems() const { return items_.size(); } @@ -3097,6 +3102,7 @@ class NetCase : public NetProc { NexusSet&nex_map, NetBus&nex_out, NetBus&enables, vector&bitmasks); + ivl_case_quality_t quality_; TYPE type_; struct Item { diff --git a/parse.y b/parse.y index 6f1165a2a..e0152f763 100644 --- a/parse.y +++ b/parse.y @@ -408,6 +408,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector svector*event_expr; + ivl_case_quality_t case_quality; NetNet::Type nettype; PGBuiltin::Type gatetype; NetNet::PortType porttype; @@ -677,6 +678,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %type lifetime lifetime_opt +%type unique_priority + %token K_TAND %right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ %right K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ @@ -6618,27 +6621,28 @@ statement_item /* This is roughly statement_item in the LRM */ | jump_statement { $$ = $1; } - | K_case '(' expression ')' case_items K_endcase - { PCase*tmp = new PCase(NetCase::EQ, $3, $5); - FILE_NAME(tmp, @1); - $$ = tmp; - } - | K_casex '(' expression ')' case_items K_endcase - { PCase*tmp = new PCase(NetCase::EQX, $3, $5); - FILE_NAME(tmp, @1); - $$ = tmp; - } - | K_casez '(' expression ')' case_items K_endcase - { PCase*tmp = new PCase(NetCase::EQZ, $3, $5); - FILE_NAME(tmp, @1); - $$ = tmp; - } - | K_case '(' expression ')' error K_endcase - { yyerrok; } - | K_casex '(' expression ')' error K_endcase - { yyerrok; } - | K_casez '(' expression ')' error K_endcase - { yyerrok; } + | unique_priority K_case '(' expression ')' case_items K_endcase + { PCase*tmp = new PCase($1, NetCase::EQ, $4, $6); + FILE_NAME(tmp, @2); + $$ = tmp; + } + | unique_priority K_casex '(' expression ')' case_items K_endcase + { PCase*tmp = new PCase($1, NetCase::EQX, $4, $6); + FILE_NAME(tmp, @2); + $$ = tmp; + } + | unique_priority K_casez '(' expression ')' case_items K_endcase + { PCase*tmp = new PCase($1, NetCase::EQZ, $4, $6); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | unique_priority K_case '(' expression ')' error K_endcase + { yyerrok; } + | unique_priority K_casex '(' expression ')' error K_endcase + { yyerrok; } + | unique_priority K_casez '(' expression ')' error K_endcase + { yyerrok; } + | K_if '(' expression ')' statement_or_null %prec less_than_K_else { PCondit*tmp = new PCondit($3, $5, 0); FILE_NAME(tmp, @1); @@ -7293,6 +7297,13 @@ udp_primitive } ; +unique_priority + : { $$ = IVL_CASE_QUALITY_BASIC; } + | K_unique { $$ = IVL_CASE_QUALITY_UNIQUE; } + | K_unique0 { $$ = IVL_CASE_QUALITY_UNIQUE0; } + | K_priority { $$ = IVL_CASE_QUALITY_PRIORITY; } + ; + /* Many keywords can be optional in the syntax, although their presence is significant. This is a fairly common pattern so collect those rules here. */ diff --git a/pform_dump.cc b/pform_dump.cc index 97a6f13af..099271d0c 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -840,6 +840,19 @@ void PCallTask::dump(ostream&out, unsigned ind) const void PCase::dump(ostream&out, unsigned ind) const { out << setw(ind) << ""; + switch (quality_) { + case IVL_CASE_QUALITY_BASIC: + break; + case IVL_CASE_QUALITY_UNIQUE: + out << "unique "; + break; + case IVL_CASE_QUALITY_UNIQUE0: + out << "unique0 "; + break; + case IVL_CASE_QUALITY_PRIORITY: + out << "priority "; + break; + } switch (type_) { case NetCase::EQ: out << "case"; diff --git a/t-dll-api.cc b/t-dll-api.cc index 89b0a5aa2..12b829cca 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -2728,6 +2728,22 @@ extern "C" ivl_expr_t ivl_stmt_case_expr(ivl_statement_t net, unsigned idx) } } +extern "C" ivl_case_quality_t ivl_stmt_case_quality(ivl_statement_t net) +{ + assert(net); + switch (net->type_) { + case IVL_ST_CASE: + case IVL_ST_CASER: + case IVL_ST_CASEX: + case IVL_ST_CASEZ: + return net->u_.case_.quality; + + default: + assert(0); + return IVL_CASE_QUALITY_BASIC; + } +} + extern "C" ivl_statement_t ivl_stmt_case_stmt(ivl_statement_t net, unsigned idx) { assert(net); diff --git a/t-dll-proc.cc b/t-dll-proc.cc index ba0d4b1a0..ca61064e3 100644 --- a/t-dll-proc.cc +++ b/t-dll-proc.cc @@ -497,6 +497,7 @@ void dll_target::proc_case(const NetCase*net) } assert(stmt_cur_->type_ != IVL_ST_NONE); + stmt_cur_->u_.case_.quality = net->case_quality(); assert(expr_ == 0); assert(net->expr()); net->expr()->expr_scan(this); diff --git a/t-dll.h b/t-dll.h index 879a5c966..98d041e00 100644 --- a/t-dll.h +++ b/t-dll.h @@ -810,6 +810,7 @@ struct ivl_statement_s { } block_; struct { /* IVL_ST_CASE, IVL_ST_CASEX, IVL_ST_CASEZ */ + ivl_case_quality_t quality; ivl_expr_t cond; unsigned ncase; ivl_expr_t*case_ex; diff --git a/tgt-stub/statement.c b/tgt-stub/statement.c index 4eb8037a2..d52d8db4d 100644 --- a/tgt-stub/statement.c +++ b/tgt-stub/statement.c @@ -375,8 +375,24 @@ void show_statement(ivl_statement_t net, unsigned ind) case IVL_ST_CASEZ: case IVL_ST_CASER: case IVL_ST_CASE: { + ivl_case_quality_t qual = ivl_stmt_case_quality(net); unsigned cnt = ivl_stmt_case_count(net); - fprintf(out, "%*scase (...) <%u cases>\n", ind, "", cnt); + const char*qual_txt = ""; + switch (qual) { + case IVL_CASE_QUALITY_BASIC: + qual_txt = "basic"; + break; + case IVL_CASE_QUALITY_UNIQUE: + qual_txt = "unique"; + break; + case IVL_CASE_QUALITY_UNIQUE0: + qual_txt = "unique0"; + break; + case IVL_CASE_QUALITY_PRIORITY: + qual_txt = "priority"; + break; + } + fprintf(out, "%*scase (...) <%u cases, %s>\n", ind, "", cnt, qual_txt); show_expression(ivl_stmt_cond_expr(net), ind+4); for (idx = 0 ; idx < cnt ; idx += 1) { diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 407df5219..fb1f22400 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -644,6 +644,7 @@ static int show_stmt_block_named(ivl_statement_t net, ivl_scope_t scope) static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope) { int rc = 0; + ivl_case_quality_t qual = ivl_stmt_case_quality(net); ivl_expr_t expr = ivl_stmt_cond_expr(net); unsigned count = ivl_stmt_case_count(net); @@ -651,6 +652,12 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope) unsigned idx, default_case; + if (qual != IVL_CASE_QUALITY_BASIC) { + fprintf(stderr, "%s:%u: tgt-vvp sorry: " + "Case unique/unique0/priority qualities are ignored.\n", + ivl_stmt_file(net), ivl_stmt_lineno(net)); + } + show_stmt_file_line(net, "Case statement."); local_count += count + 1;