MLIR-AIE
AIECtrlPacketToDma.cpp
Go to the documentation of this file.
1//===- AIECtrlPacketToDma.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 2024 Advanced Micro Devices Inc.
8//
9//===----------------------------------------------------------------------===//
10
15
16#include "mlir/IR/Attributes.h"
17#include "mlir/Pass/Pass.h"
18
19#include "llvm/ADT/TypeSwitch.h"
20
21#define DEBUG_TYPE "aie-ctrl-packet-to-dma"
22
23using namespace mlir;
24using namespace xilinx;
25using namespace xilinx::AIE;
26using namespace xilinx::AIEX;
27
29 : AIECtrlPacketInferTilesBase<AIECtrlPacketInferTilesPass> {
30 void runOnOperation() override {
31 DeviceOp device = getOperation();
32 const auto &targetModel = device.getTargetModel();
33 OpBuilder devBuilder = OpBuilder::atBlockBegin(device.getBody());
34
35 auto sequenceOps = device.getOps<AIEX::RuntimeSequenceOp>();
36 for (auto f : sequenceOps) {
37 auto ctrlPktOps = f.getOps<AIEX::NpuControlPacketOp>();
38 for (auto ctrlPktOp : ctrlPktOps) {
39 auto tOp = TileOp::getOrCreate(devBuilder, device,
40 (int)ctrlPktOp.getColumnFromAddr(),
41 (int)ctrlPktOp.getRowFromAddr());
42 // Assign controller id
43 auto tileIDMap = getTileToControllerIdMap(true, targetModel);
44 if (tOp->hasAttr("controller_id"))
45 continue;
46 auto pktInfoAttr = AIE::PacketInfoAttr::get(
47 tOp->getContext(), /*pkt_type*/ 0,
48 /*pkt_id*/ tileIDMap[{tOp.colIndex(), tOp.rowIndex()}]);
49 tOp->setAttr("controller_id", pktInfoAttr);
50 }
51 }
52 }
53};
54
55struct AIECtrlPacketToDmaPass : AIECtrlPacketToDmaBase<AIECtrlPacketToDmaPass> {
56 void runOnOperation() override {
57 DeviceOp device = getOperation();
58 const auto &targetModel = device.getTargetModel();
59 auto ctx = device->getContext();
60 auto loc = device->getLoc();
61
62 if (targetModel.getTargetArch() == AIEArch::AIE1)
63 return; // Disable this pass for AIE1; AIE1 support NYI.
64
65 SmallVector<Operation *> erased;
66 auto sequenceOps = device.getOps<AIEX::RuntimeSequenceOp>();
67 for (auto f : sequenceOps) {
68
69 auto controlPacketOps = f.getOps<AIEX::NpuControlPacketOp>();
70 if (controlPacketOps.empty())
71 continue;
72
73 OpBuilder builder(f);
74
75 auto newSeq =
76 builder.create<AIEX::RuntimeSequenceOp>(loc, f.getSymNameAttr());
77 newSeq.getBody().push_back(new Block);
78
79 // Using dynamic shape for ctrl pkt stream.
80 auto ctrlPktMemrefType = MemRefType::get(
81 ShapedType::kDynamic, IntegerType::get(ctx, 32), nullptr, 0);
82 auto newBlockArg = newSeq.getBody().addArgument(ctrlPktMemrefType, loc);
83 builder.setInsertionPointToStart(&newSeq.getBody().front());
84
85 int64_t ddrOffset = 0;
86 Block &entry = f.getBody().front();
87 for (auto &o : entry) {
88 llvm::TypeSwitch<Operation *>(&o).Case<NpuControlPacketOp>(
89 [&](auto op) {
90 // Destination tile info
91 int col = op.getColumnFromAddr();
92 int row = op.getRowFromAddr();
93
94 // Control packet offset (to raw data at ddr) and size
95 int64_t ctrlPktSize = 0;
96 auto data = op.getData();
97 if (data)
98 ctrlPktSize = data->size();
99 else if (op.getLength())
100 ctrlPktSize = *op.getLength();
101 ctrlPktSize++; // Ctrl info word
102 ctrlPktSize++; // Packet header
103
104 const std::vector<int64_t> staticOffsets = {0, 0, 0, ddrOffset};
105 ddrOffset += ctrlPktSize;
106 const std::vector<int64_t> staticSizes = {1, 1, 1, ctrlPktSize};
107 const std::vector<int64_t> staticStrides = {0, 0, 0, 1};
108
109 // Shim dma alloc symbol name
110 std::string shimDmaAllocName = "ctrlpkt";
111 shimDmaAllocName += "_col" + std::to_string(col);
112 shimDmaAllocName += "_mm2s";
113 auto rowToShimChanMap =
114 getRowToShimChanMap(targetModel, WireBundle::DMA);
115 int shimChan = rowToShimChanMap[row];
116 shimDmaAllocName += "_chan" + std::to_string(shimChan);
117
118 StringRef metadata = builder.getStringAttr(shimDmaAllocName);
119 builder.create<NpuDmaMemcpyNdOp>(
120 builder.getUnknownLoc(), newBlockArg, SmallVector<Value>{},
121 SmallVector<Value>{}, SmallVector<Value>{},
122 ArrayRef(staticOffsets), ArrayRef(staticSizes),
123 ArrayRef(staticStrides), nullptr, metadata, 0, true, 0, 0, 0,
124 0, 0, 0);
125
126 auto shimRow = builder.getI32IntegerAttr(0);
127 auto shimCol = builder.getI32IntegerAttr(col);
128 auto dir = builder.getI32IntegerAttr(1); // MM2S
129 auto chan = builder.getI32IntegerAttr(shimChan);
130 auto col_num = builder.getI32IntegerAttr(1);
131 auto row_num = builder.getI32IntegerAttr(1);
132 builder.create<AIEX::NpuSyncOp>(loc, shimCol, shimRow, dir, chan,
133 col_num, row_num);
134 });
135 }
136
137 erased.push_back(f);
138 }
139
140 for (auto e : erased)
141 e->erase();
142 }
143};
144
145std::unique_ptr<OperationPass<DeviceOp>>
147 return std::make_unique<AIECtrlPacketInferTilesPass>();
148}
149std::unique_ptr<OperationPass<DeviceOp>> AIEX::createAIECtrlPacketToDmaPass() {
150 return std::make_unique<AIECtrlPacketToDmaPass>();
151}
DenseMap< int, int > getRowToShimChanMap(const AIETargetModel &targetModel, WireBundle bundle)
DenseMap< TileID, int > getTileToControllerIdMap(bool clColumnWiseUniqueIDs, const AIETargetModel &targetModel)
std::unique_ptr< mlir::OperationPass< AIE::DeviceOp > > createAIECtrlPacketInferTilesPass()
std::unique_ptr< mlir::OperationPass< AIE::DeviceOp > > createAIECtrlPacketToDmaPass()
Include the generated interface declarations.