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->DevInst)";
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";
304 raw_ostream &output) {
306 StringRef ctx_p =
"aie_libxaie_ctx_t* ctx";
308 StringRef deviceInstRef =
"&(ctx->DevInst)";
310 DenseMap<TileID, Operation *> tiles;
311 DenseMap<Operation *, SmallVector<BufferOp, 4>> buffers;
313 if (module.getOps<DeviceOp>().empty())
314 return module.emitOpError("expected AIE.device operation at toplevel");
315 DeviceOp targetOp = *(
module.getOps<DeviceOp>().begin());
316 const auto &targetModel = targetOp.getTargetModel();
318 collectTiles(targetOp, tiles);
319 collectBuffers(targetOp, buffers);
324 output << xaie_cpp_file_header;
325 output <<
"aie_libxaie_ctx_t* mlir_aie_init_libxaie() {\n";
326 output <<
" aie_libxaie_ctx_t *ctx = new aie_libxaie_ctx_t;\n";
327 output <<
" if (!ctx)\n";
328 output <<
" return 0;\n";
330 std::string AIE1_device(
"XAIE_DEV_GEN_AIE");
331 std::string AIE2_device(
"XAIE_DEV_GEN_AIEML");
332 std::string AIE2p_device(
"XAIE_DEV_GEN_AIE2P");
336 device = AIE1_device;
339 device = AIE2_device;
342 device = AIE2p_device;
345 return module.emitOpError("Unsupported aie.device");
347 output <<
" ctx->AieConfigPtr.AieGen = " << device <<
";\n";
348 output <<
" ctx->AieConfigPtr.BaseAddr = 0x20000000000;\n";
349 output <<
" ctx->AieConfigPtr.ColShift = " << targetModel.
getColumnShift()
351 output <<
" ctx->AieConfigPtr.RowShift = " << targetModel.
getRowShift()
353 output <<
" ctx->AieConfigPtr.NumRows = " << targetModel.
rows() <<
";\n";
354 output <<
" ctx->AieConfigPtr.NumCols = " << targetModel.
columns() <<
";\n";
355 output <<
" ctx->AieConfigPtr.ShimRowNum = 0;\n";
356 output <<
" ctx->AieConfigPtr.MemTileRowStart = 1;\n";
357 output <<
" ctx->AieConfigPtr.MemTileNumRows = "
359 output <<
" // ctx->AieConfigPtr.ReservedRowStart = "
360 "XAIE_RES_TILE_ROW_START;\n";
362 <<
" // ctx->AieConfigPtr.ReservedNumRows = XAIE_RES_TILE_NUM_ROWS;\n";
363 output <<
" ctx->AieConfigPtr.AieTileRowStart = "
365 output <<
" ctx->AieConfigPtr.AieTileNumRows = "
367 output <<
" ctx->AieConfigPtr.PartProp = {0};\n";
368 output <<
" ctx->DevInst = {0};\n";
369 output <<
" return ctx;\n";
376 output <<
"int mlir_aie_configure_cores(" << ctx_p <<
") {\n";
378 for (
auto tileOp : targetOp.getOps<TileOp>()) {
379 int col = tileOp.colIndex();
380 int row = tileOp.rowIndex();
381 if (tileOp.isShimTile() || tileOp.isMemTile()) {
385 output <<
"__mlir_aie_try(XAie_CoreReset(" << deviceInstRef <<
", "
387 output <<
"__mlir_aie_try(XAie_CoreDisable(" << deviceInstRef <<
", "
391 output <<
"for (int l = 0; l < " << numLocks <<
"; ++l)\n"
392 <<
" __mlir_aie_try(XAie_LockRelease(" << deviceInstRef <<
", "
394 if (
auto coreOp = tileOp.getCoreOp()) {
395 std::string fileName;
396 if (
auto fileAttr = coreOp.getElfFile())
397 fileName = fileAttr.value().str();
399 fileName = std::string(
"core_") + std::to_string(
col) +
"_" +
400 std::to_string(
row) +
".elf";
402 <<
"AieRC RC = XAie_LoadElf(" << deviceInstRef <<
", "
404 <<
"(const char*)\"" << fileName <<
"\",0);\n";
405 output <<
"if (RC != XAIE_OK)\n"
406 <<
" __mlir_aie_verbose(fprintf(stderr, \"Failed to load elf "
407 "for Core[%d,%d], ret is %d\\n\", "
408 << std::to_string(
col) <<
", " << std::to_string(
row)
410 <<
"assert(RC == XAIE_OK);\n"
415 output <<
"return XAIE_OK;\n";
416 output <<
"} // mlir_aie_configure_cores\n\n";
421 output <<
"int mlir_aie_start_cores(" << ctx_p <<
") {\n";
423 for (
auto tileOp : targetOp.getOps<TileOp>()) {
424 int col = tileOp.colIndex();
425 int row = tileOp.rowIndex();
426 if (!tileOp.isShimTile() && !tileOp.isMemTile()) {
427 output <<
"__mlir_aie_try(XAie_CoreUnreset(" << deviceInstRef <<
", "
429 output <<
"__mlir_aie_try(XAie_CoreEnable(" << deviceInstRef <<
", "
433 output <<
"return XAIE_OK;\n";
434 output <<
"} // mlir_aie_start_cores\n\n";
439 output <<
"int mlir_aie_configure_dmas(" << ctx_p <<
") {\n";
441 for (
auto memOp : targetOp.getOps<MemOp>()) {
442 DenseMap<Block *, int> blockMap;
446 for (
auto &block : memOp.getBody()) {
447 if (!block.getOps<DMABDOp>().empty()) {
448 blockMap[&block] = bdNum;
452 auto result = generateDMAConfig(memOp, output, targetModel, blockMap);
456 for (
auto memOp : targetOp.getOps<MemTileDMAOp>()) {
457 DenseMap<Block *, int> blockMap;
459 DenseMap<Block *, int> channelMap;
461 for (
auto &block : memOp.getBody()) {
462 for (
auto op : block.getOps<DMAStartOp>()) {
463 int chNum = op.getChannelIndex();
464 channelMap[&block] = chNum;
465 auto dest = op.getDest();
467 channelMap[dest] = chNum;
468 if (dest->getSuccessors().size() < 1)
470 dest = dest->getSuccessors()[0];
471 if (channelMap.count(dest))
480 for (
auto &block : memOp.getBody()) {
481 if (block.getOps<DMABDOp>().empty())
483 assert(channelMap.count(&block));
484 if (channelMap[&block] & 1)
485 blockMap[&block] = oddBdNum++;
487 blockMap[&block] = evenBdNum++;
489 auto result = generateDMAConfig(memOp, output, targetModel, blockMap);
494 output <<
"return XAIE_OK;\n";
495 output <<
"} // mlir_aie_configure_dmas\n\n";
497 for (
auto op : targetOp.getOps<ExternalBufferOp>()) {
499 output <<
"static u64 _mlir_aie_external_" << op.name().getValue()
501 output <<
"static bool _mlir_aie_external_set_" << op.name().getValue()
504 output <<
"void mlir_aie_external_set_addr_" << op.name().getValue()
505 <<
"(" << ctx_p <<
", u64 VA) {\n"
506 <<
" u64 device_address = mlir_aie_get_device_address(ctx, (void "
508 <<
" _mlir_aie_external_set_" << op.name().getValue()
510 <<
" _mlir_aie_external_" << op.name().getValue()
511 <<
" = device_address;\n"
518 for (
auto op : targetOp.getOps<ShimDMAOp>()) {
519 int col = op.colIndex();
520 int row = op.rowIndex();
522 DenseMap<Block *, int> blockMap;
526 for (
auto &block : op.getBody()) {
527 if (!block.getOps<DMABDOp>().empty()) {
528 blockMap[&block] = bdNum;
530 for (
auto op : block.getOps<DMABDOp>()) {
531 offset = op.getOffsetInBytes();
533 cast<ExternalBufferOp>(op.getBuffer().getDefiningOp());
535 output <<
"u64 mlir_aie_external_get_addr_myBuffer_" <<
col <<
row
536 <<
"_" << bdNum <<
"(void) {\n"
537 <<
" assert(_mlir_aie_external_set_"
538 << buffer.name().getValue() <<
");\n"
539 <<
" return _mlir_aie_external_"
540 << buffer.name().getValue() <<
" + "
541 << llvm::utohexstr(offset) <<
";\n"
550 output <<
"int mlir_aie_configure_shimdma_" <<
col <<
row <<
"(" << ctx_p
552 auto result = generateDMAConfig(op, output, targetModel, blockMap);
555 output <<
"return XAIE_OK;\n";
556 output <<
"} // mlir_aie_configure_shimdma\n\n";
562 output <<
"int mlir_aie_initialize_locks(" << ctx_p <<
") {\n";
564 targetOp.walk<WalkOrder::PreOrder>([&](LockOp lock) {
565 TileOp tile = lock.getTileOp();
566 int col = tile.colIndex();
567 int row = tile.rowIndex();
568 int lockID = lock.getLockIDValue();
569 auto init = lock.getInit();
571 output <<
"__mlir_aie_try(XAie_LockSetValue(" << deviceInstRef <<
", "
573 <<
"XAie_LockInit(" << lockID <<
", " << *init <<
")));\n";
575 output <<
"return XAIE_OK;\n";
576 output <<
"} // mlir_aie_initialize_locks\n";
581 output <<
"int mlir_aie_configure_switchboxes(" << ctx_p <<
") {\n";
582 output <<
" int x, y;\n";
585 for (
auto switchboxOp : targetOp.getOps<SwitchboxOp>()) {
586 Region &r = switchboxOp.getConnections();
587 Block &b = r.front();
588 bool isEmpty = b.getOps<ConnectOp>().empty() &&
589 b.getOps<MasterSetOp>().empty() &&
590 b.getOps<PacketRulesOp>().empty();
591 bool isParam =
false;
593 if (isa<TileOp>(switchboxOp.getTile().getDefiningOp())) {
594 int col = switchboxOp.colIndex();
595 int row = switchboxOp.rowIndex();
597 output <<
"// Core Stream Switch column " <<
col <<
" row " <<
row
599 output <<
"x = " <<
col <<
";\n";
600 output <<
"y = " <<
row <<
";\n";
602 }
else if (
auto sel =
603 dyn_cast<SelectOp>(switchboxOp.getTile().getDefiningOp())) {
606 HerdOp sourceHerd = cast<HerdOp>(sel.getStartHerd().getDefiningOp());
607 std::string sourceHerdName(sourceHerd.name().getValue());
609 IterOp iterX = cast<IterOp>(sel.getIterX().getDefiningOp());
610 IterOp iterY = cast<IterOp>(sel.getIterY().getDefiningOp());
611 int startXValue = iterX.getStartValue();
612 int endXValue = iterX.getEndValue();
613 int strideXValue = iterX.getStrideValue();
614 int startYValue = iterY.getStartValue();
615 int endYValue = iterY.getEndValue();
616 int strideYValue = iterY.getStrideValue();
618 std::string startX(sourceHerdName +
"_X + " +
619 std::to_string(startXValue));
620 std::string endX(sourceHerdName +
"_X + " + std::to_string(endXValue));
621 std::string startY(sourceHerdName +
"_Y + " +
622 std::to_string(startYValue));
623 std::string endY(sourceHerdName +
"_Y + " + std::to_string(endYValue));
625 output <<
"for (x = " << startX <<
"; x < " << endX
626 <<
"; x += " << strideXValue <<
") {\n";
627 output <<
"for (y = " << startY <<
"; y < " << endY
628 <<
"; y += " << strideYValue <<
") {\n";
631 for (
auto connectOp : b.getOps<ConnectOp>())
632 output <<
"__mlir_aie_try(XAie_StrmConnCctEnable(" << deviceInstRef
634 << wireBundleToPortType(connectOp.getSourceBundle()) <<
", "
635 << connectOp.sourceIndex() <<
", "
636 << wireBundleToPortType(connectOp.getDestBundle()) <<
", "
637 << connectOp.destIndex() <<
"));\n";
639 for (
auto connectOp : b.getOps<MasterSetOp>()) {
642 for (
auto val : connectOp.getAmsels()) {
643 AMSelOp amsel = cast<AMSelOp>(val.getDefiningOp());
644 arbiter = amsel.arbiterIndex();
645 int msel = amsel.getMselValue();
648 bool isdma = (connectOp.getDestBundle() == WireBundle::DMA);
650 output <<
"__mlir_aie_try(XAie_StrmPktSwMstrPortEnable(" << deviceInstRef
652 << wireBundleToPortType(connectOp.getDestBundle()) <<
", "
653 << connectOp.destIndex() <<
", "
654 <<
"/* drop_header */ "
655 << (isdma ?
"XAIE_SS_PKT_DROP_HEADER"
656 :
"XAIE_SS_PKT_DONOT_DROP_HEADER")
658 <<
"/* arbiter */ " << arbiter <<
", "
660 <<
"0x" << llvm::utohexstr(mask) <<
"));\n";
663 for (
auto connectOp : b.getOps<PacketRulesOp>()) {
665 Block &block = connectOp.getRules().front();
666 for (
auto slotOp : block.getOps<PacketRuleOp>()) {
667 AMSelOp amselOp = cast<AMSelOp>(slotOp.getAmsel().getDefiningOp());
668 int arbiter = amselOp.arbiterIndex();
669 int msel = amselOp.getMselValue();
670 output <<
"__mlir_aie_try(XAie_StrmPktSwSlavePortEnable("
671 << deviceInstRef <<
", " <<
tileLocStr(
"x",
"y") <<
", "
672 << wireBundleToPortType(connectOp.getSourceBundle()) <<
", "
673 << connectOp.sourceIndex() <<
"));\n";
676 output <<
"__mlir_aie_try(XAie_StrmPktSwSlaveSlotEnable("
677 << deviceInstRef <<
", " <<
tileLocStr(
"x",
"y") <<
", "
678 << wireBundleToPortType(connectOp.getSourceBundle()) <<
", "
679 << connectOp.sourceIndex() <<
", "
680 <<
"/* slot */ " << slot <<
", "
681 <<
"/* packet */ " <<
packetStr(slotOp.valueInt(), 0)
684 <<
"0x" << llvm::utohexstr(slotOp.maskInt()) <<
", "
685 <<
"/* msel */ " << msel <<
", "
686 <<
"/* arbiter */ " << arbiter <<
"));\n";
696 for (
auto op : targetOp.getOps<ShimMuxOp>()) {
697 Region &r = op.getConnections();
698 Block &b = r.front();
699 bool isEmpty = b.getOps<ConnectOp>().empty();
701 if (isa<TileOp>(op.getTile().getDefiningOp())) {
702 int col = op.colIndex();
703 int row = op.rowIndex();
705 output <<
"// ShimMux column " <<
col <<
" row " <<
row <<
"\n";
706 output <<
"// NOTE ShimMux always connects from the south as "
707 <<
"directions are defined relative to the tile stream "
709 output <<
"x = " <<
col <<
";\n";
710 output <<
"y = " <<
row <<
";\n";
714 for (
auto connectOp : b.getOps<ConnectOp>()) {
716 if (connectOp.getSourceBundle() == WireBundle::DMA ||
717 connectOp.getDestBundle() == WireBundle::DMA) {
718 if (connectOp.getSourceBundle() == WireBundle::North)
720 output <<
"__mlir_aie_try(XAie_EnableAieToShimDmaStrmPort("
721 << deviceInstRef <<
", " <<
tileLocStr(
"x",
"y") <<
", "
722 << connectOp.sourceIndex() <<
"));\n";
723 else if (connectOp.getDestBundle() == WireBundle::North)
725 output <<
"__mlir_aie_try(XAie_EnableShimDmaToAieStrmPort("
726 << deviceInstRef <<
", " <<
tileLocStr(
"x",
"y") <<
", "
727 << connectOp.destIndex() <<
"));\n";
730 else if (connectOp.getSourceBundle() == WireBundle::PLIO ||
731 connectOp.getDestBundle() == WireBundle::PLIO) {
732 if (connectOp.getSourceBundle() == WireBundle::North) {
734 output <<
"__mlir_aie_try(XAie_AieToPlIntfEnable(" << deviceInstRef
736 << connectOp.destIndex() <<
", PLIF_WIDTH_64));\n";
737 }
else if (connectOp.getDestBundle() == WireBundle::North) {
739 output <<
"__mlir_aie_try(XAie_PlToAieIntfEnable(" << deviceInstRef
741 << connectOp.destIndex() <<
", PLIF_WIDTH_64));\n";
746 for (
auto switchboxOp : targetOp.getOps<ShimSwitchboxOp>()) {
747 Region &r = switchboxOp.getConnections();
748 Block &b = r.front();
749 bool isEmpty = b.getOps<ConnectOp>().empty();
750 int col = switchboxOp.getCol();
752 output <<
"// Shim Switch column " <<
col <<
"\n";
753 for (
auto connectOp : b.getOps<ConnectOp>())
754 output <<
"__mlir_aie_try(XAie_StrmConnCctEnable(" << deviceInstRef
756 << wireBundleToPortType(connectOp.getSourceBundle()) <<
", "
757 << connectOp.sourceIndex() <<
", "
758 << wireBundleToPortType(connectOp.getDestBundle()) <<
", "
759 << connectOp.destIndex() <<
"));\n";
762 output <<
"return XAIE_OK;\n";
763 output <<
"} // mlir_aie_configure_switchboxes\n\n";
768 output <<
"int mlir_aie_configure_cascade(" << ctx_p <<
") {\n";
769 for (
auto configOp : targetOp.getOps<ConfigureCascadeOp>()) {
770 TileOp tile = cast<TileOp>(configOp.getTile().getDefiningOp());
771 int col = tile.colIndex();
772 int row = tile.rowIndex();
773 output <<
"XAie_CoreConfigAccumulatorControl(" << deviceInstRef <<
", "
774 <<
"XAie_TileLoc(" <<
col <<
", " <<
row <<
"), "
775 << stringifyCascadeDir(configOp.getInputDir()).upper() <<
", "
776 << stringifyCascadeDir(configOp.getOutputDir()).upper() <<
");\n";
778 output <<
"return XAIE_OK;\n";
779 output <<
"} // mlir_aie_configure_cascade\n\n";
784 for (
auto tile : tiles) {
785 Operation *tileOp = tile.second;
786 TileID coord = cast<TileOp>(tileOp).getTileID();
791 auto bufferAccessor = [&](BufferOp buf) {
794 std::string bufName(buf.name().getValue());
795 Type t = buf.getType();
798 if (
auto memrefType = llvm::dyn_cast<MemRefType>(t)) {
799 et = memrefType.getElementType();
800 if (et.isInteger(32))
805 output <<
"// buffer " << bufName <<
" with unsupported type " << t
811 output <<
"// buffer " << bufName <<
" with unsupported type " << t
815 assert(buf.getAddress().has_value() &&
"buffer must have address");
816 output <<
"const int " << bufName
817 <<
"_offset = " << buf.getAddress().value() <<
";\n";
818 output << typestr <<
" mlir_aie_read_buffer_" << bufName <<
"(" << ctx_p
819 <<
", int index) {\n";
820 output <<
"u32 value; auto rc = XAie_DataMemRdWord(" << deviceInstRef
821 <<
", " << loc <<
", " << bufName
822 <<
"_offset + (index*4), &value);\n";
823 if (et.isInteger(32))
824 output <<
" return value;\n";
825 else if (et.isF32()) {
826 output <<
" union caster { int32_t i; float f; };\n";
827 output <<
" caster c; c.i = value;\n";
828 output <<
" return c.f;\n";
831 output <<
"int mlir_aie_write_buffer_" << bufName <<
"(" << ctx_p
832 <<
", int index, " << typestr <<
" value) {\n";
833 if (et.isInteger(32))
834 output <<
" int32_t int_value = value;\n";
835 else if (et.isF32()) {
836 output <<
" union caster { int32_t i; float f; };\n";
837 output <<
" caster c; c.f = value;\n";
838 output <<
" int32_t int_value = c.i;\n";
840 output <<
"AieRC rc = XAie_DataMemWrWord(" << deviceInstRef <<
", "
841 << loc <<
", " << bufName <<
"_offset + (index*4), int_value);\n";
842 output <<
"return rc;\n";
847 for (
auto buf : buffers[tileOp])
851 auto lockAccessor = [&](LockOp lock) {
852 int col = lock.colIndex();
853 int row = lock.rowIndex();
856 std::string lockName(lock.name().getValue());
857 output <<
"int mlir_aie_acquire_" << lockName <<
"(" << ctx_p
858 <<
", int value, int timeout) {\n";
859 output <<
" const int id = " << lock.getLockIDValue() <<
";\n";
860 output <<
" return XAie_LockAcquire(" << deviceInstRef <<
", "
864 output <<
"int mlir_aie_release_" << lockName <<
"(" << ctx_p
865 <<
", int value, int timeout) {\n";
866 output <<
" const int id = " << lock.getLockIDValue() <<
";\n";
867 output <<
" return XAie_LockRelease(" << deviceInstRef <<
", "
873 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.
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 bool isMemTile(int col, int row) const =0
Return true if the given tile is an AIE2 'Memory' tile.
virtual uint32_t getNumLocks(int col, int row) const =0
Return the number of lock objects.
virtual int rows() const =0
Return the number of rows in the device.
virtual bool isShimNOCTile(int col, int row) const =0
Return true if the given tile is a Shim NOC 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
Include the generated interface declarations.
mlir::LogicalResult AIETranslateToXAIEV2(mlir::ModuleOp module, llvm::raw_ostream &output)
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)
std::string tileLocStr(llvm::StringRef col, llvm::StringRef row)
std::string packetStr(llvm::StringRef id, llvm::StringRef type)