14#include "mlir/Dialect/Utils/StaticValueUtils.h"
15#include "mlir/IR/Attributes.h"
16#include "mlir/IR/IRMapping.h"
17#include "mlir/Pass/Pass.h"
18#include "mlir/Tools/mlir-translate/MlirTranslateMain.h"
20#include "llvm/ADT/StringExtras.h"
21#include "llvm/IR/Module.h"
31static const char *xaie_cpp_file_header = R
"code(
32// This file was auto-generated by aiecc --aie-generate-xaie.
35#define __mlir_aie_verbose(x) x
37#define __mlir_aie_verbose(x)
40// The following is a wrapper for the common "if(call() != 0) return 1" pattern.
41// Use this only in functions that return int. If the call this wrapper is used
42// on does not succeed, the expanded code will exit out of the function
43// containing this macro with an error code.
44#define __mlir_aie_try(x) do { \
46 if(ret != XAIE_OK) { \
51static XAie_DmaDimDesc *__mlir_aie_alloc_dim_desc(size_t ndims) {
52 XAie_DmaDimDesc *ret = NULL;
53 ret = (XAie_DmaDimDesc *)calloc(sizeof(XAie_DmaDimDesc), ndims);
55 __mlir_aie_verbose(fprintf(stderr, "Allocating DmaDimDesc failed.\n"));
62static std::string tileLockStr(StringRef
id, StringRef val) {
64 llvm::raw_string_ostream rss(str);
66 rss <<
"XAie_LockInit(" <<
id <<
"," << val <<
")";
71static std::string wireBundleToPortType(WireBundle bundle) {
73 case WireBundle::PLIO:
75 case WireBundle::TileControl:
78 return stringifyWireBundle(bundle).upper();
85template <
typename OpType>
86static mlir::LogicalResult generateDMAConfig(OpType memOp, raw_ostream &output,
88 DenseMap<Block *, int> blockMap) {
89 StringRef enable =
"XAIE_ENABLE";
90 StringRef disable =
"XAIE_DISABLE";
91 StringRef deviceInstRef =
"ctx->XAieDevInst";
93 int col = memOp.colIndex();
94 int row = memOp.rowIndex();
98 llvm::SetVector<Block *> blockVector =
101 llvm::SmallPtrSet<Block *, 8> oooBlocks =
104 for (
auto *block : blockVector) {
105 bool foundBdPacket =
false;
108 bool foundBd =
false;
112 int elementWidthInBytes = 0;
114 int iterSize = 0, iterStride = 0, iterCurr = 0;
115 uint32_t axcache = 0;
116 std::optional<int> oooId;
117 ArrayRef<BDDimLayoutAttr> dims;
119 SmallVector<BDDimLayoutAttr> dimsStorage;
123 for (
auto op : block->getOps<DMABDPACKETOp>()) {
124 foundBdPacket =
true;
125 packetType = op.getPacketType();
126 packetID = op.getPacketID();
128 for (
auto op : block->getOps<DMABDOp>()) {
130 if (
auto packetInfo = op.getPacket()) {
131 foundBdPacket =
true;
132 packetType = packetInfo->getPktType();
133 packetID = packetInfo->assignedId();
136 std::optional<int32_t> bufferAddr = op.getBufferOp().getAddress();
137 assert(bufferAddr &&
"buffer must have address assigned");
138 BaseAddrA = *bufferAddr;
139 int bufferCol = op.getBufferOp().getTileOp().colIndex();
140 int bufferRow = op.getBufferOp().getTileOp().rowIndex();
145 col, row, bufferCol, bufferRow);
147 BaseAddrA += addrOffset.value();
151 lenA = op.getLenInBytes();
152 offsetA = op.getOffsetInBytes();
153 elementWidthInBytes = op.getBufferElementTypeWidthInBytes();
154 if (
auto iter = op.getIteration()) {
155 iterSize = iter->getSize();
156 iterStride = iter->getStride();
157 iterCurr = iter->getCurrent();
159 axcache = op.getAxcacheOrDefault();
160 oooId = op.getOutOfOrderId();
161 if (!op.getMixedSizes().empty()) {
163 for (mlir::OpFoldResult s : op.getMixedSizes())
164 if (!mlir::getConstantIntValue(s))
165 return op->emitOpError(
166 "runtime-valued BD size/stride is not supported on the static "
167 "XAIE lowering path; use compile-time constant sizes");
168 for (mlir::OpFoldResult s : op.getMixedStrides())
169 if (!mlir::getConstantIntValue(s))
170 return op->emitOpError(
171 "runtime-valued BD size/stride is not supported on the static "
172 "XAIE lowering path; use compile-time constant sizes");
173 std::optional<SmallVector<BDDimLayoutAttr>> folded =
174 op.getConstantDimensions();
176 return op->emitOpError(
"internal error folding BD dimensions");
177 dimsStorage = std::move(*folded);
185 return memOp.emitOpError(
"DMA contains at least one multi-dimensional "
186 "buffer descriptor. This is currently only "
187 "supported for AIE-ML and later devices.");
190 if (foundBd && lenA > std::numeric_limits<uint32_t>::max()) {
191 return memOp.emitOpError(
"buffer descriptor length in bytes (")
192 << lenA <<
") does not fit in 32 bits";
195 int acqValue = 0, relValue = 0;
196 bool hasAcq =
false, hasRel =
false;
197 int acqLockID = 0, relLockID = 0;
198 for (
auto op : block->getOps<UseLockOp>()) {
199 LockOp lock = cast<LockOp>(op.getLock().getDefiningOp());
200 int lockCol = lock.colIndex();
201 int lockRow = lock.rowIndex();
202 int lockID = lock.getLockIDValue();
208 lockID += lockOffset.value();
211 if (op.acquire() || op.acquireGE()) {
214 auto value = op.getConstantValue();
219 acqValue = -acqValue;
220 }
else if (op.release()) {
223 auto value = op.getConstantValue();
229 return op.emitOpError(
"unsupported lock action");
233 int bdNum = blockMap[block];
238 output <<
"XAie_DmaDesc " <<
tileDMAInstStr(col, row, bdNum) <<
";\n";
239 output <<
"__mlir_aie_try(XAie_DmaDescInit(" << deviceInstRef <<
", "
242 if (hasAcq || hasRel) {
243 output <<
"__mlir_aie_try(XAie_DmaSetLock("
245 <<
"XAie_LockInit(" << acqLockID <<
"," << acqValue <<
"),"
246 <<
"XAie_LockInit(" << relLockID <<
"," << relValue <<
")));\n";
249 <<
".LockDesc.LockAcqEn = " << disable <<
";\n";
252 <<
".LockDesc.LockRelEn = " << disable <<
";\n";
257 output <<
"__mlir_aie_try(XAie_DmaSetAddrLen("
259 <<
"mlir_aie_external_get_addr_myBuffer_" << col << row <<
"_"
261 <<
" /* len */ " << lenA <<
"));\n";
262 output <<
"__mlir_aie_try(XAie_DmaSetAxi("
265 <<
"/* burstlen */ 4, "
267 <<
"/* Cache */ " << axcache <<
", "
268 <<
"/* Secure */ " << enable <<
"));\n";
270 if ((BaseAddrA + offsetA) % 4)
271 return memOp.emitError(
"bd address must be 4B (32b) aligned");
272 output <<
"__mlir_aie_try(XAie_DmaSetAddrLen("
274 <<
"0x" << llvm::utohexstr(BaseAddrA + offsetA) <<
", "
275 <<
" /* len */ " << lenA <<
"));\n";
279 BaseAddrA, offsetA, lenA,
280 elementWidthInBytes,
"1");
282 if (iterSize > 1 && iterStride > 0) {
283 int64_t strideInBytes =
284 static_cast<int64_t
>(iterStride) * elementWidthInBytes;
285 if (strideInBytes % 4)
286 return memOp.emitError(
"iteration_stride must result in a stride "
287 "aligned to 32-bit words");
288 int stepInWords =
static_cast<int>(strideInBytes / 4);
289 output <<
"__mlir_aie_try(XAie_DmaSetBdIteration("
291 <<
", " << iterSize <<
", " << iterCurr <<
"));\n";
294 if (block->getNumSuccessors() > 0) {
295 Block *nextBlock = block->getSuccessors()[0];
298 int enableNextBd = 1;
299 if (!nextBlock->getOps<EndOp>().empty())
301 if (oooBlocks.contains(block))
304 int nextBdNum = blockMap[nextBlock];
305 output <<
"__mlir_aie_try(XAie_DmaSetNextBd("
307 <<
" /* nextbd */ " << nextBdNum <<
", "
308 <<
" /* enableNextBd */ " << enableNextBd <<
"));\n";
312 output <<
"__mlir_aie_try(XAie_DmaSetPkt("
314 <<
packetStr(packetID, packetType) <<
"));\n";
316 if (oooId.has_value()) {
317 output <<
"__mlir_aie_try(XAie_DmaSetOutofOrderBdId("
321 output <<
"__mlir_aie_try(XAie_DmaEnableBd("
323 output <<
"__mlir_aie_try(XAie_DmaWriteBd(" << deviceInstRef <<
", "
326 <<
" /* bd */ " << bdNum <<
"));\n";
330 for (
auto *block : blockVector) {
331 for (
auto op : block->getOps<DMAStartOp>()) {
332 int bdNum = blockMap[op.getDest()];
333 StringRef dmaDir = stringifyDMAChannelDir(op.getChannelDir());
334 int chNum = op.getChannelIndex();
336 if (target_model.getTargetArch() == AIEArch::AIE1) {
337 output <<
"__mlir_aie_try(XAie_DmaChannelPushBdToQueue("
338 << deviceInstRef <<
", " <<
tileLocStr(col, row) <<
", "
339 <<
"/* ChNum */" << chNum
342 <<
"/* dmaDir */ DMA_" << dmaDir <<
", "
343 <<
"/* BdNum */" << bdNum <<
"));\n";
344 }
else if (op.getOutOfOrder()) {
347 int repeatCount = op.getRepeatCount() + 1;
349 std::string oooSuffix = std::to_string(col) +
"_" +
350 std::to_string(row) +
"_" +
351 std::to_string(chNum);
352 output <<
"XAie_DmaChannelDesc ooo_desc_" << oooSuffix <<
";\n";
353 output <<
"__mlir_aie_try(XAie_DmaChannelDescInit(" << deviceInstRef
354 <<
", &ooo_desc_" << oooSuffix <<
", " <<
tileLocStr(col, row)
356 output <<
"__mlir_aie_try(XAie_DmaChannelEnOutofOrder(&ooo_desc_"
357 << oooSuffix <<
", " << enable <<
"));\n";
358 output <<
"__mlir_aie_try(XAie_DmaWriteChannel(" << deviceInstRef
359 <<
", &ooo_desc_" << oooSuffix <<
", " <<
tileLocStr(col, row)
360 <<
", /* ChNum */" << chNum <<
", /* dmaDir */ DMA_" << dmaDir
362 output <<
"XAie_DmaDeclareQueueConfig(ooo_queue_" << oooSuffix
363 <<
", /* StartBd */ 0, /* Repeat */ " << repeatCount
364 <<
", /* EnToken */ " << disable <<
", /* EnOutOfOrder */ "
366 output <<
"__mlir_aie_try(XAie_DmaChannelSetStartQueueGeneric("
367 << deviceInstRef <<
", " <<
tileLocStr(col, row)
368 <<
", /* ChNum */" << chNum <<
", /* dmaDir */ DMA_" << dmaDir
369 <<
", &ooo_queue_" << oooSuffix <<
"));\n";
373 int repeatCount = op.getRepeatCount() + 1;
374 output <<
"__mlir_aie_try(XAie_DmaChannelSetStartQueue("
375 << deviceInstRef <<
", " <<
tileLocStr(col, row) <<
", "
376 <<
"/* ChNum */" << chNum
379 <<
"/* dmaDir */ DMA_" << dmaDir <<
", "
380 <<
"/* BdNum */" << bdNum <<
", "
381 <<
"/* Repeat */ " << repeatCount <<
", "
386 output <<
"__mlir_aie_try(XAie_DmaChannelEnable(" << deviceInstRef <<
", "
388 <<
"/* ChNum */ " << chNum
391 <<
"/* dmaDir */ DMA_" << dmaDir <<
"));\n";
399 llvm::StringRef deviceName) {
400 StringRef ctx_p =
"aie_libxaie_ctx_t* ctx";
401 StringRef deviceInstRef =
"ctx->XAieDevInst";
403 DenseMap<TileID, Operation *> tiles;
404 DenseMap<Operation *, SmallVector<BufferOp, 4>> buffers;
406 DeviceOp targetOp = AIE::DeviceOp::getForSymbolInModule(module, deviceName);
408 return module.emitOpError("expected AIE.device operation at toplevel");
411 const auto &targetModel = targetOp.getTargetModel();
419 output << xaie_cpp_file_header;
420 output <<
"aie_libxaie_ctx_t* mlir_aie_init_libxaie() {\n";
421 output <<
" aie_libxaie_ctx_t *ctx = new aie_libxaie_ctx_t;\n";
422 output <<
" if (!ctx)\n";
423 output <<
" return 0;\n";
424 output <<
" ctx->XAieConfig = new XAie_Config;\n";
425 output <<
" if (!ctx->XAieConfig)\n";
426 output <<
" return 0;\n";
427 output <<
" ctx->XAieDevInst = new XAie_DevInst;\n";
428 output <<
" if (!ctx->XAieDevInst)\n";
429 output <<
" return 0;\n";
431 std::string AIE1_device(
"XAIE_DEV_GEN_AIE");
432 std::string AIE2_device(
"XAIE_DEV_GEN_AIEML");
433 std::string AIE2p_device(
"XAIE_DEV_GEN_AIE2P");
437 device = AIE1_device;
440 device = AIE2_device;
443 device = AIE2p_device;
445 case AIEArch::AIE2ps:
449 return targetOp.emitOpError(
450 "--aie-generate-xaie is not supported for the AIE2PS architecture");
452 output <<
" ctx->XAieConfig->AieGen = " << device <<
";\n";
453 output <<
" ctx->XAieConfig->BaseAddr = 0x20000000000;\n";
454 output <<
" ctx->XAieConfig->ColShift = " << targetModel.
getColumnShift()
456 output <<
" ctx->XAieConfig->RowShift = " << targetModel.
getRowShift()
458 output <<
" ctx->XAieConfig->NumRows = " << targetModel.
rows() <<
";\n";
459 output <<
" ctx->XAieConfig->NumCols = " << targetModel.
columns() <<
";\n";
460 output <<
" ctx->XAieConfig->ShimRowNum = 0;\n";
461 output <<
" ctx->XAieConfig->MemTileRowStart = 1;\n";
462 output <<
" ctx->XAieConfig->MemTileNumRows = "
464 output <<
" // ctx->XAieConfig->ReservedRowStart = "
465 "XAIE_RES_TILE_ROW_START;\n";
467 <<
" // ctx->XAieConfig->ReservedNumRows = XAIE_RES_TILE_NUM_ROWS;\n";
468 output <<
" ctx->XAieConfig->AieTileRowStart = "
470 output <<
" ctx->XAieConfig->AieTileNumRows = "
472 output <<
" memset(ctx->XAieDevInst, 0, sizeof(XAie_DevInst));\n";
473 output <<
" return ctx;\n";
482 output <<
"int mlir_aie_initialize_buffers(" << ctx_p <<
");\n";
483 output <<
"int mlir_aie_configure_cores(" << ctx_p <<
") {\n";
485 for (
auto tileOp : targetOp.getOps<TileOp>()) {
486 int col = tileOp.colIndex();
487 int row = tileOp.rowIndex();
488 if (tileOp.isShimTile() || tileOp.isMemTile()) {
492 output <<
"__mlir_aie_try(XAie_CoreReset(" << deviceInstRef <<
", "
494 output <<
"__mlir_aie_try(XAie_CoreDisable(" << deviceInstRef <<
", "
498 output <<
"for (int l = 0; l < " << numLocks <<
"; ++l)\n"
499 <<
" __mlir_aie_try(XAie_LockRelease(" << deviceInstRef <<
", "
500 <<
tileLocStr(col, row) <<
", XAie_LockInit(l, 0x0), 0));\n";
501 if (
auto coreOp = tileOp.getCoreOp()) {
502 if (coreOp.isEmpty() && coreOp.getElfFile() == std::nullopt) {
507 std::string fileName;
508 if (
auto fileAttr = coreOp.getElfFile()) {
509 fileName = fileAttr.value().str();
511 return coreOp.emitOpError()
512 <<
"Expected lowered ELF file to be given as attribute "
513 "`elf_file` for this core. Compile cores first.";
516 <<
"AieRC RC = XAie_LoadElf(" << deviceInstRef <<
", "
518 <<
"(const char*)\"" << fileName <<
"\",0);\n";
519 output <<
"if (RC != XAIE_OK)\n"
520 <<
" __mlir_aie_verbose(fprintf(stderr, \"Failed to load elf "
521 "for Core[%d,%d], ret is %d\\n\", "
522 << std::to_string(col) <<
", " << std::to_string(row)
524 <<
"assert(RC == XAIE_OK);\n"
532 output <<
" int rc = mlir_aie_initialize_buffers(ctx);\n";
533 output <<
" if (rc != XAIE_OK)\n";
534 output <<
" return rc;\n";
536 output <<
"return XAIE_OK;\n";
537 output <<
"} // mlir_aie_configure_cores\n\n";
542 output <<
"int mlir_aie_start_cores(" << ctx_p <<
") {\n";
544 for (
auto tileOp : targetOp.getOps<TileOp>()) {
545 int col = tileOp.colIndex();
546 int row = tileOp.rowIndex();
547 if (!tileOp.isShimTile() && !tileOp.isMemTile()) {
548 output <<
"__mlir_aie_try(XAie_CoreUnreset(" << deviceInstRef <<
", "
550 output <<
"__mlir_aie_try(XAie_CoreEnable(" << deviceInstRef <<
", "
554 output <<
"return XAIE_OK;\n";
555 output <<
"} // mlir_aie_start_cores\n\n";
560 output <<
"int mlir_aie_configure_dmas(" << ctx_p <<
") {\n";
562 for (
auto memOp : targetOp.getOps<MemOp>()) {
563 DenseMap<Block *, int> blockMap;
567 for (
auto &block : memOp.getBody()) {
568 auto bdOps = block.getOps<DMABDOp>();
571 std::optional<int32_t>
id = (*bdOps.begin()).getBdId();
572 blockMap[&block] =
id.has_value() ? *id : bdNum;
575 auto result = generateDMAConfig(memOp, output, targetModel, blockMap);
579 for (
auto memOp : targetOp.getOps<MemTileDMAOp>()) {
580 DenseMap<Block *, int> blockMap;
582 DenseMap<Block *, int> channelMap;
584 for (
auto &block : memOp.getBody()) {
585 for (
auto op : block.getOps<DMAStartOp>()) {
586 int chNum = op.getChannelIndex();
587 channelMap[&block] = chNum;
588 auto *dest = op.getDest();
590 channelMap[dest] = chNum;
591 if (dest->getSuccessors().empty())
593 dest = dest->getSuccessors()[0];
594 if (channelMap.count(dest))
603 for (
auto &block : memOp.getBody()) {
604 auto bdOps = block.getOps<DMABDOp>();
607 assert(channelMap.count(&block));
608 if (std::optional<int32_t>
id = (*bdOps.begin()).getBdId())
609 blockMap[&block] = *id;
610 else if (channelMap[&block] & 1)
611 blockMap[&block] = oddBdNum++;
613 blockMap[&block] = evenBdNum++;
615 auto result = generateDMAConfig(memOp, output, targetModel, blockMap);
620 output <<
"return XAIE_OK;\n";
621 output <<
"} // mlir_aie_configure_dmas\n\n";
623 for (
auto op : targetOp.getOps<ExternalBufferOp>()) {
625 output <<
"static u64 _mlir_aie_external_" << op.name().getValue()
627 output <<
"static bool _mlir_aie_external_set_" << op.name().getValue()
630 output <<
"void mlir_aie_external_set_addr_" << op.name().getValue()
631 <<
"(" << ctx_p <<
", u64 VA) {\n"
632 <<
" u64 device_address = mlir_aie_get_device_address(ctx, (void "
634 <<
" _mlir_aie_external_set_" << op.name().getValue()
636 <<
" _mlir_aie_external_" << op.name().getValue()
637 <<
" = device_address;\n"
644 for (
auto op : targetOp.getOps<ShimDMAOp>()) {
645 int col = op.colIndex();
646 int row = op.rowIndex();
648 DenseMap<Block *, int> blockMap;
652 for (
auto &block : op.getBody()) {
653 auto bdOps = block.getOps<DMABDOp>();
656 std::optional<int32_t>
id = (*bdOps.begin()).getBdId();
657 int slot =
id.has_value() ? *id : bdNum;
658 blockMap[&block] = slot;
660 for (
auto op : block.getOps<DMABDOp>()) {
661 offset = op.getOffsetInBytes();
662 auto buffer = cast<ExternalBufferOp>(op.getBuffer().getDefiningOp());
664 output <<
"u64 mlir_aie_external_get_addr_myBuffer_" << col << row
665 <<
"_" << slot <<
"(void) {\n"
666 <<
" assert(_mlir_aie_external_set_"
667 << buffer.name().getValue() <<
");\n"
668 <<
" return _mlir_aie_external_" << buffer.name().getValue()
669 <<
" + " << llvm::utohexstr(offset) <<
";\n"
677 output <<
"int mlir_aie_configure_shimdma_" << col << row <<
"(" << ctx_p
679 auto result = generateDMAConfig(op, output, targetModel, blockMap);
682 output <<
"return XAIE_OK;\n";
683 output <<
"} // mlir_aie_configure_shimdma\n\n";
689 output <<
"int mlir_aie_initialize_locks(" << ctx_p <<
") {\n";
691 targetOp.walk<WalkOrder::PreOrder>([&](LockOp lock) {
692 TileOp tile = lock.getTileOp();
693 int col = tile.colIndex();
694 int row = tile.rowIndex();
695 int lockID = lock.getLockIDValue();
696 auto init = lock.getInit();
698 output <<
"__mlir_aie_try(XAie_LockSetValue(" << deviceInstRef <<
", "
700 <<
"XAie_LockInit(" << lockID <<
", " << *init <<
")));\n";
702 output <<
"return XAIE_OK;\n";
703 output <<
"} // mlir_aie_initialize_locks\n";
713 output <<
"int mlir_aie_initialize_buffers(" << ctx_p <<
") {\n";
714 auto initBuffersResult = targetOp.walk<WalkOrder::PreOrder>([&](BufferOp
716 auto initialValue = buffer.getInitialValue();
718 return WalkResult::advance();
719 auto denseInit = llvm::dyn_cast<DenseElementsAttr>(*initialValue);
721 return WalkResult::advance();
724 return WalkResult(buffer.emitOpError(
725 "buffer op type not supported for initialization"));
726 if (!buffer.getAddress())
727 return WalkResult(buffer.emitOpError(
728 "buffer has no address; run --aie-assign-buffer-addresses first"));
729 TileOp tile = buffer.getTileOp();
732 std::string bufName(buffer.name().getValue());
734 output <<
"static const unsigned char " << bufName <<
"_init[] = {";
735 for (
size_t i = 0; i < bytes->size(); ++i)
736 output << (i ?
"," :
"") << (unsigned)(
unsigned char)(*bytes)[i];
738 output <<
"__mlir_aie_try(XAie_DataMemBlockWrite(" << deviceInstRef <<
", "
739 <<
tileLocStr(tile.colIndex(), tile.rowIndex()) <<
", "
740 <<
"0x" << llvm::utohexstr(*buffer.getAddress()) <<
", "
741 <<
"(void *)" << bufName <<
"_init, " << bytes->size() <<
"));\n";
743 return WalkResult::advance();
745 if (initBuffersResult.wasInterrupted())
747 output <<
"return XAIE_OK;\n";
748 output <<
"} // mlir_aie_initialize_buffers\n";
753 output <<
"int mlir_aie_configure_switchboxes(" << ctx_p <<
") {\n";
754 output <<
" int x, y;\n";
757 for (
auto switchboxOp : targetOp.getOps<SwitchboxOp>()) {
758 Region &r = switchboxOp.getConnections();
759 Block &b = r.front();
760 bool isEmpty = b.getOps<ConnectOp>().empty() &&
761 b.getOps<MasterSetOp>().empty() &&
762 b.getOps<PacketRulesOp>().empty();
763 bool isParam =
false;
765 if (isa<TileOp>(switchboxOp.getTile().getDefiningOp())) {
766 int col = switchboxOp.colIndex();
767 int row = switchboxOp.rowIndex();
769 output <<
"// Core Stream Switch column " << col <<
" row " << row
771 output <<
"x = " << col <<
";\n";
772 output <<
"y = " << row <<
";\n";
776 for (
auto connectOp : b.getOps<ConnectOp>())
777 output <<
"__mlir_aie_try(XAie_StrmConnCctEnable(" << deviceInstRef
779 << wireBundleToPortType(connectOp.getSourceBundle()) <<
", "
780 << connectOp.sourceIndex() <<
", "
781 << wireBundleToPortType(connectOp.getDestBundle()) <<
", "
782 << connectOp.destIndex() <<
"));\n";
784 for (
auto connectOp : b.getOps<MasterSetOp>()) {
789 for (
auto val : connectOp.getAmsels()) {
790 AMSelOp amsel = cast<AMSelOp>(val.getDefiningOp());
791 arbiter = amsel.arbiterIndex();
792 int msel = amsel.getMselValue();
795 bool isdma = (connectOp.getDestBundle() == WireBundle::DMA);
797 output <<
"__mlir_aie_try(XAie_StrmPktSwMstrPortEnable(" << deviceInstRef
799 << wireBundleToPortType(connectOp.getDestBundle()) <<
", "
800 << connectOp.destIndex() <<
", "
801 <<
"/* drop_header */ "
802 << (isdma ?
"XAIE_SS_PKT_DROP_HEADER"
803 :
"XAIE_SS_PKT_DONOT_DROP_HEADER")
805 <<
"/* arbiter */ " << arbiter <<
", "
807 <<
"0x" << llvm::utohexstr(mask) <<
"));\n";
810 for (
auto connectOp : b.getOps<PacketRulesOp>()) {
812 Block &block = connectOp.getRules().front();
813 for (
auto slotOp : block.getOps<PacketRuleOp>()) {
814 AMSelOp amselOp = cast<AMSelOp>(slotOp.getAmsel().getDefiningOp());
815 int arbiter = amselOp.arbiterIndex();
816 int msel = amselOp.getMselValue();
817 output <<
"__mlir_aie_try(XAie_StrmPktSwSlavePortEnable("
818 << deviceInstRef <<
", " <<
tileLocStr(
"x",
"y") <<
", "
819 << wireBundleToPortType(connectOp.getSourceBundle()) <<
", "
820 << connectOp.sourceIndex() <<
"));\n";
823 output <<
"__mlir_aie_try(XAie_StrmPktSwSlaveSlotEnable("
824 << deviceInstRef <<
", " <<
tileLocStr(
"x",
"y") <<
", "
825 << wireBundleToPortType(connectOp.getSourceBundle()) <<
", "
826 << connectOp.sourceIndex() <<
", "
827 <<
"/* slot */ " << slot <<
", "
828 <<
"/* packet */ " <<
packetStr(slotOp.valueInt(), 0)
831 <<
"0x" << llvm::utohexstr(slotOp.maskInt()) <<
", "
832 <<
"/* msel */ " << msel <<
", "
833 <<
"/* arbiter */ " << arbiter <<
"));\n";
843 for (
auto op : targetOp.getOps<ShimMuxOp>()) {
844 Region &r = op.getConnections();
845 Block &b = r.front();
846 bool isEmpty = b.getOps<ConnectOp>().empty();
848 if (isa<TileOp>(op.getTile().getDefiningOp())) {
849 int col = op.colIndex();
850 int row = op.rowIndex();
852 output <<
"// ShimMux column " << col <<
" row " << row <<
"\n";
853 output <<
"// NOTE ShimMux always connects from the south as "
854 <<
"directions are defined relative to the tile stream "
856 output <<
"x = " << col <<
";\n";
857 output <<
"y = " << row <<
";\n";
861 for (
auto connectOp : b.getOps<ConnectOp>()) {
863 if (connectOp.getSourceBundle() == WireBundle::DMA ||
864 connectOp.getDestBundle() == WireBundle::DMA) {
865 if (connectOp.getSourceBundle() == WireBundle::North)
867 output <<
"__mlir_aie_try(XAie_EnableAieToShimDmaStrmPort("
868 << deviceInstRef <<
", " <<
tileLocStr(
"x",
"y") <<
", "
869 << connectOp.sourceIndex() <<
"));\n";
870 else if (connectOp.getDestBundle() == WireBundle::North)
872 output <<
"__mlir_aie_try(XAie_EnableShimDmaToAieStrmPort("
873 << deviceInstRef <<
", " <<
tileLocStr(
"x",
"y") <<
", "
874 << connectOp.destIndex() <<
"));\n";
877 else if (connectOp.getSourceBundle() == WireBundle::PLIO ||
878 connectOp.getDestBundle() == WireBundle::PLIO) {
879 if (connectOp.getSourceBundle() == WireBundle::North) {
881 output <<
"__mlir_aie_try(XAie_AieToPlIntfEnable(" << deviceInstRef
883 << connectOp.destIndex() <<
", PLIF_WIDTH_64));\n";
884 }
else if (connectOp.getDestBundle() == WireBundle::North) {
886 output <<
"__mlir_aie_try(XAie_PlToAieIntfEnable(" << deviceInstRef
888 << connectOp.destIndex() <<
", PLIF_WIDTH_64));\n";
893 output <<
"return XAIE_OK;\n";
894 output <<
"} // mlir_aie_configure_switchboxes\n\n";
899 output <<
"int mlir_aie_configure_cascade(" << ctx_p <<
") {\n";
900 for (
auto configOp : targetOp.getOps<ConfigureCascadeOp>()) {
901 TileOp tile = cast<TileOp>(configOp.getTile().getDefiningOp());
902 int col = tile.colIndex();
903 int row = tile.rowIndex();
904 output <<
"XAie_CoreConfigAccumulatorControl(" << deviceInstRef <<
", "
905 <<
"XAie_TileLoc(" << col <<
", " << row <<
"), "
906 << stringifyCascadeDir(configOp.getInputDir()).upper() <<
", "
907 << stringifyCascadeDir(configOp.getOutputDir()).upper() <<
");\n";
909 output <<
"return XAIE_OK;\n";
910 output <<
"} // mlir_aie_configure_cascade\n\n";
915 for (
auto tile : tiles) {
916 Operation *tileOp = tile.second;
917 TileID coord = cast<TileOp>(tileOp).getTileID();
922 auto bufferAccessor = [&](BufferOp buf) {
925 std::string bufName(buf.name().getValue());
926 Type t = buf.getType();
929 if (
auto memrefType = llvm::dyn_cast<MemRefType>(t)) {
930 et = memrefType.getElementType();
931 if (et.isInteger(32))
936 output <<
"// buffer " << bufName <<
" with unsupported type " << t
942 output <<
"// buffer " << bufName <<
" with unsupported type " << t
946 assert(buf.getAddress().has_value() &&
"buffer must have address");
947 output <<
"const int " << bufName
948 <<
"_offset = " << buf.getAddress().value() <<
";\n";
949 output << typestr <<
" mlir_aie_read_buffer_" << bufName <<
"(" << ctx_p
950 <<
", int index) {\n";
951 output <<
"u32 value; auto rc = XAie_DataMemRdWord(" << deviceInstRef
952 <<
", " << loc <<
", " << bufName
953 <<
"_offset + (index*4), &value);\n";
954 if (et.isInteger(32))
955 output <<
" return value;\n";
956 else if (et.isF32()) {
957 output <<
" union caster { int32_t i; float f; };\n";
958 output <<
" caster c; c.i = value;\n";
959 output <<
" return c.f;\n";
962 output <<
"int mlir_aie_write_buffer_" << bufName <<
"(" << ctx_p
963 <<
", int index, " << typestr <<
" value) {\n";
964 if (et.isInteger(32))
965 output <<
" int32_t int_value = value;\n";
966 else if (et.isF32()) {
967 output <<
" union caster { int32_t i; float f; };\n";
968 output <<
" caster c; c.f = value;\n";
969 output <<
" int32_t int_value = c.i;\n";
971 output <<
"AieRC rc = XAie_DataMemWrWord(" << deviceInstRef <<
", "
972 << loc <<
", " << bufName <<
"_offset + (index*4), int_value);\n";
973 output <<
"return rc;\n";
978 for (
auto buf : buffers[tileOp])
982 auto lockAccessor = [&](LockOp lock) {
983 int col = lock.colIndex();
984 int row = lock.rowIndex();
987 std::string lockName(lock.name().getValue());
988 output <<
"int mlir_aie_acquire_" << lockName <<
"(" << ctx_p
989 <<
", int value, int timeout) {\n";
990 output <<
" const int id = " << lock.getLockIDValue() <<
";\n";
991 output <<
" return XAie_LockAcquire(" << deviceInstRef <<
", "
992 <<
tileLocStr(col, row) <<
", " << tileLockStr(
"id",
"value")
995 output <<
"int mlir_aie_release_" << lockName <<
"(" << ctx_p
996 <<
", int value, int timeout) {\n";
997 output <<
" const int id = " << lock.getLockIDValue() <<
";\n";
998 output <<
" return XAie_LockRelease(" << deviceInstRef <<
", "
999 <<
tileLocStr(col, row) <<
", " << tileLockStr(
"id",
"value")
1004 targetOp.walk<WalkOrder::PreOrder>([&](LockOp lock) { lockAccessor(lock); });
std::optional< uint32_t > getMemLocalBaseAddress(int localCol, int localRow, int memCol, int memRow) const
Return the memory base address (or offset) in the local tile when accessing a neighbor's memory or an...
virtual AIEArch getTargetArch() const =0
Return the target architecture.
bool isMemTile(int col, int row) const
Return true if the given tile is a Mem tile.
std::optional< uint32_t > getLockLocalBaseIndex(int localCol, int localRow, int lockCol, int lockRow) const
Return the lock base index (or offset) in the local tile when accessing a neighbor's lock or an empty...
virtual uint32_t getNumLocks(AIETileType tileType) const =0
Return the number of lock objects for a given tile type.
virtual int rows() const =0
Return the number of rows in the device.
bool isShimNOCTile(int col, int row) const
Return true if the given tile is a ShimNOC tile.
@ UsesMultiDimensionalBDs
virtual uint32_t getColumnShift() const =0
bool hasProperty(ModelProperty Prop) const
virtual int columns() const =0
Return the number of columns in the device.
virtual uint32_t getNumMemTileRows() const =0
virtual uint32_t getRowShift() const =0
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.
void collectTiles(DeviceOp &device, llvm::DenseMap< TileID, mlir::Operation * > &tiles)
void collectBuffers(DeviceOp &device, llvm::DenseMap< mlir::Operation *, llvm::SmallVector< BufferOp, 4 > > &buffers)
std::string tileDMAInstStr(llvm::StringRef col, llvm::StringRef row, llvm::StringRef bdNum)
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)
struct TileID { friend std::ostream &operator<<(std::ostream &os, const TileID &s) { os<< "TileID("<< s.col<< ", "<< s.row<< ")"; return os; } friend std::string to_string(const TileID &s) { std::ostringstream ss; ss<< s; return ss.str(); } friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const TileID &s) { os<< to_string(s); return os; } inline bool operator<(const TileID &rhs) const { return std::tie(col, row)< std::tie(rhs.col, rhs.row); } bool operator==(const TileID &rhs) const { return std::tie(col, row)==std::tie(rhs.col, rhs.row); } bool operator!=(const TileID &rhs) const { return !(*this==rhs);} int col, row;} TileID
const AIETargetModel & getTargetModel(mlir::Operation *op)
mlir::LogicalResult verifyDMAChannelsResolved(DeviceOp device)
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.
std::string tileDMAInstRefStr(llvm::StringRef col, llvm::StringRef row, llvm::StringRef bdNum)
llvm::SetVector< mlir::Block * > getOrderedChainOfBlocks(mlir::Region *region)
mlir::LogicalResult AIETranslateToXAIEV2(mlir::ModuleOp module, llvm::raw_ostream &output, llvm::StringRef deviceName="")
std::string tileLocStr(llvm::StringRef col, llvm::StringRef row)
std::string packetStr(llvm::StringRef id, llvm::StringRef type)