16#include "mlir/Target/LLVMIR/Import.h"
18#include "llvm/ADT/StringExtras.h"
29 llvm::raw_string_ostream rss(str);
30 rss <<
"XAie_TileLoc(" << col <<
"," << row <<
")";
35 return tileLocStr(std::to_string(col), std::to_string(row));
40 llvm::raw_string_ostream rss(str);
41 rss <<
"dma_tile" << col << row <<
"_bd" << bdNum;
47 std::to_string(bdNum));
52 llvm::raw_string_ostream rss(str);
59 std::to_string(bdNum));
62std::string
packetStr(StringRef
id, StringRef type) {
64 llvm::raw_string_ostream rss(str);
65 rss <<
"XAie_PacketInit(" <<
id <<
"," << type <<
")";
70 return packetStr(std::to_string(
id), std::to_string(type));
73static std::string tileDMATensorStr(StringRef col, StringRef row,
76 llvm::raw_string_ostream rss(str);
77 rss <<
"dma_tile_" << col <<
"_" << row <<
"_bd_" << bdNum <<
"_tensor";
81static std::string tileDMATensorStr(
int col,
int row,
int bdNum) {
82 return tileDMATensorStr(std::to_string(col), std::to_string(row),
83 std::to_string(bdNum));
87 ArrayRef<BDDimLayoutAttr> dims,
int col,
88 int row,
int bdNum,
int baseAddrA,
89 int64_t offsetA, uint32_t lenA,
90 int elementWidthInBytes,
91 const char *errorRetval) {
93 double elementWidthIn32bWords =
94 static_cast<double>(elementWidthInBytes) / 4.0;
95 std::string tensor = tileDMATensorStr(col, row, bdNum);
96 output <<
"XAie_DmaTensor " << tensor <<
" = {};\n";
97 output << tensor <<
".NumDim = " << std::to_string(ndims) <<
";\n";
100 "__mlir_aie_alloc_dim_desc("
101 << std::to_string(ndims) <<
");\n";
102 output <<
"if(NULL == " << tensor <<
".Dim){\n"
103 <<
" return " << errorRetval <<
";\n"
105 for (
size_t i = 0; i < dims.size(); i++) {
111 int j = dims.size() - i - 1;
114 static_cast<uint32_t
>(dims[i].getStride() * elementWidthIn32bWords);
115 size = dims[i].getSize();
117 stride = dims[i].getStride();
118 size =
static_cast<uint16_t
>(dims[i].getSize() * elementWidthIn32bWords);
120 stride = stride > 0 ? stride : 1;
122 output << tensor <<
".Dim[" << std::to_string(j) <<
"].AieMlDimDesc"
123 <<
" = { /* Stride */ " << std::to_string(stride) <<
", /* Size */ "
124 << std::to_string(size) <<
"};\n";
126 if ((baseAddrA + offsetA) % 4) {
127 llvm::report_fatal_error(
"bd address must be 4B (32b) aligned");
129 output <<
"__mlir_aie_try(XAie_DmaSetMultiDimAddr("
131 <<
"0x" << llvm::utohexstr(baseAddrA + offsetA) <<
", "
132 <<
" /* len */ " << lenA <<
"));\n";
139 llvm::SetVector<Block *> blockVector;
140 SmallVector<Block *, 16> worklist;
141 Block *firstBD = ®ion->front();
142 blockVector.insert(firstBD);
143 worklist.push_back(firstBD);
144 while (!worklist.empty()) {
145 Block *block = worklist.pop_back_val();
146 if (block->empty()) {
149 auto successors = block->getTerminator()->getSuccessors();
150 for (
auto *i : successors) {
151 if (!blockVector.contains(i)) {
152 blockVector.insert(i);
153 worklist.push_back(i);
160llvm::SmallPtrSet<Block *, 8>
163 llvm::SmallPtrSet<Block *, 8> channelHeads;
164 for (Block *block : blockVector) {
165 for (
auto startOp : block->getOps<DMAStartOp>()) {
166 channelHeads.insert(startOp.getDest());
170 llvm::SmallPtrSet<Block *, 8> oooBlocks;
171 for (Block *block : blockVector) {
172 for (
auto startOp : block->getOps<DMAStartOp>()) {
173 if (!startOp.getOutOfOrder()) {
176 Block *b = startOp.getDest();
177 while (b && oooBlocks.insert(b).second && b->getNumSuccessors() > 0) {
178 Block *next = b->getSuccessor(0);
180 if (channelHeads.contains(next)) {
190std::optional<std::vector<char>>
192 mlir::Type elemType = denseInit.getElementType();
193 if (!elemType.isIntOrIndex() && !llvm::isa<mlir::FloatType>(elemType)) {
197 std::vector<char> bytes;
201 auto append = [&bytes](
const llvm::APInt &value) {
202 size_t byteSize = (value.getBitWidth() + 7) / 8;
203 const auto *first =
reinterpret_cast<const char *
>(value.getRawData());
204 bytes.insert(bytes.end(), first, first + byteSize);
206 if (elemType.isIntOrIndex()) {
207 for (
const llvm::APInt &intVal : denseInit.getValues<llvm::APInt>()) {
211 for (
const llvm::APFloat &floatVal : denseInit.getValues<llvm::APFloat>()) {
212 append(floatVal.bitcastToAPInt());
220 for (
auto buf : buffers) {
221 if (buf.getCoreData()) {
226 if (std::optional<int32_t> addr = coreData.getAddress()) {
227 return MemoryRun{*addr, (int64_t)coreData.getAllocationSize()};
232 CoreOp core = tile.getCoreOp();
233 llvm::SmallVector<std::pair<int64_t, int64_t>> occupied;
235 occupied.emplace_back(stackRun.
start, stackRun.
end());
236 for (
auto buf : buffers) {
238 occupied.emplace_back(base, base + buf.getAllocationSize());
241 targetModel.getLocalMemorySize(), std::move(occupied),
242 std::max<int64_t>(targetModel.getComputeTileMaxVectorAlignBits() / 8, 1));
246 llvm::ArrayRef<BufferOp> buffers,
249 int numBanks = targetModel.getNumBanks(tile.getCol(), tile.getRow());
250 llvm::SmallVector<MemoryRun> regions;
254 int64_t memSize = targetModel.getLocalMemorySize();
255 int64_t bankSize = memSize / numBanks;
257 std::max<int64_t>(targetModel.getComputeTileMaxVectorAlignBits() / 8, 1);
259 CoreOp core = tile.getCoreOp();
260 llvm::SmallVector<std::pair<int64_t, int64_t>> occupied;
262 occupied.emplace_back(stackRun.
start, stackRun.
end());
268 llvm::SmallVector<std::optional<MemoryRun>> reserved(numBanks, std::nullopt);
269 for (
auto buf : buffers) {
271 if (
auto bank = buf.getMemBank();
272 buf.getBankReserved() && bank && *bank < numBanks) {
273 reserved[*bank] =
MemoryRun{base, buf.getAllocationSize()};
276 occupied.emplace_back(base, base + buf.getAllocationSize());
279 occupied.emplace_back(dataRun.
start, dataRun.
end());
281 for (
int bank = 0; bank < numBanks; ++bank) {
282 if (
auto region = reserved[bank]) {
283 regions.push_back(*region);
286 MemoryRun window{bankSize * bank, bankSize};
293 regions.push_back(run);
MemoryRun largestFreeRunIn(MemoryRun window, llvm::SmallVector< std::pair< int64_t, int64_t > > occupied, int64_t alignBytes=1)
llvm::SmallPtrSet< mlir::Block *, 8 > collectOutOfOrderBlocks(const llvm::SetVector< mlir::Block * > &blockVector)
Collect every BD block reached from an out-of-order aie.dma_start channel.
std::string tileDMAInstStr(llvm::StringRef col, llvm::StringRef row, llvm::StringRef bdNum)
llvm::SmallVector< MemoryRun > coreBankRegions(TileOp tile, llvm::ArrayRef< BufferOp > buffers, MemoryRun dataRun)
One extent per memory bank for the core's bank-pinned statics, tile-relative and indexed by bank.
void generateXAieDmaSetMultiDimAddr(llvm::raw_ostream &output, int ndims, llvm::ArrayRef< BDDimLayoutAttr > dims, int col, int row, int bdNum, int baseAddrA, int64_t offsetA, uint32_t lenA, int elementWidthInBytes, const char *errorRet)
int32_t getBufferBaseAddress(mlir::Operation *bufOp)
MemoryRun largestFreeRun(int64_t memSize, llvm::SmallVector< std::pair< int64_t, int64_t > > occupied, int64_t alignBytes=1)
const AIETargetModel & getTargetModel(mlir::Operation *op)
std::optional< std::vector< char > > denseAttrToBytes(mlir::DenseElementsAttr denseInit)
A buffer's initial_value as the bytes to write to its tile memory, in element order.
MemoryRun coreDataRegion(TileOp tile, llvm::ArrayRef< BufferOp > buffers)
The extent the core compiler gets for its own .data, .rodata and .bss, tile-relative.
std::string tileDMAInstRefStr(llvm::StringRef col, llvm::StringRef row, llvm::StringRef bdNum)
llvm::SetVector< mlir::Block * > getOrderedChainOfBlocks(mlir::Region *region)
std::string tileLocStr(llvm::StringRef col, llvm::StringRef row)
std::string packetStr(llvm::StringRef id, llvm::StringRef type)