MLIR-AIE 1.4.5.dev
TargetModel.cpp
Go to the documentation of this file.
1//===- TargetModel.cpp - C API for AIE TargetModel ------------------------===//
2//
3// Copyright (C) 2024 Advanced Micro Devices, Inc.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7
8#include "aie-c/TargetModel.h"
9
14
15#include "mlir/CAPI/IR.h"
16#include "mlir/IR/Builders.h"
17#include "mlir/IR/BuiltinOps.h"
18#include "mlir/Interfaces/DataLayoutInterfaces.h"
19
20#include "llvm/Support/MathExtras.h"
21
22using namespace mlir;
23
24static inline AieTargetModel wrap(const xilinx::AIE::AIETargetModel &tm) {
25 return AieTargetModel{reinterpret_cast<std::uintptr_t>(&tm)};
26}
27
28static inline const xilinx::AIE::AIETargetModel &unwrap(AieTargetModel tm) {
29 return *reinterpret_cast<const xilinx::AIE::AIETargetModel *>(tm.d);
30}
31
32AieTargetModel aieGetTargetModel(uint32_t device) {
33 return wrap(
34 xilinx::AIE::getTargetModel(static_cast<xilinx::AIE::AIEDevice>(device)));
35}
36
37uint32_t aieGetTargetModelAddressGenGranularity(AieTargetModel targetModel) {
38 return unwrap(targetModel).getAddressGenGranularity();
39}
40
41int aieTargetModelColumns(AieTargetModel targetModel) {
42 return unwrap(targetModel).columns();
43}
44
45int aieTargetModelRows(AieTargetModel targetModel) {
46 return unwrap(targetModel).rows();
47}
48
49uint32_t aieTargetModelGetTileType(AieTargetModel targetModel, int col,
50 int row) {
51 return static_cast<uint32_t>(unwrap(targetModel).getTileType(col, row));
52}
53
54bool aieTargetModelIsCoreTile(AieTargetModel targetModel, int col, int row) {
55 return unwrap(targetModel).isCoreTile(col, row);
56}
57
58bool aieTargetModelIsMemTile(AieTargetModel targetModel, int col, int row) {
59 return unwrap(targetModel).isMemTile(col, row);
60}
61
62bool aieTargetModelIsShimNOCTile(AieTargetModel targetModel, int col, int row) {
63 return unwrap(targetModel).isShimNOCTile(col, row);
64}
65
66bool aieTargetModelIsShimPLTile(AieTargetModel targetModel, int col, int row) {
67 return unwrap(targetModel).isShimPLTile(col, row);
68}
69
70bool aieTargetModelIsShimNOCorPLTile(AieTargetModel targetModel, int col,
71 int row) {
72 return unwrap(targetModel).isShimNOCorPLTile(col, row);
73}
74
75bool aieTargetModelIsInternal(AieTargetModel targetModel, int src_col,
76 int src_row, int dst_col, int dst_row) {
77 return unwrap(targetModel).isInternal(src_col, src_row, dst_col, dst_row);
78}
79
80bool aieTargetModelIsWest(AieTargetModel targetModel, int src_col, int src_row,
81 int dst_col, int dst_row) {
82 return unwrap(targetModel).isWest(src_col, src_row, dst_col, dst_row);
83}
84
85bool aieTargetModelIsEast(AieTargetModel targetModel, int src_col, int src_row,
86 int dst_col, int dst_row) {
87 return unwrap(targetModel).isEast(src_col, src_row, dst_col, dst_row);
88}
89
90bool aieTargetModelIsNorth(AieTargetModel targetModel, int src_col, int src_row,
91 int dst_col, int dst_row) {
92 return unwrap(targetModel).isNorth(src_col, src_row, dst_col, dst_row);
93}
94
95bool aieTargetModelIsSouth(AieTargetModel targetModel, int src_col, int src_row,
96 int dst_col, int dst_row) {
97 return unwrap(targetModel).isSouth(src_col, src_row, dst_col, dst_row);
98}
99
100bool aieTargetModelIsMemWest(AieTargetModel targetModel, int src_col,
101 int src_row, int dst_col, int dst_row) {
102 return unwrap(targetModel).isMemWest(src_col, src_row, dst_col, dst_row);
103}
104
105bool aieTargetModelIsMemEast(AieTargetModel targetModel, int src_col,
106 int src_row, int dst_col, int dst_row) {
107 return unwrap(targetModel).isMemEast(src_col, src_row, dst_col, dst_row);
108}
109
110bool aieTargetModelIsMemNorth(AieTargetModel targetModel, int src_col,
111 int src_row, int dst_col, int dst_row) {
112 return unwrap(targetModel).isMemNorth(src_col, src_row, dst_col, dst_row);
113}
114
115bool aieTargetModelIsMemSouth(AieTargetModel targetModel, int src_col,
116 int src_row, int dst_col, int dst_row) {
117 return unwrap(targetModel).isMemSouth(src_col, src_row, dst_col, dst_row);
118}
119
120bool aieTargetModelIsLegalMemAffinity(AieTargetModel targetModel, int src_col,
121 int src_row, int dst_col, int dst_row) {
122 return unwrap(targetModel)
123 .isLegalMemAffinity(src_col, src_row, dst_col, dst_row);
124}
125
126uint32_t aieTargetModelGetMemSouthBaseAddress(AieTargetModel targetModel) {
127 return unwrap(targetModel).getMemSouthBaseAddress();
128}
129
130uint32_t aieTargetModelGetMemNorthBaseAddress(AieTargetModel targetModel) {
131 return unwrap(targetModel).getMemNorthBaseAddress();
132}
133
134uint32_t aieTargetModelGetMemEastBaseAddress(AieTargetModel targetModel) {
135 return unwrap(targetModel).getMemEastBaseAddress();
136}
137
138uint32_t aieTargetModelGetMemWestBaseAddress(AieTargetModel targetModel) {
139 return unwrap(targetModel).getMemWestBaseAddress();
140}
141
142uint32_t aieTargetModelGetLocalMemorySize(AieTargetModel targetModel) {
143 return unwrap(targetModel).getLocalMemorySize();
144}
145
146uint32_t aieTargetModelGetDefaultCoreStackSize(AieTargetModel targetModel) {
147 return unwrap(targetModel).getDefaultCoreStackSize();
148}
149
150uint32_t aieTargetModelGetNumLocks(AieTargetModel targetModel, int col,
151 int row) {
152 return unwrap(targetModel).getNumLocks(col, row);
153}
154
155uint32_t aieTargetModelGetNumBDs(AieTargetModel targetModel, int col, int row) {
156 return unwrap(targetModel).getNumBDs(col, row);
157}
158
159uint32_t aieTargetModelGetMaxLockValue(AieTargetModel targetModel) {
160 return unwrap(targetModel).getMaxLockValue();
161}
162
163uint32_t aieTargetModelGetMaxRepeatCount(AieTargetModel targetModel) {
164 return unwrap(targetModel).getMaxRepeatCount();
165}
166
167uint32_t aieTargetModelGetDmaTaskQueueDepth(AieTargetModel targetModel) {
168 return unwrap(targetModel).getDmaTaskQueueDepth();
169}
170
171uint32_t aieTargetModelGetDmaBdWrapBits(AieTargetModel targetModel, int col,
172 int row) {
173 return unwrap(targetModel).getDmaBdWrapBits(col, row);
174}
175
176uint32_t aieTargetModelGetDmaBdStepBits(AieTargetModel targetModel, int col,
177 int row) {
178 return unwrap(targetModel).getDmaBdStepBits(col, row);
179}
180
181uint32_t aieTargetModelGetDmaBdIterBits(AieTargetModel targetModel, int col,
182 int row) {
183 return unwrap(targetModel).getDmaBdIterBits(col, row);
184}
185
186uint32_t aieTargetModelGetNumMemTileRows(AieTargetModel targetModel) {
187 return unwrap(targetModel).getNumMemTileRows();
188}
189
190uint32_t aieTargetModelGetMemTileSize(AieTargetModel targetModel) {
191 return unwrap(targetModel).getMemTileSize();
192}
193
194uint32_t aieTargetModelGetNumBanks(AieTargetModel targetModel, int col,
195 int row) {
196 return unwrap(targetModel).getNumBanks(col, row);
197}
198
199bool aieDmaBdFits(uint32_t device, int col, int row, MlirType elementType,
200 int64_t offset, const int64_t *sizes, const int64_t *strides,
201 int64_t len) {
202 Type elemType = unwrap(elementType);
203 MLIRContext *ctx = elemType.getContext();
204 ctx->getOrLoadDialect<xilinx::AIE::AIEDialect>();
205 OpBuilder builder(ctx);
206 Location loc = builder.getUnknownLoc();
207 OwningOpRef<ModuleOp> module = ModuleOp::create(loc);
208 builder.setInsertionPointToStart(module->getBody());
209 auto dev = xilinx::AIE::DeviceOp::create(
210 builder, loc, static_cast<xilinx::AIE::AIEDevice>(device),
211 xilinx::AIE::DeviceOp::getDefaultDeviceName());
212 const xilinx::AIE::AIETargetModel &tm = dev.getTargetModel();
213
214 int64_t elemBits = DataLayout::closest(dev).getTypeSizeInBits(elemType);
215 if (offset * elemBits % tm.getAddressGenGranularity())
216 return false;
217
218 SmallVector<xilinx::AIE::BDDimLayoutAttr> dims;
219 for (unsigned d = 0; d < xilinx::AIEX::kNdDmaDims; d++) {
220 if (sizes[d] < 0 || sizes[d] > UINT32_MAX || strides[d] < 0 ||
221 strides[d] > UINT32_MAX)
222 return false;
223 dims.push_back(
224 xilinx::AIE::BDDimLayoutAttr::get(ctx, sizes[d], strides[d]));
225 }
226 // The dimensions the lowerings see: a descriptor the normalize pass makes
227 // one linear transfer is held to its length alone.
228 if (std::optional<SmallVector<xilinx::AIE::BDDimLayoutAttr>> normalized =
230 if (normalized->empty()) {
231 int64_t bits;
232 return !llvm::MulOverflow(len, elemBits, bits) &&
233 static_cast<uint64_t>(bits / tm.getAddressGenGranularity()) <=
234 tm.getDmaBdMaxLen(col, row);
235 }
236 dims = *normalized;
237 }
238 // Innermost first, the dimensions the descriptor lacks filled with units.
240 for (unsigned d = 0; d < xilinx::AIEX::kNdDmaDims; d++) {
241 bool held = d < dims.size();
242 pattern.offsets.push_back(0);
243 pattern.sizes.push_back(held ? dims[dims.size() - 1 - d].getSize() : 1);
244 pattern.strides.push_back(held ? dims[dims.size() - 1 - d].getStride() : 0);
245 }
246 bool linear = xilinx::AIEX::isLinearModeTransfer(tm, col, row, pattern.sizes,
247 pattern.strides);
249 dev, MemRefType::get({ShapedType::kDynamic}, elemType), tm, col, row,
250 pattern, linear))
251 return false;
252
253 // The wrap checks leave the length field, d0 * d1 * d2 in address granules,
254 // to NpuWriteBdOp's verifier.
255 int64_t lenBits = elemBits;
256 for (int d = 0; d < 3; d++)
257 if (llvm::MulOverflow(lenBits, pattern.sizes[d], lenBits))
258 return false;
259 return static_cast<uint64_t>(lenBits / tm.getAddressGenGranularity()) <=
260 tm.getDmaBdMaxLen(col, row);
261}
262
264 AieTargetModel targetModel, int col, int row, uint32_t bundle) {
265 xilinx::AIE::WireBundle wireBundle =
266 static_cast<xilinx::AIE::WireBundle>(bundle);
267 return unwrap(targetModel)
268 .getNumDestSwitchboxConnections(col, row, wireBundle);
269}
270
272 AieTargetModel targetModel, int col, int row, uint32_t bundle) {
273 xilinx::AIE::WireBundle wireBundle =
274 static_cast<xilinx::AIE::WireBundle>(bundle);
275 return unwrap(targetModel)
276 .getNumSourceSwitchboxConnections(col, row, wireBundle);
277}
278
279uint32_t aieTargetModelGetNumDestShimMuxConnections(AieTargetModel targetModel,
280 int col, int row,
281 uint32_t bundle) {
282 xilinx::AIE::WireBundle wireBundle =
283 static_cast<xilinx::AIE::WireBundle>(bundle);
284 return unwrap(targetModel).getNumDestShimMuxConnections(col, row, wireBundle);
285}
286
288 AieTargetModel targetModel, int col, int row, uint32_t bundle) {
289 xilinx::AIE::WireBundle wireBundle =
290 static_cast<xilinx::AIE::WireBundle>(bundle);
291 return unwrap(targetModel)
292 .getNumSourceShimMuxConnections(col, row, wireBundle);
293}
294
295bool aieTargetModelIsNPU(AieTargetModel targetModel) {
296 return unwrap(targetModel).hasProperty(xilinx::AIE::AIETargetModel::IsNPU);
297}
298
299uint32_t aieTargetModelGetTargetArch(AieTargetModel targetModel) {
300 return static_cast<uint32_t>(unwrap(targetModel).getTargetArch());
301}
302
303uint32_t aieTargetModelGetColumnShift(AieTargetModel targetModel) {
304 return unwrap(targetModel).getColumnShift();
305}
306
307uint32_t aieTargetModelGetRowShift(AieTargetModel targetModel) {
308 return unwrap(targetModel).getRowShift();
309}
bool aieTargetModelIsLegalMemAffinity(AieTargetModel targetModel, int src_col, int src_row, int dst_col, int dst_row)
uint32_t aieTargetModelGetNumSourceShimMuxConnections(AieTargetModel targetModel, int col, int row, uint32_t bundle)
int aieTargetModelRows(AieTargetModel targetModel)
Returns the number of rows in the target model.
uint32_t aieTargetModelGetTargetArch(AieTargetModel targetModel)
Returns the AIE architecture (as the underlying value of xilinx::AIE::AIEArch: AIE1=1,...
uint32_t aieTargetModelGetNumMemTileRows(AieTargetModel targetModel)
bool aieTargetModelIsShimNOCTile(AieTargetModel targetModel, int col, int row)
bool aieTargetModelIsCoreTile(AieTargetModel targetModel, int col, int row)
uint32_t aieTargetModelGetRowShift(AieTargetModel targetModel)
uint32_t aieTargetModelGetDefaultCoreStackSize(AieTargetModel targetModel)
bool aieTargetModelIsInternal(AieTargetModel targetModel, int src_col, int src_row, int dst_col, int dst_row)
uint32_t aieTargetModelGetLocalMemorySize(AieTargetModel targetModel)
bool aieTargetModelIsMemNorth(AieTargetModel targetModel, int src_col, int src_row, int dst_col, int dst_row)
bool aieDmaBdFits(uint32_t device, int col, int row, MlirType elementType, int64_t offset, const int64_t *sizes, const int64_t *strides, int64_t len)
Whether one DMA buffer descriptor of tile (col, row) on device holds the pattern, as aie-normalize-dm...
int aieTargetModelColumns(AieTargetModel targetModel)
Returns the number of columns in the target model.
uint32_t aieTargetModelGetNumBanks(AieTargetModel targetModel, int col, int row)
bool aieTargetModelIsWest(AieTargetModel targetModel, int src_col, int src_row, int dst_col, int dst_row)
bool aieTargetModelIsMemSouth(AieTargetModel targetModel, int src_col, int src_row, int dst_col, int dst_row)
uint32_t aieTargetModelGetDmaBdStepBits(AieTargetModel targetModel, int col, int row)
uint32_t aieTargetModelGetNumDestSwitchboxConnections(AieTargetModel targetModel, int col, int row, uint32_t bundle)
uint32_t aieTargetModelGetMaxRepeatCount(AieTargetModel targetModel)
Largest repeat count one DMA task queue push can carry (unsupported = 0).
uint32_t aieTargetModelGetMemTileSize(AieTargetModel targetModel)
uint32_t aieTargetModelGetDmaTaskQueueDepth(AieTargetModel targetModel)
How many tasks one DMA channel's task queue holds (unsupported = 0).
AieTargetModel aieGetTargetModel(uint32_t device)
bool aieTargetModelIsMemEast(AieTargetModel targetModel, int src_col, int src_row, int dst_col, int dst_row)
bool aieTargetModelIsSouth(AieTargetModel targetModel, int src_col, int src_row, int dst_col, int dst_row)
bool aieTargetModelIsShimPLTile(AieTargetModel targetModel, int col, int row)
bool aieTargetModelIsNorth(AieTargetModel targetModel, int src_col, int src_row, int dst_col, int dst_row)
uint32_t aieTargetModelGetMaxLockValue(AieTargetModel targetModel)
Largest value a lock register holds.
uint32_t aieTargetModelGetNumDestShimMuxConnections(AieTargetModel targetModel, int col, int row, uint32_t bundle)
uint32_t aieTargetModelGetNumBDs(AieTargetModel targetModel, int col, int row)
bool aieTargetModelIsNPU(AieTargetModel targetModel)
Returns true if this is an NPU target model.
uint32_t aieTargetModelGetNumLocks(AieTargetModel targetModel, int col, int row)
bool aieTargetModelIsMemTile(AieTargetModel targetModel, int col, int row)
bool aieTargetModelIsShimNOCorPLTile(AieTargetModel targetModel, int col, int row)
uint32_t aieTargetModelGetMemSouthBaseAddress(AieTargetModel targetModel)
uint32_t aieTargetModelGetTileType(AieTargetModel targetModel, int col, int row)
Returns the tile type for the given coordinates.
uint32_t aieTargetModelGetMemEastBaseAddress(AieTargetModel targetModel)
uint32_t aieTargetModelGetColumnShift(AieTargetModel targetModel)
bool aieTargetModelIsEast(AieTargetModel targetModel, int src_col, int src_row, int dst_col, int dst_row)
uint32_t aieTargetModelGetDmaBdIterBits(AieTargetModel targetModel, int col, int row)
uint32_t aieTargetModelGetDmaBdWrapBits(AieTargetModel targetModel, int col, int row)
Field widths of a DMA buffer descriptor, which differ by tile type.
bool aieTargetModelIsMemWest(AieTargetModel targetModel, int src_col, int src_row, int dst_col, int dst_row)
uint32_t aieTargetModelGetMemNorthBaseAddress(AieTargetModel targetModel)
uint32_t aieTargetModelGetNumSourceSwitchboxConnections(AieTargetModel targetModel, int col, int row, uint32_t bundle)
uint32_t aieTargetModelGetMemWestBaseAddress(AieTargetModel targetModel)
uint32_t aieGetTargetModelAddressGenGranularity(AieTargetModel targetModel)
Returns the data bus width for the target model.
virtual uint64_t getDmaBdMaxLen(AIETileType tileType) const =0
Return the maximum transfer length, measured in address-generation granules (see getAddressGenGranula...
virtual uint32_t getAddressGenGranularity() const =0
Return the data bus width of the device.
bool isLinearModeTransfer(const AIE::AIETargetModel &targetModel, int col, int row, llvm::ArrayRef< int64_t > sizes, llvm::ArrayRef< int64_t > strides)
bool patternPassesVerification(mlir::Operation *forOp, mlir::BaseMemRefType referencedBufType, const xilinx::AIE::AIETargetModel &tm, int tileCol, int tileRow, const NdDmaPattern &pattern, bool skipTransformationChecks=false)
Returns true when the pattern passes verifyStridesWraps for the given tile and memref element type.
std::optional< llvm::SmallVector< BDDimLayoutAttr > > normalizedBDDims(llvm::ArrayRef< BDDimLayoutAttr > dims, int64_t len)
const AIETargetModel & getTargetModel(mlir::Operation *op)
Innermost-first ND access pattern (d0..d3 / repeat), matching the convention used by verifyStridesWra...
llvm::SmallVector< int64_t, kNdDmaDims > sizes
llvm::SmallVector< int64_t, kNdDmaDims > offsets
llvm::SmallVector< int64_t, kNdDmaDims > strides