17#include "mlir/IR/Attributes.h"
18#include "mlir/IR/IRMapping.h"
19#include "mlir/Pass/Pass.h"
20#include "mlir/Tools/mlir-translate/MlirTranslateMain.h"
22#include "llvm/ADT/StringExtras.h"
23#include "llvm/IR/Module.h"
31static const char *xaie_cpp_file_header = R
"code(
32// This file was auto-generated by aiecc.py --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 for (
auto block : blockVector) {
102 bool foundBdPacket =
false;
105 bool foundBd =
false;
109 int elementWidthInBytes = 0;
111 ArrayRef<BDDimLayoutAttr> dims;
113 for (
auto op : block->getOps<DMABDOp>()) {
116 assert(op.getBufferOp().getAddress() &&
117 "buffer must have address assigned");
118 BaseAddrA = op.getBufferOp().getAddress().value();
119 int bufferCol = op.getBufferOp().getTileOp().colIndex();
120 int bufferRow = op.getBufferOp().getTileOp().rowIndex();
125 col,
row, bufferCol, bufferRow);
127 BaseAddrA += addrOffset.value();
131 lenA = op.getLenInBytes();
132 offsetA = op.getOffsetInBytes();
133 elementWidthInBytes = op.getBufferElementTypeWidthInBytes();
134 if (op.getDimensions()) {
135 dims = *op.getDimensions();
142 return memOp.emitOpError(
"DMA contains at least one multi-dimensional "
143 "buffer descriptor. This is currently only "
144 "supported for AIE-ML and later devices.");
146 int acqValue = 0, relValue = 0;
147 bool hasAcq =
false, hasRel =
false;
148 int acqLockID = 0, relLockID = 0;
149 for (
auto op : block->getOps<UseLockOp>()) {
150 LockOp lock = cast<LockOp>(op.getLock().getDefiningOp());
151 int lockCol = lock.colIndex();
152 int lockRow = lock.rowIndex();
153 int lockID = lock.getLockIDValue();
159 lockID += lockOffset.value();
162 if (op.acquire() || op.acquireGE()) {
165 acqValue = op.getLockValue();
167 acqValue = -acqValue;
168 }
else if (op.release()) {
171 relValue = op.getLockValue();
174 return op.emitOpError(
"unsupported lock action");
178 for (
auto op : block->getOps<DMABDPACKETOp>()) {
179 foundBdPacket =
true;
180 packetType = op.getPacketType();
181 packetID = op.getPacketID();
184 int bdNum = blockMap[block];
190 output <<
"__mlir_aie_try(XAie_DmaDescInit(" << deviceInstRef <<
", "
193 if (hasAcq || hasRel) {
194 output <<
"__mlir_aie_try(XAie_DmaSetLock("
196 <<
"XAie_LockInit(" << acqLockID <<
"," << acqValue <<
"),"
197 <<
"XAie_LockInit(" << relLockID <<
"," << relValue <<
")));\n";
200 <<
".LockDesc.LockAcqEn = " << disable <<
";\n";
203 <<
".LockDesc.LockRelEn = " << disable <<
";\n";
208 output <<
"__mlir_aie_try(XAie_DmaSetAddrLen("
210 <<
"mlir_aie_external_get_addr_myBuffer_" <<
col <<
row <<
"_"
212 <<
" /* len */ " << lenA <<
"));\n";
213 output <<
"__mlir_aie_try(XAie_DmaSetAxi("
216 <<
"/* burstlen */ 4, "
219 <<
"/* Secure */ " << enable <<
"));\n";
221 if ((BaseAddrA + offsetA) % 4)
222 return memOp.emitError(
"bd address must be 4B (32b) aligned");
223 output <<
"__mlir_aie_try(XAie_DmaSetAddrLen("
225 <<
"0x" << llvm::utohexstr(BaseAddrA + offsetA) <<
", "
226 <<
" /* len */ " << lenA <<
"));\n";
230 BaseAddrA, offsetA, lenA,
231 elementWidthInBytes,
"1");
233 if (block->getNumSuccessors() > 0) {
234 Block *nextBlock = block->getSuccessors()[0];
237 int enableNextBd = 1;
238 if (!nextBlock->getOps<EndOp>().empty())
241 int nextBdNum = blockMap[nextBlock];
242 output <<
"__mlir_aie_try(XAie_DmaSetNextBd("
244 <<
" /* nextbd */ " << nextBdNum <<
", "
245 <<
" /* enableNextBd */ " << enableNextBd <<
"));\n";
249 output <<
"__mlir_aie_try(XAie_DmaSetPkt("
251 <<
packetStr(packetID, packetType) <<
"));\n";
253 output <<
"__mlir_aie_try(XAie_DmaEnableBd("
255 output <<
"__mlir_aie_try(XAie_DmaWriteBd(" << deviceInstRef <<
", "
258 <<
" /* bd */ " << bdNum <<
"));\n";
262 for (
auto block : blockVector) {
263 for (
auto op : block->getOps<DMAStartOp>()) {
264 int bdNum = blockMap[op.getDest()];
265 StringRef dmaDir = stringifyDMAChannelDir(op.getChannelDir());
266 int chNum = op.getChannelIndex();
268 if (target_model.getTargetArch() == AIEArch::AIE1) {
269 output <<
"__mlir_aie_try(XAie_DmaChannelPushBdToQueue("
271 <<
"/* ChNum */" << chNum
274 <<
"/* dmaDir */ DMA_" << dmaDir <<
", "
275 <<
"/* BdNum */" << bdNum <<
"));\n";
279 int repeatCount = op.getRepeatCount() + 1;
280 output <<
"__mlir_aie_try(XAie_DmaChannelSetStartQueue("
282 <<
"/* ChNum */" << chNum
285 <<
"/* dmaDir */ DMA_" << dmaDir <<
", "
286 <<
"/* BdNum */" << bdNum <<
", "
287 <<
"/* Repeat */ " << repeatCount <<
", "
292 output <<
"__mlir_aie_try(XAie_DmaChannelEnable(" << deviceInstRef <<
", "
294 <<
"/* ChNum */ " << chNum
297 <<
"/* dmaDir */ DMA_" << dmaDir <<
"));\n";
305 llvm::StringRef deviceName) {
306 StringRef ctx_p =
"aie_libxaie_ctx_t* ctx";
307 StringRef deviceInstRef =
"ctx->XAieDevInst";
309 DenseMap<TileID, Operation *> tiles;
310 DenseMap<Operation *, SmallVector<BufferOp, 4>> buffers;
312 DeviceOp targetOp = AIE::DeviceOp::getForSymbolInModule(module, deviceName);
314 return module.emitOpError("expected AIE.device operation at toplevel");
315 const auto &targetModel = targetOp.getTargetModel();
323 output << xaie_cpp_file_header;
324 output <<
"aie_libxaie_ctx_t* mlir_aie_init_libxaie() {\n";
325 output <<
" aie_libxaie_ctx_t *ctx = new aie_libxaie_ctx_t;\n";
326 output <<
" if (!ctx)\n";
327 output <<
" return 0;\n";
328 output <<
" ctx->XAieConfig = new XAie_Config;\n";
329 output <<
" if (!ctx->XAieConfig)\n";
330 output <<
" return 0;\n";
331 output <<
" ctx->XAieDevInst = new XAie_DevInst;\n";
332 output <<
" if (!ctx->XAieDevInst)\n";
333 output <<
" return 0;\n";
335 std::string AIE1_device(
"XAIE_DEV_GEN_AIE");
336 std::string AIE2_device(
"XAIE_DEV_GEN_AIEML");
337 std::string AIE2p_device(
"XAIE_DEV_GEN_AIE2P");
341 device = AIE1_device;
344 device = AIE2_device;
347 device = AIE2p_device;
350 return module.emitOpError("Unsupported aie.device");
352 output <<
" ctx->XAieConfig->AieGen = " << device <<
";\n";
353 output <<
" ctx->XAieConfig->BaseAddr = 0x20000000000;\n";
354 output <<
" ctx->XAieConfig->ColShift = " << targetModel.
getColumnShift()
356 output <<
" ctx->XAieConfig->RowShift = " << targetModel.
getRowShift()
358 output <<
" ctx->XAieConfig->NumRows = " << targetModel.
rows() <<
";\n";
359 output <<
" ctx->XAieConfig->NumCols = " << targetModel.
columns() <<
";\n";
360 output <<
" ctx->XAieConfig->ShimRowNum = 0;\n";
361 output <<
" ctx->XAieConfig->MemTileRowStart = 1;\n";
362 output <<
" ctx->XAieConfig->MemTileNumRows = "
364 output <<
" // ctx->XAieConfig->ReservedRowStart = "
365 "XAIE_RES_TILE_ROW_START;\n";
367 <<
" // ctx->XAieConfig->ReservedNumRows = XAIE_RES_TILE_NUM_ROWS;\n";
368 output <<
" ctx->XAieConfig->AieTileRowStart = "
370 output <<
" ctx->XAieConfig->AieTileNumRows = "
372 output <<
" memset(ctx->XAieDevInst, 0, sizeof(XAie_DevInst));\n";
373 output <<
" return ctx;\n";
380 output <<
"int mlir_aie_configure_cores(" << ctx_p <<
") {\n";
382 for (
auto tileOp : targetOp.getOps<TileOp>()) {
383 int col = tileOp.colIndex();
384 int row = tileOp.rowIndex();
385 if (tileOp.isShimTile() || tileOp.isMemTile()) {
389 output <<
"__mlir_aie_try(XAie_CoreReset(" << deviceInstRef <<
", "
391 output <<
"__mlir_aie_try(XAie_CoreDisable(" << deviceInstRef <<
", "
395 output <<
"for (int l = 0; l < " << numLocks <<
"; ++l)\n"
396 <<
" __mlir_aie_try(XAie_LockRelease(" << deviceInstRef <<
", "
398 if (
auto coreOp = tileOp.getCoreOp()) {
399 if (coreOp.isEmpty() && coreOp.getElfFile() == std::nullopt) {
404 std::string fileName;
405 if (
auto fileAttr = coreOp.getElfFile()) {
406 fileName = fileAttr.value().str();
408 return coreOp.emitOpError()
409 <<
"Expected lowered ELF file to be given as attribute "
410 "`elf_file` for this core. Compile cores first.";
413 <<
"AieRC RC = XAie_LoadElf(" << deviceInstRef <<
", "
415 <<
"(const char*)\"" << fileName <<
"\",0);\n";
416 output <<
"if (RC != XAIE_OK)\n"
417 <<
" __mlir_aie_verbose(fprintf(stderr, \"Failed to load elf "
418 "for Core[%d,%d], ret is %d\\n\", "
419 << std::to_string(
col) <<
", " << std::to_string(
row)
421 <<
"assert(RC == XAIE_OK);\n"
426 output <<
"return XAIE_OK;\n";
427 output <<
"} // mlir_aie_configure_cores\n\n";
432 output <<
"int mlir_aie_start_cores(" << ctx_p <<
") {\n";
434 for (
auto tileOp : targetOp.getOps<TileOp>()) {
435 int col = tileOp.colIndex();
436 int row = tileOp.rowIndex();
437 if (!tileOp.isShimTile() && !tileOp.isMemTile()) {
438 output <<
"__mlir_aie_try(XAie_CoreUnreset(" << deviceInstRef <<
", "
440 output <<
"__mlir_aie_try(XAie_CoreEnable(" << deviceInstRef <<
", "
444 output <<
"return XAIE_OK;\n";
445 output <<
"} // mlir_aie_start_cores\n\n";
450 output <<
"int mlir_aie_configure_dmas(" << ctx_p <<
") {\n";
452 for (
auto memOp : targetOp.getOps<MemOp>()) {
453 DenseMap<Block *, int> blockMap;
457 for (
auto &block : memOp.getBody()) {
458 if (!block.getOps<DMABDOp>().empty()) {
459 blockMap[&block] = bdNum;
463 auto result = generateDMAConfig(memOp, output, targetModel, blockMap);
467 for (
auto memOp : targetOp.getOps<MemTileDMAOp>()) {
468 DenseMap<Block *, int> blockMap;
470 DenseMap<Block *, int> channelMap;
472 for (
auto &block : memOp.getBody()) {
473 for (
auto op : block.getOps<DMAStartOp>()) {
474 int chNum = op.getChannelIndex();
475 channelMap[&block] = chNum;
476 auto dest = op.getDest();
478 channelMap[dest] = chNum;
479 if (dest->getSuccessors().size() < 1)
481 dest = dest->getSuccessors()[0];
482 if (channelMap.count(dest))
491 for (
auto &block : memOp.getBody()) {
492 if (block.getOps<DMABDOp>().empty())
494 assert(channelMap.count(&block));
495 if (channelMap[&block] & 1)
496 blockMap[&block] = oddBdNum++;
498 blockMap[&block] = evenBdNum++;
500 auto result = generateDMAConfig(memOp, output, targetModel, blockMap);
505 output <<
"return XAIE_OK;\n";
506 output <<
"} // mlir_aie_configure_dmas\n\n";
508 for (
auto op : targetOp.getOps<ExternalBufferOp>()) {
510 output <<
"static u64 _mlir_aie_external_" << op.name().getValue()
512 output <<
"static bool _mlir_aie_external_set_" << op.name().getValue()
515 output <<
"void mlir_aie_external_set_addr_" << op.name().getValue()
516 <<
"(" << ctx_p <<
", u64 VA) {\n"
517 <<
" u64 device_address = mlir_aie_get_device_address(ctx, (void "
519 <<
" _mlir_aie_external_set_" << op.name().getValue()
521 <<
" _mlir_aie_external_" << op.name().getValue()
522 <<
" = device_address;\n"
529 for (
auto op : targetOp.getOps<ShimDMAOp>()) {
530 int col = op.colIndex();
531 int row = op.rowIndex();
533 DenseMap<Block *, int> blockMap;
537 for (
auto &block : op.getBody()) {
538 if (!block.getOps<DMABDOp>().empty()) {
539 blockMap[&block] = bdNum;
541 for (
auto op : block.getOps<DMABDOp>()) {
542 offset = op.getOffsetInBytes();
544 cast<ExternalBufferOp>(op.getBuffer().getDefiningOp());
546 output <<
"u64 mlir_aie_external_get_addr_myBuffer_" <<
col <<
row
547 <<
"_" << bdNum <<
"(void) {\n"
548 <<
" assert(_mlir_aie_external_set_"
549 << buffer.name().getValue() <<
");\n"
550 <<
" return _mlir_aie_external_"
551 << buffer.name().getValue() <<
" + "
552 << llvm::utohexstr(offset) <<
";\n"
561 output <<
"int mlir_aie_configure_shimdma_" <<
col <<
row <<
"(" << ctx_p
563 auto result = generateDMAConfig(op, output, targetModel, blockMap);
566 output <<
"return XAIE_OK;\n";
567 output <<
"} // mlir_aie_configure_shimdma\n\n";
573 output <<
"int mlir_aie_initialize_locks(" << ctx_p <<
") {\n";
575 targetOp.walk<WalkOrder::PreOrder>([&](LockOp lock) {
576 TileOp tile = lock.getTileOp();
577 int col = tile.colIndex();
578 int row = tile.rowIndex();
579 int lockID = lock.getLockIDValue();
580 auto init = lock.getInit();
582 output <<
"__mlir_aie_try(XAie_LockSetValue(" << deviceInstRef <<
", "
584 <<
"XAie_LockInit(" << lockID <<
", " << *init <<
")));\n";
586 output <<
"return XAIE_OK;\n";
587 output <<
"} // mlir_aie_initialize_locks\n";
592 output <<
"int mlir_aie_configure_switchboxes(" << ctx_p <<
") {\n";
593 output <<
" int x, y;\n";
596 for (
auto switchboxOp : targetOp.getOps<SwitchboxOp>()) {
597 Region &r = switchboxOp.getConnections();
598 Block &b = r.front();
599 bool isEmpty = b.getOps<ConnectOp>().
empty() &&
600 b.getOps<MasterSetOp>().
empty() &&
601 b.getOps<PacketRulesOp>().
empty();
602 bool isParam =
false;
604 if (isa<TileOp>(switchboxOp.getTile().getDefiningOp())) {
605 int col = switchboxOp.colIndex();
606 int row = switchboxOp.rowIndex();
608 output <<
"// Core Stream Switch column " <<
col <<
" row " <<
row
610 output <<
"x = " <<
col <<
";\n";
611 output <<
"y = " <<
row <<
";\n";
613 }
else if (
auto sel =
614 dyn_cast<SelectOp>(switchboxOp.getTile().getDefiningOp())) {
617 HerdOp sourceHerd = cast<HerdOp>(sel.getStartHerd().getDefiningOp());
618 std::string sourceHerdName(sourceHerd.name().getValue());
620 IterOp iterX = cast<IterOp>(sel.getIterX().getDefiningOp());
621 IterOp iterY = cast<IterOp>(sel.getIterY().getDefiningOp());
622 int startXValue = iterX.getStartValue();
623 int endXValue = iterX.getEndValue();
624 int strideXValue = iterX.getStrideValue();
625 int startYValue = iterY.getStartValue();
626 int endYValue = iterY.getEndValue();
627 int strideYValue = iterY.getStrideValue();
629 std::string startX(sourceHerdName +
"_X + " +
630 std::to_string(startXValue));
631 std::string endX(sourceHerdName +
"_X + " + std::to_string(endXValue));
632 std::string startY(sourceHerdName +
"_Y + " +
633 std::to_string(startYValue));
634 std::string endY(sourceHerdName +
"_Y + " + std::to_string(endYValue));
636 output <<
"for (x = " << startX <<
"; x < " << endX
637 <<
"; x += " << strideXValue <<
") {\n";
638 output <<
"for (y = " << startY <<
"; y < " << endY
639 <<
"; y += " << strideYValue <<
") {\n";
642 for (
auto connectOp : b.getOps<ConnectOp>())
643 output <<
"__mlir_aie_try(XAie_StrmConnCctEnable(" << deviceInstRef
645 << wireBundleToPortType(connectOp.getSourceBundle()) <<
", "
646 << connectOp.sourceIndex() <<
", "
647 << wireBundleToPortType(connectOp.getDestBundle()) <<
", "
648 << connectOp.destIndex() <<
"));\n";
650 for (
auto connectOp : b.getOps<MasterSetOp>()) {
653 for (
auto val : connectOp.getAmsels()) {
654 AMSelOp amsel = cast<AMSelOp>(val.getDefiningOp());
655 arbiter = amsel.arbiterIndex();
656 int msel = amsel.getMselValue();
659 bool isdma = (connectOp.getDestBundle() == WireBundle::DMA);
661 output <<
"__mlir_aie_try(XAie_StrmPktSwMstrPortEnable(" << deviceInstRef
663 << wireBundleToPortType(connectOp.getDestBundle()) <<
", "
664 << connectOp.destIndex() <<
", "
665 <<
"/* drop_header */ "
666 << (isdma ?
"XAIE_SS_PKT_DROP_HEADER"
667 :
"XAIE_SS_PKT_DONOT_DROP_HEADER")
669 <<
"/* arbiter */ " << arbiter <<
", "
671 <<
"0x" << llvm::utohexstr(mask) <<
"));\n";
674 for (
auto connectOp : b.getOps<PacketRulesOp>()) {
676 Block &block = connectOp.getRules().front();
677 for (
auto slotOp : block.getOps<PacketRuleOp>()) {
678 AMSelOp amselOp = cast<AMSelOp>(slotOp.getAmsel().getDefiningOp());
679 int arbiter = amselOp.arbiterIndex();
680 int msel = amselOp.getMselValue();
681 output <<
"__mlir_aie_try(XAie_StrmPktSwSlavePortEnable("
682 << deviceInstRef <<
", " <<
tileLocStr(
"x",
"y") <<
", "
683 << wireBundleToPortType(connectOp.getSourceBundle()) <<
", "
684 << connectOp.sourceIndex() <<
"));\n";
687 output <<
"__mlir_aie_try(XAie_StrmPktSwSlaveSlotEnable("
688 << deviceInstRef <<
", " <<
tileLocStr(
"x",
"y") <<
", "
689 << wireBundleToPortType(connectOp.getSourceBundle()) <<
", "
690 << connectOp.sourceIndex() <<
", "
691 <<
"/* slot */ " << slot <<
", "
692 <<
"/* packet */ " <<
packetStr(slotOp.valueInt(), 0)
695 <<
"0x" << llvm::utohexstr(slotOp.maskInt()) <<
", "
696 <<
"/* msel */ " << msel <<
", "
697 <<
"/* arbiter */ " << arbiter <<
"));\n";
707 for (
auto op : targetOp.getOps<ShimMuxOp>()) {
708 Region &r = op.getConnections();
709 Block &b = r.front();
710 bool isEmpty = b.getOps<ConnectOp>().
empty();
712 if (isa<TileOp>(op.getTile().getDefiningOp())) {
713 int col = op.colIndex();
714 int row = op.rowIndex();
716 output <<
"// ShimMux column " <<
col <<
" row " <<
row <<
"\n";
717 output <<
"// NOTE ShimMux always connects from the south as "
718 <<
"directions are defined relative to the tile stream "
720 output <<
"x = " <<
col <<
";\n";
721 output <<
"y = " <<
row <<
";\n";
725 for (
auto connectOp : b.getOps<ConnectOp>()) {
727 if (connectOp.getSourceBundle() == WireBundle::DMA ||
728 connectOp.getDestBundle() == WireBundle::DMA) {
729 if (connectOp.getSourceBundle() == WireBundle::North)
731 output <<
"__mlir_aie_try(XAie_EnableAieToShimDmaStrmPort("
732 << deviceInstRef <<
", " <<
tileLocStr(
"x",
"y") <<
", "
733 << connectOp.sourceIndex() <<
"));\n";
734 else if (connectOp.getDestBundle() == WireBundle::North)
736 output <<
"__mlir_aie_try(XAie_EnableShimDmaToAieStrmPort("
737 << deviceInstRef <<
", " <<
tileLocStr(
"x",
"y") <<
", "
738 << connectOp.destIndex() <<
"));\n";
741 else if (connectOp.getSourceBundle() == WireBundle::PLIO ||
742 connectOp.getDestBundle() == WireBundle::PLIO) {
743 if (connectOp.getSourceBundle() == WireBundle::North) {
745 output <<
"__mlir_aie_try(XAie_AieToPlIntfEnable(" << deviceInstRef
747 << connectOp.destIndex() <<
", PLIF_WIDTH_64));\n";
748 }
else if (connectOp.getDestBundle() == WireBundle::North) {
750 output <<
"__mlir_aie_try(XAie_PlToAieIntfEnable(" << deviceInstRef
752 << connectOp.destIndex() <<
", PLIF_WIDTH_64));\n";
757 for (
auto switchboxOp : targetOp.getOps<ShimSwitchboxOp>()) {
758 Region &r = switchboxOp.getConnections();
759 Block &b = r.front();
760 bool isEmpty = b.getOps<ConnectOp>().
empty();
761 int col = switchboxOp.getCol();
763 output <<
"// Shim Switch column " <<
col <<
"\n";
764 for (
auto connectOp : b.getOps<ConnectOp>())
765 output <<
"__mlir_aie_try(XAie_StrmConnCctEnable(" << deviceInstRef
767 << wireBundleToPortType(connectOp.getSourceBundle()) <<
", "
768 << connectOp.sourceIndex() <<
", "
769 << wireBundleToPortType(connectOp.getDestBundle()) <<
", "
770 << connectOp.destIndex() <<
"));\n";
773 output <<
"return XAIE_OK;\n";
774 output <<
"} // mlir_aie_configure_switchboxes\n\n";
779 output <<
"int mlir_aie_configure_cascade(" << ctx_p <<
") {\n";
780 for (
auto configOp : targetOp.getOps<ConfigureCascadeOp>()) {
781 TileOp tile = cast<TileOp>(configOp.getTile().getDefiningOp());
782 int col = tile.colIndex();
783 int row = tile.rowIndex();
784 output <<
"XAie_CoreConfigAccumulatorControl(" << deviceInstRef <<
", "
785 <<
"XAie_TileLoc(" <<
col <<
", " <<
row <<
"), "
786 << stringifyCascadeDir(configOp.getInputDir()).upper() <<
", "
787 << stringifyCascadeDir(configOp.getOutputDir()).upper() <<
");\n";
789 output <<
"return XAIE_OK;\n";
790 output <<
"} // mlir_aie_configure_cascade\n\n";
795 for (
auto tile : tiles) {
796 Operation *tileOp = tile.second;
797 TileID coord = cast<TileOp>(tileOp).getTileID();
802 auto bufferAccessor = [&](BufferOp buf) {
805 std::string bufName(buf.name().getValue());
806 Type t = buf.getType();
809 if (
auto memrefType = llvm::dyn_cast<MemRefType>(t)) {
810 et = memrefType.getElementType();
811 if (et.isInteger(32))
816 output <<
"// buffer " << bufName <<
" with unsupported type " << t
822 output <<
"// buffer " << bufName <<
" with unsupported type " << t
826 assert(buf.getAddress().has_value() &&
"buffer must have address");
827 output <<
"const int " << bufName
828 <<
"_offset = " << buf.getAddress().value() <<
";\n";
829 output << typestr <<
" mlir_aie_read_buffer_" << bufName <<
"(" << ctx_p
830 <<
", int index) {\n";
831 output <<
"u32 value; auto rc = XAie_DataMemRdWord(" << deviceInstRef
832 <<
", " << loc <<
", " << bufName
833 <<
"_offset + (index*4), &value);\n";
834 if (et.isInteger(32))
835 output <<
" return value;\n";
836 else if (et.isF32()) {
837 output <<
" union caster { int32_t i; float f; };\n";
838 output <<
" caster c; c.i = value;\n";
839 output <<
" return c.f;\n";
842 output <<
"int mlir_aie_write_buffer_" << bufName <<
"(" << ctx_p
843 <<
", int index, " << typestr <<
" value) {\n";
844 if (et.isInteger(32))
845 output <<
" int32_t int_value = value;\n";
846 else if (et.isF32()) {
847 output <<
" union caster { int32_t i; float f; };\n";
848 output <<
" caster c; c.f = value;\n";
849 output <<
" int32_t int_value = c.i;\n";
851 output <<
"AieRC rc = XAie_DataMemWrWord(" << deviceInstRef <<
", "
852 << loc <<
", " << bufName <<
"_offset + (index*4), int_value);\n";
853 output <<
"return rc;\n";
858 for (
auto buf : buffers[tileOp])
862 auto lockAccessor = [&](LockOp lock) {
863 int col = lock.colIndex();
864 int row = lock.rowIndex();
867 std::string lockName(lock.name().getValue());
868 output <<
"int mlir_aie_acquire_" << lockName <<
"(" << ctx_p
869 <<
", int value, int timeout) {\n";
870 output <<
" const int id = " << lock.getLockIDValue() <<
";\n";
871 output <<
" return XAie_LockAcquire(" << deviceInstRef <<
", "
875 output <<
"int mlir_aie_release_" << lockName <<
"(" << ctx_p
876 <<
", int value, int timeout) {\n";
877 output <<
" const int id = " << lock.getLockIDValue() <<
";\n";
878 output <<
" return XAie_LockRelease(" << deviceInstRef <<
", "
884 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
bool empty(const std::string &s)
Include the generated interface declarations.
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)
TileID { friend std::ostream &operator<<(std::ostream &os, const TileID &s) { os<< "TileID("<< s.col<< ", "<< s.row<< ")" TileID
const AIETargetModel & getTargetModel(mlir::Operation *op)
void generateXAieDmaSetMultiDimAddr(llvm::raw_ostream &output, int ndims, llvm::ArrayRef< BDDimLayoutAttr > dims, int col, int row, int bdNum, int baseAddrA, int offsetA, int lenA, int elementWidthInBytes, const char *errorRet)
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)