11#include "mlir/Dialect/Utils/StaticValueUtils.h"
12#include "mlir/Support/LogicalResult.h"
13#include "llvm/ADT/SmallPtrSet.h"
14#include "llvm/ADT/SmallSet.h"
17#include "xaiengine/xaie_core.h"
18#include "xaiengine/xaie_dma.h"
19#include "xaiengine/xaie_elfloader.h"
20#include "xaiengine/xaie_interrupt.h"
21#include "xaiengine/xaie_locks.h"
22#include "xaiengine/xaie_mem.h"
23#include "xaiengine/xaie_perfcnt.h"
24#include "xaiengine/xaie_plif.h"
25#include "xaiengine/xaie_reset.h"
26#include "xaiengine/xaie_ss.h"
27#include "xaiengine/xaie_txn.h"
28#include "xaiengine/xaiegbl.h"
29#include "xaiengine/xaiegbl_defs.h"
34#define AIERC_STR(x) x, #x
35static const std::map<AieRC, std::string> AIERCTOSTR = {
61 {
AIERC_STR(XAIE_INSUFFICIENT_BUFFER_SIZE)},
65static const std::map<xilinx::AIE::WireBundle, StrmSwPortType>
66 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE = {
67 {xilinx::AIE::WireBundle::Core, StrmSwPortType::CORE},
68 {xilinx::AIE::WireBundle::DMA, StrmSwPortType::DMA},
69 {xilinx::AIE::WireBundle::TileControl, StrmSwPortType::CTRL},
70 {xilinx::AIE::WireBundle::FIFO, StrmSwPortType::FIFO},
71 {xilinx::AIE::WireBundle::South, StrmSwPortType::SOUTH},
72 {xilinx::AIE::WireBundle::West, StrmSwPortType::WEST},
73 {xilinx::AIE::WireBundle::North, StrmSwPortType::NORTH},
74 {xilinx::AIE::WireBundle::East, StrmSwPortType::EAST},
77 {xilinx::AIE::WireBundle::Trace, StrmSwPortType::TRACE},
84static llvm::raw_ostream &showAIEXRTArgs(llvm::raw_ostream &out,
85 const char *label, H1 &&value) {
86 return out << label <<
"=" << std::forward<H1>(value);
89template <
typename H1,
typename... T>
90static llvm::raw_ostream &showAIEXRTArgs(llvm::raw_ostream &out,
91 const char *label, H1 &&value,
93 const char *pcomma = strchr(label,
',');
94 return showAIEXRTArgs(out.write(label, pcomma - label)
95 <<
"=" << std::forward<H1>(value) <<
',',
96 pcomma + 1, std::forward<T>(rest)...);
99static llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
100 const XAie_LocType &loc);
102static llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
103 const XAie_Lock &lock);
105static llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
106 const XAie_Packet &packet);
108#define SHOW_AIERT_ARGS(os, ...) showAIEXRTArgs(os, #__VA_ARGS__, __VA_ARGS__)
112static_assert(XAIE_OK == 0);
114#define TRY_XAIE_API_FATAL_ERROR(API, ...) \
116 LLVM_DEBUG(llvm::dbgs() << "trying XAIE API: " << #API << " with args: "); \
117 LLVM_DEBUG(SHOW_AIERT_ARGS(llvm::dbgs(), __VA_ARGS__)); \
118 LLVM_DEBUG(llvm::dbgs() << "\n"); \
119 if (auto r = API(__VA_ARGS__)) \
120 llvm::report_fatal_error(llvm::Twine(#API " failed with ") + \
124#define TRY_XAIE_API_EMIT_ERROR(OP, API, ...) \
126 LLVM_DEBUG(llvm::dbgs() << "trying XAIE API: " << #API << " with args: "); \
127 LLVM_DEBUG(SHOW_AIERT_ARGS(llvm::dbgs(), __VA_ARGS__)); \
128 LLVM_DEBUG(llvm::dbgs() << "\n"); \
129 if (auto r = API(__VA_ARGS__)) \
130 return OP.emitOpError() << #API " failed with " << AIERCTOSTR.at(r); \
133#define TRY_XAIE_API_LOGICAL_RESULT(API, ...) \
135 LLVM_DEBUG(llvm::dbgs() << "trying XAIE API: " << #API << " with args: "); \
136 LLVM_DEBUG(SHOW_AIERT_ARGS(llvm::dbgs(), __VA_ARGS__)); \
137 LLVM_DEBUG(llvm::dbgs() << "\n"); \
138 if (auto r = API(__VA_ARGS__)) { \
139 llvm::errs() << #API " failed with " << AIERCTOSTR.at(r); \
146#define TRY_XAIE_API_FATAL_ERROR(API, ...) \
148 if (auto r = API(__VA_ARGS__)) \
149 llvm::report_fatal_error(llvm::Twine(#API " failed with ") + \
153#define TRY_XAIE_API_EMIT_ERROR(OP, API, ...) \
155 if (auto r = API(__VA_ARGS__)) \
156 return OP.emitOpError() << #API " failed with " << AIERCTOSTR.at(r); \
159#define TRY_XAIE_API_LOGICAL_RESULT(API, ...) \
161 if (auto r = API(__VA_ARGS__)) { \
162 llvm::errs() << #API " failed with " << AIERCTOSTR.at(r); \
172#define DEBUG_TYPE "aie-aiert"
174llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
const XAie_LocType &loc) {
175 os <<
"XAie_LocType(col: " << std::to_string(loc.Col)
176 <<
", row: " << std::to_string(loc.Row) <<
")";
180llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
const XAie_Lock &lock) {
181 os <<
"XAie_Lock(id: " << std::to_string(lock.LockId)
182 <<
", val: " << std::to_string(lock.LockVal) <<
")";
186llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
187 const XAie_Packet &packet) {
188 os <<
"XAie_Packet(id: " << std::to_string(packet.PktId)
189 <<
", type: " << std::to_string(packet.PktType) <<
")";
193#define XAIE_BASE_ADDR 0x40000000
194#define XAIE_SHIM_ROW 0
195#define XAIE_MEM_TILE_ROW_START 1
196#define XAIE_PARTITION_BASE_ADDR 0x0
200#define EVEN_BD_NUM_START 0
201#define ODD_BD_NUM_START 24
220static XAie_TxnInst *getActiveTxnInst(XAie_DevInst &devInst) {
221 XAie_List *node = devInst.TxnList.Next;
224 return reinterpret_cast<XAie_TxnInst *
>(
reinterpret_cast<char *
>(node) -
225 offsetof(XAie_TxnInst, Node));
228static uint32_t getActiveTxnNumCmds(XAie_DevInst &devInst) {
229 XAie_TxnInst *inst = getActiveTxnInst(devInst);
230 return inst ? inst->NumCmds : 0;
234 : ctl(c), loc(l), startCmds(c.getCurrentTxnNumCmds()) {}
237 uint32_t endCmds = ctl.getCurrentTxnNumCmds();
238 if (endCmds <= startCmds)
243 if (mlir::isa<mlir::UnknownLoc>(loc))
245 ctl.recordTxnLocRange(startCmds, endCmds, loc);
251 : targetModel(tm), aiert(std::make_unique<
AIERtImpl>()) {
254 size_t partitionStartCol =
256 size_t partitionNumCols = tm.
columns();
257 size_t deviceRows = tm.
rows();
258 size_t deviceCols = tm.
columns() + partitionStartCol;
261 unsigned char devGen = XAIE_DEV_GEN_AIE;
264 devGen = XAIE_DEV_GEN_AIE;
269 devGen = XAIE_DEV_GEN_AIE2IPU;
272 devGen = XAIE_DEV_GEN_AIE2P_STRIX_B0;
274 case AIEArch::AIE2ps:
278 llvm::report_fatal_error(
"aie-rt configuration is not supported for the "
279 "AIE2PS architecture");
281 aiert->configPtr = XAie_Config{
284 static_cast<uint8_t>(tm.getColumnShift()),
285 static_cast<uint8_t>(tm.getRowShift()),
286 static_cast<uint8_t>(deviceRows),
287 static_cast<uint8_t>(deviceCols),
289 XAIE_MEM_TILE_ROW_START,
290 static_cast<uint8_t>(tm.getNumMemTileRows()),
292 static_cast<uint8_t>(XAIE_MEM_TILE_ROW_START + tm.getNumMemTileRows()),
294 static_cast<uint8_t>(tm.rows() - tm.getNumMemTileRows() - 1),
296 XAIE_IO_BACKEND_CDO};
297 XAie_InstDeclare(_devInst, &aiert->configPtr);
298 aiert->devInst = _devInst;
315 XAIE_IO_BACKEND_SIM);
316 }
else if (xaieDebug)
318 XAIE_IO_BACKEND_DEBUG);
321 XAIE_IO_BACKEND_CDO);
327 XAie_DmaDesc &dmaTileBd, Block &block,
int col,
int row,
329 LLVM_DEBUG(llvm::dbgs() <<
"\nstart configuring bds\n");
330 AIE::UseLockOp acquire, release;
333 std::optional<int> acqValue, relValue, acqLockId, relLockId;
338 for (
auto op : block.getOps<AIE::UseLockOp>()) {
343 lock = cast<AIE::LockOp>(op.getLock().getDefiningOp());
344 switch (op.getAction()) {
345 case AIE::LockAction::Acquire:
346 case AIE::LockAction::AcquireGreaterEqual: {
347 acqEn = op.getAcqEn();
348 acqLockId = lock.getLockIDValue();
349 auto value = op.getConstantValue();
358 case AIE::LockAction::Release: {
359 relLockId = lock.getLockIDValue();
360 auto value = op.getConstantValue();
371 col, row, lock.colIndex(), lock.rowIndex());
372 if (lockOffset && acqLockId)
373 acqLockId.value() += lockOffset.value();
374 if (lockOffset && relLockId)
375 relLockId.value() += lockOffset.value();
380 if (outOfOrder && !acqLockId) {
383 acqLockId = relLockId;
386 assert(acqLockId && acqValue && relLockId && relValue &&
387 "lock values must be resolved before init");
388 XAie_Lock acqLock = XAie_LockInit(acqLockId.value(), acqValue.value());
389 XAie_Lock relLock = XAie_LockInit(relLockId.value(), relValue.value());
391 dmaTileBd.DmaMod->SetLock, &dmaTileBd, acqLock,
392 relLock, acqEn, relEn);
396static LogicalResult configureBdInBlock(
const AIE::AIETargetModel &targetModel,
397 XAie_DevInst *devInst,
398 XAie_DmaDesc &dmaTileBd, Block &block,
399 int col,
int row,
int bdId,
400 std::optional<int> nextBdId) {
401 std::optional<int> packetType;
402 std::optional<int> packetID;
405 auto maybePacketOps = block.getOps<AIE::DMABDPACKETOp>();
406 if (!maybePacketOps.empty()) {
407 assert(llvm::range_size(maybePacketOps) == 1 &&
408 "expected only one dma_bd_packet");
409 auto packetOp = *maybePacketOps.begin();
410 packetType = packetOp.getPacketType();
411 packetID = packetOp.getPacketID();
414 auto bdOp = *block.getOps<AIE::DMABDOp>().begin();
422 uint8_t cache =
static_cast<uint8_t
>(bdOp.getAxcacheOrDefault());
425 burstLen / 16, qOs, cache, secure);
429 uint64_t baseAddr = 0;
432 cast<AIE::ExternalBufferOp>(bdOp.getBuffer().getDefiningOp());
436 if (
auto addr = bufferOp.getAddress())
439 auto bufferOp = cast<AIE::BufferOp>(bdOp.getBuffer().getDefiningOp());
440 auto addr = bufferOp.getAddress();
442 return bufferOp.emitError(
"buffer must have address assigned");
449 auto bufferOp = cast<AIE::BufferOp>(bdOp.getBuffer().getDefiningOp());
450 auto bufferRow = bufferOp.getTileOp().getRow();
451 auto bufferCol = bufferOp.getTileOp().getCol();
455 baseAddr += addrOffset.value();
460 for (mlir::OpFoldResult s : bdOp.getMixedSizes())
461 if (!mlir::getConstantIntValue(s))
462 return bdOp->emitOpError(
463 "runtime-valued BD size/stride is not supported on the static XAIE "
464 "lowering path; use compile-time constant sizes");
465 for (mlir::OpFoldResult s : bdOp.getMixedStrides())
466 if (!mlir::getConstantIntValue(s))
467 return bdOp->emitOpError(
468 "runtime-valued BD size/stride is not supported on the static XAIE "
469 "lowering path; use compile-time constant sizes");
471 std::optional<llvm::SmallVector<AIE::BDDimLayoutAttr>> dimsStorage =
472 bdOp.getConstantDimensions();
474 return bdOp->emitOpError(
"internal error folding BD dimensions");
475 std::optional<llvm::ArrayRef<AIE::BDDimLayoutAttr>> dims;
476 if (!dimsStorage->empty())
477 dims = llvm::ArrayRef<AIE::BDDimLayoutAttr>(*dimsStorage);
478 uint64_t lenInBytes = bdOp.getLenInBytes();
479 uint64_t basePlusOffsetInBytes = baseAddr + bdOp.getOffsetInBytes();
482 basePlusOffsetInBytes, lenInBytes);
484 llvm::SmallVector<XAie_DmaDimDesc, 4> dimDescs(dims->size());
485 XAie_DmaTensor dmaTileBdTensor = {};
486 dmaTileBdTensor.NumDim = dimDescs.size();
487 dmaTileBdTensor.Dim = dimDescs.data();
489 double elementWidthIn32bWords =
490 static_cast<double>(bdOp.getBufferElementTypeWidthInBytes()) / 4.0;
491 for (
size_t i = 0; i < dims->size(); i++) {
495 int j = dims->size() - i - 1;
499 stride =
static_cast<uint32_t
>(dims.value()[i].getStride() *
500 elementWidthIn32bWords);
501 size = dims.value()[i].getSize();
503 stride = dims.value()[i].getStride();
504 size =
static_cast<uint16_t
>(dims.value()[i].getSize() *
505 elementWidthIn32bWords);
507 stride = stride > 0 ? stride : 1;
510 dmaTileBdTensor.Dim[j].AieMlDimDesc = {stride, size};
513 &dmaTileBdTensor, basePlusOffsetInBytes,
518 if (
auto iter = bdOp.getIteration(); iter && iter->getSize() > 1) {
519 if (iter->getStride() > 0) {
520 double elementWidthIn32bWords =
521 static_cast<double>(bdOp.getBufferElementTypeWidthInBytes()) / 4.0;
522 uint32_t stepInWords =
523 static_cast<uint32_t
>(iter->getStride() * elementWidthIn32bWords);
524 uint8_t wrap =
static_cast<uint8_t
>(iter->getSize());
525 uint8_t iterCurr =
static_cast<uint8_t
>(iter->getCurrent());
527 stepInWords, wrap, iterCurr);
532 std::optional<llvm::ArrayRef<AIE::BDPadLayoutAttr>> padDims =
533 bdOp.getPadDimensions();
536 llvm::SmallVector<XAie_PadDesc, 4> padDescs(padDims->size());
537 XAie_DmaPadTensor dmaPadTensor = {};
538 dmaPadTensor.NumDim = padDescs.size();
539 dmaPadTensor.PadDesc = padDescs.data();
541 double elementWidthIn32bWords =
542 static_cast<double>(bdOp.getBufferElementTypeWidthInBytes()) / 4.0;
543 for (
size_t i = 0; i < padDims->size(); i++) {
545 int j = padDims->size() - i - 1;
549 before =
static_cast<uint8_t
>(padDims.value()[i].getConstPadBefore());
550 after =
static_cast<uint8_t
>(padDims.value()[i].getConstPadAfter());
552 before =
static_cast<uint8_t
>(padDims.value()[i].getConstPadBefore() *
553 elementWidthIn32bWords);
554 after =
static_cast<uint8_t
>(padDims.value()[i].getConstPadAfter() *
555 elementWidthIn32bWords);
557 dmaPadTensor.PadDesc[j] = {before, after};
563 auto enableNextBd = 1;
565 nextBdId.value(), enableNextBd);
568 if (
auto packetInfo = bdOp.getPacket()) {
569 packetType = packetInfo->getPktType();
570 packetID = packetInfo->assignedId();
575 return bdOp.emitError(
"must have packetType with packetID");
580 if (bdOp.getConstantLen() == 0)
581 return bdOp.emitOpError(
582 "For MM2S channels, if Buffer_Length=0 then Enable_Packet must be "
583 "set to 0, otherwise behavior is undefined (3.7.8 arch spec)");
585 XAie_PacketInit(*packetID, *packetType));
587 if (std::optional<int32_t> oooId = bdOp.getOutOfOrderId())
589 static_cast<uint8_t
>(*oooId));
591 auto tileLoc = XAie_TileLoc(col, row);
594 LLVM_DEBUG(llvm::dbgs() <<
"\nend configuring bds\n");
599 Operation &op,
int col,
int row,
int chNum,
const DMAChannelDir &channelDir,
600 int bdId,
int repeatCount, uint32_t padValue,
bool outOfOrder,
601 bool configureChannel,
bool pushTask) {
603 XAie_DmaDirection direction =
604 channelDir == DMAChannelDir::S2MM ? DMA_S2MM : DMA_MM2S;
605 auto tileLoc = XAie_TileLoc(col, row);
606 if (configureChannel && padValue != 0 && direction == DMA_MM2S &&
607 targetModel.isMemTile(col, row)) {
609 static_cast<uint8_t
>(chNum), padValue);
615 if (configureChannel) {
616 XAie_DmaChannelDesc dmaChannelDesc;
618 &dmaChannelDesc, tileLoc);
620 static_cast<uint8_t
>(XAIE_ENABLE));
622 &dmaChannelDesc, tileLoc,
623 static_cast<uint8_t
>(chNum), direction);
627 XAie_DmaDeclareQueueConfig(startQueueCfg, 0, repeatCount,
628 static_cast<uint8_t
>(XAIE_DISABLE),
629 static_cast<uint8_t
>(XAIE_ENABLE));
632 &aiert->devInst, tileLoc, chNum, direction,
634 }
else if (pushTask) {
635 bool enTokenIssue = tileLoc.Row == 0 && direction == DMA_S2MM;
637 tileLoc, chNum, direction, bdId, repeatCount,
640 if (configureChannel)
649 DMABDOp bd = *block.getOps<DMABDOp>().begin();
650 auto bdId = bd.getBdId();
651 assert(bdId.has_value() &&
652 "DMABDOp must have assigned bd_id; did you forget to run "
653 "aie-assign-bd-ids?");
655 XAie_DmaDesc dmaTileBd;
656 auto tileLoc = XAie_TileLoc(col, row);
659 if (!block.getOps<UseLockOp>().empty() &&
660 failed(configureLocksInBdBlock(targetModel, dmaTileBd, block, col, row,
665 std::optional<int> nextBdId =
666 outOfOrder ? std::optional<int>() : bd.getNextBdId();
667 if (!block.getOps<DMABDOp>().empty() &&
668 failed(configureBdInBlock(
669 targetModel, &aiert->devInst, dmaTileBd, block, col, row,
677 for (
auto tileOp : targetOp.getOps<TileOp>()) {
678 auto tileLoc = XAie_TileLoc(tileOp.colIndex(), tileOp.rowIndex());
679 if (!tileOp.isShimTile() && tileOp.getCoreOp()) {
685 for (uint8_t l = 0; l <
NUM_LOCKS; l++) {
686 auto locInit = XAie_LockInit(l, 0);
694 targetOp.walkOutsideRuntimeSequences<LockOp>([&](LockOp lockOp) {
695 if (lockOp.getLockID() && lockOp.getInit()) {
697 auto tileLoc = XAie_TileLoc(lockOp.getTileOp().colIndex(),
698 lockOp.getTileOp().rowIndex());
699 auto locInit = XAie_LockInit(*lockOp.getLockID(), *lockOp.getInit());
703 LLVM_DEBUG(llvm::dbgs()
704 <<
"lock op missing either id or init" << lockOp <<
"\n");
711 targetOp.walkOutsideRuntimeSequences<BufferOp>([&](BufferOp bufferOp) {
712 auto initialValue = bufferOp.getInitialValue();
716 mlir::DenseElementsAttr denseInit =
717 dyn_cast<mlir::DenseElementsAttr>(initialValue.value());
720 auto tileLoc = XAie_TileLoc(bufferOp.getTileOp().colIndex(),
721 bufferOp.getTileOp().rowIndex());
724 llvm::outs() <<
"buffer op type not supported for initialization "
729 bufferOp.getAddress().value(), byteVec->data(),
737 bool skipCtrlPktOverlay) {
738 AIEDialect::IsCtrlPktOverlayAttrHelper overlay(targetOp.getContext());
741 for (
auto switchboxOp : targetOp.getOps<SwitchboxOp>()) {
742 int32_t col = switchboxOp.colIndex();
743 int32_t row = switchboxOp.rowIndex();
744 XAie_LocType tileLoc = XAie_TileLoc(col, row);
746 "Only NPU currently supported");
748 Block &b = switchboxOp.getConnections().front();
749 for (
auto connectOp : b.getOps<ConnectOp>()) {
750 if (skipCtrlPktOverlay && overlay.isAttrPresent(connectOp))
754 switchboxOp, XAie_StrmConnCctEnable, &aiert->devInst, tileLoc,
755 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(connectOp.getSourceBundle()),
756 connectOp.sourceIndex(),
757 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(connectOp.getDestBundle()),
758 connectOp.destIndex());
761 for (
auto masterSetOp : b.getOps<MasterSetOp>()) {
762 if (skipCtrlPktOverlay && overlay.isAttrPresent(masterSetOp))
770 for (
auto val : masterSetOp.getAmsels()) {
771 AMSelOp amsel = cast<AMSelOp>(val.getDefiningOp());
772 arbiter = amsel.arbiterIndex();
773 int msel = amsel.getMselValue();
777 auto dropHeader = masterSetOp.keepsPktHeader()
778 ? XAIE_SS_PKT_DONOT_DROP_HEADER
779 : XAIE_SS_PKT_DROP_HEADER;
781 masterSetOp, XAie_StrmPktSwMstrPortEnable, &aiert->devInst, tileLoc,
782 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(masterSetOp.getDestBundle()),
783 masterSetOp.destIndex(), dropHeader, arbiter, mask);
786 for (
auto packetRulesOp : b.getOps<PacketRulesOp>()) {
787 if (skipCtrlPktOverlay && overlay.isAttrPresent(packetRulesOp))
791 Block &block = packetRulesOp.getRules().front();
795 skipCtrlPktOverlay &&
796 llvm::any_of(block.getOps<PacketRuleOp>(), [&](PacketRuleOp rule) {
797 return overlay.isAttrPresent(rule);
799 for (
auto slotOp : block.getOps<PacketRuleOp>()) {
800 if (skipCtrlPktOverlay && overlay.isAttrPresent(slotOp)) {
804 AMSelOp amselOp = cast<AMSelOp>(slotOp.getAmsel().getDefiningOp());
805 int arbiter = amselOp.arbiterIndex();
806 int msel = amselOp.getMselValue();
809 &aiert->devInst, tileLoc,
810 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(
811 packetRulesOp.getSourceBundle()),
812 packetRulesOp.sourceIndex());
813 auto packetInit = XAie_PacketInit(slotOp.valueInt(), 0);
816 &aiert->devInst, tileLoc,
817 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(
818 packetRulesOp.getSourceBundle()),
819 packetRulesOp.sourceIndex(), slot, packetInit,
820 slotOp.maskInt(), msel, arbiter);
826 for (
auto muxOp : targetOp.getOps<ShimMuxOp>()) {
830 XAie_TileLoc(muxOp.getTileOp().getCol(), muxOp.getTileOp().getRow());
831 Block &b = muxOp.getConnections().front();
832 for (
auto connectOp : b.getOps<ConnectOp>()) {
833 if (skipCtrlPktOverlay && overlay.isAttrPresent(connectOp))
837 if (connectOp.getSourceBundle() == WireBundle::North)
839 &aiert->devInst, tileLoc,
840 connectOp.sourceIndex());
842 if (connectOp.getDestBundle() == WireBundle::North)
844 &aiert->devInst, tileLoc,
845 connectOp.destIndex());
850 if (isa<AIE2TargetModel>(targetModel)) {
851 for (
auto configOp : targetOp.getOps<ConfigureCascadeOp>()) {
853 TileOp tile = cast<TileOp>(configOp.getTile().getDefiningOp());
854 auto tileLoc = XAie_TileLoc(tile.getCol(), tile.getRow());
856 targetOp, XAie_CoreConfigAccumulatorControl, &aiert->devInst, tileLoc,
857 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(
858 static_cast<WireBundle
>(configOp.getInputDir())),
859 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(
860 static_cast<WireBundle
>(configOp.getOutputDir())));
869 bool skipCtrlPktOverlay) {
870 AIEDialect::IsCtrlPktOverlayAttrHelper overlay(targetOp.getContext());
871 auto skip = [&](Operation *op) {
872 return skipCtrlPktOverlay && overlay.isAttrPresent(op);
874 for (
auto switchboxOp : targetOp.getOps<SwitchboxOp>()) {
875 XAie_LocType tileLoc =
876 XAie_TileLoc(switchboxOp.colIndex(), switchboxOp.rowIndex());
877 Block &b = switchboxOp.getConnections().front();
878 for (
auto connectOp : b.getOps<ConnectOp>()) {
883 switchboxOp, XAie_StrmConnCctDisable, &aiert->devInst, tileLoc,
884 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(connectOp.getSourceBundle()),
885 connectOp.sourceIndex(),
886 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(connectOp.getDestBundle()),
887 connectOp.destIndex());
889 for (
auto masterSetOp : b.getOps<MasterSetOp>()) {
890 if (skip(masterSetOp))
894 masterSetOp, XAie_StrmPktSwMstrPortDisable, &aiert->devInst, tileLoc,
895 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(masterSetOp.getDestBundle()),
896 masterSetOp.destIndex());
898 for (
auto packetRulesOp : b.getOps<PacketRulesOp>()) {
899 auto rules = packetRulesOp.getRules().front().getOps<PacketRuleOp>();
900 if (rules.empty() || skip(packetRulesOp))
903 StrmSwPortType port =
904 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(packetRulesOp.getSourceBundle());
905 if (llvm::none_of(rules, skip))
907 &aiert->devInst, tileLoc, port,
908 packetRulesOp.sourceIndex());
910 for (
auto [slot, rule] : llvm::enumerate(rules))
913 &aiert->devInst, tileLoc, port,
914 packetRulesOp.sourceIndex(), slot);
921 for (
auto coreOp : targetOp.getOps<CoreOp>()) {
922 TileID tile = coreOp.getTileID();
925 XAie_TileLoc(tile.col, tile.row));
931 auto memOps = llvm::to_vector_of<TileElement>(targetOp.getOps<MemOp>());
932 llvm::append_range(memOps, targetOp.getOps<MemTileDMAOp>());
933 for (TileElement memOp : memOps) {
934 TileID tile = memOp.getTileID();
935 XAie_LocType tileLoc = XAie_TileLoc(tile.col, tile.row);
936 llvm::SmallSet<std::pair<DMAChannelDir, int>, 4> reset;
937 auto resetChannel = [&](Operation *op, DMAChannelDir dir,
938 int channel) -> LogicalResult {
939 if (!reset.insert({dir, channel}).second)
942 XAie_DmaDirection direction =
943 dir == DMAChannelDir::S2MM ? DMA_S2MM : DMA_MM2S;
945 tileLoc, channel, direction,
946 XAie_DmaChReset::DMA_CHANNEL_RESET);
949 XAie_DmaChannelDesc defaults;
953 &defaults, tileLoc, channel, direction);
956 Region ®ion = memOp.getOperation()->getRegion(0);
957 for (
auto dmaOp : region.getOps<DMAOp>())
958 if (failed(resetChannel(dmaOp, dmaOp.getChannelDir(),
959 dmaOp.getChannelIndex())))
962 for (
auto startOp : block->getOps<DMAStartOp>())
963 if (failed(resetChannel(startOp, startOp.getChannelDir(),
964 startOp.getChannelIndex())))
972 bool skipCtrlPktOverlay) {
991 auto memOps = llvm::to_vector_of<TileElement>(targetOp.getOps<MemOp>());
992 llvm::append_range(memOps, targetOp.getOps<MemTileDMAOp>());
993 llvm::append_range(memOps, targetOp.getOps<ShimDMAOp>());
994 for (TileElement memOp : memOps) {
995 int col = memOp.getTileID().col;
996 int row = memOp.getTileID().row;
1000 llvm::SetVector<Block *> blockVector =
1003 llvm::SmallPtrSet<Block *, 8> unchainedBlocks =
1007 auto dmaOps = llvm::to_vector_of<DMAOp>(
1008 memOp.getOperation()->getRegion(0).getOps<DMAOp>());
1009 if (!dmaOps.empty()) {
1010 for (
auto dmaOp : dmaOps)
1011 for (
auto &bdRegion : dmaOp.getBds()) {
1012 Block &block = bdRegion.getBlocks().front();
1018 for (Block *block : blockVector) {
1019 if (block->getOps<DMABDOp>().empty())
1022 unchainedBlocks.contains(block))))
1027 if (!dmaOps.empty())
1028 for (
auto dmaOp : dmaOps) {
1029 auto &block = dmaOp.getBds().front().getBlocks().front();
1030 DMABDOp bd = *block.getOps<DMABDOp>().begin();
1031 auto bdId = bd.getBdId();
1032 assert(bdId.has_value() &&
1033 "bd_id assigned by configureLocksAndBd above");
1035 *dmaOp.getOperation(), col, row, dmaOp.getChannelIndex(),
1036 dmaOp.getChannelDir(), bdId.value(), dmaOp.getRepeatCount(),
1037 dmaOp.getPadValue(), dmaOp.getOutOfOrder())))
1041 for (Block *block : blockVector) {
1042 for (
auto op : block->getOps<DMAStartOp>()) {
1043 DMABDOp bd = *op.getDest()->getOps<DMABDOp>().begin();
1044 int chNum = op.getChannelIndex();
1045 auto channelDir = op.getChannelDir();
1046 auto bdId = bd.getBdId();
1047 assert(bdId.has_value() &&
1048 "bd_id assigned by configureLocksAndBd above");
1050 *bd.getOperation(), col, row, chNum, channelDir, bdId.value(),
1051 op.getRepeatCount(), op.getPadValue(), op.getOutOfOrder(),
1053 !op.getCorePushes())))
1064 for (
auto tileOp : targetOp.getOps<TileOp>()) {
1065 auto tileLoc = XAie_TileLoc(tileOp.colIndex(), tileOp.rowIndex());
1066 if (!tileOp.isShimTile() && tileOp.getCoreOp()) {
1067 CoreOp coreOp = tileOp.getCoreOp();
1072 if (coreOp.getProcessorBus())
1074 &aiert->devInst, tileLoc);
1083 const StringRef elfPath,
1086 XAie_TileLoc(col, row));
1088 XAie_TileLoc(col, row),
1089 XAie_DmaChReset::DMA_CHANNEL_RESET);
1094 XAie_TileLoc(col, row), elfPath.str().c_str(),
1098 XAie_TileLoc(col, row),
1099 XAie_DmaChReset::DMA_CHANNEL_UNRESET);
1110 auto tileLoc = XAie_TileLoc(col, row);
1111 XAie_DmaDesc dmaTileBd;
1116 on ? XAie_DmaChReset::DMA_CHANNEL_UNRESET
1117 : XAie_DmaChReset::DMA_CHANNEL_RESET);
1122 auto tileLoc = XAie_TileLoc(col, row);
1128 XAie_LocType tileLoc = XAie_TileLoc(col, row);
1131 for (
auto endpoint_a : WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE) {
1132 for (
auto endpoint_b : WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE) {
1133 unsigned n_a_connections = targetModel.getNumSourceSwitchboxConnections(
1134 col, row, endpoint_a.first);
1135 unsigned n_b_connections = targetModel.getNumDestSwitchboxConnections(
1136 col, row, endpoint_b.first);
1137 for (
unsigned a_index = 0; a_index < n_a_connections; a_index++) {
1138 for (
unsigned b_index = 0; b_index < n_b_connections; b_index++) {
1139 if (!targetModel.isLegalTileConnection(col, row, endpoint_a.first,
1140 a_index, endpoint_b.first,
1145 tileLoc, endpoint_a.second, a_index,
1146 endpoint_b.second, b_index);
1156 auto tileLoc = XAie_TileLoc(col, row);
1163 auto tileLoc = XAie_TileLoc(col, row);
1166 lock.LockId = lockId;
1174 int col,
int row, WireBundle sourceBundle,
int sourceChannel,
1175 WireBundle destBundle,
int destChannel) {
1176 auto tileLoc = XAie_TileLoc(col, row);
1179 auto mapBundle = [](WireBundle bundle) -> StrmSwPortType {
1181 case WireBundle::Core:
1183 case WireBundle::DMA:
1185 case WireBundle::FIFO:
1187 case WireBundle::South:
1189 case WireBundle::West:
1191 case WireBundle::North:
1193 case WireBundle::East:
1195 case WireBundle::Trace:
1202 StrmSwPortType sourcePortType = mapBundle(sourceBundle);
1203 StrmSwPortType destPortType = mapBundle(destBundle);
1207 sourcePortType, sourceChannel, destPortType,
1214 auto tileLoc = XAie_TileLoc(col, row);
1217 for (
int counterId = 0; counterId < 4; counterId++) {
1219 (void)XAie_PerfCounterReset(&aiert->devInst, tileLoc, XAIE_CORE_MOD,
1223 for (
int counterId = 0; counterId < 4; counterId++) {
1224 (void)XAie_PerfCounterReset(&aiert->devInst, tileLoc, XAIE_MEM_MOD,
1228 for (
int counterId = 0; counterId < 4; counterId++) {
1229 (void)XAie_PerfCounterReset(&aiert->devInst, tileLoc, XAIE_PL_MOD,
1236 const StringRef elfPath,
1238 for (
auto tileOp : targetOp.getOps<TileOp>())
1239 if (tileOp.isShimNOCorPLTile()) {
1242 int col = tileOp.colIndex();
1243 int row = tileOp.rowIndex();
1244 if (
auto coreOp = tileOp.getCoreOp()) {
1245 std::string fileName;
1246 if (
auto fileAttr = coreOp.getElfFile()) {
1247 fileName = fileAttr->str();
1255 std::string fullPath;
1256 if (std::filesystem::path(fileName).is_absolute()) {
1257 fullPath = fileName;
1259 auto ps = std::filesystem::path::preferred_separator;
1261 (llvm::Twine(elfPath) + std::string(1, ps) + fileName).str();
1263 if (failed(
addAieElf(col, row, fullPath, aieSim)))
1272 auto tileLoc = XAie_TileLoc(col, row);
1278 aiert->txnCmdLocs.clear();
1279 aiert->txnOpLocs.clear();
1281 XAIE_TRANSACTION_DISABLE_AUTO_FLUSH);
1293static std::vector<mlir::Location>
1294projectCmdLocsOntoSerializedOps(
const XAie_TxnInst &inst,
1295 const std::vector<mlir::Location> &cmdLocs) {
1296 std::vector<mlir::Location> opLocs;
1297 opLocs.reserve(inst.NumCmds);
1299 mlir::Location unknown = mlir::UnknownLoc::get(cmdLocs.front().getContext());
1300 bool pendingBlockWrite =
false;
1301 mlir::Location pendingBlockWriteLoc = unknown;
1302 uint64_t blockWriteEndOff = 0;
1304 for (uint32_t i = 0; i < inst.NumCmds; ++i) {
1305 const XAie_TxnCmd &cmd = inst.CmdBuf[i];
1306 mlir::Location loc = i < cmdLocs.size() ? cmdLocs[i] : unknown;
1308 if (cmd.Opcode == XAIE_IO_BLOCKWRITE) {
1311 if (!pendingBlockWrite || cmd.RegOff != blockWriteEndOff) {
1312 if (pendingBlockWrite)
1313 opLocs.push_back(pendingBlockWriteLoc);
1314 pendingBlockWrite =
true;
1315 pendingBlockWriteLoc = loc;
1317 blockWriteEndOff = cmd.RegOff + cmd.Size *
sizeof(uint32_t);
1321 if (cmd.Opcode == XAIE_IO_LOAD_PM_END_INTERNAL)
1324 if (pendingBlockWrite && cmd.Opcode != XAIE_IO_CUSTOM_OP_DDR_PATCH) {
1325 opLocs.push_back(pendingBlockWriteLoc);
1326 pendingBlockWrite =
false;
1328 opLocs.push_back(loc);
1330 if (pendingBlockWrite)
1331 opLocs.push_back(pendingBlockWriteLoc);
1338 uint8_t *txn_ptr = XAie_ExportSerializedTransaction(&aiert->devInst, 0, 0);
1339 XAie_TxnHeader *hdr = (XAie_TxnHeader *)txn_ptr;
1340 std::vector<uint8_t> txn_data(txn_ptr, txn_ptr + hdr->TxnSize);
1346 XAie_TxnInst *inst = getActiveTxnInst(aiert->devInst);
1347 if (inst && !aiert->txnCmdLocs.empty())
1349 projectCmdLocsOntoSerializedOps(*inst, aiert->txnCmdLocs);
1354const std::vector<mlir::Location> &
1356 return aiert->txnOpLocs;
1360 return getActiveTxnNumCmds(aiert->devInst);
1365 mlir::Location loc) {
1366 if (endCmds <= startCmds)
1368 if (aiert->txnCmdLocs.size() < endCmds)
1369 aiert->txnCmdLocs.resize(endCmds, mlir::UnknownLoc::get(loc.getContext()));
1370 for (uint32_t i = startCmds; i < endCmds; ++i)
1371 aiert->txnCmdLocs[i] = loc;
#define XAIE_PARTITION_BASE_ADDR
#define TRY_XAIE_API_LOGICAL_RESULT(API,...)
#define TRY_XAIE_API_FATAL_ERROR(API,...)
#define TRY_XAIE_API_EMIT_ERROR(OP, API,...)
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 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.
bool hasProperty(ModelProperty Prop) const
virtual int columns() const =0
Return the number of columns in the device.
TxnLocBracket(AIERTControl &ctl, mlir::Location loc)
uint32_t getShimBurstLengthBytes(const AIE::AIETargetModel &tm, uint32_t burstLength)
mlir::LogicalResult verifyBdLockPair(mlir::Block &block, bool outOfOrder, UseLockOp &acquire, UseLockOp &release)
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
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.
llvm::SmallPtrSet< mlir::Block *, 8 > collectUnchainedBlocks(const llvm::SetVector< mlir::Block * > &blockVector)
Collect BD blocks that require use_next_bd=0 during configuration.
llvm::SetVector< mlir::Block * > getOrderedChainOfBlocks(mlir::Region *region)
std::vector< mlir::Location > txnCmdLocs
std::vector< mlir::Location > txnOpLocs
mlir::LogicalResult configureSwitches(DeviceOp &targetOp, bool skipCtrlPktOverlay=false)
mlir::LogicalResult resetPerfCounters(int col, int row)
mlir::LogicalResult configureLocksAndBd(mlir::Block &block, int col, int row, bool outOfOrder=false)
mlir::LogicalResult resetCore(int col, int row)
void dmaUpdateBdAddr(int col, int row, size_t addr, size_t bdId)
mlir::LogicalResult resetPartition()
mlir::LogicalResult resetCoreUnreset(int col, int row)
mlir::LogicalResult setIOBackend(bool aieSim, bool xaieDebug)
uint32_t getCurrentTxnNumCmds() const
std::vector< uint8_t > exportSerializedTransaction()
AIERTControl(const xilinx::AIE::AIETargetModel &tm)
mlir::LogicalResult initLocks(DeviceOp &targetOp)
mlir::LogicalResult resetDMA(int col, int row, bool on)
mlir::LogicalResult disableCores(DeviceOp &targetOp)
mlir::LogicalResult initBuffers(DeviceOp &targetOp)
mlir::LogicalResult resetSwitch(int col, int row)
mlir::LogicalResult addCoreEnable(DeviceOp &targetOp)
mlir::LogicalResult resetSwitchConnection(int col, int row, WireBundle sourceBundle, int sourceChannel, WireBundle destBundle, int destChannel)
const std::vector< mlir::Location > & getTxnOpLocs() const
mlir::LogicalResult addInitConfig(DeviceOp &targetOp, bool skipCtrlPktOverlay=false)
mlir::LogicalResult addAieElf(uint8_t col, uint8_t row, const mlir::StringRef elfPath, bool aieSim)
void recordTxnLocRange(uint32_t startCmds, uint32_t endCmds, mlir::Location loc)
mlir::LogicalResult resetDmaChannels(DeviceOp &targetOp)
mlir::LogicalResult pushToBdQueueAndEnable(mlir::Operation &op, int col, int row, int chNum, const DMAChannelDir &channelDir, int bdId, int repeatCount, uint32_t padValue=0, bool outOfOrder=false, bool configureChannel=true, bool pushTask=true)
mlir::LogicalResult addAieElfs(DeviceOp &targetOp, const mlir::StringRef elfPath, bool aieSim)
mlir::LogicalResult resetLock(int col, int row, int lockId)
mlir::LogicalResult teardownSwitches(DeviceOp &targetOp, bool skipCtrlPktOverlay=false)