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:
parent
6736e92cdb
commit
dbcaad99c5
|
|
@ -94,7 +94,10 @@ class AstToDfgVisitor final : public VNVisitor {
|
||||||
nodep->foreach([this](const AstVarRef* refp) {
|
nodep->foreach([this](const AstVarRef* refp) {
|
||||||
// No need to (and in fact cannot) mark variables with unsupported dtypes
|
// No need to (and in fact cannot) mark variables with unsupported dtypes
|
||||||
if (!DfgVertex::isSupportedDType(refp->varp()->dtypep())) return;
|
if (!DfgVertex::isSupportedDType(refp->varp()->dtypep())) return;
|
||||||
|
// Mark vertex as having a module reference outside current DFG
|
||||||
getNet(refp->varp())->setHasModRefs();
|
getNet(refp->varp())->setHasModRefs();
|
||||||
|
// Mark variable as written from non-DFG logic
|
||||||
|
if (refp->access().isWriteOrRW()) refp->varp()->user3(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -415,14 +415,14 @@ class DfgToAstVisitor final : DfgVisitor {
|
||||||
// Remap all references to point to the canonical variables, if one exists
|
// Remap all references to point to the canonical variables, if one exists
|
||||||
VNDeleter deleter;
|
VNDeleter deleter;
|
||||||
m_modp->foreach([&](AstVarRef* refp) {
|
m_modp->foreach([&](AstVarRef* refp) {
|
||||||
// Any variable that is written outside the DFG will have itself as the canonical
|
// Any variable that is written partially outside the DFG will have itself as the
|
||||||
// var, so need not be replaced, furthermore, if a variable is traced, we don't
|
// canonical var, so need not be replaced, furthermore, if a variable is traced, we
|
||||||
// want to update the write ref we just created above, so we only replace read only
|
// don't want to update the write-refs we just created above, so we only replace
|
||||||
// references.
|
// read-only references to those variables to those variables we know are not written
|
||||||
if (!refp->access().isReadOnly()) return;
|
// in non-DFG logic.
|
||||||
|
if (!refp->access().isReadOnly() || refp->varp()->user3()) return;
|
||||||
const auto it = m_canonVars.find(refp->varp());
|
const auto it = m_canonVars.find(refp->varp());
|
||||||
if (it == m_canonVars.end()) return;
|
if (it == m_canonVars.end() || it->second == refp->varp()) return;
|
||||||
if (it->second == refp->varp()) return;
|
|
||||||
refp->replaceWith(new AstVarRef{refp->fileline(), it->second, refp->access()});
|
refp->replaceWith(new AstVarRef{refp->fileline(), it->second, refp->access()});
|
||||||
deleter.pushDeletep(refp);
|
deleter.pushDeletep(refp);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -244,9 +244,12 @@ void V3DfgOptimizer::optimize(AstNetlist* netlistp, const string& label) {
|
||||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||||
|
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
// AstVar::user1 -> Used by V3DfgPasses::astToDfg
|
// AstVar::user1 -> Used by V3DfgPasses::astToDfg and DfgPassed::dfgToAst
|
||||||
// AstVar::user2 -> bool: Flag indicating referenced by AstVarXRef
|
// 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 VNUser2InUse user2InUse;
|
||||||
|
const VNUser3InUse user3InUse;
|
||||||
|
|
||||||
// Mark cross-referenced variables
|
// Mark cross-referenced variables
|
||||||
netlistp->foreach([](const AstVarXRef* xrefp) { xrefp->varp()->user2(true); });
|
netlistp->foreach([](const AstVarXRef* xrefp) { xrefp->varp()->user2(true); });
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,8 @@ public:
|
||||||
if (v3Global.opt.trace() && varp()->isTrace()) return true;
|
if (v3Global.opt.trace() && varp()->isTrace()) return true;
|
||||||
// Keep if public
|
// Keep if public
|
||||||
if (varp()->isSigPublic()) return true;
|
if (varp()->isSigPublic()) return true;
|
||||||
|
// Keep if written in non-DFG code
|
||||||
|
if (varp()->user3()) return true;
|
||||||
// Otherwise it can be removed
|
// Otherwise it can be removed
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue