Fix V3Gate crash on circular logic

The recent patch to defer substitutions on V3Gate crashes on circular
logic that has cycle length >= 3 with all inlineable signals (cycle
length 2 is detected correctly and is not inlined). Fix by stopping
recursion at the loop-back edge.

Fixes #3543
This commit is contained in:
Geza Lore 2022-09-02 19:31:13 +01:00
parent 8e8f4b1e5c
commit d42a2d6494
4 changed files with 47 additions and 3 deletions

View File

@ -13,6 +13,8 @@ Verilator 4.227 devel
**Minor:**
Fix crash in gate optimization of circular logic (#3543). [Bill Flynn]
Verilator 4.226 2022-08-31
==========================

View File

@ -985,11 +985,18 @@ static void eliminate(AstNode* logicp,
const std::unordered_map<AstVarScope*, AstNode*>& substitutions,
GateDedupeVarVisitor* varVisp) {
const std::function<void(AstNodeVarRef*)> visit
= [&substitutions, &visit, varVisp](AstNodeVarRef* nodep) -> void {
// Recursion filter holding already replaced variables
std::unordered_set<const AstVarScope*> replaced(substitutions.size() * 2);
const std::function<void(AstNodeVarRef*)> visit = [&, varVisp](AstNodeVarRef* nodep) -> void {
// See if this variable has a substitution
const auto& it = substitutions.find(nodep->varScopep());
AstVarScope* const vscp = nodep->varScopep();
const auto& it = substitutions.find(vscp);
if (it == substitutions.end()) return;
// Do not substitute circular logic
if (!replaced.insert(vscp).second) return;
AstNode* const substp = it->second;
// Substitute in the new tree
@ -1016,6 +1023,9 @@ static void eliminate(AstNode* logicp,
VL_DO_DANGLING(nodep->deleteTree(), nodep);
// Recursively substitute the new tree
newp->foreach<AstNodeVarRef>(visit);
// Remove from recursion filter
replaced.erase(vscp);
};
logicp->foreach<AstNodeVarRef>(visit);

18
test_regress/t/t_gate_loop.pl Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2022 by Geza Lore. 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(
verilator_flags2 => ["-Wno-UNOPTFLAT"]
);
ok(1);
1;

View File

@ -0,0 +1,14 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Geza Lore.
// SPDX-License-Identifier: CC0-1.0
module t;
wire a;
wire b;
wire c;
assign a = b;
assign b = c;
assign c = a;
endmodule