31 int stacksize, SmallVector<BufferOp> &buffers) {
32 if (address > maxDataMemorySize) {
33 InFlightDiagnostic error =
34 tile.emitOpError(
"allocated buffers exceeded available memory\n");
35 auto ¬e = error.attachNote() <<
"MemoryMap:\n";
36 auto printbuffer = [&](StringRef name,
int address,
int size) {
37 note <<
"\t" << name <<
" \t"
38 <<
": 0x" << llvm::utohexstr(address) <<
"-0x"
39 << llvm::utohexstr(address + size - 1) <<
" \t(" << size
43 printbuffer(
"(stack)", 0, stacksize);
45 error <<
"(no stack allocated)\n";
47 for (
auto buffer : buffers) {
48 assert(buffer.getAddress().has_value() &&
49 "buffer must have address assigned");
50 printbuffer(buffer.name(), buffer.getAddress().value(),
51 buffer.getAllocationSize());
59 auto device = tile->getParentOfType<AIE::DeviceOp>();
64 int maxDataMemorySize = 0;
66 maxDataMemorySize = targetModel.getMemTileSize();
68 maxDataMemorySize = targetModel.getLocalMemorySize();
70 SmallVector<BufferOp> buffers;
71 SmallVector<BufferOp> allocated_buffers;
74 device.walk<WalkOrder::PreOrder>([&](BufferOp buffer) {
75 if (buffer.getTileOp() == tile) {
76 if (buffer.getAddress())
77 allocated_buffers.push_back(buffer);
79 buffers.push_back(buffer);
84 std::sort(buffers.begin(), buffers.end(), [](BufferOp a, BufferOp b) {
85 return a.getAllocationSize() > b.getAllocationSize();
89 std::sort(allocated_buffers.begin(), allocated_buffers.end(),
90 [](BufferOp a, BufferOp b) {
91 return a.getAddress().value() < b.getAddress().value();
100 if (
auto core = tile.getCoreOp()) {
101 stacksize = core.getStackSize();
102 address += stacksize;
107 auto current_alloc = allocated_buffers.begin();
108 for (
auto buffer : buffers) {
109 assert(!buffer.getAddress());
110 while (current_alloc != allocated_buffers.end() &&
111 address + buffer.getAllocationSize() >
112 current_alloc->getAddress().value()) {
113 address = current_alloc->getAddress().value() +
114 current_alloc->getAllocationSize();
117 buffer.setAddress(address);
118 address += buffer.getAllocationSize();
122 std::sort(buffers.begin(), buffers.end(), [](BufferOp a, BufferOp b) {
123 assert(a.getAddress().has_value() &&
"buffer must have address assigned");
124 assert(b.getAddress().has_value() &&
"buffer must have address assigned");
125 return a.getAddress().value() < b.getAddress().value();
171 std::vector<int64_t> &nextAddrInBanks,
172 std::vector<BankLimits> &bankLimits) {
173 auto addrAttr = buffer->getAttrOfType<IntegerAttr>(
"address");
177 int addr = addrAttr.getInt();
178 for (
int i = 0; i < numBanks; i++) {
180 if (addr < bankLimits[i].startAddr || addr >= bankLimits[i].endAddr)
184 if (addr < nextAddrInBanks[i])
185 return buffer->emitOpError(
"would override allocated address");
188 nextAddrInBanks[i] = addr + buffer.getAllocationSize();
189 buffer.setMemBank(i);
202 std::vector<int64_t> &nextAddrInBanks,
203 std::vector<BankLimits> &bankLimits) {
204 auto memBankAttr = buffer->getAttrOfType<IntegerAttr>(
"mem_bank");
208 int mem_bank = memBankAttr.getInt();
209 int64_t startAddr = nextAddrInBanks[mem_bank];
210 int64_t endAddr = startAddr + buffer.getAllocationSize();
211 if (endAddr > bankLimits[mem_bank].endAddr)
212 return buffer->emitOpError(
"would override existing mem_bank");
218void printMemMap(TileOp tile, SmallVector<BufferOp> &allocatedBuffers,
219 SmallVector<BufferOp> &preAllocatedBuffers,
int numBanks,
220 std::vector<BankLimits> &bankLimits,
int stacksize) {
221 InFlightDiagnostic error = tile.emitWarning(
222 "Not all requested buffers fit in the available memory.\n");
223 auto ¬e = error.attachNote()
224 <<
"Current configuration of buffers in bank(s) : ";
225 note <<
"MemoryMap:\n";
226 auto printbuffer = [&](StringRef name,
int address,
int size) {
228 <<
"\t" << name <<
" \t"
229 <<
": 0x" << llvm::utohexstr(address) <<
"-0x"
230 << llvm::utohexstr(address + size - 1) <<
" \t(" << size
233 for (
int i = 0; i < numBanks; i++) {
236 printbuffer(
"(stack)", 0, stacksize);
238 note <<
"(no stack allocated)\n";
241 <<
"bank : " << i <<
"\t"
242 <<
"0x" << llvm::utohexstr(bankLimits[i].startAddr) <<
"-0x"
243 << llvm::utohexstr(bankLimits[i].endAddr - 1) <<
"\n";
244 for (
auto buffer : preAllocatedBuffers) {
245 auto addr = buffer.getAddress().value();
246 auto mem_bank = buffer.getMemBank().value();
248 printbuffer(buffer.name(), addr, buffer.getAllocationSize());
250 for (
auto buffer : allocatedBuffers) {
251 auto addr = buffer.getAddress().value();
252 auto mem_bank = buffer.getMemBank().value();
254 printbuffer(buffer.name(), addr, buffer.getAllocationSize());
268 std::vector<int64_t> &nextAddrInBanks,
269 std::vector<BankLimits> &bankLimits) {
270 assert(startBankIndex < numBanks &&
271 "Unexpected input value for startBankIndex");
272 int bankIndex = startBankIndex;
273 bool allocated =
false;
274 for (
int i = 0; i < numBanks; i++) {
275 int64_t startAddr = nextAddrInBanks[bankIndex];
276 int64_t endAddr = startAddr + buffer.getAllocationSize();
277 if (endAddr <= bankLimits[bankIndex].endAddr) {
278 buffer.setMemBank(bankIndex);
281 bankIndex = (bankIndex + 1) % numBanks;
282 startBankIndex = bankIndex;
286 bankIndex = (bankIndex + 1) % numBanks;
290 buffer.emitWarning(
"Failed to allocate buffer: ")
291 << buffer.name() <<
" with size: " << buffer.getAllocationSize()
299 SmallVector<BufferOp> &allBuffers,
300 std::vector<int64_t> &nextAddrInBanks,
301 std::vector<BankLimits> &bankLimits) {
302 bool foundOverflow =
false;
303 std::vector<int> overflow_banks;
304 for (
int i = 0; i < numBanks; i++) {
305 if (nextAddrInBanks[i] > bankLimits[i].endAddr) {
306 foundOverflow =
true;
307 overflow_banks.push_back(i);
311 InFlightDiagnostic error =
312 tile.emitWarning(
"allocated buffers exceeded available memory\n");
313 auto ¬e = error.attachNote() <<
"Error in bank(s) : ";
314 for (
auto bank : overflow_banks)
317 note <<
"MemoryMap:\n";
318 auto printbuffer = [&](StringRef name,
int address,
int size) {
320 <<
"\t" << name <<
" \t"
321 <<
": 0x" << llvm::utohexstr(address) <<
"-0x"
322 << llvm::utohexstr(address + size - 1) <<
" \t(" << size
325 for (
int i = 0; i < numBanks; i++) {
327 <<
"bank : " << i <<
"\t"
328 <<
"0x" << llvm::utohexstr(bankLimits[i].startAddr) <<
"-0x"
329 << llvm::utohexstr(bankLimits[i].endAddr - 1) <<
"\n";
332 printbuffer(
"(stack)", 0, stacksize);
334 error <<
"(no stack allocated)\n";
336 for (
auto buffer : allBuffers) {
337 auto addr = buffer.getAddress().value();
338 auto mem_bank = buffer.getMemBank().value();
340 printbuffer(buffer.name(), addr, buffer.getAllocationSize());
357 auto device = tile->getParentOfType<AIE::DeviceOp>();
366 std::vector<BankLimits> bankLimits;
370 int maxDataMemorySize = 0;
371 if (tile.isMemTile())
372 maxDataMemorySize = targetModel.getMemTileSize();
374 maxDataMemorySize = targetModel.getLocalMemorySize();
376 int numBanks = targetModel.getNumBanks(tile.getCol(), tile.getRow());
377 int bankSize = maxDataMemorySize / numBanks;
384 for (
int i = 0; i < numBanks; i++)
385 nextAddrInBanks.push_back(bankSize * i);
386 if (
auto core = tile.getCoreOp()) {
387 stacksize = core.getStackSize();
388 nextAddrInBanks[0] += stacksize;
392 SmallVector<BufferOp> preAllocatedBuffers;
393 SmallVector<BufferOp> buffersToAlloc;
394 SmallVector<BufferOp> allBuffers;
396 device.walk<WalkOrder::PreOrder>([&](BufferOp buffer) {
397 if (buffer.getTileOp() == tile)
398 allBuffers.push_back(buffer);
405 for (
auto buffer : allBuffers) {
406 if (buffer.getTileOp() == tile) {
408 nextAddrInBanks, bankLimits);
410 nextAddrInBanks, bankLimits);
411 if (failed(has_addr) || failed(has_bank))
413 if (!has_addr.value() && !has_bank.value())
414 buffersToAlloc.push_back(buffer);
416 preAllocatedBuffers.push_back(buffer);
421 std::sort(buffersToAlloc.begin(), buffersToAlloc.end(),
422 [](BufferOp a, BufferOp b) {
423 return a.getAllocationSize() > b.getAllocationSize();
427 SmallVector<BufferOp> allocatedBuffers;
429 for (
auto buffer : buffersToAlloc) {
437 printMemMap(tile, allocatedBuffers, preAllocatedBuffers, numBanks,
438 bankLimits, stacksize);
442 allocatedBuffers.push_back(buffer);
447 std::sort(allBuffers.begin(), allBuffers.end(), [](BufferOp a, BufferOp b) {
448 assert(a.getAddress().has_value() &&
"buffer must have address assigned");
449 assert(b.getAddress().has_value() &&
"buffer must have address assigned");
450 return a.getAddress().value() < b.getAddress().value();
454 nextAddrInBanks, bankLimits);