diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index a3786d519..7a7ad5e2f 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -54,6 +54,52 @@ public: bool unnamed() const { return m_unnamed; } bool isFirstInMyListOfStatements(AstNode* nodep) const override { return nodep == stmtsp(); } }; +class AstNodeCoverDecl VL_NOT_FINAL : public AstNode { + // Coverage analysis point declaration + // + // [After V3CoverageJoin] Duplicate declaration to get data from instead + // @astgen ptr := m_dataDeclp : Optional[AstNodeCoverDecl] + string m_page; // Coverage point's page tag + string m_text; // Coverage point's text + string m_hier; // Coverage point's hierarchy + int m_binNum = 0; // Set by V3EmitCSyms to tell final V3Emit what to increment +public: + AstNodeCoverDecl(VNType t, FileLine* fl, const string& page, const string& comment) + : AstNode(t, fl) + , m_page{page} + , m_text{comment} {} + ASTGEN_MEMBERS_AstNodeCoverDecl; + const char* broken() const override { + if (m_dataDeclp + && (m_dataDeclp == this || m_dataDeclp->m_dataDeclp)) { // Avoid O(n^2) accessing + v3fatalSrc("dataDeclp should point to real data, not be a list: " << cvtToHex(this)); + } + return nullptr; + } + void dump(std::ostream& str) const override; + void dumpJson(std::ostream& str) const override; + int instrCount() const override { return 1 + 2 * INSTR_COUNT_LD; } + bool maybePointedTo() const override VL_MT_SAFE { return true; } + int binNum() const { return m_binNum; } + void binNum(int flag) { m_binNum = flag; } + virtual int size() const = 0; + const string& comment() const { return m_text; } // text to insert in code + const string& page() const { return m_page; } + const string& hier() const { return m_hier; } + void hier(const string& flag) { m_hier = flag; } + void comment(const string& flag) { m_text = flag; } + bool sameNode(const AstNode* samep) const override { + const AstNodeCoverDecl* const asamep = VN_DBG_AS(samep, NodeCoverDecl); + return (fileline() == asamep->fileline() && hier() == asamep->hier() + && comment() == asamep->comment() && page() == asamep->page()); + } + bool isPredictOptimizable() const override { return false; } + void dataDeclp(AstNodeCoverDecl* nodep) { m_dataDeclp = nodep; } + // dataDecl nullptr means "use this one", but often you want "this" to + // indicate to get data from here + AstNodeCoverDecl* dataDeclNullp() const { return m_dataDeclp; } + AstNodeCoverDecl* dataDeclThisp() { return dataDeclNullp() ? dataDeclNullp() : this; } +}; class AstNodeFTask VL_NOT_FINAL : public AstNode { // Output variable in functions, nullptr in tasks // @astgen op1 := fvarp : Optional[AstNode] @@ -2248,6 +2294,49 @@ public: void joinType(const VJoinType& flag) { m_joinType = flag; } }; +// === AstNodeCoverDecl === +class AstCoverOtherDecl final : public AstNodeCoverDecl { + // Coverage analysis point declaration + // Used for other than toggle types of coverage + string m_linescov; + int m_offset; // Offset column numbers to uniq-ify IFs +public: + AstCoverOtherDecl(FileLine* fl, const string& page, const string& comment, + const string& linescov, int offset) + : ASTGEN_SUPER_CoverOtherDecl(fl, page, comment) + , m_linescov{linescov} + , m_offset{offset} {} + ASTGEN_MEMBERS_AstCoverOtherDecl; + void dump(std::ostream& str) const override; + void dumpJson(std::ostream& str) const override; + int offset() const { return m_offset; } + int size() const override { return 1; } + const string& linescov() const { return m_linescov; } + bool sameNode(const AstNode* samep) const override { + const AstCoverOtherDecl* const asamep = VN_DBG_AS(samep, CoverOtherDecl); + return AstNodeCoverDecl::sameNode(samep) && linescov() == asamep->linescov(); + } +}; +class AstCoverToggleDecl final : public AstNodeCoverDecl { + // Coverage analysis point declaration + // Used for toggle coverage + const VNumRange m_range; // Packed array range covering each toggle bit +public: + AstCoverToggleDecl(FileLine* fl, const string& page, const string& comment, + const VNumRange& range) + : ASTGEN_SUPER_CoverToggleDecl(fl, page, comment) + , m_range{range} {} + ASTGEN_MEMBERS_AstCoverToggleDecl; + void dump(std::ostream& str) const override; + void dumpJson(std::ostream& str) const override; + int size() const override { return m_range.elements(); } + const VNumRange& range() const { return m_range; } + bool sameNode(const AstNode* samep) const override { + const AstCoverToggleDecl* const asamep = VN_DBG_AS(samep, CoverToggleDecl); + return AstNodeCoverDecl::sameNode(samep) && range() == asamep->range(); + } +}; + // === AstNodeFTask === class AstFunc final : public AstNodeFTask { // A function inside a module diff --git a/src/V3AstNodeStmt.h b/src/V3AstNodeStmt.h index 154578d43..fcc1977e7 100644 --- a/src/V3AstNodeStmt.h +++ b/src/V3AstNodeStmt.h @@ -85,52 +85,6 @@ public: ASTGEN_MEMBERS_AstNodeCase; int instrCount() const override { return INSTR_COUNT_BRANCH; } }; -class AstNodeCoverDecl VL_NOT_FINAL : public AstNodeStmt { - // Coverage analysis point declaration - // - // [After V3CoverageJoin] Duplicate declaration to get data from instead - // @astgen ptr := m_dataDeclp : Optional[AstNodeCoverDecl] - string m_page; // Coverage point's page tag - string m_text; // Coverage point's text - string m_hier; // Coverage point's hierarchy - int m_binNum = 0; // Set by V3EmitCSyms to tell final V3Emit what to increment -public: - AstNodeCoverDecl(VNType t, FileLine* fl, const string& page, const string& comment) - : AstNodeStmt(t, fl) - , m_page{page} - , m_text{comment} {} - ASTGEN_MEMBERS_AstNodeCoverDecl; - const char* broken() const override { - if (m_dataDeclp - && (m_dataDeclp == this || m_dataDeclp->m_dataDeclp)) { // Avoid O(n^2) accessing - v3fatalSrc("dataDeclp should point to real data, not be a list: " << cvtToHex(this)); - } - return nullptr; - } - void dump(std::ostream& str) const override; - void dumpJson(std::ostream& str) const override; - int instrCount() const override { return 1 + 2 * INSTR_COUNT_LD; } - bool maybePointedTo() const override VL_MT_SAFE { return true; } - int binNum() const { return m_binNum; } - void binNum(int flag) { m_binNum = flag; } - virtual int size() const = 0; - const string& comment() const { return m_text; } // text to insert in code - const string& page() const { return m_page; } - const string& hier() const { return m_hier; } - void hier(const string& flag) { m_hier = flag; } - void comment(const string& flag) { m_text = flag; } - bool sameNode(const AstNode* samep) const override { - const AstNodeCoverDecl* const asamep = VN_DBG_AS(samep, NodeCoverDecl); - return (fileline() == asamep->fileline() && hier() == asamep->hier() - && comment() == asamep->comment() && page() == asamep->page()); - } - bool isPredictOptimizable() const override { return false; } - void dataDeclp(AstNodeCoverDecl* nodep) { m_dataDeclp = nodep; } - // dataDecl nullptr means "use this one", but often you want "this" to - // indicate to get data from here - AstNodeCoverDecl* dataDeclNullp() const { return m_dataDeclp; } - AstNodeCoverDecl* dataDeclThisp() { return dataDeclNullp() ? dataDeclNullp() : this; } -}; class AstNodeCoverOrAssert VL_NOT_FINAL : public AstNodeStmt { // Cover or Assert // Parents: {statement list} @@ -1239,47 +1193,6 @@ public: : ASTGEN_SUPER_GenCase(fl, exprp, itemsp) {} ASTGEN_MEMBERS_AstGenCase; }; -class AstCoverOtherDecl final : public AstNodeCoverDecl { - // Coverage analysis point declaration - // Used for other than toggle types of coverage - string m_linescov; - int m_offset; // Offset column numbers to uniq-ify IFs -public: - AstCoverOtherDecl(FileLine* fl, const string& page, const string& comment, - const string& linescov, int offset) - : ASTGEN_SUPER_CoverOtherDecl(fl, page, comment) - , m_linescov{linescov} - , m_offset{offset} {} - ASTGEN_MEMBERS_AstCoverOtherDecl; - void dump(std::ostream& str) const override; - void dumpJson(std::ostream& str) const override; - int offset() const { return m_offset; } - int size() const override { return 1; } - const string& linescov() const { return m_linescov; } - bool sameNode(const AstNode* samep) const override { - const AstCoverOtherDecl* const asamep = VN_DBG_AS(samep, CoverOtherDecl); - return AstNodeCoverDecl::sameNode(samep) && linescov() == asamep->linescov(); - } -}; -class AstCoverToggleDecl final : public AstNodeCoverDecl { - // Coverage analysis point declaration - // Used for toggle coverage - const VNumRange m_range; // Packed array range covering each toggle bit -public: - AstCoverToggleDecl(FileLine* fl, const string& page, const string& comment, - const VNumRange& range) - : ASTGEN_SUPER_CoverToggleDecl(fl, page, comment) - , m_range{range} {} - ASTGEN_MEMBERS_AstCoverToggleDecl; - void dump(std::ostream& str) const override; - void dumpJson(std::ostream& str) const override; - int size() const override { return m_range.elements(); } - const VNumRange& range() const { return m_range; } - bool sameNode(const AstNode* samep) const override { - const AstCoverToggleDecl* const asamep = VN_DBG_AS(samep, CoverToggleDecl); - return AstNodeCoverDecl::sameNode(samep) && range() == asamep->range(); - } -}; // === AstNodeCoverOrAssert === class AstAssert final : public AstNodeCoverOrAssert { diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index a4f223e32..60a87ef90 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -2914,7 +2914,7 @@ void AstBegin::dumpJson(std::ostream& str) const { dumpJsonGen(str); } void AstNodeCoverDecl::dump(std::ostream& str) const { - this->AstNodeStmt::dump(str); + this->AstNode::dump(str); if (!page().empty()) str << " page=" << page(); if (this->dataDeclNullp()) { static bool s_recursing = false;