mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Fix purity calculation during V3Const simplifying Ast
This commit is contained in:
parent
46f8a659b3
commit
684aba0e90
@ -33,7 +33,7 @@ VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
//======================================================================
|
||||
// Statics
|
||||
|
||||
uint32_t VIsCached::s_cachedCntGbl = 1;
|
||||
uint64_t VIsCached::s_cachedCntGbl = 1;
|
||||
|
||||
uint64_t AstNode::s_editCntLast = 0;
|
||||
uint64_t AstNode::s_editCntGbl = 0; // Hot cache line
|
||||
|
11
src/V3Ast.h
11
src/V3Ast.h
@ -171,10 +171,9 @@ class VIsCached final {
|
||||
// Used in some nodes to cache results of boolean methods
|
||||
// If cachedCnt == 0, not cached
|
||||
// else if cachedCnt == s_cachedCntGbl, then m_state is if cached
|
||||
uint32_t m_cachedCnt : 31; // Mark of when cache was computed
|
||||
uint32_t m_state : 1;
|
||||
static uint32_t s_cachedCntGbl; // Global computed count
|
||||
static constexpr uint32_t MAX_CNT = (1UL << 31) - 1; // Max for m_cachedCnt
|
||||
uint64_t m_cachedCnt : 63; // Mark of when cache was computed
|
||||
uint64_t m_state : 1;
|
||||
static uint64_t s_cachedCntGbl; // Global computed count
|
||||
|
||||
public:
|
||||
VIsCached()
|
||||
@ -192,7 +191,8 @@ public:
|
||||
}
|
||||
static void clearCacheTree() {
|
||||
++s_cachedCntGbl;
|
||||
UASSERT_STATIC(s_cachedCntGbl < MAX_CNT, "Overflow of cache counting");
|
||||
// 64 bits so won't overflow
|
||||
// UASSERT_STATIC(s_cachedCntGbl < MAX_CNT, "Overflow of cache counting");
|
||||
}
|
||||
};
|
||||
|
||||
@ -1956,6 +1956,7 @@ public:
|
||||
uint64_t editCount() const { return m_editCount; }
|
||||
void editCountInc() {
|
||||
m_editCount = ++s_editCntGbl; // Preincrement, so can "watch AstNode::s_editCntGbl=##"
|
||||
VIsCached::clearCacheTree(); // Any edit clears all caching
|
||||
}
|
||||
#else
|
||||
void editCountInc() { ++s_editCntGbl; }
|
||||
|
@ -64,7 +64,6 @@ public:
|
||||
|
||||
// Wrap This expression into an AstStmtExpr to denote it occurs in statement position
|
||||
inline AstStmtExpr* makeStmt();
|
||||
virtual void clearCachedPurity(){}; // Most nodes don't cache their purity
|
||||
};
|
||||
class AstNodeBiop VL_NOT_FINAL : public AstNodeExpr {
|
||||
// Binary expression
|
||||
@ -98,7 +97,6 @@ public:
|
||||
bool same(const AstNode*) const override { return true; }
|
||||
bool isPure() override;
|
||||
const char* broken() const override;
|
||||
void clearCachedPurity() override;
|
||||
|
||||
private:
|
||||
bool getPurityRecurse() const { return lhsp()->isPure() && rhsp()->isPure(); }
|
||||
@ -265,7 +263,6 @@ public:
|
||||
string emitVerilog() final override { V3ERROR_NA_RETURN(""); }
|
||||
string emitC() final override { V3ERROR_NA_RETURN(""); }
|
||||
bool cleanOut() const final override { V3ERROR_NA_RETURN(true); }
|
||||
void clearCachedPurity() override;
|
||||
|
||||
private:
|
||||
bool getPurityRecurse() const;
|
||||
@ -296,7 +293,6 @@ public:
|
||||
bool cleanOut() const final override { V3ERROR_NA_RETURN(true); }
|
||||
bool isPure() override;
|
||||
const char* broken() const override;
|
||||
void clearCachedPurity() override;
|
||||
|
||||
private:
|
||||
bool getPurityRecurse() const {
|
||||
@ -340,7 +336,6 @@ public:
|
||||
bool same(const AstNode*) const override { return true; }
|
||||
bool isPure() override;
|
||||
const char* broken() const override;
|
||||
void clearCachedPurity() override;
|
||||
|
||||
private:
|
||||
bool getPurityRecurse() const {
|
||||
@ -393,7 +388,6 @@ public:
|
||||
bool same(const AstNode*) const override { return true; }
|
||||
bool isPure() override;
|
||||
const char* broken() const override;
|
||||
void clearCachedPurity() override;
|
||||
|
||||
private:
|
||||
bool getPurityRecurse() const {
|
||||
@ -473,7 +467,6 @@ public:
|
||||
bool same(const AstNode*) const override { return true; }
|
||||
bool isPure() override;
|
||||
const char* broken() const override;
|
||||
void clearCachedPurity() override;
|
||||
};
|
||||
class AstNodeSystemUniopD VL_NOT_FINAL : public AstNodeUniop {
|
||||
public:
|
||||
|
@ -72,11 +72,6 @@ bool AstNodeFTaskRef::isPure() {
|
||||
}
|
||||
}
|
||||
|
||||
void AstNodeFTaskRef::clearCachedPurity() {
|
||||
m_purity.clearCache();
|
||||
if (AstNodeExpr* const exprp = VN_CAST(backp(), NodeExpr)) exprp->clearCachedPurity();
|
||||
}
|
||||
|
||||
bool AstNodeFTaskRef::getPurityRecurse() const {
|
||||
AstNodeFTask* const taskp = this->taskp();
|
||||
// Unlinked yet, so treat as impure
|
||||
@ -152,11 +147,6 @@ const char* AstNodeUniop::broken() const {
|
||||
BROKEN_RTN(m_purity.isCached() && m_purity.get() != lhsp()->isPure());
|
||||
return nullptr;
|
||||
}
|
||||
void AstNodeUniop::clearCachedPurity() {
|
||||
m_purity.clearCache();
|
||||
if (AstNodeExpr* const exprp = VN_CAST(backp(), NodeExpr)) exprp->clearCachedPurity();
|
||||
}
|
||||
|
||||
bool AstNodeBiop::isPure() {
|
||||
if (!m_purity.isCached()) m_purity.set(getPurityRecurse());
|
||||
return m_purity.get();
|
||||
@ -165,10 +155,6 @@ const char* AstNodeBiop::broken() const {
|
||||
BROKEN_RTN(m_purity.isCached() && m_purity.get() != getPurityRecurse());
|
||||
return nullptr;
|
||||
}
|
||||
void AstNodeBiop::clearCachedPurity() {
|
||||
m_purity.clearCache();
|
||||
if (AstNodeExpr* const exprp = VN_CAST(backp(), NodeExpr)) exprp->clearCachedPurity();
|
||||
}
|
||||
|
||||
bool AstNodeTriop::isPure() {
|
||||
if (!m_purity.isCached()) m_purity.set(getPurityRecurse());
|
||||
@ -178,10 +164,6 @@ const char* AstNodeTriop::broken() const {
|
||||
BROKEN_RTN(m_purity.isCached() && m_purity.get() != getPurityRecurse());
|
||||
return nullptr;
|
||||
}
|
||||
void AstNodeTriop::clearCachedPurity() {
|
||||
m_purity.clearCache();
|
||||
if (AstNodeExpr* const exprp = VN_CAST(backp(), NodeExpr)) exprp->clearCachedPurity();
|
||||
}
|
||||
|
||||
bool AstNodePreSel::isPure() {
|
||||
if (!m_purity.isCached()) m_purity.set(getPurityRecurse());
|
||||
@ -191,10 +173,6 @@ const char* AstNodePreSel::broken() const {
|
||||
BROKEN_RTN(m_purity.isCached() && m_purity.get() != getPurityRecurse());
|
||||
return nullptr;
|
||||
}
|
||||
void AstNodePreSel::clearCachedPurity() {
|
||||
m_purity.clearCache();
|
||||
if (AstNodeExpr* const exprp = VN_CAST(backp(), NodeExpr)) exprp->clearCachedPurity();
|
||||
}
|
||||
|
||||
bool AstNodeQuadop::isPure() {
|
||||
if (!m_purity.isCached()) m_purity.set(getPurityRecurse());
|
||||
@ -204,10 +182,6 @@ const char* AstNodeQuadop::broken() const {
|
||||
BROKEN_RTN(m_purity.isCached() && m_purity.get() != getPurityRecurse());
|
||||
return nullptr;
|
||||
}
|
||||
void AstNodeQuadop::clearCachedPurity() {
|
||||
m_purity.clearCache();
|
||||
if (AstNodeExpr* const exprp = VN_CAST(backp(), NodeExpr)) exprp->clearCachedPurity();
|
||||
}
|
||||
|
||||
AstNodeCond::AstNodeCond(VNType t, FileLine* fl, AstNodeExpr* condp, AstNodeExpr* thenp,
|
||||
AstNodeExpr* elsep)
|
||||
|
@ -174,7 +174,7 @@ private:
|
||||
// MethodCalls not currently supported by inliner, so keep linked
|
||||
if (!nodep->classOrPackagep() && !VN_IS(nodep, MethodCall)) {
|
||||
nodep->taskp(nullptr);
|
||||
nodep->clearCachedPurity();
|
||||
VIsCached::clearCacheTree();
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
@ -3726,6 +3726,7 @@ public:
|
||||
// Link class functions
|
||||
|
||||
void V3LinkDot::linkDotGuts(AstNetlist* rootp, VLinkDotStep step) {
|
||||
VIsCached::clearCacheTree(); // Avoid using any stale isPure
|
||||
if (debug() >= 5 || dumpTreeLevel() >= 9) {
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot.tree"));
|
||||
}
|
||||
|
@ -331,7 +331,7 @@ private:
|
||||
// We're going to need the expression several times in the expanded code,
|
||||
// so might as well make it a common expression
|
||||
createDeepTemp(nodep->condp(), false);
|
||||
nodep->clearCachedPurity();
|
||||
VIsCached::clearCacheTree();
|
||||
}
|
||||
checkNode(nodep);
|
||||
}
|
||||
|
@ -396,7 +396,7 @@ private:
|
||||
UINFO(9, " New pkg-taskref " << nodep << endl);
|
||||
} else if (!VN_IS(nodep, MethodCall)) {
|
||||
nodep->taskp(nullptr);
|
||||
nodep->clearCachedPurity();
|
||||
VIsCached::clearCacheTree();
|
||||
UINFO(9, " New pkg-taskref " << nodep << endl);
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
|
@ -1469,9 +1469,9 @@ private:
|
||||
beginp = new AstExprStmt{nodep->fileline(), beginp, outrefp};
|
||||
// AstExprStmt is currently treated as impure, so clear the cached purity of its
|
||||
// parents
|
||||
nodep->clearCachedPurity();
|
||||
nodep->replaceWith(beginp);
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
VIsCached::clearCacheTree();
|
||||
} else {
|
||||
insertBeforeStmt(nodep, beginp);
|
||||
if (nodep->taskp()->isFunction()) {
|
||||
|
Loading…
Reference in New Issue
Block a user