forked from github/verilator
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:
parent
8e8f4b1e5c
commit
d42a2d6494
2
Changes
2
Changes
@ -13,6 +13,8 @@ Verilator 4.227 devel
|
|||||||
|
|
||||||
**Minor:**
|
**Minor:**
|
||||||
|
|
||||||
|
Fix crash in gate optimization of circular logic (#3543). [Bill Flynn]
|
||||||
|
|
||||||
|
|
||||||
Verilator 4.226 2022-08-31
|
Verilator 4.226 2022-08-31
|
||||||
==========================
|
==========================
|
||||||
|
@ -985,11 +985,18 @@ static void eliminate(AstNode* logicp,
|
|||||||
const std::unordered_map<AstVarScope*, AstNode*>& substitutions,
|
const std::unordered_map<AstVarScope*, AstNode*>& substitutions,
|
||||||
GateDedupeVarVisitor* varVisp) {
|
GateDedupeVarVisitor* varVisp) {
|
||||||
|
|
||||||
const std::function<void(AstNodeVarRef*)> visit
|
// Recursion filter holding already replaced variables
|
||||||
= [&substitutions, &visit, varVisp](AstNodeVarRef* nodep) -> void {
|
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
|
// 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;
|
if (it == substitutions.end()) return;
|
||||||
|
|
||||||
|
// Do not substitute circular logic
|
||||||
|
if (!replaced.insert(vscp).second) return;
|
||||||
|
|
||||||
AstNode* const substp = it->second;
|
AstNode* const substp = it->second;
|
||||||
|
|
||||||
// Substitute in the new tree
|
// Substitute in the new tree
|
||||||
@ -1016,6 +1023,9 @@ static void eliminate(AstNode* logicp,
|
|||||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||||
// Recursively substitute the new tree
|
// Recursively substitute the new tree
|
||||||
newp->foreach<AstNodeVarRef>(visit);
|
newp->foreach<AstNodeVarRef>(visit);
|
||||||
|
|
||||||
|
// Remove from recursion filter
|
||||||
|
replaced.erase(vscp);
|
||||||
};
|
};
|
||||||
|
|
||||||
logicp->foreach<AstNodeVarRef>(visit);
|
logicp->foreach<AstNodeVarRef>(visit);
|
||||||
|
18
test_regress/t/t_gate_loop.pl
Executable file
18
test_regress/t/t_gate_loop.pl
Executable 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;
|
14
test_regress/t/t_gate_loop.v
Normal file
14
test_regress/t/t_gate_loop.v
Normal 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
|
Loading…
Reference in New Issue
Block a user