CIRCT 20.0.0git
Loading...
Searching...
No Matches
RemoveGroups.cpp
Go to the documentation of this file.
1//===- RemoveGroups.cpp - Remove Groups 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// Contains the definitions of the Remove Groups pass.
10//
11//===----------------------------------------------------------------------===//
12
16#include "circt/Support/LLVM.h"
17#include "mlir/IR/BuiltinTypes.h"
18#include "mlir/IR/OperationSupport.h"
19
20namespace circt {
21namespace calyx {
22#define GEN_PASS_DEF_REMOVEGROUPS
23#include "circt/Dialect/Calyx/CalyxPasses.h.inc"
24} // namespace calyx
25} // namespace circt
26
27using namespace circt;
28using namespace calyx;
29using namespace mlir;
30
31/// Makes several modifications to the operations of a GroupOp:
32/// 1. Assign the 'done' signal of the component with the done_op of the top
33/// level control group.
34/// 2. Append the 'go' signal of the component to guard of each assignment.
35/// 3. Replace all uses of GroupGoOp with the respective guard, and delete the
36/// GroupGoOp.
37/// 4. Remove the GroupDoneOp.
38static void modifyGroupOperations(ComponentOp component) {
39 auto control = component.getControlOp();
40 // Get the only EnableOp in the control.
41 auto topLevel = *control.getRegion().getOps<EnableOp>().begin();
42 auto topLevelName = topLevel.getGroupName();
43
44 auto wires = component.getWiresOp();
45 Value componentGoPort = component.getGoPort();
46 wires.walk([&](GroupOp group) {
47 auto &groupRegion = group->getRegion(0);
48 OpBuilder builder(groupRegion);
49 // Walk the assignments and append component's 'go' signal to each guard.
50 updateGroupAssignmentGuards(builder, group, componentGoPort);
51
52 auto groupDone = group.getDoneOp();
53 if (topLevelName == group.getSymName()) {
54 // Replace `calyx.group_done %0, %1 ? : i1`
55 // with `calyx.assign %done, %0, %1 ? : i1`
56 auto assignOp =
57 builder.create<AssignOp>(group->getLoc(), component.getDonePort(),
58 groupDone.getSrc(), groupDone.getGuard());
59 groupDone->replaceAllUsesWith(assignOp);
60 } else {
61 // Replace calyx.group_go's uses with its guard, e.g.
62 // %A.go = calyx.group_go %true, %3 ? : i1
63 // %0 = comb.and %1, %A.go : i1
64 // ->
65 // %0 = comb.and %1, %3 : i1
66 auto groupGo = group.getGoOp();
67 auto groupGoGuard = groupGo.getGuard();
68 groupGo.replaceAllUsesWith(groupGoGuard);
69 groupGo->erase();
70 }
71 // In either case, remove the group's done value.
72 groupDone->erase();
73 });
74}
75
76/// Inlines each group in the WiresOp.
77void inlineGroups(ComponentOp component) {
78 auto &wiresRegion = component.getWiresOp().getRegion();
79 auto &wireBlocks = wiresRegion.getBlocks();
80 auto lastBlock = wiresRegion.end();
81
82 // Inline the body of each group as a Block into the WiresOp.
83 wiresRegion.walk([&](GroupOp group) {
84 wireBlocks.splice(lastBlock, group.getRegion().getBlocks());
85 group->erase();
86 });
87
88 // Merge the operations of each Block into the first block of the WiresOp.
89 auto firstBlock = wireBlocks.begin();
90 for (auto it = firstBlock, e = lastBlock; it != e; ++it) {
91 if (it == firstBlock)
92 continue;
93 firstBlock->getOperations().splice(firstBlock->end(), it->getOperations());
94 }
95
96 // Erase the (now) empty blocks.
97 while (&wiresRegion.front() != &wiresRegion.back())
98 wiresRegion.back().erase();
99}
100
101namespace {
102
103struct RemoveGroupsPass
104 : public circt::calyx::impl::RemoveGroupsBase<RemoveGroupsPass> {
105 void runOnOperation() override;
106};
107
108} // end anonymous namespace
109
110void RemoveGroupsPass::runOnOperation() {
111 ComponentOp component = getOperation();
112
113 // Early exit if there is no control to compile.
114 if (component.getControlOp().getOps().empty())
115 return;
116
117 // Make the necessary modifications to each group's operations.
118 modifyGroupOperations(component);
119
120 // Inline the body of each group.
121 inlineGroups(component);
122
123 // Remove the last EnableOp from the control.
124 auto control = component.getControlOp();
125 control.walk([&](EnableOp enable) { enable->erase(); });
126}
127
128std::unique_ptr<mlir::Pass> circt::calyx::createRemoveGroupsPass() {
129 return std::make_unique<RemoveGroupsPass>();
130}
static void modifyGroupOperations(ComponentOp component)
Makes several modifications to the operations of a GroupOp:
void inlineGroups(ComponentOp component)
Inlines each group in the WiresOp.
static void updateGroupAssignmentGuards(OpBuilder &builder, GroupOp &group, Op &op)
Updates the guard of each assignment within a group with op.
std::unique_ptr< mlir::Pass > createRemoveGroupsPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.