CIRCT  20.0.0git
KanagawaMethodsToContainers.cpp
Go to the documentation of this file.
1 //===- KanagawaMethodsToContainers.cpp - Implementation of containerizing -===//
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 
11 #include "mlir/Pass/Pass.h"
12 
17 
19 #include "circt/Support/SymCache.h"
20 #include "mlir/Transforms/DialectConversion.h"
21 
22 namespace circt {
23 namespace kanagawa {
24 #define GEN_PASS_DEF_KANAGAWACONVERTMETHODSTOCONTAINERS
25 #include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
26 } // namespace kanagawa
27 } // namespace circt
28 
29 using namespace circt;
30 using namespace kanagawa;
31 
32 namespace {
33 
34 struct DataflowMethodOpConversion
35  : public OpConversionPattern<DataflowMethodOp> {
37  using OpAdaptor = typename DataflowMethodOp::Adaptor;
38 
39  LogicalResult
40  matchAndRewrite(DataflowMethodOp op, OpAdaptor adaptor,
41  ConversionPatternRewriter &rewriter) const override {
42  // Replace the class by a container of the same name.
43  auto newContainer = rewriter.create<ContainerOp>(
44  op.getLoc(), op.getInnerSym(), /*isTopLevel=*/false);
45  rewriter.setInsertionPointToStart(newContainer.getBodyBlock());
46 
47  // Create mandatory %this
48  // TODO @mortbopet: this will most likely already be present at the
49  // method.df level soon...
50  rewriter.create<ThisOp>(op.getLoc(), newContainer.getInnerRef());
51 
52  // Create in- and output ports.
53  llvm::SmallVector<Value> argValues;
54  for (auto [arg, name] : llvm::zip_equal(
55  op.getArguments(), op.getArgNames().getAsRange<StringAttr>())) {
56  auto port = rewriter.create<InputPortOp>(
57  arg.getLoc(), hw::InnerSymAttr::get(name), arg.getType(), name);
58  argValues.push_back(rewriter.create<PortReadOp>(arg.getLoc(), port));
59  }
60 
61  ReturnOp returnOp = cast<ReturnOp>(op.getBodyBlock()->getTerminator());
62  for (auto [idx, resType] : llvm::enumerate(
63  cast<MethodLikeOpInterface>(op.getOperation()).getResultTypes())) {
64  auto portName = rewriter.getStringAttr("out" + std::to_string(idx));
65  auto port = rewriter.create<OutputPortOp>(
66  op.getLoc(), hw::InnerSymAttr::get(portName), resType, portName);
67  rewriter.create<PortWriteOp>(op.getLoc(), port, returnOp.getOperand(idx));
68  }
69 
70  rewriter.mergeBlocks(op.getBodyBlock(), newContainer.getBodyBlock(),
71  argValues);
72  rewriter.eraseOp(op);
73  rewriter.eraseOp(returnOp);
74  return success();
75  }
76 };
77 
78 struct MethodsToContainersPass
79  : public circt::kanagawa::impl::KanagawaConvertMethodsToContainersBase<
80  MethodsToContainersPass> {
81  void runOnOperation() override;
82 };
83 } // anonymous namespace
84 
85 void MethodsToContainersPass::runOnOperation() {
86  auto *context = &getContext();
87  ConversionTarget target(*context);
88  target.addLegalDialect<KanagawaDialect>();
89  target.addIllegalOp<DataflowMethodOp>();
90  target.addIllegalOp<ReturnOp>();
91  RewritePatternSet patterns(context);
92 
93  patterns.insert<DataflowMethodOpConversion>(context);
94  if (failed(
95  applyPartialConversion(getOperation(), target, std::move(patterns))))
96  signalPassFailure();
97 }
98 
100  return std::make_unique<MethodsToContainersPass>();
101 }
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:55
std::unique_ptr< mlir::Pass > createConvertMethodsToContainersPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21