forked from github/verilator
Add internal assertion that VarScopes properly formed.
This commit is contained in:
parent
c64cc989f0
commit
e74cc32f2d
@ -238,6 +238,8 @@ public:
|
|||||||
// Broken state, as a visitor of each AstNode
|
// Broken state, as a visitor of each AstNode
|
||||||
|
|
||||||
class BrokenCheckVisitor : public AstNVisitor {
|
class BrokenCheckVisitor : public AstNVisitor {
|
||||||
|
bool m_inScope = false; // Under AstScope
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void checkWidthMin(const AstNode* nodep) {
|
static void checkWidthMin(const AstNode* nodep) {
|
||||||
UASSERT_OBJ(nodep->width() == nodep->widthMin()
|
UASSERT_OBJ(nodep->width() == nodep->widthMin()
|
||||||
@ -278,6 +280,22 @@ private:
|
|||||||
&& !VN_CAST(nodep->lhsp(), NodeVarRef)->access().isWriteOrRW()),
|
&& !VN_CAST(nodep->lhsp(), NodeVarRef)->access().isWriteOrRW()),
|
||||||
nodep, "Assignment LHS is not an lvalue");
|
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 {
|
virtual void visit(AstNode* nodep) override {
|
||||||
// Process not just iterate
|
// Process not just iterate
|
||||||
processAndIterate(nodep);
|
processAndIterate(nodep);
|
||||||
|
@ -304,6 +304,7 @@ public:
|
|||||||
|
|
||||||
void V3Descope::descopeAll(AstNetlist* nodep) {
|
void V3Descope::descopeAll(AstNetlist* nodep) {
|
||||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||||
|
v3Global.assertScoped(false);
|
||||||
{ DescopeVisitor visitor(nodep); } // Destruct before checking
|
{ DescopeVisitor visitor(nodep); } // Destruct before checking
|
||||||
V3Global::dumpCheckGlobalTree("descope", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
V3Global::dumpCheckGlobalTree("descope", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,7 @@ class V3Global {
|
|||||||
|
|
||||||
int m_debugFileNumber = 0; // Number to append to debug files created
|
int m_debugFileNumber = 0; // Number to append to debug files created
|
||||||
bool m_assertDTypesResolved = false; // Tree should have dtypep()'s
|
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_constRemoveXs = false; // Const needs to strip any Xs
|
||||||
bool m_needHeavy = false; // Need verilated_heavy.h include
|
bool m_needHeavy = false; // Need verilated_heavy.h include
|
||||||
bool m_needTraceDumper = false; // Need __Vm_dumperp in symbols
|
bool m_needTraceDumper = false; // Need __Vm_dumperp in symbols
|
||||||
@ -125,6 +126,7 @@ public:
|
|||||||
AstNetlist* rootp() const { return m_rootp; }
|
AstNetlist* rootp() const { return m_rootp; }
|
||||||
VWidthMinUsage widthMinUsage() const { return m_widthMinUsage; }
|
VWidthMinUsage widthMinUsage() const { return m_widthMinUsage; }
|
||||||
bool assertDTypesResolved() const { return m_assertDTypesResolved; }
|
bool assertDTypesResolved() const { return m_assertDTypesResolved; }
|
||||||
|
bool assertScoped() const { return m_assertScoped; }
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
void readFiles();
|
void readFiles();
|
||||||
@ -132,6 +134,7 @@ public:
|
|||||||
static void dumpCheckGlobalTree(const string& stagename, int newNumber = 0,
|
static void dumpCheckGlobalTree(const string& stagename, int newNumber = 0,
|
||||||
bool doDump = true);
|
bool doDump = true);
|
||||||
void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; }
|
void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; }
|
||||||
|
void assertScoped(bool flag) { m_assertScoped = flag; }
|
||||||
void widthMinUsage(const VWidthMinUsage& flag) { m_widthMinUsage = flag; }
|
void widthMinUsage(const VWidthMinUsage& flag) { m_widthMinUsage = flag; }
|
||||||
bool constRemoveXs() const { return m_constRemoveXs; }
|
bool constRemoveXs() const { return m_constRemoveXs; }
|
||||||
void constRemoveXs(bool flag) { m_constRemoveXs = flag; }
|
void constRemoveXs(bool flag) { m_constRemoveXs = flag; }
|
||||||
|
@ -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,
|
// 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.
|
// process AstScope's. This needs to be separate pass after whole hierarchy graph created.
|
||||||
LinkDotScopeVisitor visitors(rootp, &state);
|
LinkDotScopeVisitor visitors(rootp, &state);
|
||||||
|
v3Global.assertScoped(true);
|
||||||
if (LinkDotState::debug() >= 5 || v3Global.opt.dumpTree() >= 9) {
|
if (LinkDotState::debug() >= 5 || v3Global.opt.dumpTree() >= 9) {
|
||||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-scoped.tree"));
|
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-scoped.tree"));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user