diff --git a/src/V3DfgAstToDfg.cpp b/src/V3DfgAstToDfg.cpp index d81ecbfb3..b9445d674 100644 --- a/src/V3DfgAstToDfg.cpp +++ b/src/V3DfgAstToDfg.cpp @@ -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); }); } diff --git a/src/V3DfgDfgToAst.cpp b/src/V3DfgDfgToAst.cpp index 32fb87b8f..315088dec 100644 --- a/src/V3DfgDfgToAst.cpp +++ b/src/V3DfgDfgToAst.cpp @@ -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); }); diff --git a/src/V3DfgOptimizer.cpp b/src/V3DfgOptimizer.cpp index f093b453d..d3b2eba4f 100644 --- a/src/V3DfgOptimizer.cpp +++ b/src/V3DfgOptimizer.cpp @@ -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); }); diff --git a/src/V3DfgVertices.h b/src/V3DfgVertices.h index 5c3700308..a440f9b8d 100644 --- a/src/V3DfgVertices.h +++ b/src/V3DfgVertices.h @@ -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; } diff --git a/test_regress/t/t_dfg_multidriver_non_dfg.pl b/test_regress/t/t_dfg_multidriver_non_dfg.pl new file mode 100755 index 000000000..84ae125be --- /dev/null +++ b/test_regress/t/t_dfg_multidriver_non_dfg.pl @@ -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; diff --git a/test_regress/t/t_dfg_multidriver_non_dfg.v b/test_regress/t/t_dfg_multidriver_non_dfg.v new file mode 100644 index 000000000..9fcb61b5e --- /dev/null +++ b/test_regress/t/t_dfg_multidriver_non_dfg.v @@ -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