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:
parent
d415757b0e
commit
d2edab458e
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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()) {
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue