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