14 using namespace circt;
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) {
33 if (childAppIDPaths.find(
id) != childAppIDPaths.end()) {
34 return op->emitOpError(
"Found multiple identical AppIDs in same module")
35 .attachNote(childAppIDPaths[
id]->getLoc())
36 <<
"first AppID located here."
37 << (inherited ?
" Must insert appid to differentiate one instance "
38 "branch from the other."
41 childAppIDPaths[id] = op;
42 childAppIDPathsOrdered.emplace_back(
id, op);
46 FailureOr<Operation *>
lookup(AppIDAttr
id, Location loc)
const {
47 auto f = childAppIDPaths.find(
id);
48 if (f == childAppIDPaths.end())
49 return emitError(loc,
"could not find appid '") <<
id <<
"'";
55 return llvm::make_first_range(childAppIDPathsOrdered);
59 ArrayRef<std::pair<AppIDAttr, Operation *>>
getChildren()
const {
60 return childAppIDPathsOrdered;
72 Block &topBlock = mlirTop->getRegion(0).front();
73 symCache.addDefinitions(mlirTop);
77 for (
auto mod : topBlock.getOps<hw::HWModuleLike>())
78 if (failed(buildIndexFor(mod))) {
83 AppIDIndex::~AppIDIndex() {
84 for (
auto [appId, childAppIDs] : containerAppIDs)
88 ArrayAttr AppIDIndex::getChildAppIDsOf(hw::HWModuleLike fromMod)
const {
89 auto f = containerAppIDs.find(fromMod);
90 if (f == containerAppIDs.end())
93 const ModuleAppIDs *fromModIdx = f->getSecond();
94 SmallVector<Attribute, 8> attrs(llvm::map_range(
95 fromModIdx->getAppIDs(), [](AppIDAttr a) -> Attribute { return a; }));
100 LogicalResult AppIDIndex::walk(
101 hw::HWModuleLike top, hw::HWModuleLike current,
102 SmallVectorImpl<AppIDAttr> &pathStack,
103 SmallVectorImpl<Operation *> &opStack,
104 function_ref<
void(AppIDPathAttr, ArrayRef<Operation *>)> fn)
const {
105 ModuleAppIDs *modIDs = containerAppIDs.lookup(current);
109 for (
auto [appid, op] : modIDs->getChildren()) {
119 auto inst = dyn_cast<hw::HWInstanceLike>(op);
120 assert(inst &&
"Search bottomed out. Invalid appid index.");
122 auto moduleNames = inst.getReferencedModuleNamesAttr();
123 if (moduleNames.size() != 1)
124 return inst.emitError(
"expected an instance with a single reference");
127 dyn_cast<hw::HWModuleLike>(symCache.getDefinition(moduleNames[0]));
128 assert(tgtMod &&
"invalid module reference");
130 ModuleAppIDs *ffModIds = containerAppIDs.at(tgtMod);
131 assert(ffModIds &&
"could not find module in index.");
133 auto opF = ffModIds->lookup(appid, op->getLoc());
135 "could not find appid in module index. Invalid index.");
143 opStack.push_back(op);
144 pathStack.push_back(appid);
153 if (
auto inst = dyn_cast<hw::HWInstanceLike>(op)) {
154 auto moduleNames = inst.getReferencedModuleNamesAttr();
155 if (moduleNames.size() != 1)
156 return inst.emitError(
"expected an instance with a single reference");
159 dyn_cast<hw::HWModuleLike>(symCache.getDefinition(moduleNames[0]));
160 assert(tgtMod &&
"invalid module reference");
162 if (failed(walk(top, tgtMod, pathStack, opStack, fn)))
167 pathStack.pop_back();
173 LogicalResult AppIDIndex::walk(
174 hw::HWModuleLike top,
175 function_ref<
void(AppIDPathAttr, ArrayRef<Operation *>)> fn)
const {
176 SmallVector<AppIDAttr, 8> path;
177 SmallVector<Operation *, 8> opStack;
178 return walk(top, top, path, opStack, fn);
180 LogicalResult AppIDIndex::walk(
182 function_ref<
void(AppIDPathAttr, ArrayRef<Operation *>)> fn)
const {
183 Operation *op = symCache.getDefinition(
185 if (
auto topMod = dyn_cast_or_null<hw::HWModuleLike>(op))
186 return walk(topMod, fn);
187 return mlirTop->emitOpError(
"Could not find module '") << top <<
"'";
190 FailureOr<ArrayAttr> AppIDIndex::getAppIDPathAttr(hw::HWModuleLike fromMod,
192 Location loc)
const {
193 SmallVector<Attribute, 8> path;
195 auto f = containerAppIDs.find(fromMod);
196 if (f == containerAppIDs.end())
197 return emitError(loc,
"Could not find appid index for module '")
198 << fromMod.getName() <<
"'";
200 const ModuleAppIDs *modIDs = f->getSecond();
201 FailureOr<hw::InnerSymbolOpInterface> op = modIDs->lookup(appid, loc);
204 path.push_back(op->getInnerRef());
209 if (
auto inst = dyn_cast<hw::HWInstanceLike>(op->getOperation())) {
210 auto moduleNames = inst.getReferencedModuleNamesAttr();
211 if (moduleNames.size() != 1)
212 return inst.emitError(
"expected an instance with a single reference");
213 fromMod = cast<hw::HWModuleLike>(symCache.getDefinition(moduleNames[0]));
215 assert(
false &&
"Search bottomed out");
222 FailureOr<const AppIDIndex::ModuleAppIDs *>
223 AppIDIndex::buildIndexFor(hw::HWModuleLike mod) {
225 ModuleAppIDs *&appIDs = containerAppIDs[mod];
226 if (appIDs !=
nullptr)
228 appIDs =
new ModuleAppIDs();
230 auto done = mod.walk([&](Operation *op) {
234 if (AppIDAttr appid =
getAppID(op)) {
235 if (failed(appIDs->add(appid, op,
false)))
236 return WalkResult::interrupt();
237 return WalkResult::advance();
241 if (
auto inst = dyn_cast<hw::HWInstanceLike>(op)) {
242 auto moduleNames = inst.getReferencedModuleNamesAttr();
243 if (moduleNames.size() != 1) {
244 inst.emitError(
"expected an instance with a single reference");
245 return WalkResult::interrupt();
248 dyn_cast<hw::HWModuleLike>(symCache.getDefinition(moduleNames[0]));
250 assert(tgtMod &&
"invalid module reference");
253 FailureOr<const ModuleAppIDs *> childIds = buildIndexFor(tgtMod);
254 if (failed(childIds))
255 return WalkResult::interrupt();
258 for (AppIDAttr appid : (*childIds)->getAppIDs())
259 if (failed(appIDs->add(appid, op,
true)))
260 return WalkResult::interrupt();
262 return WalkResult::advance();
265 if (done.wasInterrupted())
assert(baseType &&"element must be base type")
Helper class constructed on a per-HWModuleLike basis.
SmallVector< std::pair< AppIDAttr, Operation * >, 8 > childAppIDPathsOrdered
LogicalResult add(AppIDAttr id, Operation *op, bool inherited)
Add an appid component to the index.
FailureOr< Operation * > lookup(AppIDAttr id, Location loc) const
DenseMap< AppIDAttr, Operation * > childAppIDPaths
ArrayRef< std::pair< AppIDAttr, Operation * > > getChildren() const
AppIDIndex(Operation *mlirTop)
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
AppIDAttr getAppID(Operation *op)
Get the AppID of a particular operation.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.