Internals: Simplify CaptureVisitor in V3Randomize (#5397)

This commit is contained in:
Krzysztof Bieganski 2024-08-23 13:57:57 +02:00 committed by GitHub
parent ed7040adc0
commit eb8bbcda05
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -122,6 +122,7 @@ class RandomizeMarkVisitor final : public VNVisitor {
// randomized variable
// AstVar::user1() -> bool. Set true to indicate needs rand_mode
// AstVar::user2p() -> AstNodeModule*. Pointer to containing module
// AstNodeFTask::user2p() -> AstNodeModule*. Pointer to containing module
const VNUser1InUse m_inuser1;
const VNUser2InUse m_inuser2;
@ -432,6 +433,10 @@ class RandomizeMarkVisitor final : public VNVisitor {
m_modp = nodep;
iterateChildrenConst(nodep);
}
void visit(AstNodeFTask* nodep) override {
nodep->user2p(m_modp);
iterateChildrenConst(nodep);
}
void visit(AstVar* nodep) override {
nodep->user2p(m_modp);
iterateChildrenConst(nodep);
@ -770,63 +775,6 @@ public:
}
};
class ClassLookupHelper final {
std::set<AstNodeModule*> m_visibleModules; // Modules directly reachable from our lookup point
std::map<AstNode*, AstNodeModule*>
m_classMap; // Memoized mapping between nodes and modules that define them
// BFS search
template <typename Action>
static void foreachSuperClass(AstClass* classp, Action action) {
std::queue<AstClass*> classes;
classes.push(classp);
while (!classes.empty()) {
classp = classes.front();
classes.pop();
for (AstClassExtends* extendsp = classp->extendsp(); extendsp;
extendsp = VN_AS(extendsp->nextp(), ClassExtends)) {
AstClass* const superClassp
= VN_AS(extendsp->childDTypep(), ClassRefDType)->classp();
action(superClassp);
classes.push(superClassp);
}
}
}
static std::set<AstNodeModule*> initVisibleModules(AstClass* classp) {
std::set<AstNodeModule*> visibleModules = {classp};
std::vector<AstNodeModule*> symLookupOrder = {classp};
foreachSuperClass(classp,
[&](AstClass* superclassp) { visibleModules.emplace(superclassp); });
return visibleModules;
}
public:
bool moduleInClassHierarchy(AstNodeModule* modp) const {
return m_visibleModules.count(modp) != 0;
}
AstNodeModule* findDeclaringModule(AstNode* nodep, bool classHierarchyOnly = true) {
auto it = m_classMap.find(nodep);
if (it != m_classMap.end()) return it->second;
for (AstNode* backp = nodep; backp; backp = backp->backp()) {
AstNodeModule* const modp = VN_CAST(backp, NodeModule);
if (modp) {
m_classMap.emplace(nodep, modp);
if (classHierarchyOnly)
UASSERT_OBJ(moduleInClassHierarchy(modp), nodep,
"Node does not belong to class");
return modp;
}
}
return nullptr;
}
ClassLookupHelper(AstClass* classp) {
if (classp) m_visibleModules = initVisibleModules(classp);
}
};
enum class CaptureMode : uint8_t {
CAP_NO = 0x0,
CAP_VALUE = 0x01,
@ -852,7 +800,6 @@ class CaptureVisitor final : public VNVisitor {
AstClass* m_targetp; // Module of inner context (for symbol lookup)
std::map<const AstVar*, AstVar*> m_varCloneMap; // Map original var nodes to their clones
std::set<AstNode*> m_ignore; // Nodes to ignore for capturing
ClassLookupHelper m_lookup; // Util for class lookup
AstVar* m_thisp = nullptr; // Variable for outer context's object, if necessary
// METHODS
@ -877,7 +824,7 @@ class CaptureVisitor final : public VNVisitor {
template <typename NodeT>
void fixupClassOrPackage(AstNode* memberp, NodeT refp) {
AstNodeModule* const declClassp = m_lookup.findDeclaringModule(memberp, false);
AstNodeModule* const declClassp = VN_AS(memberp->user2p(), NodeModule);
if (declClassp != m_targetp) refp->classOrPackagep(declClassp);
}
@ -907,20 +854,19 @@ class CaptureVisitor final : public VNVisitor {
}
CaptureMode getVarRefCaptureMode(AstNodeVarRef* varRefp) {
AstNodeModule* const modp = m_lookup.findDeclaringModule(varRefp->varp(), false);
AstNodeModule* const varModp = VN_AS(varRefp->varp()->user2p(), NodeModule);
AstClass* const varClassp = VN_CAST(varModp, Class);
AstClass* const callerClassp = VN_CAST(m_callerp, Class);
const bool callerIsClass = VN_IS(m_callerp, Class);
const bool callerIsClass = callerClassp;
const bool refIsXref = VN_IS(varRefp, VarXRef);
const bool varIsFuncLocal = varRefp->varp()->isFuncLocal();
const bool varHasAutomaticLifetime = varRefp->varp()->lifetime().isAutomatic();
const bool varIsDeclaredInCaller = modp == m_callerp;
const bool varIsFieldOfCaller = modp ? m_lookup.moduleInClassHierarchy(modp) : false;
const bool varIsFieldOfCaller = AstClass::isClassExtendedFrom(callerClassp, varClassp);
if (refIsXref) return CaptureMode::CAP_VALUE | CaptureMode::CAP_F_XREF;
if (varIsFuncLocal && varHasAutomaticLifetime) return CaptureMode::CAP_VALUE;
// Static var in function (will not be inlined, because it's in class)
if (callerIsClass && varIsFuncLocal) return CaptureMode::CAP_VALUE;
if (callerIsClass && varIsDeclaredInCaller) return CaptureMode::CAP_THIS;
if (callerIsClass && varIsFieldOfCaller) return CaptureMode::CAP_THIS;
UASSERT_OBJ(!callerIsClass, varRefp, "Invalid reference?");
return CaptureMode::CAP_VALUE;
@ -983,7 +929,7 @@ class CaptureVisitor final : public VNVisitor {
iterateChildren(nodep);
return;
}
AstClass* classp = VN_CAST(m_lookup.findDeclaringModule(nodep->taskp(), false), Class);
AstClass* classp = VN_CAST(nodep->taskp()->user2p(), Class);
if ((classp == m_callerp) && VN_IS(m_callerp, Class)) {
AstNodeExpr* const pinsp = nodep->pinsp();
if (pinsp) pinsp->unlinkFrBack();
@ -1040,8 +986,7 @@ public:
explicit CaptureVisitor(AstNode* const nodep, AstNodeModule* callerp, AstClass* const targetp)
: m_argsp(nullptr)
, m_callerp(callerp)
, m_targetp(targetp)
, m_lookup(VN_CAST(callerp, Class)) {
, m_targetp(targetp) {
iterateAndNextNull(nodep);
}
@ -1072,7 +1017,8 @@ class RandomizeVisitor final : public VNVisitor {
// NODE STATE
// Cleared on Netlist
// AstClass::user1() -> bool. Set true to indicate needs randomize processing
// AstVar::user2p() -> AstClass*. Pointer to containing class
// AstVar::user2p() -> AstNodeModule*. Pointer to containing module
// AstNodeFTask::user2p() -> AstNodeModule*. Pointer to containing module
// AstEnumDType::user2() -> AstVar*. Pointer to table with enum values
// AstConstraint::user2p() -> AstTask*. Pointer to constraint setup procedure
// AstClass::user2p() -> AstVar*. Rand mode state variable