-
Notifications
You must be signed in to change notification settings - Fork 87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fall back routine when bank-aware allocation fails #1625
Changes from 55 commits
2bbcab6
fd0c7d3
820b90c
7f45c9f
4aeb180
d95e1c5
b0a128f
5a1d14d
2c8d17d
a8677c4
cecdf76
d5c919a
613b845
fe14350
8d5eeb0
2347789
a5a89eb
eb76073
1ee9a2a
181314d
6201c29
7d26945
71ba614
383b6db
33ac05d
8fb7e05
b5eef3a
8f578fd
6d2ea22
5b9c742
f1b967a
552cdfe
47de60c
e042b38
78466e7
3fcdbde
ca9e514
4384c9b
a53a7a5
978f55e
7612c39
bd5a81b
22c5533
fc6dca2
4c34c28
08de1fc
6bdd30f
1b0a348
84b94ac
5202302
9989149
ad7a10b
55c7220
34a3e0f
fc49e0b
04dcd7f
e155c24
33c659a
8b79b43
5420b86
d853109
e7c69b6
86a8a86
61070b2
e697bbd
d74b3c7
95f06b0
f587300
9e8d7a1
5cf8cd5
f4a40bc
e8288d8
709f5cd
d5ac2a6
2c2d1a2
8df83e3
c7f97b5
5ad8aba
56ba356
0a9639b
937a620
baf6490
93ab668
329a3f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,8 +28,8 @@ LogicalResult checkAndPrintOverflow(TileOp tile, int address, | |
int maxDataMemorySize, int stacksize, | ||
SmallVector<BufferOp, 4> buffers) { | ||
if (address > maxDataMemorySize) { | ||
InFlightDiagnostic error = | ||
tile.emitOpError("allocated buffers exceeded available memory\n"); | ||
InFlightDiagnostic error = tile.emitOpError( | ||
"allocated buffers exceeded available memory: Sequential\n"); | ||
auto ¬e = error.attachNote() << "MemoryMap:\n"; | ||
auto printbuffer = [&](StringRef name, int address, int size) { | ||
note << "\t" << name << " \t" | ||
|
@@ -53,7 +53,7 @@ LogicalResult checkAndPrintOverflow(TileOp tile, int address, | |
return success(); | ||
} | ||
|
||
LogicalResult basicAllocation(TileOp &tile) { | ||
LogicalResult basicAllocation(TileOp tile) { | ||
auto device = tile->getParentOfType<AIE::DeviceOp>(); | ||
if (!device) | ||
return failure(); | ||
|
@@ -113,14 +113,6 @@ typedef struct BankLimits { | |
int64_t endAddr; | ||
} BankLimits; | ||
|
||
// TODO: add to target model | ||
int getNumBanks(TileOp tile) { | ||
if (tile.isMemTile()) | ||
return 1; | ||
else | ||
return 4; | ||
} | ||
|
||
// Function that given a number of banks and their size, computes | ||
// the start and end addresses for each bank and fills in the entry | ||
// in the bankLimits vector. | ||
|
@@ -195,14 +187,56 @@ bool checkAndAddBufferWithMemBank(BufferOp buffer, int numBanks, | |
return false; | ||
} | ||
|
||
// Prints the memory map across banks | ||
void printMemMap(TileOp tile, SmallVector<BufferOp, 4> allocatedBuffers, | ||
SmallVector<BufferOp, 4> preAllocatedBuffers, int numBanks, | ||
std::vector<BankLimits> &bankLimits, int stacksize) { | ||
InFlightDiagnostic error = | ||
tile.emitOpError("All requested buffers don't fit in the available " | ||
"memory: Bank aware\n"); | ||
auto ¬e = error.attachNote() | ||
<< "Current configuration of buffers in bank(s) : "; | ||
note << "MemoryMap:\n"; | ||
auto printbuffer = [&](StringRef name, int address, int size) { | ||
note << "\t" | ||
<< "\t" << name << " \t" | ||
<< ": 0x" << llvm::utohexstr(address) << "-0x" | ||
<< llvm::utohexstr(address + size - 1) << " \t(" << size | ||
<< " bytes)\n"; | ||
}; | ||
for (int i = 0; i < numBanks; i++) { | ||
if (i == 0) { | ||
if (stacksize > 0) | ||
printbuffer("(stack)", 0, stacksize); | ||
else | ||
note << "(no stack allocated)\n"; | ||
} | ||
note << "\t" | ||
<< "bank : " << i << "\t" | ||
<< "0x" << llvm::utohexstr(bankLimits[i].startAddr) << "-0x" | ||
<< llvm::utohexstr(bankLimits[i].endAddr - 1) << "\n"; | ||
for (auto buffer : preAllocatedBuffers) { | ||
auto addr = buffer.getAddress().value(); | ||
auto mem_bank = buffer.getMemBank().value(); | ||
if (mem_bank == i) | ||
printbuffer(buffer.name(), addr, buffer.getAllocationSize()); | ||
} | ||
for (auto buffer : allocatedBuffers) { | ||
auto addr = buffer.getAddress().value(); | ||
auto mem_bank = buffer.getMemBank().value(); | ||
if (mem_bank == i) | ||
printbuffer(buffer.name(), addr, buffer.getAllocationSize()); | ||
} | ||
} | ||
} | ||
|
||
// Function that given a buffer will iterate over all the memory banks | ||
// starting from the given index to try and find a bank with enough | ||
// space. If it does, it will set the buffer's address and mem_bank | ||
// attributes and update the nextAddrInBanks vector. | ||
// If it does not find one with enough space, it will allocate the | ||
// buffer in the last checked bank (this will be picked up during | ||
// overflow error checking). Finally, the function returns the index | ||
// of the next bank to search (which should be given to subsequent | ||
// If it does not find one with enough space, it will throw an error. | ||
// Finally, the function returns a pass or a fail. | ||
// The index of the next bank to search (which should be given to subsequent | ||
// calls of this function to ensure a round-robin allocation scheme | ||
// over the available banks). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The function now only returns a pass or fail, and no longer the index, correct? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you Andra, updated the comment accordingly. |
||
int setBufferAddress(BufferOp buffer, int numBanks, int startBankIndex, | ||
|
@@ -211,18 +245,30 @@ int setBufferAddress(BufferOp buffer, int numBanks, int startBankIndex, | |
assert(startBankIndex < numBanks && | ||
"Unexpected input value for startBankIndex"); | ||
int bankIndex = startBankIndex; | ||
bool allocated = false; | ||
for (int i = 0; i < numBanks; i++) { | ||
int64_t startAddr = nextAddrInBanks[bankIndex]; | ||
int64_t endAddr = startAddr + buffer.getAllocationSize(); | ||
if (endAddr <= bankLimits[bankIndex].endAddr || i == numBanks - 1) { | ||
if (endAddr <= bankLimits[bankIndex].endAddr) { | ||
buffer.setMemBank(bankIndex); | ||
setAndUpdateAddressInBank(buffer, startAddr, endAddr, nextAddrInBanks); | ||
bankIndex = (bankIndex + 1) % numBanks; | ||
allocated = true; | ||
bankIndex++; | ||
bankIndex %= numBanks; | ||
break; | ||
} | ||
bankIndex = (bankIndex + 1) % numBanks; | ||
// Move to the next bank | ||
bankIndex++; | ||
bankIndex %= numBanks; | ||
} | ||
// If no bank has enough space, throws error | ||
if (!allocated) { | ||
buffer.emitError("Failed to allocate buffer: ") | ||
<< buffer.name() << " with size: " << buffer.getAllocationSize() | ||
<< " bytes."; | ||
return false; | ||
} | ||
return bankIndex; | ||
return true; | ||
} | ||
|
||
LogicalResult checkAndPrintOverflow(TileOp tile, int numBanks, int stacksize, | ||
|
@@ -238,8 +284,8 @@ LogicalResult checkAndPrintOverflow(TileOp tile, int numBanks, int stacksize, | |
} | ||
} | ||
if (foundOverflow) { | ||
InFlightDiagnostic error = | ||
tile.emitOpError("allocated buffers exceeded available memory\n"); | ||
InFlightDiagnostic error = tile.emitOpError( | ||
"allocated buffers exceeded available memory: Bank aware\n"); | ||
auto ¬e = error.attachNote() << "Error in bank(s) : "; | ||
for (auto bank : overflow_banks) | ||
note << bank << " "; | ||
|
@@ -275,6 +321,14 @@ LogicalResult checkAndPrintOverflow(TileOp tile, int numBanks, int stacksize, | |
return success(); | ||
} | ||
|
||
// Function to deallocate attributes of buffers in case of a failure | ||
void deAllocationBuffers(SmallVector<BufferOp, 4> &buffers) { | ||
for (auto buffer : buffers) { | ||
buffer->removeAttr("address"); | ||
buffer->removeAttr("mem_bank"); | ||
} | ||
} | ||
|
||
LogicalResult simpleBankAwareAllocation(TileOp tile) { | ||
auto device = tile->getParentOfType<AIE::DeviceOp>(); | ||
if (!device) | ||
|
@@ -295,7 +349,7 @@ LogicalResult simpleBankAwareAllocation(TileOp tile) { | |
else | ||
maxDataMemorySize = targetModel.getLocalMemorySize(); | ||
|
||
int numBanks = getNumBanks(tile); | ||
int numBanks = targetModel.getNumBanks(tile.getCol(), tile.getRow()); | ||
int bankSize = maxDataMemorySize / numBanks; | ||
|
||
// Address range owned by the MemTile is 0x80000. | ||
|
@@ -312,6 +366,7 @@ LogicalResult simpleBankAwareAllocation(TileOp tile) { | |
fillBankLimits(numBanks, bankSize, bankLimits); | ||
|
||
SmallVector<BufferOp, 4> buffersToAlloc; | ||
SmallVector<BufferOp, 4> preAllocatedBuffers; | ||
SmallVector<BufferOp, 4> allBuffers; | ||
// Collect all the buffers for this tile. | ||
device.walk<WalkOrder::PreOrder>([&](BufferOp buffer) { | ||
|
@@ -331,6 +386,8 @@ LogicalResult simpleBankAwareAllocation(TileOp tile) { | |
nextAddrInBanks, bankLimits); | ||
if (!has_addr && !has_bank) | ||
buffersToAlloc.push_back(buffer); | ||
else | ||
preAllocatedBuffers.push_back(buffer); | ||
} | ||
} | ||
|
||
|
@@ -341,10 +398,24 @@ LogicalResult simpleBankAwareAllocation(TileOp tile) { | |
}); | ||
|
||
// Set addresses for remaining buffers. | ||
SmallVector<BufferOp, 4> allocatedBuffers; | ||
int bankIndex = 0; | ||
for (auto buffer : buffersToAlloc) | ||
bankIndex = setBufferAddress(buffer, numBanks, bankIndex, nextAddrInBanks, | ||
bankLimits); | ||
for (auto buffer : buffersToAlloc) { | ||
// If the buffer doesn't fit in any of the bank space then | ||
// it prints the current memory map of the banks, | ||
// deallocates all the buffers, and | ||
// returns a failure. | ||
if (!setBufferAddress(buffer, numBanks, bankIndex, nextAddrInBanks, | ||
bankLimits)) { | ||
|
||
printMemMap(tile, allocatedBuffers, preAllocatedBuffers, numBanks, | ||
bankLimits, stacksize); | ||
deAllocationBuffers(allocatedBuffers); | ||
return failure(); | ||
} else { | ||
allocatedBuffers.push_back(buffer); | ||
} | ||
} | ||
|
||
// Sort by smallest address before printing memory map. | ||
std::sort(allBuffers.begin(), allBuffers.end(), [](BufferOp a, BufferOp b) { | ||
|
@@ -380,16 +451,23 @@ struct AIEAssignBufferAddressesPass | |
}); | ||
|
||
// Select allocation scheme | ||
if (clBasicAlloc) { | ||
if (clAllocScheme == "basic-sequential") { | ||
for (auto tile : device.getOps<TileOp>()) { | ||
if (auto res = basicAllocation(tile); res.failed()) | ||
return signalPassFailure(); | ||
} | ||
} else { | ||
} else if (clAllocScheme == "bank-aware") { | ||
for (auto tile : device.getOps<TileOp>()) { | ||
if (auto res = simpleBankAwareAllocation(tile); res.failed()) | ||
return signalPassFailure(); | ||
} | ||
} else { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. might want to warn or error here if clAllocScheme was given by user but unrecognized |
||
for (auto tile : device.getOps<TileOp>()) { | ||
if (auto res = simpleBankAwareAllocation(tile); res.failed()) { | ||
if (auto res2 = basicAllocation(tile); res2.failed()) | ||
return signalPassFailure(); | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be made to fit into ~80-100 columns?