18 if (
auto appidOp = dyn_cast<esi::HasAppID>(op))
19 return appidOp.getAppID();
20 if (
auto appid = op->getAttrOfType<AppIDAttr>(AppIDAttr::AppIDAttrName))
32 LogicalResult
add(AppIDAttr
id, Operation *op,
bool inherited) {
35 return op->emitOpError(
"Found multiple identical AppIDs in same module")
36 .attachNote(existingIter->getSecond()->getLoc())
37 <<
"first AppID located here."
38 << (inherited ?
" Must insert appid to differentiate one instance "
39 "branch from the other."
47 FailureOr<Operation *>
lookup(AppIDAttr
id, Location loc)
const {
50 return emitError(loc,
"could not find appid '") <<
id <<
"'";
60 ArrayRef<std::pair<AppIDAttr, Operation *>>
getChildren()
const {
72AppIDIndex::AppIDIndex(Operation *mlirTop) : valid(true), mlirTop(mlirTop) {
73 Block &topBlock = mlirTop->getRegion(0).front();
74 symCache.addDefinitions(mlirTop);
78 for (
auto mod : topBlock.getOps<hw::HWModuleLike>())
79 if (failed(buildIndexFor(mod))) {
84AppIDIndex::~AppIDIndex() {
85 for (
auto [appId, childAppIDs] : containerAppIDs)
89ArrayAttr AppIDIndex::getChildAppIDsOf(hw::HWModuleLike fromMod)
const {
90 auto f = containerAppIDs.find(fromMod);
91 if (f == containerAppIDs.end())
92 return ArrayAttr::get(fromMod.getContext(), {});
94 const ModuleAppIDs *fromModIdx = f->getSecond();
95 SmallVector<Attribute, 8> attrs(llvm::map_range(
96 fromModIdx->getAppIDs(), [](AppIDAttr a) -> Attribute { return a; }));
97 return ArrayAttr::get(fromMod.getContext(), attrs);
101LogicalResult AppIDIndex::walk(
102 hw::HWModuleLike top, hw::HWModuleLike current,
103 SmallVectorImpl<AppIDAttr> &pathStack,
104 SmallVectorImpl<Operation *> &opStack,
105 function_ref<
void(AppIDPathAttr, ArrayRef<Operation *>)> fn)
const {
106 ModuleAppIDs *modIDs = containerAppIDs.lookup(current);
110 for (
auto [appid, op] : modIDs->getChildren()) {
120 auto inst = dyn_cast<hw::HWInstanceLike>(op);
121 assert(inst &&
"Search bottomed out. Invalid appid index.");
123 auto moduleNames = inst.getReferencedModuleNamesAttr();
124 if (moduleNames.size() != 1)
125 return inst.emitError(
"expected an instance with a single reference");
128 dyn_cast<hw::HWModuleLike>(symCache.getDefinition(moduleNames[0]));
129 assert(tgtMod &&
"invalid module reference");
131 ModuleAppIDs *ffModIds = containerAppIDs.at(tgtMod);
132 assert(ffModIds &&
"could not find module in index.");
134 auto opF = ffModIds->lookup(appid, op->getLoc());
136 "could not find appid in module index. Invalid index.");
144 opStack.push_back(op);
145 pathStack.push_back(appid);
148 AppIDPathAttr path = AppIDPathAttr::get(
149 current.getContext(), FlatSymbolRefAttr::get(top.getNameAttr()),
154 if (
auto inst = dyn_cast<hw::HWInstanceLike>(op)) {
155 auto moduleNames = inst.getReferencedModuleNamesAttr();
156 if (moduleNames.size() != 1)
157 return inst.emitError(
"expected an instance with a single reference");
160 dyn_cast<hw::HWModuleLike>(symCache.getDefinition(moduleNames[0]));
161 assert(tgtMod &&
"invalid module reference");
163 if (failed(walk(top, tgtMod, pathStack, opStack, fn)))
168 pathStack.pop_back();
174LogicalResult AppIDIndex::walk(
175 hw::HWModuleLike top,
176 function_ref<
void(AppIDPathAttr, ArrayRef<Operation *>)> fn)
const {
177 SmallVector<AppIDAttr, 8> path;
178 SmallVector<Operation *, 8> opStack;
179 return walk(top, top, path, opStack, fn);
181LogicalResult AppIDIndex::walk(
183 function_ref<
void(AppIDPathAttr, ArrayRef<Operation *>)> fn)
const {
184 Operation *op = symCache.getDefinition(
185 FlatSymbolRefAttr::get(mlirTop->getContext(), top));
186 if (
auto topMod = dyn_cast_or_null<hw::HWModuleLike>(op))
187 return walk(topMod, fn);
188 return mlirTop->emitOpError(
"Could not find module '") << top <<
"'";
191FailureOr<ArrayAttr> AppIDIndex::getAppIDPathAttr(hw::HWModuleLike fromMod,
193 Location loc)
const {
194 SmallVector<Attribute, 8> path;
196 auto f = containerAppIDs.find(fromMod);
197 if (f == containerAppIDs.end())
198 return emitError(loc,
"Could not find appid index for module '")
199 << fromMod.getName() <<
"'";
201 const ModuleAppIDs *modIDs = f->getSecond();
202 FailureOr<hw::InnerSymbolOpInterface> op = modIDs->lookup(appid, loc);
205 path.push_back(op->getInnerRef());
210 if (
auto inst = dyn_cast<hw::HWInstanceLike>(op->getOperation())) {
211 auto moduleNames = inst.getReferencedModuleNamesAttr();
212 if (moduleNames.size() != 1)
213 return inst.emitError(
"expected an instance with a single reference");
214 fromMod = cast<hw::HWModuleLike>(symCache.getDefinition(moduleNames[0]));
216 assert(
false &&
"Search bottomed out");
219 return ArrayAttr::get(fromMod.getContext(), path);
223FailureOr<const AppIDIndex::ModuleAppIDs *>
224AppIDIndex::buildIndexFor(hw::HWModuleLike mod) {
226 auto appidsIter = containerAppIDs.find(mod);
227 if (appidsIter != containerAppIDs.end())
228 return appidsIter->getSecond();
229 ModuleAppIDs *appIDs =
new ModuleAppIDs();
230 containerAppIDs.try_emplace(mod, appIDs);
232 auto done = mod.walk([&](Operation *op) {
236 if (AppIDAttr appid =
getAppID(op)) {
237 if (failed(appIDs->add(appid, op,
false)))
238 return WalkResult::interrupt();
239 return WalkResult::advance();
243 if (
auto inst = dyn_cast<hw::HWInstanceLike>(op)) {
244 auto moduleNames = inst.getReferencedModuleNamesAttr();
245 if (moduleNames.size() != 1) {
246 inst.emitError(
"expected an instance with a single reference");
247 return WalkResult::interrupt();
250 dyn_cast<hw::HWModuleLike>(symCache.getDefinition(moduleNames[0]));
252 assert(tgtMod &&
"invalid module reference");
255 FailureOr<const ModuleAppIDs *> childIds = buildIndexFor(tgtMod);
256 if (failed(childIds))
257 return WalkResult::interrupt();
260 for (AppIDAttr appid : (*childIds)->getAppIDs())
261 if (failed(appIDs->add(appid, op, true)))
262 return WalkResult::interrupt();
264 return WalkResult::advance();
267 if (done.wasInterrupted())
assert(baseType &&"element must be base type")
Helper class constructed on a per-HWModuleLike basis.
FailureOr< Operation * > lookup(AppIDAttr id, Location loc) const
SmallVector< std::pair< AppIDAttr, Operation * >, 8 > childAppIDPathsOrdered
LogicalResult add(AppIDAttr id, Operation *op, bool inherited)
Add an appid component to the index.
ArrayRef< std::pair< AppIDAttr, Operation * > > getChildren() const
DenseMap< AppIDAttr, Operation * > childAppIDPaths
AppIDAttr getAppID(Operation *op)
Get the AppID of a particular operation.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.