13 #include "../PassDetails.h"
20 #include "mlir/Transforms/DialectConversion.h"
24 #define GEN_PASS_DEF_LOWERESITOPHYSICAL
25 #include "circt/Dialect/ESI/ESIPasses.h.inc"
29 using namespace circt;
40 using OpConversionPattern::OpConversionPattern;
43 matchAndRewrite(ChannelBufferOp buffer, OpAdaptor adaptor,
44 ConversionPatternRewriter &rewriter)
const final;
48 LogicalResult ChannelBufferLowering::matchAndRewrite(
49 ChannelBufferOp buffer, OpAdaptor adaptor,
50 ConversionPatternRewriter &rewriter)
const {
51 auto loc = buffer.getLoc();
53 auto type = buffer.getType();
56 auto stages = buffer.getStagesAttr();
57 uint64_t numStages = 1;
60 numStages = stages.getValue().getLimitedValue();
62 Value input = buffer.getInput();
63 StringAttr bufferName = buffer.getNameAttr();
64 for (uint64_t i = 0; i < numStages; ++i) {
66 auto stage = rewriter.create<PipelineStageOp>(loc, type, buffer.getClk(),
67 buffer.getRst(), input);
69 SmallString<64> stageName(
70 {bufferName.getValue(),
"_stage", std::to_string(i)});
71 stage->setAttr(
"name",
StringAttr::get(rewriter.getContext(), stageName));
77 rewriter.replaceOp(buffer, input);
85 using OpConversionPattern::OpConversionPattern;
88 matchAndRewrite(ESIPureModuleOp pureMod, OpAdaptor adaptor,
89 ConversionPatternRewriter &rewriter)
const final;
94 PureModuleLowering::matchAndRewrite(ESIPureModuleOp pureMod, OpAdaptor adaptor,
95 ConversionPatternRewriter &rewriter)
const {
96 auto loc = pureMod.getLoc();
97 Block *body = &pureMod.getBody().front();
101 DenseMap<StringAttr, ESIPureModuleInputOp> inputPortNames;
103 SmallVector<hw::PortInfo> ports;
105 SmallVector<ESIPureModuleInputOp> inputs;
106 SmallVector<ESIPureModuleOutputOp> outputs;
107 SmallVector<Attribute> params;
109 for (Operation &op : llvm::make_early_inc_range(body->getOperations())) {
110 if (
auto port = dyn_cast<ESIPureModuleInputOp>(op)) {
114 auto existingPort = inputPortNames.find(port.getNameAttr());
115 if (existingPort != inputPortNames.end()) {
116 rewriter.replaceAllUsesWith(port.getResult(),
117 existingPort->getSecond().getResult());
118 rewriter.eraseOp(port);
123 hw::PortInfo{{port.getNameAttr(), port.getResult().getType(),
128 inputs.push_back(port);
129 }
else if (
auto port = dyn_cast<ESIPureModuleOutputOp>(op)) {
131 hw::PortInfo{{port.getNameAttr(), port.getValue().getType(),
136 outputs.push_back(port);
137 }
else if (
auto param = dyn_cast<ESIPureModuleParamOp>(op)) {
140 rewriter.eraseOp(param);
146 loc, pureMod.getNameAttr(), ports,
ArrayAttr::get(getContext(), params));
147 hwMod->setDialectAttrs(pureMod->getDialectAttrs());
148 rewriter.eraseBlock(hwMod.getBodyBlock());
149 rewriter.inlineRegionBefore(*body->getParent(), hwMod.getBodyRegion(),
150 hwMod.getBodyRegion().end());
151 body = hwMod.getBodyBlock();
154 for (
auto input : inputs) {
155 BlockArgument newArg;
156 rewriter.modifyOpInPlace(hwMod, [&]() {
157 newArg = body->addArgument(input.getResult().getType(), input.getLoc());
159 rewriter.replaceAllUsesWith(input.getResult(), newArg);
160 rewriter.eraseOp(input);
164 SmallVector<Value> hwOutputOperands;
165 for (
auto output : outputs) {
166 hwOutputOperands.push_back(output.getValue());
167 rewriter.eraseOp(output);
169 rewriter.setInsertionPointToEnd(body);
170 rewriter.create<hw::OutputOp>(pureMod.getLoc(), hwOutputOperands);
173 rewriter.eraseOp(pureMod);
179 struct ESIToPhysicalPass
180 :
public circt::esi::impl::LowerESIToPhysicalBase<ESIToPhysicalPass> {
181 void runOnOperation()
override;
185 void ESIToPhysicalPass::runOnOperation() {
187 ConversionTarget target(getContext());
188 target.markUnknownOpDynamicallyLegal([](Operation *) {
return true; });
189 target.addIllegalOp<ChannelBufferOp>();
190 target.addIllegalOp<ESIPureModuleOp>();
193 RewritePatternSet
patterns(&getContext());
194 patterns.insert<ChannelBufferLowering>(&getContext());
195 patterns.insert<PureModuleLowering>(&getContext());
199 applyPartialConversion(getOperation(), target, std::move(
patterns))))
203 std::unique_ptr<OperationPass<ModuleOp>>
205 return std::make_unique<ESIToPhysicalPass>();
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
std::unique_ptr< OperationPass< ModuleOp > > createESIPhysicalLoweringPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.