Revisit unresolved `ParseRef`s and `Dot`s

Signed-off-by: Krzysztof Bieganski <kbieganski@antmicro.com>
This commit is contained in:
Krzysztof Bieganski 2025-02-26 14:04:15 +01:00
parent f122f25a16
commit d16f8af63c
2 changed files with 48 additions and 7 deletions

View File

@ -2256,6 +2256,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
bool m_insideClassExtParam = false; // Inside a class from m_extendsParam
bool m_explicitSuperNew = false; // Hit a "super.new" call inside a "new" function
std::map<AstNode*, AstPin*> m_usedPins; // Pin used in this cell, map to duplicate
std::map<std::string, AstNodeModule*> m_modulesToRevisit; // Modules to revisit a second time
AstNode* m_lastDeferredp = nullptr; // Last node which requested a revisit of its module
struct DotStates final {
DotPosition m_dotPos; // Scope part of dotted resolution
@ -2501,6 +2503,13 @@ class LinkDotResolveVisitor final : public VNVisitor {
symIterateNull(nodep, m_statep->getNodeSym(nodep));
}
// Marks the current module to be revisited after the initial AST iteration
void revisitLater(AstNode* deferredNodep) {
// Need to revisit entire module to build up all the necessary context
m_lastDeferredp = deferredNodep;
m_modulesToRevisit.insert(std::make_pair(m_modp->name(), m_modp));
}
void updateVarUse(AstVar* nodep) {
// Avoid dotted.PARAM false positive when in a parameter block
// that is if ()'ed off by same dotted name as another block
@ -2745,23 +2754,38 @@ class LinkDotResolveVisitor final : public VNVisitor {
}
}
}
} else if (VN_IS(nodep->lhsp(), ClassOrPackageRef)) {
} else if (AstClassOrPackageRef* const lhsp
= VN_CAST(nodep->lhsp(), ClassOrPackageRef)) {
// m_ds.m_dotText communicates the cell prefix between stages
UINFO(8, indent() << "iter.lhs " << m_ds.ascii() << " " << nodep << endl);
iterateAndNextNull(nodep->lhsp());
iterateAndNextNull(lhsp);
m_ds.m_dotPos = DP_PACKAGE;
// nodep->lhsp() may be a new node
if (AstClassOrPackageRef* const classOrPackageRefp
= VN_CAST(nodep->lhsp(), ClassOrPackageRef)) {
if (AstNode* classOrPackageNodep = classOrPackageRefp->classOrPackageNodep()) {
if (AstNode* classOrPackageNodep = classOrPackageRefp->classOrPackageSkipp()) {
m_ds.m_dotSymp = m_statep->getNodeSym(classOrPackageNodep);
}
}
UINFO(8, indent() << "iter.ldone " << m_ds.ascii() << " " << nodep << endl);
} else if ((VN_IS(nodep->lhsp(), Dot) && VN_AS(nodep->lhsp(), Dot)->colon())) {
} else if (VN_IS(nodep->lhsp(), Dot) && VN_AS(nodep->lhsp(), Dot)->colon()) {
// m_ds.m_dotText communicates the cell prefix between stages
UINFO(8, indent() << "iter.lhs " << m_ds.ascii() << " " << nodep << endl);
m_ds.m_dotPos = DP_PACKAGE;
iterateAndNextNull(nodep->lhsp());
// nodep->lhsp() may be a new node
if (AstClassOrPackageRef* const crefp
= VN_CAST(nodep->lhsp(), ClassOrPackageRef)) {
if (!crefp->classOrPackageSkipp()) {
revisitLater(nodep);
m_ds = lastStates;
return;
}
}
if (m_lastDeferredp == nodep->lhsp()) {
m_ds = lastStates;
return;
}
UINFO(8, indent() << "iter.ldone " << m_ds.ascii() << " " << nodep << endl);
} else {
m_ds.m_dotPos = DP_FIRST;
@ -2947,7 +2971,12 @@ class LinkDotResolveVisitor final : public VNVisitor {
m_ds.m_dotSymp, cpackagerefp, true, false, ":: reference");
if (!foundp) return;
classOrPackagep = cpackagerefp->classOrPackageSkipp();
m_ds.m_dotSymp = m_statep->getNodeSym(classOrPackagep);
if (classOrPackagep) {
m_ds.m_dotSymp = m_statep->getNodeSym(classOrPackagep);
} else {
m_ds = lastStates;
return;
}
} else {
classOrPackagep = cpackagerefp->classOrPackageSkipp();
UASSERT_OBJ(classOrPackagep, m_ds.m_dotp->lhsp(), "Bad package link");
@ -3312,6 +3341,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
// ClassRef's have pins, so track
if (nodep->classOrPackageSkipp()) {
m_pinSymp = m_statep->getNodeSym(nodep->classOrPackageSkipp());
} else if (nodep->name() != "local::") {
return;
}
AstClass* const refClassp = VN_CAST(nodep->classOrPackageSkipp(), Class);
// Make sure any extends() are properly imported within referenced class
@ -4340,6 +4371,13 @@ public:
: m_statep{statep} {
UINFO(4, __FUNCTION__ << ": " << endl);
iterate(rootp);
auto modulesToRevisit = std::move(m_modulesToRevisit);
m_lastDeferredp = nullptr;
for (auto& p : modulesToRevisit) {
AstNodeModule* const modp = p.second;
modp->foreach([](AstNode* const nodep) { nodep->user3(false); });
iterate(modp);
}
}
~LinkDotResolveVisitor() override = default;
};

View File

@ -5,10 +5,12 @@
// SPDX-License-Identifier: CC0-1.0
typedef class Bar;
typedef Bar Baz;
module t;
initial begin
Bar::Qux::boo();
Bar::Qux::boo(1);
Baz::Qux::boo(1);
if (!Bar::Qux::finish) $stop;
$write("*-* All Finished *-*\n");
$finish;
@ -17,7 +19,8 @@ endmodule
class Foo #(type T);
static logic finish = 0;
static function void boo();
static function void boo(input logic rec);
if (rec) Bar::Qux::boo(0);
finish = 1;
endfunction
endclass