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) {
602 XAie_DmaDirection direction =
603 channelDir == DMAChannelDir::S2MM ? DMA_S2MM : DMA_MM2S;
604 auto tileLoc = XAie_TileLoc(col, row);
605 if (padValue != 0 && direction == DMA_MM2S &&
606 targetModel.isMemTile(col, row)) {
608 static_cast<uint8_t
>(chNum), padValue);
614 XAie_DmaChannelDesc dmaChannelDesc;
616 &dmaChannelDesc, tileLoc);
618 static_cast<uint8_t
>(XAIE_ENABLE));
620 &dmaChannelDesc, tileLoc,
621 static_cast<uint8_t
>(chNum), direction);
624 XAie_DmaDeclareQueueConfig(startQueueCfg, 0, repeatCount,
625 static_cast<uint8_t
>(XAIE_DISABLE),
626 static_cast<uint8_t
>(XAIE_ENABLE));
628 &aiert->devInst, tileLoc, chNum, direction,
631 bool enTokenIssue = tileLoc.Row == 0 && direction == DMA_S2MM;
633 tileLoc, chNum, direction, bdId, repeatCount,
644 DMABDOp bd = *block.getOps<DMABDOp>().begin();
645 auto bdId = bd.getBdId();
646 assert(bdId.has_value() &&
647 "DMABDOp must have assigned bd_id; did you forget to run "
648 "aie-assign-bd-ids?");
650 XAie_DmaDesc dmaTileBd;
651 auto tileLoc = XAie_TileLoc(col, row);
654 if (!block.getOps<UseLockOp>().empty() &&
655 failed(configureLocksInBdBlock(targetModel, dmaTileBd, block, col, row,
660 std::optional<int> nextBdId =
661 outOfOrder ? std::optional<int>() : bd.getNextBdId();
662 if (!block.getOps<DMABDOp>().empty() &&
663 failed(configureBdInBlock(
664 targetModel, &aiert->devInst, dmaTileBd, block, col, row,
672 for (
auto tileOp : targetOp.getOps<TileOp>()) {
673 auto tileLoc = XAie_TileLoc(tileOp.colIndex(), tileOp.rowIndex());
674 if (!tileOp.isShimTile() && tileOp.getCoreOp()) {
680 for (uint8_t l = 0; l <
NUM_LOCKS; l++) {
681 auto locInit = XAie_LockInit(l, 0);
689 targetOp.walkOutsideRuntimeSequences<LockOp>([&](LockOp lockOp) {
690 if (lockOp.getLockID() && lockOp.getInit()) {
692 auto tileLoc = XAie_TileLoc(lockOp.getTileOp().colIndex(),
693 lockOp.getTileOp().rowIndex());
694 auto locInit = XAie_LockInit(*lockOp.getLockID(), *lockOp.getInit());
698 LLVM_DEBUG(llvm::dbgs()
699 <<
"lock op missing either id or init" << lockOp <<
"\n");
706 targetOp.walkOutsideRuntimeSequences<BufferOp>([&](BufferOp bufferOp) {
707 auto initialValue = bufferOp.getInitialValue();
711 mlir::DenseElementsAttr denseInit =
712 dyn_cast<mlir::DenseElementsAttr>(initialValue.value());
715 auto tileLoc = XAie_TileLoc(bufferOp.getTileOp().colIndex(),
716 bufferOp.getTileOp().rowIndex());
719 llvm::outs() <<
"buffer op type not supported for initialization "
724 bufferOp.getAddress().value(), byteVec->data(),
732 bool skipCtrlPktOverlay) {
733 AIEDialect::IsCtrlPktOverlayAttrHelper overlay(targetOp.getContext());
736 for (
auto switchboxOp : targetOp.getOps<SwitchboxOp>()) {
737 int32_t col = switchboxOp.colIndex();
738 int32_t row = switchboxOp.rowIndex();
739 XAie_LocType tileLoc = XAie_TileLoc(col, row);
741 "Only NPU currently supported");
743 Block &b = switchboxOp.getConnections().front();
744 for (
auto connectOp : b.getOps<ConnectOp>()) {
745 if (skipCtrlPktOverlay && overlay.isAttrPresent(connectOp))
749 switchboxOp, XAie_StrmConnCctEnable, &aiert->devInst, tileLoc,
750 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(connectOp.getSourceBundle()),
751 connectOp.sourceIndex(),
752 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(connectOp.getDestBundle()),
753 connectOp.destIndex());
756 for (
auto masterSetOp : b.getOps<MasterSetOp>()) {
757 if (skipCtrlPktOverlay && overlay.isAttrPresent(masterSetOp))
765 for (
auto val : masterSetOp.getAmsels()) {
766 AMSelOp amsel = cast<AMSelOp>(val.getDefiningOp());
767 arbiter = amsel.arbiterIndex();
768 int msel = amsel.getMselValue();
772 auto dropHeader = masterSetOp.keepsPktHeader()
773 ? XAIE_SS_PKT_DONOT_DROP_HEADER
774 : XAIE_SS_PKT_DROP_HEADER;
776 masterSetOp, XAie_StrmPktSwMstrPortEnable, &aiert->devInst, tileLoc,
777 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(masterSetOp.getDestBundle()),
778 masterSetOp.destIndex(), dropHeader, arbiter, mask);
781 for (
auto packetRulesOp : b.getOps<PacketRulesOp>()) {
782 if (skipCtrlPktOverlay && overlay.isAttrPresent(packetRulesOp))
786 Block &block = packetRulesOp.getRules().front();
790 skipCtrlPktOverlay &&
791 llvm::any_of(block.getOps<PacketRuleOp>(), [&](PacketRuleOp rule) {
792 return overlay.isAttrPresent(rule);
794 for (
auto slotOp : block.getOps<PacketRuleOp>()) {
795 if (skipCtrlPktOverlay && overlay.isAttrPresent(slotOp)) {
799 AMSelOp amselOp = cast<AMSelOp>(slotOp.getAmsel().getDefiningOp());
800 int arbiter = amselOp.arbiterIndex();
801 int msel = amselOp.getMselValue();
804 &aiert->devInst, tileLoc,
805 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(
806 packetRulesOp.getSourceBundle()),
807 packetRulesOp.sourceIndex());
808 auto packetInit = XAie_PacketInit(slotOp.valueInt(), 0);
811 &aiert->devInst, tileLoc,
812 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(
813 packetRulesOp.getSourceBundle()),
814 packetRulesOp.sourceIndex(), slot, packetInit,
815 slotOp.maskInt(), msel, arbiter);
821 for (
auto muxOp : targetOp.getOps<ShimMuxOp>()) {
825 XAie_TileLoc(muxOp.getTileOp().getCol(), muxOp.getTileOp().getRow());
826 Block &b = muxOp.getConnections().front();
827 for (
auto connectOp : b.getOps<ConnectOp>()) {
830 if (connectOp.getSourceBundle() == WireBundle::North)
832 &aiert->devInst, tileLoc,
833 connectOp.sourceIndex());
835 if (connectOp.getDestBundle() == WireBundle::North)
837 &aiert->devInst, tileLoc,
838 connectOp.destIndex());
843 if (isa<AIE2TargetModel>(targetModel)) {
844 for (
auto configOp : targetOp.getOps<ConfigureCascadeOp>()) {
846 TileOp tile = cast<TileOp>(configOp.getTile().getDefiningOp());
847 auto tileLoc = XAie_TileLoc(tile.getCol(), tile.getRow());
849 targetOp, XAie_CoreConfigAccumulatorControl, &aiert->devInst, tileLoc,
850 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(
851 static_cast<WireBundle
>(configOp.getInputDir())),
852 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(
853 static_cast<WireBundle
>(configOp.getOutputDir())));
861 for (
auto switchboxOp : targetOp.getOps<SwitchboxOp>()) {
862 XAie_LocType tileLoc =
863 XAie_TileLoc(switchboxOp.colIndex(), switchboxOp.rowIndex());
864 Block &b = switchboxOp.getConnections().front();
865 for (
auto connectOp : b.getOps<ConnectOp>()) {
868 switchboxOp, XAie_StrmConnCctDisable, &aiert->devInst, tileLoc,
869 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(connectOp.getSourceBundle()),
870 connectOp.sourceIndex(),
871 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(connectOp.getDestBundle()),
872 connectOp.destIndex());
874 for (
auto masterSetOp : b.getOps<MasterSetOp>()) {
877 masterSetOp, XAie_StrmPktSwMstrPortDisable, &aiert->devInst, tileLoc,
878 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(masterSetOp.getDestBundle()),
879 masterSetOp.destIndex());
881 for (
auto packetRulesOp : b.getOps<PacketRulesOp>()) {
882 auto rules = packetRulesOp.getRules().front().getOps<PacketRuleOp>();
886 StrmSwPortType port =
887 WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE.at(packetRulesOp.getSourceBundle());
889 &aiert->devInst, tileLoc, port,
890 packetRulesOp.sourceIndex());
892 for (
auto [slot, rule] : llvm::enumerate(rules))
894 &aiert->devInst, tileLoc, port,
895 packetRulesOp.sourceIndex(), slot);
902 for (
auto coreOp : targetOp.getOps<CoreOp>()) {
903 TileID tile = coreOp.getTileID();
906 XAie_TileLoc(tile.col, tile.row));
912 auto memOps = llvm::to_vector_of<TileElement>(targetOp.getOps<MemOp>());
913 llvm::append_range(memOps, targetOp.getOps<MemTileDMAOp>());
914 for (TileElement memOp : memOps) {
915 TileID tile = memOp.getTileID();
916 XAie_LocType tileLoc = XAie_TileLoc(tile.col, tile.row);
917 llvm::SmallSet<std::pair<DMAChannelDir, int>, 4> reset;
918 auto resetChannel = [&](Operation *op, DMAChannelDir dir,
919 int channel) -> LogicalResult {
920 if (!reset.insert({dir, channel}).second)
923 XAie_DmaDirection direction =
924 dir == DMAChannelDir::S2MM ? DMA_S2MM : DMA_MM2S;
926 tileLoc, channel, direction,
927 XAie_DmaChReset::DMA_CHANNEL_RESET);
930 XAie_DmaChannelDesc defaults;
934 &defaults, tileLoc, channel, direction);
937 Region ®ion = memOp.getOperation()->getRegion(0);
938 for (
auto dmaOp : region.getOps<DMAOp>())
939 if (failed(resetChannel(dmaOp, dmaOp.getChannelDir(),
940 dmaOp.getChannelIndex())))
943 for (
auto startOp : block->getOps<DMAStartOp>())
944 if (failed(resetChannel(startOp, startOp.getChannelDir(),
945 startOp.getChannelIndex())))
953 bool skipCtrlPktOverlay) {
972 auto memOps = llvm::to_vector_of<TileElement>(targetOp.getOps<MemOp>());
973 llvm::append_range(memOps, targetOp.getOps<MemTileDMAOp>());
974 llvm::append_range(memOps, targetOp.getOps<ShimDMAOp>());
975 for (TileElement memOp : memOps) {
976 int col = memOp.getTileID().col;
977 int row = memOp.getTileID().row;
981 llvm::SetVector<Block *> blockVector =
984 llvm::SmallPtrSet<Block *, 8> oooBlocks =
988 auto dmaOps = llvm::to_vector_of<DMAOp>(
989 memOp.getOperation()->getRegion(0).getOps<DMAOp>());
990 if (!dmaOps.empty()) {
991 for (
auto dmaOp : dmaOps)
992 for (
auto &bdRegion : dmaOp.getBds()) {
993 Block &block = bdRegion.getBlocks().front();
999 for (Block *block : blockVector) {
1000 if (block->getOps<DMABDOp>().empty())
1003 oooBlocks.contains(block))))
1008 if (!dmaOps.empty())
1009 for (
auto dmaOp : dmaOps) {
1010 auto &block = dmaOp.getBds().front().getBlocks().front();
1011 DMABDOp bd = *block.getOps<DMABDOp>().begin();
1012 auto bdId = bd.getBdId();
1013 assert(bdId.has_value() &&
1014 "bd_id assigned by configureLocksAndBd above");
1016 *dmaOp.getOperation(), col, row, dmaOp.getChannelIndex(),
1017 dmaOp.getChannelDir(), bdId.value(), dmaOp.getRepeatCount(),
1018 dmaOp.getPadValue(), dmaOp.getOutOfOrder())))
1022 for (Block *block : blockVector) {
1023 for (
auto op : block->getOps<DMAStartOp>()) {
1024 DMABDOp bd = *op.getDest()->getOps<DMABDOp>().begin();
1025 int chNum = op.getChannelIndex();
1026 auto channelDir = op.getChannelDir();
1027 auto bdId = bd.getBdId();
1028 assert(bdId.has_value() &&
1029 "bd_id assigned by configureLocksAndBd above");
1031 *bd.getOperation(), col, row, chNum, channelDir, bdId.value(),
1032 op.getRepeatCount(), op.getPadValue(), op.getOutOfOrder())))
1043 for (
auto tileOp : targetOp.getOps<TileOp>()) {
1044 auto tileLoc = XAie_TileLoc(tileOp.colIndex(), tileOp.rowIndex());
1045 if (!tileOp.isShimTile() && tileOp.getCoreOp()) {
1055 const StringRef elfPath,
1058 XAie_TileLoc(col, row));
1060 XAie_TileLoc(col, row),
1061 XAie_DmaChReset::DMA_CHANNEL_RESET);
1066 XAie_TileLoc(col, row), elfPath.str().c_str(),
1070 XAie_TileLoc(col, row),
1071 XAie_DmaChReset::DMA_CHANNEL_UNRESET);
1082 auto tileLoc = XAie_TileLoc(col, row);
1083 XAie_DmaDesc dmaTileBd;
1088 on ? XAie_DmaChReset::DMA_CHANNEL_UNRESET
1089 : XAie_DmaChReset::DMA_CHANNEL_RESET);
1094 auto tileLoc = XAie_TileLoc(col, row);
1100 XAie_LocType tileLoc = XAie_TileLoc(col, row);
1103 for (
auto endpoint_a : WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE) {
1104 for (
auto endpoint_b : WIRE_BUNDLE_TO_STRM_SW_PORT_TYPE) {
1105 unsigned n_a_connections = targetModel.getNumSourceSwitchboxConnections(
1106 col, row, endpoint_a.first);
1107 unsigned n_b_connections = targetModel.getNumDestSwitchboxConnections(
1108 col, row, endpoint_b.first);
1109 for (
unsigned a_index = 0; a_index < n_a_connections; a_index++) {
1110 for (
unsigned b_index = 0; b_index < n_b_connections; b_index++) {
1111 if (!targetModel.isLegalTileConnection(col, row, endpoint_a.first,
1112 a_index, endpoint_b.first,
1117 tileLoc, endpoint_a.second, a_index,
1118 endpoint_b.second, b_index);
1128 auto tileLoc = XAie_TileLoc(col, row);
1135 auto tileLoc = XAie_TileLoc(col, row);
1138 lock.LockId = lockId;
1146 int col,
int row, WireBundle sourceBundle,
int sourceChannel,
1147 WireBundle destBundle,
int destChannel) {
1148 auto tileLoc = XAie_TileLoc(col, row);
1151 auto mapBundle = [](WireBundle bundle) -> StrmSwPortType {
1153 case WireBundle::Core:
1155 case WireBundle::DMA:
1157 case WireBundle::FIFO:
1159 case WireBundle::South:
1161 case WireBundle::West:
1163 case WireBundle::North:
1165 case WireBundle::East:
1167 case WireBundle::Trace:
1174 StrmSwPortType sourcePortType = mapBundle(sourceBundle);
1175 StrmSwPortType destPortType = mapBundle(destBundle);
1179 sourcePortType, sourceChannel, destPortType,
1186 auto tileLoc = XAie_TileLoc(col, row);
1189 for (
int counterId = 0; counterId < 4; counterId++) {
1191 (void)XAie_PerfCounterReset(&aiert->devInst, tileLoc, XAIE_CORE_MOD,
1195 for (
int counterId = 0; counterId < 4; counterId++) {
1196 (void)XAie_PerfCounterReset(&aiert->devInst, tileLoc, XAIE_MEM_MOD,
1200 for (
int counterId = 0; counterId < 4; counterId++) {
1201 (void)XAie_PerfCounterReset(&aiert->devInst, tileLoc, XAIE_PL_MOD,
1208 const StringRef elfPath,
1210 for (
auto tileOp : targetOp.getOps<TileOp>())
1211 if (tileOp.isShimNOCorPLTile()) {
1214 int col = tileOp.colIndex();
1215 int row = tileOp.rowIndex();
1216 if (
auto coreOp = tileOp.getCoreOp()) {
1217 std::string fileName;
1218 if (
auto fileAttr = coreOp.getElfFile()) {
1219 fileName = fileAttr->str();
1227 std::string fullPath;
1228 if (std::filesystem::path(fileName).is_absolute()) {
1229 fullPath = fileName;
1231 auto ps = std::filesystem::path::preferred_separator;
1233 (llvm::Twine(elfPath) + std::string(1, ps) + fileName).str();
1235 if (failed(
addAieElf(col, row, fullPath, aieSim)))
1244 auto tileLoc = XAie_TileLoc(col, row);
1250 aiert->txnCmdLocs.clear();
1251 aiert->txnOpLocs.clear();
1253 XAIE_TRANSACTION_DISABLE_AUTO_FLUSH);
1265static std::vector<mlir::Location>
1266projectCmdLocsOntoSerializedOps(
const XAie_TxnInst &inst,
1267 const std::vector<mlir::Location> &cmdLocs) {
1268 std::vector<mlir::Location> opLocs;
1269 opLocs.reserve(inst.NumCmds);
1271 mlir::Location unknown = mlir::UnknownLoc::get(cmdLocs.front().getContext());
1272 bool pendingBlockWrite =
false;
1273 mlir::Location pendingBlockWriteLoc = unknown;
1274 uint64_t blockWriteEndOff = 0;
1276 for (uint32_t i = 0; i < inst.NumCmds; ++i) {
1277 const XAie_TxnCmd &cmd = inst.CmdBuf[i];
1278 mlir::Location loc = i < cmdLocs.size() ? cmdLocs[i] : unknown;
1280 if (cmd.Opcode == XAIE_IO_BLOCKWRITE) {
1283 if (!pendingBlockWrite || cmd.RegOff != blockWriteEndOff) {
1284 if (pendingBlockWrite)
1285 opLocs.push_back(pendingBlockWriteLoc);
1286 pendingBlockWrite =
true;
1287 pendingBlockWriteLoc = loc;
1289 blockWriteEndOff = cmd.RegOff + cmd.Size *
sizeof(uint32_t);
1293 if (cmd.Opcode == XAIE_IO_LOAD_PM_END_INTERNAL)
1296 if (pendingBlockWrite && cmd.Opcode != XAIE_IO_CUSTOM_OP_DDR_PATCH) {
1297 opLocs.push_back(pendingBlockWriteLoc);
1298 pendingBlockWrite =
false;
1300 opLocs.push_back(loc);
1302 if (pendingBlockWrite)
1303 opLocs.push_back(pendingBlockWriteLoc);
1310 uint8_t *txn_ptr = XAie_ExportSerializedTransaction(&aiert->devInst, 0, 0);
1311 XAie_TxnHeader *hdr = (XAie_TxnHeader *)txn_ptr;
1312 std::vector<uint8_t> txn_data(txn_ptr, txn_ptr + hdr->TxnSize);
1318 XAie_TxnInst *inst = getActiveTxnInst(aiert->devInst);
1319 if (inst && !aiert->txnCmdLocs.empty())
1321 projectCmdLocsOntoSerializedOps(*inst, aiert->txnCmdLocs);
1326const std::vector<mlir::Location> &
1328 return aiert->txnOpLocs;
1332 return getActiveTxnNumCmds(aiert->devInst);
1337 mlir::Location loc) {
1338 if (endCmds <= startCmds)
1340 if (aiert->txnCmdLocs.size() < endCmds)
1341 aiert->txnCmdLocs.resize(endCmds, mlir::UnknownLoc::get(loc.getContext()));
1342 for (uint32_t i = startCmds; i < endCmds; ++i)
1343 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)
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.
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::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 pushToBdQueueAndEnable(mlir::Operation &op, int col, int row, int chNum, const DMAChannelDir &channelDir, int bdId, int repeatCount, uint32_t padValue=0, bool outOfOrder=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 addAieElfs(DeviceOp &targetOp, const mlir::StringRef elfPath, bool aieSim)
mlir::LogicalResult teardownSwitches(DeviceOp &targetOp)
mlir::LogicalResult resetLock(int col, int row, int lockId)