78 #include "mlir/IR/BuiltinTypes.h"
79 #include "mlir/IR/OperationSupport.h"
80 #include "mlir/Transforms/DialectConversion.h"
81 #include "mlir/Transforms/GreedyPatternRewriteDriver.h"
85 #define GEN_PASS_DEF_REMOVECOMBGROUPS
86 #include "circt/Dialect/Calyx/CalyxPasses.h.inc"
90 using namespace circt;
91 using namespace calyx;
96 static calyx::RegisterOp createReg(ComponentOp component,
97 PatternRewriter &rewriter, Location loc,
98 Twine prefix,
size_t width) {
99 IRRewriter::InsertionGuard guard(rewriter);
100 rewriter.setInsertionPointToStart(component.getBodyBlock());
101 return rewriter.create<calyx::RegisterOp>(loc, (prefix +
"_reg").str(),
107 template <
typename TOp>
108 static TOp wrapInsideOp(OpBuilder &builder, Operation *op) {
109 OpBuilder::InsertionGuard g(builder);
110 builder.setInsertionPoint(op);
111 auto newOp = builder.create<TOp>(op->getLoc());
112 op->moveBefore(newOp.getBodyBlock(), newOp.getBodyBlock()->begin());
116 using CombResRegMapping = DenseMap<Value, RegisterOp>;
118 struct RemoveCombGroupsPattern :
public OpRewritePattern<calyx::CombGroupOp> {
119 using OpRewritePattern::OpRewritePattern;
121 RemoveCombGroupsPattern(MLIRContext *ctx, CombResRegMapping *mapping)
124 LogicalResult matchAndRewrite(calyx::CombGroupOp combGroup,
125 PatternRewriter &rewriter)
const override {
127 auto component = combGroup->getParentOfType<ComponentOp>();
128 auto group = rewriter.create<calyx::GroupOp>(combGroup.getLoc(),
129 combGroup.getName());
130 rewriter.mergeBlocks(combGroup.getBodyBlock(), group.getBodyBlock());
131 rewriter.replaceOp(combGroup, group);
134 SetVector<Operation *> cellsAssigned;
135 for (
auto op : group.getOps<calyx::AssignOp>()) {
136 auto defOp = dyn_cast<CellInterface>(op.getDest().getDefiningOp());
137 assert(defOp &&
"expected some assignment to a cell");
138 cellsAssigned.insert(defOp);
141 rewriter.setInsertionPointToStart(group.getBodyBlock());
143 group.getLoc(), APInt(1, 1,
true,
true));
147 SetVector<Value> alreadyAssignedResults;
151 SetVector<Value> registerDoneSigs;
162 for (
auto *cellOp : cellsAssigned) {
163 auto cell = dyn_cast<CellInterface>(cellOp);
164 for (
auto combRes : cell.getOutputPorts()) {
165 for (
auto &use : llvm::make_early_inc_range(combRes.getUses())) {
166 if (use.getOwner()->getParentOfType<calyx::ControlOp>()) {
167 auto combResReg = combResRegMapping->find(combRes);
168 if (combResReg == combResRegMapping->end()) {
170 auto reg = createReg(component, rewriter, combRes.getLoc(),
172 combRes.getType().getIntOrFloatBitWidth());
173 auto it = combResRegMapping->insert({combRes,
reg});
174 combResReg = it.first;
179 if (!alreadyAssignedResults.contains(combRes)) {
180 rewriter.create<AssignOp>(combRes.getLoc(),
181 combResReg->second.getIn(), combRes);
182 rewriter.create<AssignOp>(combRes.getLoc(),
183 combResReg->second.getWriteEn(),
185 alreadyAssignedResults.insert(combRes);
188 registerDoneSigs.insert(combResReg->second.getDone());
196 assert(!registerDoneSigs.empty() &&
197 "No registers assigned in the combinational group?");
198 rewriter.setInsertionPointToEnd(group.getBodyBlock());
199 rewriter.create<calyx::GroupDoneOp>(
203 registerDoneSigs.takeVector()));
208 mutable CombResRegMapping *combResRegMapping;
211 struct RemoveCombGroupsPass
212 :
public circt::calyx::impl::RemoveCombGroupsBase<RemoveCombGroupsPass> {
213 void runOnOperation()
override;
217 void rewriteIfWithCombGroup(OpBuilder &builder) {
218 OpBuilder::InsertionGuard guard(builder);
219 getOperation().walk([&](IfOp ifOp) {
220 if (!ifOp.getGroupName())
222 auto groupName = ifOp.getGroupName();
224 wrapInsideOp<SeqOp>(builder, ifOp);
225 builder.setInsertionPoint(ifOp);
226 builder.create<EnableOp>(ifOp.getLoc(), groupName.value());
227 ifOp.removeGroupNameAttr();
231 void rewriteWhileWithCombGroup(OpBuilder &builder) {
232 OpBuilder::InsertionGuard guard(builder);
233 getOperation().walk([&](WhileOp whileOp) {
234 if (!whileOp.getGroupName())
236 auto groupName = whileOp.getGroupName().value();
238 wrapInsideOp<SeqOp>(builder, whileOp);
239 builder.setInsertionPoint(whileOp);
240 builder.create<EnableOp>(whileOp.getLoc(), groupName);
241 whileOp.removeGroupNameAttr();
244 auto &curWhileBodyOp = whileOp.getBodyBlock()->front();
245 builder.setInsertionPointToStart(whileOp.getBodyBlock());
246 auto newSeqBody = builder.create<SeqOp>(curWhileBodyOp.getLoc());
247 builder.setInsertionPointToStart(newSeqBody.getBodyBlock());
249 builder.create<EnableOp>(curWhileBodyOp.getLoc(), groupName);
250 curWhileBodyOp.moveBefore(condEnable);
254 void rewriteCellResults() {
255 for (
auto &&[res,
reg] : combResToReg) {
256 for (
auto &use : llvm::make_early_inc_range(res.getUses())) {
257 if (use.getOwner()->getParentOfType<calyx::ControlOp>()) {
258 use.set(
reg.getOut());
264 CombResRegMapping combResToReg;
269 void RemoveCombGroupsPass::runOnOperation() {
270 ConversionTarget target(getContext());
271 target.addLegalDialect<calyx::CalyxDialect>();
272 target.addLegalDialect<hw::HWDialect>();
273 target.addLegalDialect<comb::CombDialect>();
274 target.addIllegalOp<calyx::CombGroupOp>();
276 RewritePatternSet
patterns(&getContext());
281 patterns.add<RemoveCombGroupsPattern>(&getContext(), &combResToReg);
283 if (applyPartialConversion(getOperation(), target, std::move(
patterns))
288 rewriteCellResults();
291 OpBuilder builder(&getContext());
292 rewriteIfWithCombGroup(builder);
293 rewriteWhileWithCombGroup(builder);
297 return std::make_unique<RemoveCombGroupsPass>();
assert(baseType &&"element must be base type")
def create(data_type, value)
std::unique_ptr< mlir::Pass > createRemoveCombGroupsPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
def reg(value, clock, reset=None, reset_value=None, name=None, sym_name=None)