156 DeviceOp targetOp = getOperation();
158 return signalPassFailure();
161 auto memOps = llvm::to_vector_of<TileElement>(targetOp.getOps<MemOp>());
162 llvm::append_range(memOps, targetOp.getOps<MemTileDMAOp>());
163 llvm::append_range(memOps, targetOp.getOps<ShimDMAOp>());
169 for (TileElement memOp : memOps) {
170 int col = memOp.getTileID().col;
171 int row = memOp.getTileID().row;
174 gens.try_emplace(std::make_pair(col, row), col, row, targetModel);
176 if (emplaced.second) {
177 for (TileOp tile : targetOp.getOps<TileOp>()) {
178 if (tile.getCol() != col || tile.getRow() != row)
180 if (
auto reserved = tile->getAttrOfType<DenseI32ArrayAttr>(
181 "aiex.reserved_bd_ids"))
182 for (int32_t bdId : reserved.asArrayRef()) {
183 auto id =
static_cast<uint32_t
>(bdId);
189 auto checkBdChannelAccessible = [&](DMABDOp bd,
int bdId,
190 int channelIndex) ->
bool {
193 bd.emitOpError() <<
"assigned bd_id " << bdId
194 <<
" is not accessible from channel " << channelIndex
198 bool bdIdCollision =
false;
199 memOp->walk<WalkOrder::PreOrder>([&](DMABDOp bd) {
200 if (!bd.getBdId().has_value())
202 uint32_t bdId = bd.getBdId().value();
204 bd.emitOpError() <<
"assigned bd_id " << bdId
205 <<
" is already used by another BD on this tile";
206 bdIdCollision =
true;
212 return signalPassFailure();
214 auto dmaOps = memOp.getOperation()->getRegion(0).getOps<DMAOp>();
215 if (!dmaOps.empty()) {
216 for (
auto dmaOp : dmaOps) {
217 auto bdRegions = dmaOp.getBds();
218 for (
auto &bdRegion : bdRegions) {
219 auto &block = bdRegion.getBlocks().front();
220 DMABDOp bd = *block.getOps<DMABDOp>().begin();
221 if (
auto existingBdId = bd.getBdId()) {
224 "bdId assigned by user but not found during previous walk");
225 int channelIndex = dmaOp.getChannelIndex();
226 if (!checkBdChannelAccessible(bd, *existingBdId, channelIndex))
227 return signalPassFailure();
229 std::optional<int32_t> nextId =
230 gen.
nextBdId(dmaOp.getChannelIndex());
232 int channelIndex = dmaOp.getChannelIndex();
234 <<
"Allocator exhausted available BD IDs (maximum "
236 <<
" available for channel " << channelIndex <<
").";
237 return signalPassFailure();
244 DenseMap<Block *, int> blockChannelMap;
247 for (Block &block : memOp.getOperation()->getRegion(0))
248 for (
auto op : block.getOps<DMAStartOp>()) {
249 int chNum = op.getChannelIndex();
250 blockChannelMap[&block] = chNum;
251 Block *dest = op.getDest();
253 blockChannelMap[dest] = chNum;
254 if (dest->hasNoSuccessors())
256 dest = dest->getSuccessors()[0];
257 if (blockChannelMap.contains(dest))
262 for (Block &block : memOp.getOperation()->getRegion(0)) {
263 if (block.getOps<DMABDOp>().empty())
265 assert(blockChannelMap.count(&block));
266 DMABDOp bd = (*block.getOps<DMABDOp>().begin());
267 if (
auto existingBdId = bd.getBdId()) {
269 "bdId assigned by user but not found during previous walk");
270 int channelIndex = blockChannelMap[&block];
271 if (!checkBdChannelAccessible(bd, *existingBdId, channelIndex))
272 return signalPassFailure();
274 std::optional<int32_t> nextId =
275 gen.
nextBdId(blockChannelMap[&block]);
277 int channelIndex = blockChannelMap[&block];
279 <<
"Allocator exhausted available BD IDs (maximum "
281 <<
" available for channel " << channelIndex <<
").";
282 return signalPassFailure();
289 for (TileElement memOp : memOps) {
290 auto dmaOps = memOp.getOperation()->getRegion(0).getOps<DMAOp>();
291 if (!dmaOps.empty()) {
292 for (
auto dmaOp : dmaOps) {
293 auto bdRegions = dmaOp.getBds();
294 for (
auto *bdRegionIt = bdRegions.begin();
295 bdRegionIt != bdRegions.end();) {
296 auto &block = bdRegionIt->getBlocks().front();
297 DMABDOp bd = *block.getOps<DMABDOp>().begin();
298 std::optional<int> nextBdId;
299 if (++bdRegionIt != bdRegions.end())
301 (*bdRegionIt->getBlocks().front().getOps<DMABDOp>().begin())
303 else if (dmaOp.getLoop())
304 nextBdId = (*bdRegions.front()
310 bd.setNextBdId(nextBdId);
314 DenseMap<Block *, int> blockBdIdMap;
315 for (Block &block : memOp.getOperation()->getRegion(0)) {
316 if (block.getOps<DMABDOp>().empty())
318 DMABDOp bd = *block.getOps<DMABDOp>().begin();
319 auto bdId = bd.getBdId();
320 assert(bdId.has_value() &&
321 "DMABDOp should have bd_id assigned by now");
322 blockBdIdMap[&block] = *bdId;
325 for (Block &block : memOp.getOperation()->getRegion(0)) {
326 if (block.getOps<DMABDOp>().empty())
328 DMABDOp bd = *block.getOps<DMABDOp>().begin();
329 std::optional<int> nextBdId;
330 if (block.getNumSuccessors()) {
331 assert(llvm::range_size(block.getSuccessors()) == 1 &&
332 "should have only one successor block");
333 Block *nextBlock = block.getSuccessor(0);
334 if (blockBdIdMap.contains(nextBlock)) {
335 nextBdId = blockBdIdMap[nextBlock];
336 }
else if (nextBlock->getOperations().size() != 1 ||
337 !isa<EndOp>(nextBlock->getOperations().front())) {
338 bd.emitOpError(
"must be followed by a block with a dma_bd or "
339 "by a block with only aie.end");
340 return signalPassFailure();
342 bd.setNextBdId(nextBdId);
348 populateRearmBindings(targetOp);