Dfg: Fix crash on additional driver from non-DFG logic

Ensure variables written by non-DFG code are kept

Fixes #3740
This commit is contained in:
Geza Lore 2022-11-12 11:35:23 +00:00
parent 6736e92cdb
commit dbcaad99c5
6 changed files with 55 additions and 9 deletions

View File

@ -94,7 +94,10 @@ class AstToDfgVisitor final : public VNVisitor {
nodep->foreach([this](const AstVarRef* refp) {
// No need to (and in fact cannot) mark variables with unsupported dtypes
if (!DfgVertex::isSupportedDType(refp->varp()->dtypep())) return;
// Mark vertex as having a module reference outside current DFG
getNet(refp->varp())->setHasModRefs();
// Mark variable as written from non-DFG logic
if (refp->access().isWriteOrRW()) refp->varp()->user3(true);
});
}

View File

@ -415,14 +415,14 @@ class DfgToAstVisitor final : DfgVisitor {
// Remap all references to point to the canonical variables, if one exists
VNDeleter deleter;
m_modp->foreach([&](AstVarRef* refp) {
// Any variable that is written outside the DFG will have itself as the canonical
// var, so need not be replaced, furthermore, if a variable is traced, we don't
// want to update the write ref we just created above, so we only replace read only
// references.
if (!refp->access().isReadOnly()) return;
// Any variable that is written partially outside the DFG will have itself as the
// canonical var, so need not be replaced, furthermore, if a variable is traced, we
// don't want to update the write-refs we just created above, so we only replace
// read-only references to those variables to those variables we know are not written
// in non-DFG logic.
if (!refp->access().isReadOnly() || refp->varp()->user3()) return;
const auto it = m_canonVars.find(refp->varp());
if (it == m_canonVars.end()) return;
if (it->second == refp->varp()) return;
if (it == m_canonVars.end() || it->second == refp->varp()) return;
refp->replaceWith(new AstVarRef{refp->fileline(), it->second, refp->access()});
deleter.pushDeletep(refp);
});

View File

@ -244,9 +244,12 @@ void V3DfgOptimizer::optimize(AstNetlist* netlistp, const string& label) {
UINFO(2, __FUNCTION__ << ": " << endl);
// NODE STATE
// AstVar::user1 -> Used by V3DfgPasses::astToDfg
// AstVar::user2 -> bool: Flag indicating referenced by AstVarXRef
// AstVar::user1 -> Used by V3DfgPasses::astToDfg and DfgPassed::dfgToAst
// AstVar::user2 -> bool: Flag indicating referenced by AstVarXRef (set just below)
// AstVar::user3 -> bool: Flag indicating written by logic not representable as DFG
// (set by V3DfgPasses::astToDfg)
const VNUser2InUse user2InUse;
const VNUser3InUse user3InUse;
// Mark cross-referenced variables
netlistp->foreach([](const AstVarXRef* xrefp) { xrefp->varp()->user2(true); });

View File

@ -76,6 +76,8 @@ public:
if (v3Global.opt.trace() && varp()->isTrace()) return true;
// Keep if public
if (varp()->isSigPublic()) return true;
// Keep if written in non-DFG code
if (varp()->user3()) return true;
// Otherwise it can be removed
return false;
}

View File

@ -0,0 +1,16 @@
#!/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(vlt => 1);
compile();
ok(1);
1;

View File

@ -0,0 +1,22 @@
// 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
`default_nettype none
module t(
input wire i,
output wire o
);
logic a;
logic b;
initial begin
a = 1'd0;
b = 1'd0;
end
assign a = ~i;
assign b = a;
assign o = b;
endmodule