mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 10:03:44 +02:00
Internals: Disambiguate variable references under with clauses of randomize() methods (#5277)
This commit is contained in:
+66
-17
@@ -65,6 +65,7 @@
|
||||
|
||||
#include "V3LinkDot.h"
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3Graph.h"
|
||||
#include "V3MemberMap.h"
|
||||
#include "V3Parse.h"
|
||||
@@ -2046,6 +2047,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
VSymEnt* m_curSymp = nullptr; // SymEnt for current lookup point
|
||||
VSymEnt* m_modSymp = nullptr; // SymEnt for current module
|
||||
VSymEnt* m_pinSymp = nullptr; // SymEnt for pin lookups
|
||||
VSymEnt* m_fromSymp = nullptr; // SymEnt for randomize lookups
|
||||
const AstCell* m_cellp = nullptr; // Current cell
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
AstNodeFTask* m_ftaskp = nullptr; // Current function/task
|
||||
@@ -2465,6 +2467,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
UINFO(8, " " << nodep << endl);
|
||||
const DotStates lastStates = m_ds;
|
||||
const bool start = (m_ds.m_dotPos == DP_NONE); // Save, as m_dotp will be changed
|
||||
VL_RESTORER(m_fromSymp);
|
||||
{
|
||||
if (start) { // Starting dot sequence
|
||||
if (debug() >= 9) nodep->dumpTree("- dot-in: ");
|
||||
@@ -2580,6 +2583,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
"ParseRefs should no longer exist");
|
||||
const DotStates lastStates = m_ds;
|
||||
const bool start = (m_ds.m_dotPos == DP_NONE); // Save, as m_dotp will be changed
|
||||
|
||||
if (start) {
|
||||
m_ds.init(m_curSymp);
|
||||
// Note m_ds.m_dot remains nullptr; this is a reference not under a dot
|
||||
@@ -2648,12 +2652,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
classOrPackagep = cpackagerefp->classOrPackagep();
|
||||
UASSERT_OBJ(classOrPackagep, m_ds.m_dotp->lhsp(), "Bad package link");
|
||||
if (cpackagerefp->name() == "local::") {
|
||||
if (m_pinSymp) {
|
||||
m_ds.m_dotSymp = m_curSymp->fallbackp();
|
||||
} else {
|
||||
nodep->v3error("Illegal 'local::' outside 'randomize() with'");
|
||||
m_ds.m_dotErr = true;
|
||||
}
|
||||
m_fromSymp = nullptr;
|
||||
} else {
|
||||
m_ds.m_dotSymp = m_statep->getNodeSym(classOrPackagep);
|
||||
}
|
||||
@@ -2675,6 +2674,19 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
VSymEnt* foundp;
|
||||
string baddot;
|
||||
VSymEnt* okSymp = nullptr;
|
||||
if (m_fromSymp) {
|
||||
foundp = m_fromSymp->findIdFlat(nodep->name());
|
||||
if (foundp) {
|
||||
UINFO(9, " randomize-with fromSym " << foundp->nodep() << endl);
|
||||
if (m_ds.m_dotPos != DP_NONE) m_ds.m_dotPos = DP_MEMBER;
|
||||
AstLambdaArgRef* const lambdaRefp
|
||||
= new AstLambdaArgRef{nodep->fileline(), "item", false};
|
||||
nodep->replaceWith(new AstMemberSel{nodep->fileline(), lambdaRefp,
|
||||
VFlagChildDType{}, nodep->name()});
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (allowScope) {
|
||||
foundp = m_statep->findDotted(nodep->fileline(), m_ds.m_dotSymp, nodep->name(),
|
||||
baddot, okSymp); // Maybe nullptr
|
||||
@@ -2730,8 +2742,12 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
}
|
||||
}
|
||||
} else if (allowFTask && VN_IS(foundp->nodep(), NodeFTask)) {
|
||||
AstTaskRef* const taskrefp
|
||||
= new AstTaskRef{nodep->fileline(), nodep->name(), nullptr};
|
||||
AstNodeFTaskRef* taskrefp;
|
||||
if (VN_IS(foundp->nodep(), Task)) {
|
||||
taskrefp = new AstTaskRef{nodep->fileline(), nodep->name(), nullptr};
|
||||
} else {
|
||||
taskrefp = new AstFuncRef{nodep->fileline(), nodep->name(), nullptr};
|
||||
}
|
||||
nodep->replaceWith(taskrefp);
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
if (start) m_ds = lastStates;
|
||||
@@ -2979,6 +2995,12 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
UINFO(4, "(Backto) Link ClassOrPackageRef: " << nodep << endl);
|
||||
iterateChildren(nodep);
|
||||
|
||||
if (nodep->name() == "local::") {
|
||||
if (!m_fromSymp) {
|
||||
nodep->v3error("Illegal 'local::' outside 'randomize() with'");
|
||||
m_ds.m_dotErr = true;
|
||||
}
|
||||
}
|
||||
AstClass* const modClassp = VN_CAST(m_modp, Class);
|
||||
if (m_statep->forPrimary() && refClassp && !nodep->paramsp()
|
||||
&& nodep->classOrPackagep()->hasGParam()
|
||||
@@ -3124,10 +3146,10 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
void visit(AstMethodCall* nodep) override {
|
||||
// Created here so should already be resolved.
|
||||
VL_RESTORER(m_ds);
|
||||
VL_RESTORER(m_pinSymp);
|
||||
VL_RESTORER(m_fromSymp);
|
||||
{
|
||||
m_ds.init(m_curSymp);
|
||||
if (nodep->name() == "randomize" && VN_IS(nodep->pinsp(), With)) {
|
||||
if (nodep->name() == "randomize" && nodep->pinsp()) {
|
||||
const AstNodeDType* fromDtp = nodep->fromp()->dtypep();
|
||||
if (!fromDtp) {
|
||||
if (const AstNodeVarRef* const varRefp = VN_CAST(nodep->fromp(), NodeVarRef)) {
|
||||
@@ -3157,8 +3179,16 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
nodep->v3error("'randomize() with' on a non-class-instance "
|
||||
<< fromDtp->prettyNameQ());
|
||||
else
|
||||
m_pinSymp = m_statep->getNodeSym(classDtp->classp());
|
||||
m_fromSymp = m_statep->getNodeSym(classDtp->classp());
|
||||
}
|
||||
AstNode* pinsp = nodep->pinsp();
|
||||
if (VN_IS(pinsp, With)) {
|
||||
iterate(pinsp);
|
||||
pinsp = pinsp->nextp();
|
||||
}
|
||||
m_fromSymp = nullptr;
|
||||
iterateAndNextNull(pinsp);
|
||||
return;
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
@@ -3191,6 +3221,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
VL_RESTORER(m_fromSymp);
|
||||
|
||||
bool staticAccess = false;
|
||||
if (m_ds.m_unresolvedClass) {
|
||||
// Unable to link before V3Param
|
||||
@@ -3210,12 +3242,12 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
staticAccess = true;
|
||||
AstClassOrPackageRef* const cpackagerefp
|
||||
= VN_AS(m_ds.m_dotp->lhsp(), ClassOrPackageRef);
|
||||
if (cpackagerefp->name() == "local") {
|
||||
nodep->v3warn(E_UNSUPPORTED,
|
||||
"Unsupported: " << AstNode::prettyNameQ(cpackagerefp->name()));
|
||||
}
|
||||
UASSERT_OBJ(cpackagerefp->classOrPackagep(), m_ds.m_dotp->lhsp(), "Bad package link");
|
||||
nodep->classOrPackagep(cpackagerefp->classOrPackagep());
|
||||
if (cpackagerefp->name() == "local::") {
|
||||
m_fromSymp = nullptr;
|
||||
} else {
|
||||
nodep->classOrPackagep(cpackagerefp->classOrPackagep());
|
||||
}
|
||||
// Class/package :: HERE function() . method_called_on_function_return_value()
|
||||
m_ds.m_dotPos = DP_MEMBER;
|
||||
m_ds.m_dotp = nullptr;
|
||||
@@ -3284,6 +3316,24 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
dotSymp = m_statep->findDotted(nodep->fileline(), dotSymp, nodep->dotted(), baddot,
|
||||
okSymp); // Maybe nullptr
|
||||
}
|
||||
if (m_fromSymp) {
|
||||
VSymEnt* const foundp = m_fromSymp->findIdFlat(nodep->name());
|
||||
if (foundp) {
|
||||
UINFO(9, " randomize-with fromSym " << foundp->nodep() << endl);
|
||||
AstNodeExpr* argsp = nullptr;
|
||||
if (nodep->pinsp()) {
|
||||
iterateAndNextNull(nodep->pinsp());
|
||||
argsp = nodep->pinsp()->unlinkFrBackWithNext();
|
||||
}
|
||||
if (m_ds.m_dotPos != DP_NONE) m_ds.m_dotPos = DP_MEMBER;
|
||||
AstNode* const newp = new AstMethodCall{
|
||||
nodep->fileline(), new AstLambdaArgRef{nodep->fileline(), "item", false},
|
||||
VFlagChildDType{}, nodep->name(), argsp};
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
return;
|
||||
}
|
||||
}
|
||||
VSymEnt* const foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot);
|
||||
AstNodeFTask* const taskp
|
||||
= foundp ? VN_CAST(foundp->nodep(), NodeFTask) : nullptr; // Maybe nullptr
|
||||
@@ -3524,7 +3574,6 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||
VL_RESTORER(m_curSymp);
|
||||
{
|
||||
m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep);
|
||||
if (m_pinSymp) m_curSymp->importFromClass(m_statep->symsp(), m_pinSymp);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
m_ds.m_dotSymp = VL_RESTORER_PREV(m_curSymp);
|
||||
|
||||
Reference in New Issue
Block a user