MLIR-AIE
AIELowerMemcpy.cpp
Go to the documentation of this file.
1//===- AIELowerMemcpy.cpp ---------------------------------------*- C++ -*-===//
2//
3// This file is licensed 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// (c) Copyright 2019 Xilinx Inc.
8//
9//===----------------------------------------------------------------------===//
10
15
16#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
17#include "mlir/Dialect/Func/IR/FuncOps.h"
18#include "mlir/IR/Attributes.h"
19#include "mlir/IR/IRMapping.h"
20#include "mlir/IR/Location.h"
21#include "mlir/IR/PatternMatch.h"
22#include "mlir/Pass/Pass.h"
23#include "mlir/Tools/mlir-translate/MlirTranslateMain.h"
24#include "mlir/Transforms/DialectConversion.h"
25
26namespace xilinx::AIEX {
27#define GEN_PASS_DEF_AIELOWERMEMCPY
28#include "aie/Dialect/AIEX/Transforms/AIEXPasses.h.inc"
29} // namespace xilinx::AIEX
30
31using namespace mlir;
32using namespace xilinx;
33using namespace xilinx::AIE;
34using namespace xilinx::AIEX;
35
36static TileOp srcTileOp(xilinx::AIEX::MemcpyOp op) {
37 return llvm::dyn_cast<xilinx::AIE::TileOp>(op.getSrcTile().getDefiningOp());
38}
39static TileOp dstTileOp(xilinx::AIEX::MemcpyOp op) {
40 return llvm::dyn_cast<xilinx::AIE::TileOp>(op.getDstTile().getDefiningOp());
41}
42
43struct LowerAIEMemcpy : public OpConversionPattern<MemcpyOp> {
45
46 LowerAIEMemcpy(MLIRContext *context, PatternBenefit benefit = 1)
47 : OpConversionPattern<MemcpyOp>(context, benefit) {}
48
49 void createDMABlocksAndOps(MemOp &mem, StringRef tokenName, int acquireTknVal,
50 int releaseTknVal, Value buf, int offset, int len,
51 DMAChannelDir dmaDir, int channelIndex,
52 ConversionPatternRewriter &rewriter) const {
53
54 Region &r = mem.getBody();
55 Block &endBlock = r.back();
56 Block *dmaBlock = rewriter.createBlock(&endBlock);
57 Block *bdBlock = rewriter.createBlock(&endBlock);
58
59 rewriter.setInsertionPointToStart(dmaBlock);
60 DMAStartOp::create(rewriter, rewriter.getUnknownLoc(), dmaDir, channelIndex,
61 /*repeatCount*/ 0, bdBlock, &endBlock);
62
63 // Setup bd Block
64 // It should contain locking operations (lock or token) as well as DMABD op
65 // for specifying DMA Block description (which buffer type (A/B), transfer
66 // length/address, etc.)
67 rewriter.setInsertionPointToStart(bdBlock);
68 UseTokenOp::create(rewriter, rewriter.getUnknownLoc(), tokenName,
69 acquireTknVal, LockAction::Acquire);
70 DMABDOp::create(rewriter, rewriter.getUnknownLoc(), buf, offset, len);
71 UseTokenOp::create(rewriter, rewriter.getUnknownLoc(), tokenName,
72 releaseTknVal, LockAction::Release);
73 NextBDOp::create(rewriter, rewriter.getUnknownLoc(), &endBlock);
74 }
75
76 LogicalResult
77 matchAndRewrite(MemcpyOp op, OpAdaptor adaptor,
78 ConversionPatternRewriter &rewriter) const override {
79 Value srcBuf = op.getSrcBuf();
80 Value dstBuf = op.getDstBuf();
81
82 StringRef tokenName = op.getTokenName();
83 int acquireTknVal = op.getAcquireTokenValue();
84 int releaseTknVal = op.getReleaseTokenValue();
85 int srcOffset = op.getSrcOffsetValue();
86 int dstOffset = op.getDstOffsetValue();
87 int srcLen = op.getSrcLenValue();
88 int dstLen = op.getDstLenValue();
89
90 MemOp srcMem = srcTileOp(op).getMemOp();
91 MemOp dstMem = dstTileOp(op).getMemOp();
92
93 createDMABlocksAndOps(srcMem, tokenName, acquireTknVal, releaseTknVal,
94 srcBuf, srcOffset, srcLen, DMAChannelDir::MM2S, 0,
95 rewriter);
96 createDMABlocksAndOps(dstMem, tokenName, acquireTknVal, releaseTknVal,
97 dstBuf, dstOffset, dstLen, DMAChannelDir::S2MM, 0,
98 rewriter);
99
100 rewriter.eraseOp(op);
101 return success();
102 }
103};
104
106 : public xilinx::AIEX::impl::AIELowerMemcpyBase<AIELowerMemcpyPass> {
107 void runOnOperation() override {
108
109 DeviceOp device = getOperation();
110 OpBuilder builder = OpBuilder::atBlockTerminator(device.getBody());
111
112 // Setup FlowOps
113 // Since memcpy moves data from one memory module to another, we use
114 // WireBundle::DMA for both the source and the destination In addition, we
115 // only have two DMA ports per each direction (MM2S/S2MM), and in a
116 // circuit-switch mode, dest port/channel sharing is not possible.
117 // Therefore, we will generate error if the number of logical flows
118 // (streams) targeting the same destination (S2MM) is more than 2
119 DenseMap<Value, int> destChannel;
120 for (auto op : device.getOps<MemcpyOp>()) {
121 builder.setInsertionPoint(op);
122 TileOp srcTile = dyn_cast<TileOp>(op.getSrcTile().getDefiningOp());
123 TileOp dstTile = dyn_cast<TileOp>(op.getDstTile().getDefiningOp());
124 // TODO: perhaps a better approach is to not assert here, but rather have
125 // a subsequent pass that legally relocates the ports
126 assert(destChannel[op.getDstTile()] <= 2 &&
127 "Could not allocate more than two dest. channel when creating "
128 "FlowOp");
129 FlowOp::create(builder, builder.getUnknownLoc(), srcTile, WireBundle::DMA,
130 0, dstTile, WireBundle::DMA, destChannel[op.getDstTile()]);
131 destChannel[op.getDstTile()]++;
132 }
133
134 ConversionTarget target(getContext());
135 RewritePatternSet patterns(&getContext());
136 target.addLegalOp<DMAStartOp>();
137 target.addLegalOp<DMABDOp>();
138 target.addLegalOp<UseTokenOp>();
139 target.addLegalOp<NextBDOp>();
140
141 patterns.insert<LowerAIEMemcpy>(&getContext());
142
143 if (failed(applyPartialConversion(device, target, std::move(patterns))))
144 signalPassFailure();
145 }
146};
147
148std::unique_ptr<OperationPass<AIE::DeviceOp>>
150 return std::make_unique<AIELowerMemcpyPass>();
151}
std::unique_ptr< mlir::OperationPass< AIE::DeviceOp > > createAIELowerMemcpyPass()
Include the generated interface declarations.
void runOnOperation() override
LowerAIEMemcpy(MLIRContext *context, PatternBenefit benefit=1)
LogicalResult matchAndRewrite(MemcpyOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
void createDMABlocksAndOps(MemOp &mem, StringRef tokenName, int acquireTknVal, int releaseTknVal, Value buf, int offset, int len, DMAChannelDir dmaDir, int channelIndex, ConversionPatternRewriter &rewriter) const