mirror of
https://github.com/verilator/verilator.git
synced 2026-09-03 08:24:31 +02:00
Internals: Move CReset under Assign (#6978)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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()) {
|
||||
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user