CIRCT  20.0.0git
ESIAppIDHier.cpp
Go to the documentation of this file.
1 //===- ESIAppIDHier.cpp - ESI build AppID hierarchy pass --------*- C++ -*-===//
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 
9 #include "../PassDetails.h"
10 
14 
15 namespace circt {
16 namespace esi {
17 #define GEN_PASS_DEF_ESIAPPIDHIER
18 #include "circt/Dialect/ESI/ESIPasses.h.inc"
19 } // namespace esi
20 } // namespace circt
21 
22 using namespace circt;
23 using namespace esi;
24 
25 namespace {
26 struct ESIAppIDHierPass
27  : public circt::esi::impl::ESIAppIDHierBase<ESIAppIDHierPass> {
28  void runOnOperation() override;
29 
30 private:
31  // Existing node blocks.
32  DenseMap<AppIDPathAttr, Block *> nodeBlock;
33 
34  /// Get the AppIDHierNodeOp's or AppIDHierRootOp's block for a particular
35  /// path.
36  // NOLINTNEXTLINE(misc-no-recursion)
37  Block *getBlock(AppIDPathAttr path, ArrayRef<Operation *> opStack) {
38  Block *&block = nodeBlock[path];
39  if (block)
40  return block;
41 
42  // Check if we need to create a root node.
43  if (path.getPath().empty()) {
44  auto rootOp = OpBuilder::atBlockEnd(getOperation().getBody())
45  .create<AppIDHierRootOp>(UnknownLoc::get(&getContext()),
46  path.getRoot());
47  block = &rootOp.getChildren().emplaceBlock();
48  } else {
49  Block *parentBlock = getBlock(path.getParent(), opStack.drop_back());
50  Operation *op = opStack.back();
51  if (auto inst = dyn_cast<hw::InstanceOp>(op)) {
52  // Create a normal node underneath the parent AppID.
53  auto node = OpBuilder::atBlockEnd(parentBlock)
54  .create<AppIDHierNodeOp>(UnknownLoc::get(&getContext()),
55  path.getPath().back(),
56  inst.getModuleNameAttr());
57  block = &node.getChildren().emplaceBlock();
58  } else {
59  block = parentBlock;
60  }
61  }
62  return block;
63  };
64 };
65 } // anonymous namespace
66 
67 void ESIAppIDHierPass::runOnOperation() {
68  auto mod = getOperation();
69  AppIDIndex index(mod);
70  if (!index.isValid())
71  return signalPassFailure();
72 
73  // Clone in manifest data, creating the instance hierarchy as we go.
74  LogicalResult rc = index.walk(
75  top, [&](AppIDPathAttr appidPath, ArrayRef<Operation *> opStack) {
76  assert(appidPath.getPath().size() == opStack.size() &&
77  "path and opStack must be the same size.");
78  auto *block = getBlock(appidPath, opStack);
79  auto *op = opStack.back();
80  if (isa<IsManifestData>(op))
81  OpBuilder::atBlockEnd(block).clone(*op);
82  });
83  if (failed(rc))
84  return signalPassFailure();
85 }
86 
87 std::unique_ptr<OperationPass<ModuleOp>> circt::esi::createESIAppIDHierPass() {
88  return std::make_unique<ESIAppIDHierPass>();
89 }
assert(baseType &&"element must be base type")
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:55
std::unique_ptr< OperationPass< ModuleOp > > createESIAppIDHierPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
Definition: esi.py:1