79 #include "mlir/IR/BuiltinTypes.h"
80 #include "mlir/IR/OperationSupport.h"
81 #include "mlir/Transforms/DialectConversion.h"
82 #include "mlir/Transforms/GreedyPatternRewriteDriver.h"
84 using namespace circt;
85 using namespace calyx;
90 static calyx::RegisterOp createReg(ComponentOp component,
91 PatternRewriter &rewriter, Location loc,
92 Twine prefix,
size_t width) {
93 IRRewriter::InsertionGuard guard(rewriter);
94 rewriter.setInsertionPointToStart(component.getBodyBlock());
95 return rewriter.create<calyx::RegisterOp>(loc, (prefix +
"_reg").str(),
101 template <
typename TOp>
102 static TOp wrapInsideOp(OpBuilder &
builder, Operation *op) {
103 OpBuilder::InsertionGuard g(
builder);
105 auto newOp =
builder.create<TOp>(op->getLoc());
106 op->moveBefore(newOp.getBodyBlock(), newOp.getBodyBlock()->begin());
110 using CombResRegMapping = DenseMap<Value, RegisterOp>;
112 struct RemoveCombGroupsPattern :
public OpRewritePattern<calyx::CombGroupOp> {
113 using OpRewritePattern::OpRewritePattern;
115 RemoveCombGroupsPattern(MLIRContext *ctx, CombResRegMapping *mapping)
118 LogicalResult matchAndRewrite(calyx::CombGroupOp combGroup,
119 PatternRewriter &rewriter)
const override {
121 auto component = combGroup->getParentOfType<ComponentOp>();
122 auto group = rewriter.create<calyx::GroupOp>(combGroup.getLoc(),
123 combGroup.getName());
124 rewriter.mergeBlocks(combGroup.getBodyBlock(), group.getBodyBlock());
125 rewriter.replaceOp(combGroup, group);
128 SetVector<Operation *> cellsAssigned;
129 for (
auto op : group.getOps<calyx::AssignOp>()) {
130 auto defOp = dyn_cast<CellInterface>(op.getDest().getDefiningOp());
131 assert(defOp &&
"expected some assignment to a cell");
132 cellsAssigned.insert(defOp);
135 rewriter.setInsertionPointToStart(group.getBodyBlock());
137 group.getLoc(), APInt(1, 1,
true));
141 SetVector<Value> alreadyAssignedResults;
145 SetVector<Value> registerDoneSigs;
156 for (
auto *cellOp : cellsAssigned) {
157 auto cell = dyn_cast<CellInterface>(cellOp);
158 for (
auto combRes : cell.getOutputPorts()) {
159 for (
auto &use : llvm::make_early_inc_range(combRes.getUses())) {
160 if (use.getOwner()->getParentOfType<calyx::ControlOp>()) {
161 auto combResReg = combResRegMapping->find(combRes);
162 if (combResReg == combResRegMapping->end()) {
164 auto reg = createReg(component, rewriter, combRes.getLoc(),
166 combRes.getType().getIntOrFloatBitWidth());
167 auto it = combResRegMapping->insert({combRes,
reg});
168 combResReg = it.first;
173 if (!alreadyAssignedResults.contains(combRes)) {
174 rewriter.create<AssignOp>(combRes.getLoc(),
175 combResReg->second.getIn(), combRes);
176 rewriter.create<AssignOp>(combRes.getLoc(),
177 combResReg->second.getWriteEn(),
179 alreadyAssignedResults.insert(combRes);
182 registerDoneSigs.insert(combResReg->second.getDone());
190 assert(!registerDoneSigs.empty() &&
191 "No registers assigned in the combinational group?");
192 rewriter.setInsertionPointToEnd(group.getBodyBlock());
193 rewriter.create<calyx::GroupDoneOp>(
197 registerDoneSigs.takeVector()));
202 mutable CombResRegMapping *combResRegMapping;
205 struct RemoveCombGroupsPass
206 :
public RemoveCombGroupsBase<RemoveCombGroupsPass> {
207 void runOnOperation()
override;
211 void rewriteIfWithCombGroup(OpBuilder &
builder) {
212 OpBuilder::InsertionGuard guard(
builder);
213 getOperation().walk([&](IfOp ifOp) {
214 if (!ifOp.getGroupName())
216 auto groupName = ifOp.getGroupName();
218 wrapInsideOp<SeqOp>(
builder, ifOp);
219 builder.setInsertionPoint(ifOp);
220 builder.create<EnableOp>(ifOp.getLoc(), groupName.value());
221 ifOp.removeGroupNameAttr();
225 void rewriteWhileWithCombGroup(OpBuilder &
builder) {
226 OpBuilder::InsertionGuard guard(
builder);
227 getOperation().walk([&](WhileOp whileOp) {
228 if (!whileOp.getGroupName())
230 auto groupName = whileOp.getGroupName().value();
232 wrapInsideOp<SeqOp>(
builder, whileOp);
233 builder.setInsertionPoint(whileOp);
234 builder.create<EnableOp>(whileOp.getLoc(), groupName);
235 whileOp.removeGroupNameAttr();
238 auto &curWhileBodyOp = whileOp.getBodyBlock()->front();
239 builder.setInsertionPointToStart(whileOp.getBodyBlock());
240 auto newSeqBody =
builder.create<SeqOp>(curWhileBodyOp.getLoc());
241 builder.setInsertionPointToStart(newSeqBody.getBodyBlock());
243 builder.create<EnableOp>(curWhileBodyOp.getLoc(), groupName);
244 curWhileBodyOp.moveBefore(condEnable);
248 void rewriteCellResults() {
249 for (
auto &&[res,
reg] : combResToReg) {
250 for (
auto &use : llvm::make_early_inc_range(res.getUses())) {
251 if (use.getOwner()->getParentOfType<calyx::ControlOp>()) {
252 use.set(
reg.getOut());
258 CombResRegMapping combResToReg;
263 void RemoveCombGroupsPass::runOnOperation() {
264 ConversionTarget target(getContext());
265 target.addLegalDialect<calyx::CalyxDialect>();
266 target.addLegalDialect<hw::HWDialect>();
267 target.addLegalDialect<comb::CombDialect>();
268 target.addIllegalOp<calyx::CombGroupOp>();
270 RewritePatternSet
patterns(&getContext());
275 patterns.add<RemoveCombGroupsPattern>(&getContext(), &combResToReg);
277 if (applyPartialConversion(getOperation(), target, std::move(
patterns))
282 rewriteCellResults();
285 OpBuilder
builder(&getContext());
286 rewriteIfWithCombGroup(
builder);
287 rewriteWhileWithCombGroup(
builder);
291 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)