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