diff --git a/Changes b/Changes index 939ed5694..a53b5fd16 100644 --- a/Changes +++ b/Changes @@ -112,6 +112,7 @@ Verilator 5.047 devel * Fix `disable iff` imply-delay statement linking (#7337). [Nick Brereton] * Fix lost `$stop` on implied assertion `$error` failures. * Fix wait() hang when interface uses process calls and VIF function (#7342). [Yilou Wang] +* Fix error on illegal nand/nor binary operators (#7353). Verilator 5.046 2026-02-28 diff --git a/src/verilog.y b/src/verilog.y index 2585fdc11..acf14048c 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -27,6 +27,7 @@ #define YYERROR_VERBOSE 1 // For prior to Bison 3.6 #define YYINITDEPTH 10000 // Older bisons ignore YYMAXDEPTH #define YYMAXDEPTH 10000 +#define YYNEWLINE "\n" // Pick up new lexer #define yylex PARSEP->tokenToBison @@ -5059,8 +5060,14 @@ expr: // IEEE: part of expression/constant_expression/ | ~l~expr '|' ~r~expr { $$ = new AstOr{$2, $1, $3}; } | ~l~expr '^' ~r~expr { $$ = new AstXor{$2, $1, $3}; } | ~l~expr yP_XNOR ~r~expr { $$ = new AstNot{$2, new AstXor{$2, $1, $3}}; } - | ~l~expr yP_NOR ~r~expr { $$ = new AstNot{$2, new AstOr{$2, $1, $3}}; } - | ~l~expr yP_NAND ~r~expr { $$ = new AstNot{$2, new AstAnd{$2, $1, $3}}; } + | ~l~expr yP_NOR ~r~expr + { $$ = new AstNot{$2, new AstOr{$2, $1, $3}}; + $2->v3error("Syntax error: '~|' is not a 'nor' binary operator, but a unary '~ |'" + << YYNEWLINE << $1->warnMore() << "... Suggest '~ (... | ...)'"); } + | ~l~expr yP_NAND ~r~expr + { $$ = new AstNot{$2, new AstAnd{$2, $1, $3}}; + $2->v3error("Syntax error: '~&' is not a 'nand' binary operator, but a unary '~ &'" + << YYNEWLINE << $1->warnMore() << "... Suggest '~ (... & ...)'"); } | ~l~expr yP_SLEFT ~r~expr { $$ = new AstShiftL{$2, $1, $3}; } | ~l~expr yP_SRIGHT ~r~expr { $$ = new AstShiftR{$2, $1, $3}; } | ~l~expr yP_SSRIGHT ~r~expr { $$ = new AstShiftRS{$2, $1, $3}; } diff --git a/test_regress/t/t_fuzz_nor_bad.out b/test_regress/t/t_fuzz_nor_bad.out new file mode 100644 index 000000000..92902350a --- /dev/null +++ b/test_regress/t/t_fuzz_nor_bad.out @@ -0,0 +1,10 @@ +%Error: t/t_fuzz_nor_bad.v:14:21: Syntax error: '~|' is not a 'nor' binary operator, but a unary '~ |' + : ... Suggest '~ (... | ...)' + 14 | assign out1 = var1~|var2; + | ^~ + ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. +%Error: t/t_fuzz_nor_bad.v:16:21: Syntax error: '~&' is not a 'nand' binary operator, but a unary '~ &' + : ... Suggest '~ (... & ...)' + 16 | assign out2 = var1~&var2; + | ^~ +%Error: Exiting due to diff --git a/test_regress/t/t_fuzz_nor_bad.py b/test_regress/t/t_fuzz_nor_bad.py new file mode 100755 index 000000000..c7d9b21a5 --- /dev/null +++ b/test_regress/t/t_fuzz_nor_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# 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-FileCopyrightText: 2024 Wilson Snyder +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_fuzz_nor_bad.v b/test_regress/t/t_fuzz_nor_bad.v new file mode 100644 index 000000000..cb20fc9e2 --- /dev/null +++ b/test_regress/t/t_fuzz_nor_bad.v @@ -0,0 +1,20 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Wilson Snyder +// SPDX-License-Identifier: CC0-1.0 + +module bug_reduction_nor_binary ( + input logic [3:0] var1, + input logic [3:0] var2, + output logic [3:0] out1, + output logic [3:0] out2 +); + + assign out1 = var1~|var2; //< ~| is a unary reduction operator, not a binary infix operator + + assign out2 = var1~&var2; //< ~& is a unary reduction operator, not a binary infix operator + + // ~^ is legal + +endmodule