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 OpBuilder devBuilder = OpBuilder::atBlockBegin(device.getBody());
62
63 if (targetModel.getTargetArch() == AIEArch::AIE1)
64 return; // Disable this pass for AIE1; AIE1 support NYI.
65
66 SmallVector<Operation *> erased;
67 auto sequenceOps = device.getOps<AIEX::RuntimeSequenceOp>();
68 for (auto f : sequenceOps) {
69
70 auto controlPacketOps = f.getOps<AIEX::NpuControlPacketOp>();
71 if (controlPacketOps.empty())
72 continue;
73
74 OpBuilder builder(f);
75
76 auto newSeq =
77 builder.create<AIEX::RuntimeSequenceOp>(loc, f.getSymNameAttr());
78 newSeq.getBody().push_back(new Block);
79
80 // Using dynamic shape for ctrl pkt stream.
81 auto ctrlPktMemrefType = MemRefType::get(
82 ShapedType::kDynamic, IntegerType::get(ctx, 32), nullptr, 0);
83 auto newBlockArg = newSeq.getBody().addArgument(ctrlPktMemrefType, loc);
84 builder.setInsertionPointToStart(&newSeq.getBody().front());
85
86 int ddrOffset = 0;
87 Block &entry = f.getBody().front();
88 for (auto &o : entry) {
89 llvm::TypeSwitch<Operation *>(&o).Case<NpuControlPacketOp>(
90 [&](auto op) {
91 // Destination tile info
92 int col = op.getColumnFromAddr();
93 int row = op.getRowFromAddr();
94 AIE::TileOp destTileOp =
95 TileOp::getOrCreate(devBuilder, device, col, row);
96 assert(destTileOp->hasAttr("controller_id"));
97 auto controllerIdPkt =
98 destTileOp->getAttrOfType<AIE::PacketInfoAttr>(
99 "controller_id");
100
101 // Control packet offset (to raw data at ddr) and size
102 uint32_t ctrlPktSize = 0;
103 auto data = op.getData();
104 auto length = op.getLength();
105 if (data)
106 ctrlPktSize = data->size();
107 if (!data && length)
108 ctrlPktSize = *length;
109 ctrlPktSize++; // Ctrl info word
110
111 const std::vector<int64_t> staticOffsets = {0, 0, 0, ddrOffset};
112 ddrOffset += ctrlPktSize;
113 const std::vector<int64_t> staticSizes = {1, 1, 1,
114 (int64_t)ctrlPktSize};
115 const std::vector<int64_t> staticStrides = {0, 0, 0, 1};
116
117 // Shim dma alloc symbol name
118 std::string shimDmaAllocName = "ctrlpkt";
119 shimDmaAllocName += "_col" + std::to_string(col);
120 shimDmaAllocName += "_mm2s";
121 auto rowToShimChanMap =
122 getRowToShimChanMap(targetModel, WireBundle::DMA);
123 int shimChan = rowToShimChanMap[destTileOp.rowIndex()];
124 shimDmaAllocName += "_chan" + std::to_string(shimChan);
125
126 StringRef metadata = builder.getStringAttr(shimDmaAllocName);
127 builder.create<NpuDmaMemcpyNdOp>(
128 builder.getUnknownLoc(), newBlockArg, SmallVector<Value>{},
129 SmallVector<Value>{}, SmallVector<Value>{},
130 ArrayRef(staticOffsets), ArrayRef(staticSizes),
131 ArrayRef(staticStrides), controllerIdPkt, metadata, 0, true,
132 0, 0, 0, 0, 0, 0);
133
134 auto shimRow = builder.getI32IntegerAttr(0);
135 auto shimCol = builder.getI32IntegerAttr(col);
136 auto dir = builder.getI32IntegerAttr(1); // MM2S
137 auto chan = builder.getI32IntegerAttr(shimChan);
138 auto col_num = builder.getI32IntegerAttr(1);
139 auto row_num = builder.getI32IntegerAttr(1);
140 builder.create<AIEX::NpuSyncOp>(loc, shimCol, shimRow, dir, chan,
141 col_num, row_num);
142 });
143 }
144
145 erased.push_back(f);
146 }
147
148 for (auto e : erased)
149 e->erase();
150 }
151};
152
153std::unique_ptr<OperationPass<DeviceOp>>
155 return std::make_unique<AIECtrlPacketInferTilesPass>();
156}
157std::unique_ptr<OperationPass<DeviceOp>> AIEX::createAIECtrlPacketToDmaPass() {
158 return std::make_unique<AIECtrlPacketToDmaPass>();
159}
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.