diff --git a/Changes b/Changes index 4c45d300d..a5a16263e 100644 --- a/Changes +++ b/Changes @@ -13,9 +13,9 @@ Verilator 5.009 devel **Minor:** +* Support complicated IEEE 'for' assignments. * Support $fopen as an expression. - Verilator 5.008 2023-03-04 ========================== diff --git a/src/verilog.y b/src/verilog.y index d44c466ba..20ea127fc 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -3503,9 +3503,8 @@ statement_item: // IEEE: statement_item if ($1 == uniq_UNIQUE0) newp->unique0Pragma(true); if ($1 == uniq_PRIORITY) newp->priorityPragma(true); } // - | finc_or_dec_expression ';' { $$ = $1; } // // IEEE: inc_or_dec_expression - // // Below under expr + | finc_or_dec_expression ';' { $$ = $1; } // // // IEEE: subroutine_call_statement // // IEEE says we then expect a function call @@ -3530,18 +3529,8 @@ statement_item: // IEEE: statement_item FileLine* const newfl = new FileLine{$$->fileline()}; newfl->warnOff(V3ErrorCode::IGNOREDRETURN, true); $$->fileline(newfl); } - // // Expr included here to resolve our not knowing what is a method call - // // Expr here must result in a subroutine_call - | task_subroutine_callNoMethod ';' { $$ = $1->makeStmt(); } - //UNSUP fexpr '.' array_methodNoRoot ';' { UNSUP } - | fexpr '.' task_subroutine_callNoMethod ';' { $$ = (new AstDot{$2, false, $1, $3})->makeStmt(); } - | system_t_call ';' { $$ = $1; } - //UNSUP fexprScope ';' { UNSUP } - // // Not here in IEEE; from class_constructor_declaration - // // Because we've joined class_constructor_declaration into generic functions - // // Way over-permissive; - // // IEEE: [ ySUPER '.' yNEW [ '(' list_of_arguments ')' ] ';' ] - | fexpr '.' class_new ';' { $$ = (new AstDot{$2, false, $1, $3})->makeStmt(); } + // + | task_subroutine_callNoSemi ';' { $$ = $1; } // | statementVerilatorPragmas { $$ = $1; } // @@ -3933,18 +3922,11 @@ for_step: // IEEE: for_step | for_step ',' for_step_assignment { $$ = addNextNull($1, $3); } ; -for_step_assignment: // ==IEEE: for_step_assignment - //UNSUP operator_assignment { $$ = $1; } - // - //UNSUP inc_or_dec_expression { $$ = $1; } - // // IEEE: subroutine_call - //UNSUP function_subroutine_callNoMethod { $$ = $1; } - // // method_call:array_method requires a '.' - //UNSUP expr '.' array_methodNoRoot { } - //UNSUP exprScope { $$ = $1; } - //UNSUP remove below - genvar_iteration { $$ = $1; } - //UNSUP remove above +for_step_assignment: // ==IEEE: for_step_assignment + foperator_assignment { $$ = $1; } + | finc_or_dec_expression { $$ = $1; } + // // IEEE: function_subroutine_call + | task_subroutine_callNoSemi { $$ = $1; } ; loop_variables: // IEEE: loop_variables @@ -3981,6 +3963,19 @@ funcRef: // IEEE: part of tf_call //UNSUP: idDotted is really just id to allow dotted method calls ; +task_subroutine_callNoSemi: // similar to IEEE task_subroutine_call but without ';' + // // Expr included here to resolve our not knowing what is a method call + // // Expr here must result in a subroutine_call + task_subroutine_callNoMethod { $$ = $1->makeStmt(); } + | fexpr '.' task_subroutine_callNoMethod { $$ = (new AstDot{$2, false, $1, $3})->makeStmt(); } + | system_t_call { $$ = $1; } + // // Not here in IEEE; from class_constructor_declaration + // // Because we've joined class_constructor_declaration into generic functions + // // Way over-permissive; + // // IEEE: [ ySUPER '.' yNEW [ '(' list_of_arguments ')' ] ';' ] + | fexpr '.' class_new { $$ = (new AstDot{$2, false, $1, $3})->makeStmt(); } + ; + task_subroutine_callNoMethod: // function_subroutine_callNoMethod (as task) // // IEEE: tf_call taskRef { $$ = $1; } diff --git a/test_regress/t/t_for_assign.pl b/test_regress/t/t_for_assign.pl new file mode 100755 index 000000000..b46d46042 --- /dev/null +++ b/test_regress/t/t_for_assign.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_for_assign.v b/test_regress/t/t_for_assign.v new file mode 100644 index 000000000..61e0d6c85 --- /dev/null +++ b/test_regress/t/t_for_assign.v @@ -0,0 +1,42 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0); + +module t (/*AUTOARG*/); + + int a, b; + int sum; + // Complicated assignment cases + + initial begin + sum = 0; + for (integer a=0; a<3; ) begin + a = a + 1; + sum = sum + a; + end + `checkd(sum, 6); + + // foperator_assignment + sum = 0; + for (integer a=0; a<3; a=a+1, sum += a) ; + `checkd(sum, 6); + + // inc_or_dec_expression + sum = 0; + for (integer a=0; a<3; a++, ++sum) ; + `checkd(sum, 3); + + // task_subroutine_call + sum = 0; + for (integer a=0; a<3; a++, sum += $clog2(a)) ; + `checkd(sum, 3); + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule