Refactor Dfg variable flags (#6259)

Store all flags in a DfgVertexVar relating to the underlying
AstVar/AstVarScope stored via AstNode::user1(). user2/user3/user4 are
then usable by DFG algorithms as needed.
This commit is contained in:
Geza Lore 2025-08-05 10:24:54 +01:00 committed by GitHub
parent d415757b0e
commit d2edab458e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 102 additions and 136 deletions

View File

@ -77,10 +77,6 @@ std::unique_ptr<DfgGraph> DfgGraph::clone() const {
break; break;
} }
} }
if (vp->hasDfgRefs()) cp->setHasDfgRefs();
if (vp->hasModRefs()) cp->setHasModRefs();
if (vp->hasExtRefs()) cp->setHasExtRefs();
} }
// Clone operation vertices // Clone operation vertices
for (const DfgVertex& vtx : m_opVertices) { for (const DfgVertex& vtx : m_opVertices) {
@ -262,8 +258,6 @@ static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {
os << ", shape=box, style=filled, fillcolor=darkorange1"; // Orange os << ", shape=box, style=filled, fillcolor=darkorange1"; // Orange
} else if (varVtxp->hasDfgRefs()) { } else if (varVtxp->hasDfgRefs()) {
os << ", shape=box, style=filled, fillcolor=gold2"; // Yellow os << ", shape=box, style=filled, fillcolor=gold2"; // Yellow
} else if (varVtxp->keep()) {
os << ", shape=box, style=filled, fillcolor=grey";
} else { } else {
os << ", shape=box"; os << ", shape=box";
} }
@ -290,8 +284,6 @@ static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {
os << ", shape=box3d, style=filled, fillcolor=darkorange1"; // Orange os << ", shape=box3d, style=filled, fillcolor=darkorange1"; // Orange
} else if (arrVtxp->hasDfgRefs()) { } else if (arrVtxp->hasDfgRefs()) {
os << ", shape=box3d, style=filled, fillcolor=gold2"; // Yellow os << ", shape=box3d, style=filled, fillcolor=gold2"; // Yellow
} else if (arrVtxp->keep()) {
os << ", shape=box3d, style=filled, fillcolor=grey";
} else { } else {
os << ", shape=box3d"; os << ", shape=box3d";
} }
@ -597,16 +589,23 @@ DfgVertexVar* DfgVertex::getResultVar() {
resp = varp; resp = varp;
return; return;
} }
// Prefer those variables that must be kept anyway // Prefer those variables that must be kept anyway
const bool keepOld = resp->keep() || resp->hasDfgRefs(); if (resp->hasExtRefs() != varp->hasExtRefs()) {
const bool keepNew = varp->keep() || varp->hasDfgRefs(); if (!resp->hasExtRefs()) resp = varp;
if (keepOld != keepNew) { return;
if (!keepOld) resp = varp; }
if (resp->hasModWrRefs() != varp->hasModWrRefs()) {
if (!resp->hasModWrRefs()) resp = varp;
return;
}
if (resp->hasDfgRefs() != varp->hasDfgRefs()) {
if (!resp->hasDfgRefs()) resp = varp;
return; return;
} }
// Prefer those that already have module references // Prefer those that already have module references
if (resp->hasModRefs() != varp->hasModRefs()) { if (resp->hasModRdRefs() != varp->hasModRdRefs()) {
if (!resp->hasModRefs()) resp = varp; if (!resp->hasModRdRefs()) resp = varp;
return; return;
} }
// Prefer the earlier one in source order // Prefer the earlier one in source order

View File

@ -87,8 +87,8 @@ template <bool T_Scoped>
class AstToDfgVisitor final : public VNVisitor { class AstToDfgVisitor final : public VNVisitor {
// NODE STATE // NODE STATE
// AstNode::user1p // DfgVertex for this AstNode // AstNode::user2p // DfgVertex for this AstNode
const VNUser1InUse m_user1InUse; const VNUser2InUse m_user2InUse;
// TYPES // TYPES
using RootType = std::conditional_t<T_Scoped, AstNetlist, AstModule>; using RootType = std::conditional_t<T_Scoped, AstNetlist, AstModule>;
@ -124,15 +124,12 @@ class AstToDfgVisitor final : public VNVisitor {
} }
void markReferenced(AstNode* nodep) { void markReferenced(AstNode* nodep) {
nodep->foreach([this](const AstVarRef* refp) { nodep->foreach([](const AstVarRef* refp) {
// No need to (and in fact cannot) mark variables if:
if (!DfgVertex::isSupportedDType(refp->varp()->dtypep())) return; // unsupported type
if (refp->varp()->isSc()) return; // SystemC
VariableType* const tgtp = getTarget(refp); VariableType* const tgtp = getTarget(refp);
// Mark vertex as having a module reference outside current DFG // Mark as read from non-DFG logic
getNet(tgtp)->setHasModRefs(); if (refp->access().isReadOrRW()) DfgVertexVar::setHasModRdRefs(tgtp);
// Mark variable as written from non-DFG logic // Mark as written from non-DFG logic
if (refp->access().isWriteOrRW()) tgtp->user3(true); if (refp->access().isWriteOrRW()) DfgVertexVar::setHasModWrRefs(tgtp);
}); });
} }
@ -144,27 +141,27 @@ class AstToDfgVisitor final : public VNVisitor {
} }
DfgVertexVar* getNet(VariableType* vp) { DfgVertexVar* getNet(VariableType* vp) {
if (!vp->user1p()) { if (!vp->user2p()) {
// vp DfgVertexVar vertices are not added to m_uncommittedVertices, because we // vp DfgVertexVar vertices are not added to m_uncommittedVertices, because we
// want to hold onto them via AstVar::user1p, and the AstVar might be referenced via // want to hold onto them via AstVar::user2p, and the AstVar might be referenced via
// multiple AstVarRef instances, so we will never revert a DfgVertexVar once // multiple AstVarRef instances, so we will never revert a DfgVertexVar once
// created. We will delete unconnected variable vertices at the end. // created. We will delete unconnected variable vertices at the end.
if (VN_IS(vp->dtypep()->skipRefp(), UnpackArrayDType)) { if (VN_IS(vp->dtypep()->skipRefp(), UnpackArrayDType)) {
DfgVarArray* const vtxp = new DfgVarArray{*m_dfgp, vp}; DfgVarArray* const vtxp = new DfgVarArray{*m_dfgp, vp};
vp->user1p(); vp->user2p();
m_varArrayps.push_back(vtxp); m_varArrayps.push_back(vtxp);
vp->user1p(vtxp); vp->user2p(vtxp);
} else { } else {
DfgVarPacked* const vtxp = new DfgVarPacked{*m_dfgp, vp}; DfgVarPacked* const vtxp = new DfgVarPacked{*m_dfgp, vp};
m_varPackedps.push_back(vtxp); m_varPackedps.push_back(vtxp);
vp->user1p(vtxp); vp->user2p(vtxp);
} }
} }
return vp->user1u().template to<DfgVertexVar*>(); return vp->user2u().template to<DfgVertexVar*>();
} }
DfgVertex* getVertex(AstNode* nodep) { DfgVertex* getVertex(AstNode* nodep) {
DfgVertex* vtxp = nodep->user1u().to<DfgVertex*>(); DfgVertex* vtxp = nodep->user2u().to<DfgVertex*>();
UASSERT_OBJ(vtxp, nodep, "Missing Dfg vertex"); UASSERT_OBJ(vtxp, nodep, "Missing Dfg vertex");
return vtxp; return vtxp;
} }
@ -713,42 +710,6 @@ class AstToDfgVisitor final : public VNVisitor {
void visit(AstCell* nodep) override { markReferenced(nodep); } void visit(AstCell* nodep) override { markReferenced(nodep); }
void visit(AstNodeProcedure* nodep) override { markReferenced(nodep); } void visit(AstNodeProcedure* nodep) override { markReferenced(nodep); }
void visit(AstVar* nodep) override {
if VL_CONSTEXPR_CXX17 (T_Scoped) {
return;
} else {
if (nodep->isSc()) return;
// No need to (and in fact cannot) handle variables with unsupported dtypes
if (!DfgVertex::isSupportedDType(nodep->dtypep())) return;
// Mark variables with external references
if (nodep->isIO() // Ports
|| nodep->user2() // Target of a hierarchical reference
|| nodep->isForced() // Forced
) {
getNet(reinterpret_cast<VariableType*>(nodep))->setHasExtRefs();
}
}
}
void visit(AstVarScope* nodep) override {
if VL_CONSTEXPR_CXX17 (!T_Scoped) {
return;
} else {
if (nodep->varp()->isSc()) return;
// No need to (and in fact cannot) handle variables with unsupported dtypes
if (!DfgVertex::isSupportedDType(nodep->dtypep())) return;
// Mark variables with external references
if (nodep->varp()->isIO() // Ports
|| nodep->user2() // Target of a hierarchical reference
|| nodep->varp()->isForced() // Forced
) {
getNet(reinterpret_cast<VariableType*>(nodep))->setHasExtRefs();
}
}
}
void visit(AstAssignW* nodep) override { void visit(AstAssignW* nodep) override {
++m_ctx.m_inputEquations; ++m_ctx.m_inputEquations;
@ -820,7 +781,7 @@ class AstToDfgVisitor final : public VNVisitor {
} }
void visit(AstVarRef* nodep) override { void visit(AstVarRef* nodep) override {
UASSERT_OBJ(!nodep->user1p(), nodep, "Already has Dfg vertex"); UASSERT_OBJ(!nodep->user2p(), nodep, "Already has Dfg vertex");
if (unhandled(nodep)) return; if (unhandled(nodep)) return;
if (nodep->access().isRW() // Cannot represent read-write references if (nodep->access().isRW() // Cannot represent read-write references
@ -853,19 +814,19 @@ class AstToDfgVisitor final : public VNVisitor {
return; return;
} }
nodep->user1p(getNet(getTarget(nodep))); nodep->user2p(getNet(getTarget(nodep)));
} }
void visit(AstConst* nodep) override { void visit(AstConst* nodep) override {
UASSERT_OBJ(!nodep->user1p(), nodep, "Already has Dfg vertex"); UASSERT_OBJ(!nodep->user2p(), nodep, "Already has Dfg vertex");
if (unhandled(nodep)) return; if (unhandled(nodep)) return;
DfgVertex* const vtxp = new DfgConst{*m_dfgp, nodep->fileline(), nodep->num()}; DfgVertex* const vtxp = new DfgConst{*m_dfgp, nodep->fileline(), nodep->num()};
m_uncommittedVertices.push_back(vtxp); m_uncommittedVertices.push_back(vtxp);
nodep->user1p(vtxp); nodep->user2p(vtxp);
} }
void visit(AstSel* nodep) override { void visit(AstSel* nodep) override {
UASSERT_OBJ(!nodep->user1p(), nodep, "Already has Dfg vertex"); UASSERT_OBJ(!nodep->user2p(), nodep, "Already has Dfg vertex");
if (unhandled(nodep)) return; if (unhandled(nodep)) return;
iterate(nodep->fromp()); iterate(nodep->fromp());
@ -875,19 +836,19 @@ class AstToDfgVisitor final : public VNVisitor {
DfgVertex* vtxp = nullptr; DfgVertex* vtxp = nullptr;
if (AstConst* const constp = VN_CAST(nodep->lsbp(), Const)) { if (AstConst* const constp = VN_CAST(nodep->lsbp(), Const)) {
DfgSel* const selp = new DfgSel{*m_dfgp, flp, DfgVertex::dtypeFor(nodep)}; DfgSel* const selp = new DfgSel{*m_dfgp, flp, DfgVertex::dtypeFor(nodep)};
selp->fromp(nodep->fromp()->user1u().to<DfgVertex*>()); selp->fromp(nodep->fromp()->user2u().to<DfgVertex*>());
selp->lsb(constp->toUInt()); selp->lsb(constp->toUInt());
vtxp = selp; vtxp = selp;
} else { } else {
iterate(nodep->lsbp()); iterate(nodep->lsbp());
if (m_foundUnhandled) return; if (m_foundUnhandled) return;
DfgMux* const muxp = new DfgMux{*m_dfgp, flp, DfgVertex::dtypeFor(nodep)}; DfgMux* const muxp = new DfgMux{*m_dfgp, flp, DfgVertex::dtypeFor(nodep)};
muxp->fromp(nodep->fromp()->user1u().to<DfgVertex*>()); muxp->fromp(nodep->fromp()->user2u().to<DfgVertex*>());
muxp->lsbp(nodep->lsbp()->user1u().to<DfgVertex*>()); muxp->lsbp(nodep->lsbp()->user2u().to<DfgVertex*>());
vtxp = muxp; vtxp = muxp;
} }
m_uncommittedVertices.push_back(vtxp); m_uncommittedVertices.push_back(vtxp);
nodep->user1p(vtxp); nodep->user2p(vtxp);
} }
// The rest of the 'visit' methods are generated by 'astgen' // The rest of the 'visit' methods are generated by 'astgen'

View File

@ -330,13 +330,10 @@ class ExtractCyclicComponents final {
} }
} }
UASSERT_OBJ(clonep, &vtx, "Unhandled 'DfgVertexVar' sub-type"); UASSERT_OBJ(clonep, &vtx, "Unhandled 'DfgVertexVar' sub-type");
if (vtx.hasModRefs()) clonep->setHasModRefs();
if (vtx.hasExtRefs()) clonep->setHasExtRefs();
VertexState& cloneStatep = allocState(*clonep); VertexState& cloneStatep = allocState(*clonep);
cloneStatep.component = component; cloneStatep.component = component;
// We need to mark both the original and the clone as having references in other DFGs // Mark variable as having references in other DFGs
vtx.setHasDfgRefs(); vtx.setHasDfgRefs();
clonep->setHasDfgRefs();
} }
return *clonep; return *clonep;
} }

View File

@ -129,8 +129,8 @@ template <bool T_Scoped>
class DfgToAstVisitor final : DfgVisitor { class DfgToAstVisitor final : DfgVisitor {
// NODE STATE // NODE STATE
// AstScope::user1p // The combinational AstActive under this scope // AstScope::user2p // The combinational AstActive under this scope
const VNUser1InUse m_user1InUse; const VNUser2InUse m_user2InUse;
// TYPES // TYPES
using VariableType = std::conditional_t<T_Scoped, AstVarScope, AstVar>; using VariableType = std::conditional_t<T_Scoped, AstVarScope, AstVar>;
@ -152,28 +152,28 @@ class DfgToAstVisitor final : DfgVisitor {
} }
static AstActive* getCombActive(AstScope* scopep) { static AstActive* getCombActive(AstScope* scopep) {
if (!scopep->user1p()) { if (!scopep->user2p()) {
// Try to find the existing combinational AstActive // Try to find the existing combinational AstActive
for (AstNode* nodep = scopep->blocksp(); nodep; nodep = nodep->nextp()) { for (AstNode* nodep = scopep->blocksp(); nodep; nodep = nodep->nextp()) {
AstActive* const activep = VN_CAST(nodep, Active); AstActive* const activep = VN_CAST(nodep, Active);
if (!activep) continue; if (!activep) continue;
if (activep->hasCombo()) { if (activep->hasCombo()) {
scopep->user1p(activep); scopep->user2p(activep);
break; break;
} }
} }
// If there isn't one, create a new one // If there isn't one, create a new one
if (!scopep->user1p()) { if (!scopep->user2p()) {
FileLine* const flp = scopep->fileline(); FileLine* const flp = scopep->fileline();
AstSenTree* const senTreep AstSenTree* const senTreep
= new AstSenTree{flp, new AstSenItem{flp, AstSenItem::Combo{}}}; = new AstSenTree{flp, new AstSenItem{flp, AstSenItem::Combo{}}};
AstActive* const activep = new AstActive{flp, "", senTreep}; AstActive* const activep = new AstActive{flp, "", senTreep};
activep->sensesStorep(senTreep); activep->sensesStorep(senTreep);
scopep->addBlocksp(activep); scopep->addBlocksp(activep);
scopep->user1p(activep); scopep->user2p(activep);
} }
} }
return VN_AS(scopep->user1p(), Active); return VN_AS(scopep->user2p(), Active);
} }
AstNodeExpr* convertDfgVertexToAstNodeExpr(DfgVertex* vtxp) { AstNodeExpr* convertDfgVertexToAstNodeExpr(DfgVertex* vtxp) {

View File

@ -296,16 +296,15 @@ void V3DfgOptimizer::optimize(AstNetlist* netlistp, const string& label) {
UINFO(2, __FUNCTION__ << ":"); UINFO(2, __FUNCTION__ << ":");
// NODE STATE // NODE STATE
// AstVar::user1 -> Used by: // AstVar::user1, AstVarScope::user1 -> int, used as a bit-field
// - V3DfgPasses::astToDfg, // - bit0: Read via AstVarXRef (hierarchical reference)
// - V3DfgPasses::eliminateVars, // - bit1: Written via AstVarXRef (hierarchical reference)
// - V3DfgPasses::dfgToAst, // - bit2: Read by logic in same module/netlist not represented in DFG
// AstVar::user2 -> bool: Flag indicating referenced by AstVarXRef (set just below) // - bit3: Written by logic in same module/netlist not represented in DFG
// AstVar::user3, AstVarScope::user3 // - bit4: Referenced by other DFG in same module/netlist
// -> bool: Flag indicating written by logic not representable as DFG //
// (set by V3DfgPasses::astToDfg) // AstNode::user2/user3/user4 can be used by various DFG algorithms
const VNUser2InUse user2InUse; const VNUser1InUse user1InUse;
const VNUser3InUse user3InUse;
V3DfgContext ctx{label}; V3DfgContext ctx{label};
@ -313,7 +312,11 @@ void V3DfgOptimizer::optimize(AstNetlist* netlistp, const string& label) {
// Pre V3Scope application. Run on each module separately. // Pre V3Scope application. Run on each module separately.
// Mark cross-referenced variables // Mark cross-referenced variables
netlistp->foreach([](const AstVarXRef* xrefp) { xrefp->varp()->user2(true); }); netlistp->foreach([](const AstVarXRef* xrefp) {
AstVar* const tgtp = xrefp->varp();
if (xrefp->access().isReadOrRW()) DfgVertexVar::setHasRdXRefs(tgtp);
if (xrefp->access().isWriteOrRW()) DfgVertexVar::setHasWrXRefs(tgtp);
});
// Run the optimization phase // Run the optimization phase
for (AstNode* nodep = netlistp->modulesp(); nodep; nodep = nodep->nextp()) { for (AstNode* nodep = netlistp->modulesp(); nodep; nodep = nodep->nextp()) {

View File

@ -294,7 +294,7 @@ void V3DfgPasses::binToOneHot(DfgGraph& dfg, V3DfgBinToOneHotContext& ctx) {
varp->varp()->isInternal(true); varp->varp()->isInternal(true);
varp->srcp(srcp); varp->srcp(srcp);
} }
varp->setHasModRefs(); varp->setHasModRdRefs();
return varp; return varp;
}(); }();
// The previous index variable - we don't need a vertex for this // The previous index variable - we don't need a vertex for this
@ -314,7 +314,7 @@ void V3DfgPasses::binToOneHot(DfgGraph& dfg, V3DfgBinToOneHotContext& ctx) {
= dfg.makeNewVar(flp, name, tabDTypep, nullptr)->as<DfgVarArray>(); = dfg.makeNewVar(flp, name, tabDTypep, nullptr)->as<DfgVarArray>();
varp->varp()->isInternal(true); varp->varp()->isInternal(true);
varp->varp()->noReset(true); varp->varp()->noReset(true);
varp->setHasModRefs(); varp->setHasModWrRefs();
return varp; return varp;
}(); }();
@ -417,9 +417,9 @@ void V3DfgPasses::eliminateVars(DfgGraph& dfg, V3DfgEliminateVarsContext& ctx) {
// List of variables (AstVar or AstVarScope) we are replacing // List of variables (AstVar or AstVarScope) we are replacing
std::vector<AstNode*> replacedVariables; std::vector<AstNode*> replacedVariables;
// AstVar::user1p() : AstVar* -> The replacement variables // AstVar::user2p() : AstVar* -> The replacement variables
// AstVarScope::user1p() : AstVarScope* -> The replacement variables // AstVarScope::user2p() : AstVarScope* -> The replacement variables
const VNUser1InUse user1InUse; const VNUser2InUse user2InUse;
// Process the work list // Process the work list
while (workListp != sentinelp) { while (workListp != sentinelp) {
@ -448,10 +448,11 @@ void V3DfgPasses::eliminateVars(DfgGraph& dfg, V3DfgEliminateVarsContext& ctx) {
// Can't remove if it has external drivers // Can't remove if it has external drivers
if (!varp->isDrivenFullyByDfg()) continue; if (!varp->isDrivenFullyByDfg()) continue;
// Can't remove if must be kept (including external, non module references) // Can't remove if referenced external to the module/netlist
if (varp->keep()) continue; if (varp->hasExtRefs()) continue;
// Can't remove if written in the module
// Can't remove if referenced in other DFGs of the same module (otherwise might rm twice) if (varp->hasModWrRefs()) continue;
// Can't remove if referenced in other DFGs of the same module
if (varp->hasDfgRefs()) continue; if (varp->hasDfgRefs()) continue;
// If it has multiple sinks, it can't be eliminated // If it has multiple sinks, it can't be eliminated
@ -469,9 +470,9 @@ void V3DfgPasses::eliminateVars(DfgGraph& dfg, V3DfgEliminateVarsContext& ctx) {
UASSERT_OBJ(!varp->hasSinks(), varp, "Variable inlining should make this impossible"); UASSERT_OBJ(!varp->hasSinks(), varp, "Variable inlining should make this impossible");
// Grab the AstVar/AstVarScope // Grab the AstVar/AstVarScope
AstNode* const nodep = varp->nodep(); AstNode* const nodep = varp->nodep();
UASSERT_OBJ(!nodep->user1p(), nodep, "Replacement already exists"); UASSERT_OBJ(!nodep->user2p(), nodep, "Replacement already exists");
replacedVariables.emplace_back(nodep); replacedVariables.emplace_back(nodep);
nodep->user1p(driverp->nodep()); nodep->user2p(driverp->nodep());
} else { } else {
// Otherwise this *is* the canonical var // Otherwise this *is* the canonical var
continue; continue;
@ -490,13 +491,13 @@ void V3DfgPasses::eliminateVars(DfgGraph& dfg, V3DfgEliminateVarsContext& ctx) {
if (AstModule* const modp = dfg.modulep()) { if (AstModule* const modp = dfg.modulep()) {
modp->foreach([&](AstVarRef* refp) { modp->foreach([&](AstVarRef* refp) {
AstVar* varp = refp->varp(); AstVar* varp = refp->varp();
while (AstVar* const replacep = VN_AS(varp->user1p(), Var)) varp = replacep; while (AstVar* const replacep = VN_AS(varp->user2p(), Var)) varp = replacep;
refp->varp(varp); refp->varp(varp);
}); });
} else { } else {
v3Global.rootp()->foreach([&](AstVarRef* refp) { v3Global.rootp()->foreach([&](AstVarRef* refp) {
AstVarScope* vscp = refp->varScopep(); AstVarScope* vscp = refp->varScopep();
while (AstVarScope* const replacep = VN_AS(vscp->user1p(), VarScope)) vscp = replacep; while (AstVarScope* const replacep = VN_AS(vscp->user2p(), VarScope)) vscp = replacep;
refp->varScopep(vscp); refp->varScopep(vscp);
refp->varp(vscp->varp()); refp->varp(vscp->varp());
}); });

View File

@ -41,9 +41,6 @@
class DfgVertexVar VL_NOT_FINAL : public DfgVertexUnary { class DfgVertexVar VL_NOT_FINAL : public DfgVertexUnary {
AstVar* const m_varp; // The AstVar associated with this vertex (not owned by this vertex) AstVar* const m_varp; // The AstVar associated with this vertex (not owned by this vertex)
AstVarScope* const m_varScopep; // The AstVarScope associated with this vertex (not owned) AstVarScope* const m_varScopep; // The AstVarScope associated with this vertex (not owned)
bool m_hasDfgRefs = false; // This AstVar is referenced in a different DFG of the module
bool m_hasModRefs = false; // This AstVar is referenced outside the DFG, but in the module
bool m_hasExtRefs = false; // This AstVar is referenced from outside the module
// Location of driver of this variable. Only used for converting back to Ast. Might be nullptr. // Location of driver of this variable. Only used for converting back to Ast. Might be nullptr.
FileLine* m_driverFileLine = nullptr; FileLine* m_driverFileLine = nullptr;
@ -62,13 +59,6 @@ public:
AstNode* nodep() const { AstNode* nodep() const {
return m_varScopep ? static_cast<AstNode*>(m_varScopep) : static_cast<AstNode*>(m_varp); return m_varScopep ? static_cast<AstNode*>(m_varScopep) : static_cast<AstNode*>(m_varp);
} }
bool hasDfgRefs() const { return m_hasDfgRefs; }
void setHasDfgRefs() { m_hasDfgRefs = true; }
bool hasModRefs() const { return m_hasModRefs; }
void setHasModRefs() { m_hasModRefs = true; }
bool hasExtRefs() const { return m_hasExtRefs; }
void setHasExtRefs() { m_hasExtRefs = true; }
bool hasNonLocalRefs() const { return hasDfgRefs() || hasModRefs() || hasExtRefs(); }
FileLine* driverFileLine() const { return m_driverFileLine; } FileLine* driverFileLine() const { return m_driverFileLine; }
void driverFileLine(FileLine* flp) { m_driverFileLine = flp; } void driverFileLine(FileLine* flp) { m_driverFileLine = flp; }
@ -77,17 +67,32 @@ public:
return srcp() && !srcp()->is<DfgVertexSplice>() && !varp()->isForced(); return srcp() && !srcp()->is<DfgVertexSplice>() && !varp()->isForced();
} }
// Variable cannot be removed, even if redundant in the DfgGraph (might be used externally) // Variable referenced via an AstVarXRef (hierarchical reference)
bool keep() const { bool hasXRefs() const { return nodep()->user1() & 0x03; }
// Keep if referenced outside this module static void setHasRdXRefs(AstNode* nodep) { nodep->user1(nodep->user1() | 0x01); }
if (hasExtRefs()) return true; static void setHasWrXRefs(AstNode* nodep) { nodep->user1(nodep->user1() | 0x02); }
// Keep if traced
if (v3Global.opt.trace() && varp()->isTrace()) return true; // Variable referenced from Ast code in the same module/netlist
// Keep if public bool hasModRdRefs() const { return nodep()->user1() & 0x04; }
if (varp()->isSigPublic()) return true; bool hasModWrRefs() const { return nodep()->user1() & 0x08; }
// Keep if written in non-DFG code bool hasModRefs() const { return nodep()->user1() & 0x0c; }
if (nodep()->user3()) return true; static void setHasModRdRefs(AstNode* nodep) { nodep->user1(nodep->user1() | 0x04); }
// Otherwise it can be removed static void setHasModWrRefs(AstNode* nodep) { nodep->user1(nodep->user1() | 0x08); }
void setHasModRdRefs() const { setHasModRdRefs(nodep()); }
void setHasModWrRefs() const { setHasModWrRefs(nodep()); }
// Variable referenced from other DFG in the same module/netlist
bool hasDfgRefs() const { return nodep()->user1() & 0x10; }
void setHasDfgRefs() { nodep()->user1(nodep()->user1() | 0x10); }
// Variable referenced outside the containing module/netlist.
bool hasExtRefs() const {
if (m_varp->isIO()) return true; // Ports
if (m_varp->isTrace()) return true; // Traced
if (m_varp->isForced()) return true; // Forced
if (hasXRefs()) return true; // Target of a hierarchical reference
if (m_varp->isPrimaryIO()) return true; // Top level ports
if (m_varp->isSigPublic()) return true; // Public
return false; return false;
} }
}; };

View File

@ -1250,13 +1250,13 @@ def write_dfg_ast_to_dfg(filename):
continue continue
fh.write("void visit(Ast{t}* nodep) override {{\n".format(t=node.name)) fh.write("void visit(Ast{t}* nodep) override {{\n".format(t=node.name))
fh.write(' UASSERT_OBJ(!nodep->user1p(), nodep, "Already has Dfg vertex");\n\n') fh.write(' UASSERT_OBJ(!nodep->user2p(), nodep, "Already has Dfg vertex");\n\n')
fh.write(" if (unhandled(nodep)) return;\n\n") fh.write(" if (unhandled(nodep)) return;\n\n")
for i in range(node.arity): for i in range(node.arity):
fh.write(" iterate(nodep->op{j}p());\n".format(j=i + 1)) fh.write(" iterate(nodep->op{j}p());\n".format(j=i + 1))
fh.write(" if (m_foundUnhandled) return;\n") fh.write(" if (m_foundUnhandled) return;\n")
fh.write( fh.write(
' UASSERT_OBJ(nodep->op{j}p()->user1p(), nodep, "Child {j} missing Dfg vertex");\n' ' UASSERT_OBJ(nodep->op{j}p()->user2p(), nodep, "Child {j} missing Dfg vertex");\n'
.format(j=i + 1)) .format(j=i + 1))
fh.write("\n") fh.write("\n")
fh.write(" Dfg{t}* const vtxp = makeVertex<Dfg{t}>(nodep, *m_dfgp);\n".format( fh.write(" Dfg{t}* const vtxp = makeVertex<Dfg{t}>(nodep, *m_dfgp);\n".format(
@ -1268,11 +1268,11 @@ def write_dfg_ast_to_dfg(filename):
fh.write(" }\n\n") fh.write(" }\n\n")
for i in range(node.arity): for i in range(node.arity):
fh.write( fh.write(
" vtxp->relinkSource<{i}>(nodep->op{j}p()->user1u().to<DfgVertex*>());\n". " vtxp->relinkSource<{i}>(nodep->op{j}p()->user2u().to<DfgVertex*>());\n".
format(i=i, j=i + 1)) format(i=i, j=i + 1))
fh.write("\n") fh.write("\n")
fh.write(" m_uncommittedVertices.push_back(vtxp);\n") fh.write(" m_uncommittedVertices.push_back(vtxp);\n")
fh.write(" nodep->user1p(vtxp);\n") fh.write(" nodep->user2p(vtxp);\n")
fh.write("}\n") fh.write("}\n")