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:**
|
||||
|
||||
Fix crash in gate optimization of circular logic (#3543). [Bill Flynn]
|
||||
|
||||
|
||||
Verilator 4.226 2022-08-31
|
||||
==========================
|
||||
|
@ -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
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