mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Internals: Simplify CaptureVisitor
in V3Randomize
(#5397)
This commit is contained in:
parent
ed7040adc0
commit
eb8bbcda05
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user