CIRCT 23.0.0git
Loading...
Searching...
No Matches
HierarchicalNames.cpp
Go to the documentation of this file.
1//===- Expressions.cpp - Slang expression conversion ----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
11using namespace circt;
12using namespace ImportVerilog;
13
14/// Traverse the instance body.
15namespace {
16struct InstBodyVisitor
17 : public slang::ast::ASTVisitor<InstBodyVisitor,
18 /*VisitStatements=*/true,
19 /*VisitExpressions=*/true> {
20
21 InstBodyVisitor(Context &context, const slang::ast::Symbol &outermostModule)
22 : context(context), outermostModule(outermostModule) {}
23
24 void handle(const slang::ast::InstanceSymbol &instNode) {
25 context.traverseInstanceBody(instNode.body);
26 }
27
28 void handle(const slang::ast::HierarchicalValueExpression &expr) {
29 auto builder = context.builder;
30 auto *currentInstBody =
31 expr.symbol.getParentScope()->getContainingInstance();
32 auto *outermostInstBody =
33 outermostModule.as_if<slang::ast::InstanceBodySymbol>();
34
35 // Like module Foo; int a; Foo.a; endmodule.
36 // Ignore "Foo.a" invoked by this module itself.
37 if (currentInstBody == outermostInstBody)
38 return;
39
40 auto hierName = builder.getStringAttr(expr.symbol.name);
41 const slang::ast::InstanceBodySymbol *parentInstBody = nullptr;
42
43 // Collect hierarchical names that are added to the port list.
44 std::function<void(const slang::ast::InstanceBodySymbol *, bool)>
45 collectHierarchicalPaths = [&](auto sym, bool isUpward) {
46 // Here we use "sameHierPaths" to avoid collecting the repeat
47 // hierarchical names on the same path.
48 if (!context.sameHierPaths.contains(hierName) ||
49 !context.hierPaths.contains(sym)) {
50 context.hierPaths[sym].push_back(
51 HierPathInfo{hierName,
52 {},
53 isUpward ? slang::ast::ArgumentDirection::Out
54 : slang::ast::ArgumentDirection::In,
55 &expr.symbol});
56 context.sameHierPaths.insert(hierName);
57 }
58
59 // Iterate up from the current instance body symbol until meeting the
60 // outermost module.
61 parentInstBody =
62 sym->parentInstance->getParentScope()->getContainingInstance();
63 if (!parentInstBody)
64 return;
65
66 if (isUpward) {
67 // Avoid collecting hierarchical names into the outermost module.
68 if (parentInstBody && parentInstBody != outermostInstBody) {
69 hierName =
70 builder.getStringAttr(sym->parentInstance->name +
71 llvm::Twine(".") + hierName.getValue());
72 collectHierarchicalPaths(parentInstBody, isUpward);
73 }
74 } else {
75 if (parentInstBody && parentInstBody != currentInstBody)
76 collectHierarchicalPaths(parentInstBody, isUpward);
77 }
78 };
79
80 // Determine whether hierarchical names are upward or downward.
81 auto *tempInstBody = currentInstBody;
82 while (tempInstBody) {
83 tempInstBody = tempInstBody->parentInstance->getParentScope()
84 ->getContainingInstance();
85 if (tempInstBody == outermostInstBody) {
86 collectHierarchicalPaths(currentInstBody, true);
87 return;
88 }
89 }
90
91 hierName = builder.getStringAttr(currentInstBody->parentInstance->name +
92 llvm::Twine(".") + hierName.getValue());
93 collectHierarchicalPaths(outermostInstBody, false);
94 }
95
96 Context &context;
97 const slang::ast::Symbol &outermostModule;
98};
99
100} // namespace
101
102void Context::traverseInstanceBody(const slang::ast::Symbol &symbol) {
103 if (auto *instBodySymbol = symbol.as_if<slang::ast::InstanceBodySymbol>())
104 for (auto &member : instBodySymbol->members()) {
105 auto &outermostModule = member.getParentScope()->asSymbol();
106 InstBodyVisitor visitor(*this, outermostModule);
107 member.visit(visitor);
108 }
109}
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
A helper class to facilitate the conversion from a Slang AST to MLIR operations.
void traverseInstanceBody(const slang::ast::Symbol &symbol)