Fix false unique assertions on `else ;` (#6450).

This commit is contained in:
Wilson Snyder 2025-09-17 17:43:21 -04:00
parent 0e2f0381d0
commit 57c82b9c34
5 changed files with 96 additions and 2 deletions

View File

@ -51,6 +51,7 @@ Verilator 5.041 devel
* Fix internal error on out-of-bounds real array access.
* Fix pre/post increments in assertions (#6434).
* Fix elaboration displays with `%m` (#6445). [Alex Solomatnikov]
* Fix false unique assertions on `else ;` (#6450). [Don Owen]
Verilator 5.040 2025-08-30

View File

@ -248,6 +248,13 @@ public:
return nump;
}
// For 'unique if' cannot have empty else statements as then assertion
// would misfire
AstNode* newBlock(FileLine* fl, AstNode* nodep) {
if (nodep) return nodep;
return new AstBegin{fl, "", nullptr, false, true};
}
// Bison sometimes needs error context without a token, so remember last token's line
// Only use this if do not have and cannot get a token-relevant fileline
FileLine* bisonLastFileline() const { return m_bisonLastFileline; }

View File

@ -3522,13 +3522,16 @@ statement_item<nodep>: // IEEE: statement_item
//
// // IEEE: conditional_statement
| unique_priorityE yIF '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE
{ AstIf* const newp = new AstIf{$2, $4, $6};
{ AstIf* const newp = new AstIf{$2, $4,
PARSEP->newBlock($2, $6)};
$$ = newp;
if ($1 == uniq_UNIQUE) newp->uniquePragma(true);
if ($1 == uniq_UNIQUE0) newp->unique0Pragma(true);
if ($1 == uniq_PRIORITY) newp->priorityPragma(true); }
| unique_priorityE yIF '(' expr ')' stmtBlock yELSE stmtBlock
{ AstIf* const newp = new AstIf{$2, $4, $6, $8};
{ AstIf* const newp = new AstIf{$2, $4,
PARSEP->newBlock($2, $6),
PARSEP->newBlock($2, $8)};
$$ = newp;
if ($1 == uniq_UNIQUE) newp->uniquePragma(true);
if ($1 == uniq_UNIQUE0) newp->unique0Pragma(true);

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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
import vltest_bootstrap
test.scenarios('simulator_st')
test.compile(verilator_flags2=['--binary'])
test.execute()
test.passes()

View File

@ -0,0 +1,65 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
// verilog_format: off
`define stop $stop
`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);
// verilog_format: on
module t;
logic clk;
logic A, B, C;
logic reset;
logic x;
always #1 clk = ~clk;
initial begin
clk = 0;
reset = 0;
A = 0;
B = 0;
C = 0;
#10;
reset = 1;
#2;
A = 1;
#2;
`checkd(x, 1'b0);
#2;
B = 1;
#2;
`checkd(x, 1'b0);
#2;
B = 0;
C = 1;
#2;
`checkd(x, 1'b1);
#10;
$finish;
end
always_ff @(posedge clk or negedge reset) begin
if (!reset) begin
x <= '0;
end
else if (A) begin
unique if (B) begin
x <= '0;
end
else if (C) begin
x <= '1;
end
// This passes:
// else begin end
else; // For unique if to not have a false positive
end
end
endmodule