26 int maxDataMemorySize,
int stacksize,
27 SmallVector<BufferOp> &buffers) {
28 if (address > maxDataMemorySize) {
29 InFlightDiagnostic error =
30 tile.emitOpError(
"allocated buffers exceeded available memory\n");
31 auto ¬e = error.attachNote() <<
"MemoryMap:\n";
32 auto printbuffer = [&](StringRef name,
int address,
int size) {
33 note <<
"\t" << name <<
" \t"
34 <<
": 0x" << llvm::utohexstr(address) <<
"-0x"
35 << llvm::utohexstr(address + size - 1) <<
" \t(" << size
39 printbuffer(
"(stack)", 0, stacksize);
41 error <<
"(no stack allocated)\n";
43 for (
auto buffer : buffers) {
44 assert(buffer.getAddress().has_value() &&
45 "buffer must have address assigned");
46 printbuffer(buffer.name(), buffer.getAddress().value(),
47 buffer.getAllocationSize());
55 auto device = tile->getParentOfType<AIE::DeviceOp>();
60 int maxDataMemorySize = 0;
62 maxDataMemorySize = targetModel.getMemTileSize();
64 maxDataMemorySize = targetModel.getLocalMemorySize();
66 SmallVector<BufferOp> buffers;
67 SmallVector<BufferOp> allocated_buffers;
70 device.walk<WalkOrder::PreOrder>([&](BufferOp buffer) {
71 if (buffer.getTileOp() == tile) {
72 if (buffer.getAddress())
73 allocated_buffers.push_back(buffer);
75 buffers.push_back(buffer);
80 std::sort(buffers.begin(), buffers.end(), [](BufferOp a, BufferOp b) {
81 return a.getAllocationSize() > b.getAllocationSize();
85 std::sort(allocated_buffers.begin(), allocated_buffers.end(),
86 [](BufferOp a, BufferOp b) {
87 return a.getAddress().value() < b.getAddress().value();
96 if (
auto core = tile.getCoreOp()) {
97 stacksize = core.getStackSize();
103 auto current_alloc = allocated_buffers.begin();
104 for (
auto buffer : buffers) {
105 assert(!buffer.getAddress());
106 while (current_alloc != allocated_buffers.end() &&
107 address + buffer.getAllocationSize() >
108 current_alloc->getAddress().value()) {
109 address = current_alloc->getAddress().value() +
110 current_alloc->getAllocationSize();
113 buffer.setAddress(address);
114 address += buffer.getAllocationSize();
118 std::sort(buffers.begin(), buffers.end(), [](BufferOp a, BufferOp b) {
119 assert(a.getAddress().has_value() &&
"buffer must have address assigned");
120 assert(b.getAddress().has_value() &&
"buffer must have address assigned");
121 return a.getAddress().value() < b.getAddress().value();
167 std::vector<int64_t> &nextAddrInBanks,
168 std::vector<BankLimits> &bankLimits) {
169 auto addrAttr = buffer->getAttrOfType<IntegerAttr>(
"address");
173 int addr = addrAttr.getInt();
174 for (
int i = 0; i < numBanks; i++) {
176 if (addr < bankLimits[i].startAddr || addr >= bankLimits[i].endAddr)
180 if (addr < nextAddrInBanks[i])
181 return buffer->emitOpError(
"would override allocated address");
184 nextAddrInBanks[i] = addr + buffer.getAllocationSize();
185 buffer.setMemBank(i);
198 std::vector<int64_t> &nextAddrInBanks,
199 std::vector<BankLimits> &bankLimits) {
200 auto memBankAttr = buffer->getAttrOfType<IntegerAttr>(
"mem_bank");
204 int mem_bank = memBankAttr.getInt();
205 int64_t startAddr = nextAddrInBanks[mem_bank];
206 int64_t endAddr = startAddr + buffer.getAllocationSize();
207 if (endAddr > bankLimits[mem_bank].endAddr)
208 return buffer->emitOpError(
"would override existing mem_bank");
214void printMemMap(TileOp tile, SmallVector<BufferOp> &allocatedBuffers,
215 SmallVector<BufferOp> &preAllocatedBuffers,
int numBanks,
216 std::vector<BankLimits> &bankLimits,
int stacksize) {
217 InFlightDiagnostic error = tile.emitOpError(
218 "Not all requested buffers fit in the available memory.\n");
219 auto ¬e = error.attachNote()
220 <<
"Current configuration of buffers in bank(s) : ";
221 note <<
"MemoryMap:\n";
222 auto printbuffer = [&](StringRef name,
int address,
int size) {
224 <<
"\t" << name <<
" \t"
225 <<
": 0x" << llvm::utohexstr(address) <<
"-0x"
226 << llvm::utohexstr(address + size - 1) <<
" \t(" << size
229 for (
int i = 0; i < numBanks; i++) {
232 printbuffer(
"(stack)", 0, stacksize);
234 note <<
"(no stack allocated)\n";
237 <<
"bank : " << i <<
"\t"
238 <<
"0x" << llvm::utohexstr(bankLimits[i].startAddr) <<
"-0x"
239 << llvm::utohexstr(bankLimits[i].endAddr - 1) <<
"\n";
240 for (
auto buffer : preAllocatedBuffers) {
241 auto addr = buffer.getAddress().value();
242 auto mem_bank = buffer.getMemBank().value();
244 printbuffer(buffer.name(), addr, buffer.getAllocationSize());
246 for (
auto buffer : allocatedBuffers) {
247 auto addr = buffer.getAddress().value();
248 auto mem_bank = buffer.getMemBank().value();
250 printbuffer(buffer.name(), addr, buffer.getAllocationSize());
264 std::vector<int64_t> &nextAddrInBanks,
265 std::vector<BankLimits> &bankLimits) {
266 assert(startBankIndex < numBanks &&
267 "Unexpected input value for startBankIndex");
268 int bankIndex = startBankIndex;
269 bool allocated =
false;
270 for (
int i = 0; i < numBanks; i++) {
271 int64_t startAddr = nextAddrInBanks[bankIndex];
272 int64_t endAddr = startAddr + buffer.getAllocationSize();
273 if (endAddr <= bankLimits[bankIndex].endAddr) {
274 buffer.setMemBank(bankIndex);
277 bankIndex = (bankIndex + 1) % numBanks;
278 startBankIndex = bankIndex;
282 bankIndex = (bankIndex + 1) % numBanks;
286 buffer.emitError(
"Failed to allocate buffer: ")
287 << buffer.name() <<
" with size: " << buffer.getAllocationSize()
295 SmallVector<BufferOp> &allBuffers,
296 std::vector<int64_t> &nextAddrInBanks,
297 std::vector<BankLimits> &bankLimits) {
298 bool foundOverflow =
false;
299 std::vector<int> overflow_banks;
300 for (
int i = 0; i < numBanks; i++) {
301 if (nextAddrInBanks[i] > bankLimits[i].endAddr) {
302 foundOverflow =
true;
303 overflow_banks.push_back(i);
307 InFlightDiagnostic error =
308 tile.emitOpError(
"allocated buffers exceeded available memory\n");
309 auto ¬e = error.attachNote() <<
"Error in bank(s) : ";
310 for (
auto bank : overflow_banks)
313 note <<
"MemoryMap:\n";
314 auto printbuffer = [&](StringRef name,
int address,
int size) {
316 <<
"\t" << name <<
" \t"
317 <<
": 0x" << llvm::utohexstr(address) <<
"-0x"
318 << llvm::utohexstr(address + size - 1) <<
" \t(" << size
321 for (
int i = 0; i < numBanks; i++) {
323 <<
"bank : " << i <<
"\t"
324 <<
"0x" << llvm::utohexstr(bankLimits[i].startAddr) <<
"-0x"
325 << llvm::utohexstr(bankLimits[i].endAddr - 1) <<
"\n";
328 printbuffer(
"(stack)", 0, stacksize);
330 error <<
"(no stack allocated)\n";
332 for (
auto buffer : allBuffers) {
333 auto addr = buffer.getAddress().value();
334 auto mem_bank = buffer.getMemBank().value();
336 printbuffer(buffer.name(), addr, buffer.getAllocationSize());
353 auto device = tile->getParentOfType<AIE::DeviceOp>();
362 std::vector<BankLimits> bankLimits;
366 int maxDataMemorySize = 0;
367 if (tile.isMemTile())
368 maxDataMemorySize = targetModel.getMemTileSize();
370 maxDataMemorySize = targetModel.getLocalMemorySize();
372 int numBanks = targetModel.getNumBanks(tile.getCol(), tile.getRow());
373 int bankSize = maxDataMemorySize / numBanks;
380 for (
int i = 0; i < numBanks; i++)
381 nextAddrInBanks.push_back(bankSize * i);
382 if (
auto core = tile.getCoreOp()) {
383 stacksize = core.getStackSize();
384 nextAddrInBanks[0] += stacksize;
388 SmallVector<BufferOp> preAllocatedBuffers;
389 SmallVector<BufferOp> buffersToAlloc;
390 SmallVector<BufferOp> allBuffers;
392 device.walk<WalkOrder::PreOrder>([&](BufferOp buffer) {
393 if (buffer.getTileOp() == tile)
394 allBuffers.push_back(buffer);
401 for (
auto buffer : allBuffers) {
402 if (buffer.getTileOp() == tile) {
404 nextAddrInBanks, bankLimits);
406 nextAddrInBanks, bankLimits);
407 if (failed(has_addr) || failed(has_bank))
409 if (!has_addr.value() && !has_bank.value())
410 buffersToAlloc.push_back(buffer);
412 preAllocatedBuffers.push_back(buffer);
417 std::sort(buffersToAlloc.begin(), buffersToAlloc.end(),
418 [](BufferOp a, BufferOp b) {
419 return a.getAllocationSize() > b.getAllocationSize();
423 SmallVector<BufferOp> allocatedBuffers;
425 for (
auto buffer : buffersToAlloc) {
433 printMemMap(tile, allocatedBuffers, preAllocatedBuffers, numBanks,
434 bankLimits, stacksize);
438 allocatedBuffers.push_back(buffer);
443 std::sort(allBuffers.begin(), allBuffers.end(), [](BufferOp a, BufferOp b) {
444 assert(a.getAddress().has_value() &&
"buffer must have address assigned");
445 assert(b.getAddress().has_value() &&
"buffer must have address assigned");
446 return a.getAddress().value() < b.getAddress().value();
450 nextAddrInBanks, bankLimits);