Internals: Move CReset under Assign (#6978)

This commit is contained in:
Wilson Snyder
2026-01-31 21:27:36 -05:00
committed by GitHub
parent d9234501e0
commit 07ce0ac2ea
11 changed files with 1042 additions and 1004 deletions
+26
View File
@@ -673,6 +673,32 @@ public:
private:
void setPurity();
};
class AstCReset final : public AstNodeExpr {
// Reset variable at startup
const bool m_constructing; // Previously cleared by constructor
public:
AstCReset(FileLine* fl, AstVar* varp, bool constructing)
: ASTGEN_SUPER_CReset(fl)
, m_constructing{constructing} {
dtypeFrom(varp);
}
ASTGEN_MEMBERS_AstCReset;
void dump(std::ostream& str) const override;
void dumpJson(std::ostream& str) const override;
bool isPure() override { return true; }
int instrCount() const override { return widthInstrs(); }
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { return true; }
const char* broken() const override {
BROKEN_RTN(!VN_IS(backp(), NodeAssign)); // V3Emit* assumption
return nullptr;
}
bool sameNode(const AstNode* samep) const override {
return constructing() == VN_DBG_AS(samep, CReset)->constructing();
}
bool constructing() const { return m_constructing; }
};
class AstCast final : public AstNodeExpr {
// Cast to appropriate data type
// @astgen op1 := fromp : AstNodeExpr
-20
View File
@@ -253,26 +253,6 @@ public:
string verilogKwd() const override { return "break"; }
bool isBrancher() const override { V3ERROR_NA_RETURN(true); } // Node removed early
};
class AstCReset final : public AstNodeStmt {
// Reset variable at startup
// @astgen op1 := varrefp : AstVarRef
const bool m_constructing; // Previously cleared by constructor
public:
AstCReset(FileLine* fl, AstVarRef* varrefp, bool constructing)
: ASTGEN_SUPER_CReset(fl)
, m_constructing{constructing} {
this->varrefp(varrefp);
}
ASTGEN_MEMBERS_AstCReset;
void dump(std::ostream& str) const override;
void dumpJson(std::ostream& str) const override;
bool isGateOptimizable() const override { return false; }
bool isPredictOptimizable() const override { return false; }
bool sameNode(const AstNode* samep) const override {
return constructing() == VN_DBG_AS(samep, CReset)->constructing();
}
bool constructing() const { return m_constructing; }
};
class AstCReturn final : public AstNodeStmt {
// C++ return from a function
// @astgen op1 := lhsp : AstNodeExpr
+5 -4
View File
@@ -192,12 +192,13 @@ class CCtorsVisitor final : public VNVisitor {
}
void visit(AstVar* nodep) override {
if (nodep->needsCReset()) {
AstNode* const crstp = new AstAssign{
nodep->fileline(), new AstVarRef{nodep->fileline(), nodep, VAccess::WRITE},
new AstCReset{nodep->fileline(), nodep, true}};
if (m_varResetp) {
AstVarRef* const vrefp = new AstVarRef{nodep->fileline(), nodep, VAccess::WRITE};
m_varResetp->add(new AstCReset{nodep->fileline(), vrefp, true});
m_varResetp->add(crstp);
} else if (m_cfuncp) {
AstVarRef* const vrefp = new AstVarRef{nodep->fileline(), nodep, VAccess::WRITE};
nodep->addNextHere(new AstCReset{nodep->fileline(), vrefp, true});
nodep->addNextHere(crstp);
}
}
}
-1
View File
@@ -81,7 +81,6 @@ class CfgBuilder final : public VNVisitorConst {
// Non-representable statements
void visit(AstAssignDly* nodep) override { nonRepresentable(nodep); }
void visit(AstCase* nodep) override { nonRepresentable(nodep); } // V3Case will eliminate
void visit(AstCReset* nodep) override { nonRepresentable(nodep); }
void visit(AstDelay* nodep) override { nonRepresentable(nodep); }
// Representable non control-flow statements
+5 -4
View File
@@ -523,6 +523,11 @@ public:
}
void visit(AstNodeAssign* nodep) override {
if (AstCReset* const resetp = VN_CAST(nodep->rhsp(), CReset)) {
AstVar* const varp = VN_AS(nodep->lhsp(), NodeVarRef)->varp();
emitVarReset(varp, resetp->constructing());
return;
}
bool paren = true;
bool decind = false;
bool rhs = true;
@@ -1736,10 +1741,6 @@ public:
puts(")");
}
}
void visit(AstCReset* nodep) override {
AstVar* const varp = nodep->varrefp()->varp();
emitVarReset(varp, nodep->constructing());
}
void visit(AstExecGraph* nodep) override {
// The location of the AstExecGraph within the containing AstCFunc is where we want to
// invoke the graph and wait for it to complete. Emitting the children does just that.
+1 -35
View File
@@ -46,13 +46,11 @@ class LifeState final {
public:
VDouble0 m_statAssnDel; // Statistic tracking
VDouble0 m_statAssnCon; // Statistic tracking
VDouble0 m_statCResetDel; // Statistic tracking
// CONSTRUCTORS
LifeState() = default;
~LifeState() {
V3Stats::addStatSum("Optimizations, Lifetime assign deletions", m_statAssnDel);
V3Stats::addStatSum("Optimizations, Lifetime creset deletions", m_statCResetDel);
V3Stats::addStatSum("Optimizations, Lifetime constant prop", m_statAssnCon);
}
};
@@ -87,12 +85,6 @@ public:
m_everSet = true;
if (VN_IS(nodep->rhsp(), Const)) m_constp = VN_AS(nodep->rhsp(), Const);
}
void resetStatement(AstCReset* nodep) { // New CReset(A) assignment
UASSERT_OBJ(!m_isNew, nodep, "Uninitialized new entry");
m_assignp = nodep;
m_constp = nullptr;
m_everSet = true;
}
void complexAssign() { // A[x]=... or some complicated assignment
UASSERT(!m_isNew, "Uninitialized new entry");
m_assignp = nullptr;
@@ -148,26 +140,9 @@ public:
UINFOTREE(7, oldassp, "", "REMOVE/SAMEBLK");
entr.complexAssign();
oldassp->unlinkFrBack();
if (VN_IS(oldassp, CReset)) {
++m_statep->m_statCResetDel;
} else {
++m_statep->m_statAssnDel;
}
++m_statep->m_statAssnDel;
VL_DO_DANGLING(m_deleter.pushDeletep(oldassp), oldassp);
}
void resetStatement(AstVarScope* nodep, AstCReset* rstp) {
// Do we have a old assignment we can nuke?
UINFO(4, " CRESETof: " << nodep);
UINFO(7, " new: " << rstp);
LifeVarEntry& entr = m_map[nodep];
if (entr.isNew()) {
entr.init(true);
} else {
checkRemoveAssign(nodep, entr);
}
entr.resetStatement(rstp);
// lifeDump();
}
void simpleAssign(AstVarScope* nodep, AstNodeAssign* assp) {
// Do we have a old assignment we can nuke?
UINFO(4, " ASSIGNof: " << nodep);
@@ -333,15 +308,6 @@ class LifeVisitor final : public VNVisitor {
iterateAndNextNull(nodep->lhsp());
}
}
void visit(AstCReset* nodep) override {
if (!m_noopt) {
AstVarScope* const vscp = nodep->varrefp()->varScopep();
UASSERT_OBJ(vscp, nodep, "Scope lost on variable");
m_lifep->resetStatement(vscp, nodep);
} else {
iterateAndNextNull(nodep->varrefp());
}
}
void visit(AstAssignDly* nodep) override {
// V3Life doesn't understand time sense
if (nodep->isTimingControl()) {
+1
View File
@@ -241,6 +241,7 @@ class SliceVisitor final : public VNVisitor {
const AstUnpackArrayDType* const arrayp = VN_CAST(dtp, UnpackArrayDType);
if (!arrayp) return false;
if (VN_IS(stp, CvtPackedToArray)) return false;
if (VN_IS(stp, CReset)) return false;
// Any isSc variables must be expanded regardless of --fno-slice
const bool hasSc
+5 -3
View File
@@ -649,9 +649,11 @@ class TaskVisitor final : public VNVisitor {
if (portp->needsCReset() && portp->lifetime().isAutomatic()
&& !portp->valuep()) {
// Reset automatic var to its default, on each invocation of function
AstVarRef* const vrefp
= new AstVarRef{portp->fileline(), portp, VAccess::WRITE};
portp->replaceWith(new AstCReset{portp->fileline(), vrefp, false});
AstNode* const crstp = new AstAssign{
portp->fileline(),
new AstVarRef{portp->fileline(), portp, VAccess::WRITE},
new AstCReset{portp->fileline(), portp, false}};
portp->replaceWith(crstp);
} else {
portp->unlinkFrBack();
}