From e74cc32f2d372b551055f94c8b0ca54a1361811d Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 14 Nov 2020 16:13:06 -0500 Subject: [PATCH] Add internal assertion that VarScopes properly formed. --- src/V3Broken.cpp | 18 ++++++++++++++++++ src/V3Descope.cpp | 1 + src/V3Global.h | 3 +++ src/V3LinkDot.cpp | 1 + 4 files changed, 23 insertions(+) diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index f017c7fe5..de3a674b8 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -238,6 +238,8 @@ public: // Broken state, as a visitor of each AstNode class BrokenCheckVisitor : public AstNVisitor { + bool m_inScope = false; // Under AstScope + private: static void checkWidthMin(const AstNode* nodep) { UASSERT_OBJ(nodep->width() == nodep->widthMin() @@ -278,6 +280,22 @@ private: && !VN_CAST(nodep->lhsp(), NodeVarRef)->access().isWriteOrRW()), nodep, "Assignment LHS is not an lvalue"); } + virtual void visit(AstScope* nodep) override { + VL_RESTORER(m_inScope); + { + m_inScope = true; + processAndIterate(nodep); + } + } + virtual void visit(AstNodeVarRef* nodep) override { + processAndIterate(nodep); + // m_inScope because some Vars have initial variable references without scopes + // This might false fire with some debug flags, as not certain we don't have temporary + // clear varScopep's during some an infrequent dump just before we re-LinkDot. + UASSERT_OBJ( + !(v3Global.assertScoped() && m_inScope && nodep->varp() && !nodep->varScopep()), nodep, + "VarRef missing VarScope pointer"); + } virtual void visit(AstNode* nodep) override { // Process not just iterate processAndIterate(nodep); diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp index 9cf15822b..dcaddcae5 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -304,6 +304,7 @@ public: void V3Descope::descopeAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); + v3Global.assertScoped(false); { DescopeVisitor visitor(nodep); } // Destruct before checking V3Global::dumpCheckGlobalTree("descope", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); } diff --git a/src/V3Global.h b/src/V3Global.h index ec4b6d0f1..41afa569d 100644 --- a/src/V3Global.h +++ b/src/V3Global.h @@ -95,6 +95,7 @@ class V3Global { int m_debugFileNumber = 0; // Number to append to debug files created bool m_assertDTypesResolved = false; // Tree should have dtypep()'s + bool m_assertScoped = false; // Tree is scoped bool m_constRemoveXs = false; // Const needs to strip any Xs bool m_needHeavy = false; // Need verilated_heavy.h include bool m_needTraceDumper = false; // Need __Vm_dumperp in symbols @@ -125,6 +126,7 @@ public: AstNetlist* rootp() const { return m_rootp; } VWidthMinUsage widthMinUsage() const { return m_widthMinUsage; } bool assertDTypesResolved() const { return m_assertDTypesResolved; } + bool assertScoped() const { return m_assertScoped; } // METHODS void readFiles(); @@ -132,6 +134,7 @@ public: static void dumpCheckGlobalTree(const string& stagename, int newNumber = 0, bool doDump = true); void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; } + void assertScoped(bool flag) { m_assertScoped = flag; } void widthMinUsage(const VWidthMinUsage& flag) { m_widthMinUsage = flag; } bool constRemoveXs() const { return m_constRemoveXs; } void constRemoveXs(bool flag) { m_constRemoveXs = flag; } diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 7877f7b17..a7dac78db 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -2947,6 +2947,7 @@ void V3LinkDot::linkDotGuts(AstNetlist* rootp, VLinkDotStep step) { // Well after the initial link when we're ready to operate on the flat design, // process AstScope's. This needs to be separate pass after whole hierarchy graph created. LinkDotScopeVisitor visitors(rootp, &state); + v3Global.assertScoped(true); if (LinkDotState::debug() >= 5 || v3Global.opt.dumpTree() >= 9) { v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-scoped.tree")); }