12using namespace ImportVerilog;
17 :
public slang::ast::ASTVisitor<InstBodyVisitor,
18 slang::ast::VisitFlags::AllGood> {
20 Context &context,
const slang::ast::Symbol &outermostModule,
21 DenseSet<const slang::ast::InstanceBodySymbol *> &visitedBodies)
22 : context(context), outermostModule(outermostModule),
23 visitedBodies(visitedBodies) {}
25 void handle(
const slang::ast::InstanceSymbol &instNode) {
26 traverseInstanceBody(context, instNode, visitedBodies);
29 for (
auto *conn : instNode.getPortConnections())
30 if (auto *connExpr =
conn->getExpression())
31 connExpr->visit(*this);
34 void handle(
const slang::ast::HierarchicalValueExpression &expr) {
35 auto builder = context.builder;
36 auto *currentInstBody =
37 expr.symbol.getParentScope()->getContainingInstance();
38 auto *outermostInstBody =
39 outermostModule.as_if<slang::ast::InstanceBodySymbol>();
43 if (currentInstBody == outermostInstBody)
51 if (expr.ref.isViaIfacePort())
57 auto hierName = builder.getStringAttr(expr.symbol.name);
58 const slang::ast::InstanceBodySymbol *parentInstBody =
nullptr;
62 auto addHierPath = [&](
const slang::ast::InstanceBodySymbol *body,
63 mlir::StringAttr name,
64 slang::ast::ArgumentDirection direction) {
65 for (
auto &path : context.hierPaths[body])
66 if (path.hierName == name) {
67 if (!llvm::any_of(path.valueSyms, [&](
auto &alias) {
68 return alias.first == &expr.symbol;
70 path.valueSyms.push_back({&expr.symbol, currentInstBody});
73 context.hierPaths[body].push_back(
74 HierPathInfo{name, {}, direction, {{&expr.symbol, currentInstBody}}});
77 auto *tempInstBody = currentInstBody;
78 while (tempInstBody) {
79 tempInstBody = tempInstBody->parentInstance->getParentScope()
80 ->getContainingInstance();
81 if (tempInstBody == outermostInstBody) {
84 SmallVector<const slang::ast::InstanceSymbol *> instChain;
85 for (
auto *b = currentInstBody; b && b != outermostInstBody;
86 b = b->parentInstance->getParentScope()->getContainingInstance())
87 instChain.push_back(b->parentInstance);
95 SmallVector<const slang::ast::InstanceBodySymbol *> canonChain(
97 const slang::ast::InstanceBodySymbol *parentCanon = outermostInstBody;
98 for (
size_t i = instChain.size(); i-- > 0;) {
99 const slang::ast::InstanceSymbol *inst = instChain[i];
100 if (inst->getParentScope()->getContainingInstance() != parentCanon)
101 if (
auto *resolved = parentCanon->find(inst->name))
102 if (
auto *resolvedInst =
103 resolved->as_if<slang::ast::InstanceSymbol>())
106 parentCanon = canonChain[i];
108 for (
size_t i = 0; i < instChain.size(); ++i) {
109 addHierPath(canonChain[i], hierName,
110 slang::ast::ArgumentDirection::Out);
111 hierName = builder.getStringAttr(
112 instChain[i]->name + llvm::Twine(
".") + hierName.getValue());
120 std::function<void(
const slang::ast::InstanceBodySymbol *)>
121 collectHierarchicalPaths = [&](
auto sym) {
123 slang::ast::ArgumentDirection::In);
125 sym->parentInstance->getParentScope()->getContainingInstance();
126 if (parentInstBody && parentInstBody != currentInstBody)
127 collectHierarchicalPaths(parentInstBody);
129 hierName = builder.getStringAttr(currentInstBody->parentInstance->name +
130 llvm::Twine(
".") + hierName.getValue());
131 collectHierarchicalPaths(outermostInstBody);
135 const slang::ast::Symbol &outermostModule;
136 DenseSet<const slang::ast::InstanceBodySymbol *> &visitedBodies;
138 static void traverseInstanceBody(
139 Context &context,
const slang::ast::InstanceSymbol &symbol,
140 DenseSet<const slang::ast::InstanceBodySymbol *> &visitedBodies) {
142 if (visitedBodies.insert(body).second) {
143 for (
auto &member : body->members()) {
144 auto &outermostModule = member.getParentScope()->asSymbol();
145 InstBodyVisitor visitor(context, outermostModule, visitedBodies);
146 member.visit(visitor);
154void Context::traverseInstanceBody(
const slang::ast::InstanceSymbol &symbol) {
157 DenseSet<const slang::ast::InstanceBodySymbol *> visitedBodies;
158 InstBodyVisitor::traverseInstanceBody(*
this, symbol, visitedBodies);
const slang::ast::InstanceBodySymbol * getCanonicalBody(const slang::ast::InstanceSymbol &inst)
Get the slang canonical body for the given instance, if there is one.
bool isCompileTimeConstant(slang::ast::SymbolKind kind)
Return true if symbols of this kind are elaboration-time constants.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
A helper class to facilitate the conversion from a Slang AST to MLIR operations.
Hierarchical path information.