From f36718045ebf48e6e59a1c25b264bd2d04d0fb13 Mon Sep 17 00:00:00 2001 From: Zhewen Yu Date: Fri, 10 Jan 2025 23:22:02 +0000 Subject: [PATCH] [TargetCDODirect] Separate aie-rt related functions into a new library (#1018) The following interface functions between the `xilinx::aie` dialect and `aie-rt` have been relocated and renamed `Target/AMDAIETargetCDODirect.cpp/addAieElfsToCDO` ->`Target/AMDAIERT.cpp/addAllAieElfs` `Target/AMDAIETargetCDODirect.cpp/addCoreEnableToCDO` -> `Target/AMDAIERT.cpp/addAllCoreEnable` `Target/AMDAIETargetCDODirect.cpp/addInitConfigToCDO` -> `Target/AMDAIERT.cpp/addInitConfig` The motivation is, these functions are not specific to the CDO and can be useful in other contexts, such as generating control packets. Brief documentation has also been added for these functions in the new header file. related: https://github.com/Xilinx/mlir-aie/pull/1760 --- .../AMD-AIE/iree-amd-aie/Target/AMDAIERT.cpp | 322 ++++++++++++++++++ .../AMD-AIE/iree-amd-aie/Target/AMDAIERT.h | 34 ++ .../Target/AMDAIETargetCDODirect.cpp | 315 +---------------- .../iree-amd-aie/Target/CMakeLists.txt | 13 + 4 files changed, 375 insertions(+), 309 deletions(-) create mode 100644 compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/AMDAIERT.cpp create mode 100644 compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/AMDAIERT.h diff --git a/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/AMDAIERT.cpp b/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/AMDAIERT.cpp new file mode 100644 index 000000000..34c8522b4 --- /dev/null +++ b/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/AMDAIERT.cpp @@ -0,0 +1,322 @@ +// Copyright 2025 The IREE Authors +// +// Licensed under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "AMDAIERT.h" + +#include "iree-amd-aie/aie_runtime/iree_aie_configure.h" + +using namespace mlir; + +using xilinx::AIE::AMSelOp; +using xilinx::AIE::BDDimLayoutAttr; +using xilinx::AIE::BDPadLayoutAttr; +using xilinx::AIE::BufferOp; +using xilinx::AIE::ConnectOp; +using xilinx::AIE::CoreOp; +using xilinx::AIE::DeviceOp; +using xilinx::AIE::DMABDOp; +using xilinx::AIE::DMABDPACKETOp; +using xilinx::AIE::DMAChannelDir; +using xilinx::AIE::DMAStartOp; +using xilinx::AIE::LockAction; +using xilinx::AIE::LockOp; +using xilinx::AIE::MasterSetOp; +using xilinx::AIE::MemOp; +using xilinx::AIE::MemTileDMAOp; +using xilinx::AIE::PacketRuleOp; +using xilinx::AIE::PacketRulesOp; +using xilinx::AIE::ShimMuxOp; +using xilinx::AIE::SwitchboxOp; +using xilinx::AIE::TileOp; +using xilinx::AIE::UseLockOp; + +using Path = std::filesystem::path; + +namespace mlir::iree_compiler::AMDAIE { + +LogicalResult addAllAieElfs(const AMDAIEDeviceModel &deviceModel, + DeviceOp &device, const Path &workDirPath, + bool aieSim) { + for (auto tileOp : device.getOps()) { + TileLoc tileLoc{tileOp.getCol(), tileOp.getRow()}; + if (deviceModel.isShimNOCorPLTile(tileLoc.col, tileLoc.row)) continue; + if (CoreOp coreOp = getCoreOp(tileOp)) { + std::string fileName; + std::optional elfFile = coreOp.getElfFile(); + if (elfFile.has_value()) { + fileName = *elfFile; + } else { + fileName = "core_" + std::to_string(tileLoc.col) + "_" + + std::to_string(tileLoc.row) + ".elf"; + } + if (failed(addElfToTile(deviceModel, tileLoc, workDirPath / fileName, + aieSim))) { + return failure(); + } + } + } + return success(); +} + +LogicalResult addAllCoreEnable(const AMDAIEDeviceModel &deviceModel, + DeviceOp &device) { + // Start execution of all the cores. + for (auto tileOp : device.getOps()) { + TileLoc tileLoc = {tileOp.getCol(), tileOp.getRow()}; + if (auto coreOp = getCoreOp(tileOp); + coreOp && failed(coreEnable(deviceModel, tileLoc))) + return failure(); + } + return success(); +} + +Lock::Action toLock(LockAction l) { + // Convert `xilinx::AIE::LockAction` to + // `mlir::iree_compiler::AMDAIE::LockAction`. + switch (l) { + case LockAction::Acquire: + return Lock::Action::Acquire; + case LockAction::AcquireGreaterEqual: + return Lock::Action::AcquireGreaterEqual; + case LockAction::Release: + return Lock::Action::Release; + } + llvm::report_fatal_error("unhandled lock action"); +} + +LogicalResult configureLocksAndBd(Block &block, const TileLoc &tileLoc, + const AMDAIEDeviceModel &deviceModel) { + FailureOr dmaTileBd = initDMADesc(deviceModel, tileLoc); + if (failed(dmaTileBd)) return failure(); + std::optional acqValue, relValue, acqLockId, relLockId; + bool acqEn; + for (UseLockOp op : block.getOps()) { + // Only dyn_cast if you are going to check if it was of the type + // expected; if you aren't checking use cast instead as it will at + // least assert in debug mode with an easier to understand error than + // dereferencing. + LockOp lock = cast(op.getLock().getDefiningOp()); + switch (toLock(op.getAction())) { + case Lock::Action::Acquire: + case Lock::Action::AcquireGreaterEqual: + acqEn = op.getAcqEn(); + acqLockId = lock.getLockID(); + acqValue = op.getValue().value_or(1); + if (op.getAction() == LockAction::AcquireGreaterEqual) + acqValue.value() = -acqValue.value(); + break; + case Lock::Action::Release: + relLockId = lock.getLockID(); + relValue = op.getValue().value_or(1); + break; + } + } + // Disable acquire and release locks if not set. + if (!acqLockId) { + acqLockId = 0; + acqValue = 0; + acqEn = false; + } + if (!relLockId) { + relLockId = 0; + relValue = 0; + } + assert(acqValue && relValue && acqLockId && relLockId && + "expected both use_lock(acquire) and use_lock(release) with bd"); + if (failed(configureDMALocks(deviceModel, dmaTileBd.value(), tileLoc, + *acqValue, *relValue, *acqLockId, *relLockId, + acqEn))) { + return failure(); + } + + // Pull metadata related to packet routing, bdId, buffer length, size, stride + // to pass to aie-rt. + DMABDOp bdOp = *block.getOps().begin(); + assert(bdOp.getBdId().has_value() && + "DMABDOp must have assigned bd_id; did you forget to run " + "aie-assign-bd-ids?"); + bool validBd = true; + std::optional packetType; + std::optional packetID; + bool enablePacket = false; + auto maybePacketOps = block.getOps(); + if (!maybePacketOps.empty()) { + assert(llvm::range_size(maybePacketOps) == 1 && + "expected only one dma_bd_packet"); + DMABDPACKETOp packetOp = *maybePacketOps.begin(); + packetType = packetOp.getPacketType(); + packetID = packetOp.getPacketId(); + enablePacket = true; + } + + BufferOp bufferOp = cast(bdOp.getBuffer().getDefiningOp()); + if (!bufferOp.getAddress()) + return bufferOp.emitError("buffer must have address assigned"); + // Convert `xilinx::AIE::BDDimLayoutAttr` to + // `mlir::iree_compiler::AMDAIE::BDDimLayout`. + std::optional> maybeDims; + if (std::optional> dims = bdOp.getDimensions()) { + maybeDims = std::vector{}; + for (const BDDimLayoutAttr &dim : (*dims)) { + maybeDims->emplace_back(BDDimLayout{dim.getSize(), dim.getStride()}); + } + } + + // Convert `xilinx::AIE::BDPadLayoutAttr` to + // `mlir::iree_compiler::AMDAIE::BDPadLayout`. + std::optional> maybePadDims; + if (std::optional> dims = + bdOp.getPadDimensions()) { + maybePadDims = std::vector{}; + for (const BDPadLayoutAttr &dim : (*dims)) { + maybePadDims->emplace_back( + BDPadLayout{dim.getConstPadBefore(), dim.getConstPadAfter()}); + } + } + + bool enableNextBd = bdOp.getNextBdId().has_value(); + std::optional nextBdId = + enableNextBd + ? std::optional{static_cast(*bdOp.getNextBdId())} + : std::nullopt; + std::optional maybeIter = std::nullopt; + if (failed(configureDMABD(deviceModel, dmaTileBd.value(), tileLoc, validBd, + static_cast(*bdOp.getBdId()), enableNextBd, + nextBdId, enablePacket, packetType, packetID, + *bufferOp.getAddress(), getLenInBytes(bdOp), + getOffsetInBytes(bdOp), + getBufferElementTypeWidthInBytes(bdOp), maybeDims, + maybePadDims, maybeIter))) { + return failure(); + } + return success(); +} + +LogicalResult addInitConfig(const AMDAIEDeviceModel &deviceModel, + DeviceOp &device) { + for (auto tileOp : device.getOps()) { + TileLoc tileLoc = {tileOp.getCol(), tileOp.getRow()}; + if (deviceModel.isShimTile(tileOp.getCol(), tileOp.getRow())) { + continue; + } + if (auto coreOp = getCoreOp(tileOp); + coreOp && failed(resetUnResetCore(deviceModel, tileLoc))) { + return failure(); + } + } + + // Set locks with explicit initializers. + WalkResult r; + r = device.walk([&](LockOp lockOp) { + if (lockOp.getLockID() && lockOp.getInit()) { + TileOp t = xilinx::AIE::getTileOp(*lockOp.getOperation()); + TileLoc tileLoc = {t.getCol(), t.getRow()}; + Lock lock{tileLoc, static_cast(*lockOp.getLockID()), + static_cast(*lockOp.getInit())}; + if (failed(initializeLock(deviceModel, lock))) + return WalkResult::interrupt(); + } + return WalkResult::advance(); + }); + if (r.wasInterrupted()) return failure(); + + auto memOps = llvm::to_vector_of(device.getOps()); + llvm::append_range(memOps, device.getOps()); + for (Operation *memOp : memOps) { + TileOp t = xilinx::AIE::getTileOp(*memOp); + TileLoc tileLoc = {t.getCol(), t.getRow()}; + if (deviceModel.isShimNOCorPLTile(tileLoc.col, tileLoc.row)) { + continue; + } + + // Handle DMA ops separately. + for (Block &block : memOp->getRegion(0)) { + if (block.getOps().empty()) continue; + if (failed(configureLocksAndBd(block, tileLoc, deviceModel))) + return failure(); + } + + for (Block &block : memOp->getRegion(0)) { + for (auto op : block.getOps()) { + DMABDOp bd = *op.getDest()->getOps().begin(); + int chNum = op.getChannelIndex(); + auto channelDir = static_cast(op.getChannelDir()); + bool issueToken = tileLoc.row == 0 && channelDir == DMAChannelDir::MM2S; + bool setChannelEnable = true; + if (failed(configurePushToBdQueue( + deviceModel, tileLoc, chNum, channelDir, bd.getBdId().value(), + op.getRepeatCount(), issueToken, setChannelEnable))) + return failure(); + } + } + } + + // StreamSwitch (switchbox) configuration. + for (auto switchboxOp : device.getOps()) { + TileOp t = xilinx::AIE::getTileOp(*switchboxOp.getOperation()); + TileLoc tileLoc = {t.getCol(), t.getRow()}; + std::vector connects; + for (auto connectOp : switchboxOp.getOps()) { + connects.emplace_back( + Port{connectOp.getSourceBundle(), connectOp.getSourceChannel()}, + Port{connectOp.getDestBundle(), connectOp.getDestChannel()}, + Connect::Interconnect::SWB, tileLoc.col, tileLoc.row); + } + if (failed(configureStreamSwitch(deviceModel, tileLoc, connects))) { + return failure(); + } + + Block &b = switchboxOp.getConnections().front(); + for (auto masterSetOp : b.getOps()) { + std::vector amSels; + for (Value val : masterSetOp.getAmsels()) { + AMSelOp amsel = cast(val.getDefiningOp()); + amSels.push_back({static_cast(amsel.getArbiterID()), + static_cast(amsel.getMsel())}); + } + if (failed(configureSwitchPacketMasters( + deviceModel, tileLoc, masterSetOp.getDestBundle(), + masterSetOp.getDestChannel(), amSels, + masterSetOp->hasAttr("keep_pkt_header")))) + return failure(); + } + + for (auto packetRulesOp : b.getOps()) { + int slot = 0; + Block &block = packetRulesOp.getRules().front(); + for (auto packetRuleOp : block.getOps()) { + AMSelOp amselOp = + cast(packetRuleOp.getAmsel().getDefiningOp()); + if (failed(configureSwitchPacketSlaves( + deviceModel, tileLoc, packetRulesOp.getSourceBundle(), + packetRulesOp.getSourceChannel(), + AMSel{amselOp.getArbiterID(), amselOp.getMsel()}, + packetRuleOp.getValue(), packetRuleOp.getMask(), slot))) + return failure(); + slot++; + } + } + } + + for (auto muxOp : device.getOps()) { + TileOp t = xilinx::AIE::getTileOp(*muxOp.getOperation()); + TileLoc tileLoc = {t.getCol(), t.getRow()}; + std::vector connects; + for (auto connectOp : muxOp.getOps()) { + connects.emplace_back( + Port{connectOp.getSourceBundle(), connectOp.getSourceChannel()}, + Port{connectOp.getDestBundle(), connectOp.getDestChannel()}, + Connect::Interconnect::SHIMMUX, tileLoc.col, tileLoc.row); + } + if (failed(configureStreamSwitch(deviceModel, tileLoc, connects))) { + return failure(); + } + } + + return success(); +} + +} // namespace mlir::iree_compiler::AMDAIE diff --git a/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/AMDAIERT.h b/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/AMDAIERT.h new file mode 100644 index 000000000..b7f1f4782 --- /dev/null +++ b/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/AMDAIERT.h @@ -0,0 +1,34 @@ +// Copyright 2025 The IREE Authors +// +// Licensed under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef IREE_AMD_AIE_TARGET_AMDAIERT_H_ +#define IREE_AMD_AIE_TARGET_AMDAIERT_H_ + +#include + +#include "aie/AIEDialect.h" + +namespace mlir::iree_compiler::AMDAIE { + +/// Load ELF files for all cores within the device operation. +LogicalResult addAllAieElfs(const AMDAIEDeviceModel &deviceModel, + xilinx::AIE::DeviceOp &device, + const std::filesystem::path &workDirPath, + bool aieSim); + +/// Update core control registers to enable all cores within the device +/// operation. +LogicalResult addAllCoreEnable(const AMDAIEDeviceModel &deviceModel, + xilinx::AIE::DeviceOp &device); + +/// Utility function to reset all cores, initialize hardware locks, +/// and configure all switchboxes. +LogicalResult addInitConfig(const AMDAIEDeviceModel &deviceModel, + xilinx::AIE::DeviceOp &device); + +} // namespace mlir::iree_compiler::AMDAIE + +#endif // IREE_AMD_AIE_TARGET_AMDAIERT_H_ diff --git a/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/AMDAIETargetCDODirect.cpp b/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/AMDAIETargetCDODirect.cpp index ed1fd6cae..a09cebba4 100644 --- a/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/AMDAIETargetCDODirect.cpp +++ b/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/AMDAIETargetCDODirect.cpp @@ -10,344 +10,41 @@ #include #include +#include "AMDAIERT.h" #include "AMDAIETargets.h" #include "aie/AIEDialect.h" -#include "aie/AIEEnums.h" #include "iree-amd-aie/aie_runtime/iree_aie_configure.h" -#include "iree-amd-aie/aie_runtime/iree_aie_runtime.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "mlir/IR/Block.h" -#include "mlir/Support/LLVM.h" -#include "mlir/Support/LogicalResult.h" #define DEBUG_TYPE "aie-generate-cdo" using namespace mlir; -using xilinx::AIE::AMSelOp; -using xilinx::AIE::BufferOp; -using xilinx::AIE::ConnectOp; + using xilinx::AIE::CoreOp; using xilinx::AIE::DeviceOp; -using xilinx::AIE::DMABDOp; -using xilinx::AIE::DMABDPACKETOp; -using xilinx::AIE::DMAChannelDir; -using xilinx::AIE::DMAStartOp; -using xilinx::AIE::LockAction; -using xilinx::AIE::LockOp; -using xilinx::AIE::MasterSetOp; -using xilinx::AIE::MemOp; -using xilinx::AIE::MemTileDMAOp; -using xilinx::AIE::PacketRuleOp; -using xilinx::AIE::PacketRulesOp; -using xilinx::AIE::ShimMuxOp; -using xilinx::AIE::SwitchboxOp; -using xilinx::AIE::TileOp; -using xilinx::AIE::UseLockOp; -using xilinx::AIE::WireBundle; using Path = std::filesystem::path; -namespace { - -mlir::iree_compiler::AMDAIE::Lock::Action toLock(xilinx::AIE::LockAction l) { - switch (l) { - case xilinx::AIE::LockAction::Acquire: - return mlir::iree_compiler::AMDAIE::Lock::Action::Acquire; - case xilinx::AIE::LockAction::AcquireGreaterEqual: - return mlir::iree_compiler::AMDAIE::Lock::Action::AcquireGreaterEqual; - case xilinx::AIE::LockAction::Release: - return mlir::iree_compiler::AMDAIE::Lock::Action::Release; - } - llvm::report_fatal_error("unhandled lock action"); -} - -} // namespace - namespace mlir::iree_compiler::AMDAIE { -LogicalResult configureLocksAndBd(Block &block, const TileLoc &tileLoc, - const AMDAIEDeviceModel &deviceModel) { - FailureOr dmaTileBd = initDMADesc(deviceModel, tileLoc); - if (failed(dmaTileBd)) return failure(); - std::optional acqValue, relValue, acqLockId, relLockId; - bool acqEn; - for (auto op : block.getOps()) { - // Only dyn_cast if you are going to check if it was of the type - // expected; if you aren't checking use cast instead as it will at - // least assert in debug mode with an easier to understand error than - // dereferencing. - LockOp lock = cast(op.getLock().getDefiningOp()); - switch (toLock(op.getAction())) { - case Lock::Action::Acquire: - case Lock::Action::AcquireGreaterEqual: - acqEn = op.getAcqEn(); - acqLockId = lock.getLockID(); - acqValue = op.getValue().value_or(1); - if (op.getAction() == LockAction::AcquireGreaterEqual) - acqValue.value() = -acqValue.value(); - break; - case Lock::Action::Release: - relLockId = lock.getLockID(); - relValue = op.getValue().value_or(1); - break; - } - } - // Disable acquire and release locks if not set. - if (!acqLockId) { - acqLockId = 0; - acqValue = 0; - acqEn = false; - } - if (!relLockId) { - relLockId = 0; - relValue = 0; - } - assert(acqValue && relValue && acqLockId && relLockId && - "expected both use_lock(acquire) and use_lock(release) with bd"); - if (failed(configureDMALocks(deviceModel, dmaTileBd.value(), tileLoc, - *acqValue, *relValue, *acqLockId, *relLockId, - acqEn))) { - return failure(); - } - - // pull metadata related to packet routing, bdid, buffer length, size, stride - // to pass to aie-rt - DMABDOp bdOp = *block.getOps().begin(); - assert(bdOp.getBdId().has_value() && - "DMABDOp must have assigned bd_id; did you forget to run " - "aie-assign-bd-ids?"); - bool validBd = true; - std::optional packetType; - std::optional packetID; - bool enablePacket = false; - auto maybePacketOps = block.getOps(); - if (!maybePacketOps.empty()) { - assert(llvm::range_size(maybePacketOps) == 1 && - "expected only one dma_bd_packet"); - auto packetOp = *maybePacketOps.begin(); - packetType = packetOp.getPacketType(); - packetID = packetOp.getPacketId(); - enablePacket = true; - } - - BufferOp bufferOp = cast(bdOp.getBuffer().getDefiningOp()); - if (!bufferOp.getAddress()) - return bufferOp.emitError("buffer must have address assigned"); - std::optional> maybeDims; - if (auto dims = bdOp.getDimensions()) { - maybeDims = std::vector{}; - for (const auto &dim : (*dims)) { - maybeDims->emplace_back(BDDimLayout{dim.getSize(), dim.getStride()}); - } - } - - std::optional> maybePadDims; - if (auto dims = bdOp.getPadDimensions()) { - maybePadDims = std::vector{}; - for (const auto &dim : (*dims)) { - maybePadDims->emplace_back( - BDPadLayout{dim.getConstPadBefore(), dim.getConstPadAfter()}); - } - } - - bool enableNextBd = bdOp.getNextBdId().has_value(); - std::optional nextBdId = - enableNextBd - ? std::optional{static_cast(*bdOp.getNextBdId())} - : std::nullopt; - std::optional maybeIter = std::nullopt; - if (failed(configureDMABD(deviceModel, dmaTileBd.value(), tileLoc, validBd, - static_cast(*bdOp.getBdId()), enableNextBd, - nextBdId, enablePacket, packetType, packetID, - *bufferOp.getAddress(), getLenInBytes(bdOp), - getOffsetInBytes(bdOp), - getBufferElementTypeWidthInBytes(bdOp), maybeDims, - maybePadDims, maybeIter))) { - return failure(); - } - return success(); -} - -LogicalResult addAieElfsToCDO(const AMDAIEDeviceModel &deviceModel, - DeviceOp &device, const Path &workDirPath, - bool aieSim) { - for (auto tileOp : device.getOps()) { - TileLoc tileLoc{tileOp.getCol(), tileOp.getRow()}; - if (deviceModel.isShimNOCorPLTile(tileLoc.col, tileLoc.row)) continue; - if (auto coreOp = getCoreOp(tileOp)) { - std::string fileName; - if (auto elfFile = coreOp.getElfFile()) - fileName = *elfFile; - else - fileName = "core_" + std::to_string(tileLoc.col) + "_" + - std::to_string(tileLoc.row) + ".elf"; - if (failed(addElfToTile(deviceModel, tileLoc, workDirPath / fileName, - aieSim))) { - return failure(); - } - } - } - return success(); -} - -LogicalResult addInitConfigToCDO(const AMDAIEDeviceModel &deviceModel, - DeviceOp &device) { - for (auto tileOp : device.getOps()) { - TileLoc tileLoc = {tileOp.getCol(), tileOp.getRow()}; - if (deviceModel.isShimTile(tileOp.getCol(), tileOp.getRow())) { - continue; - } - if (auto coreOp = getCoreOp(tileOp); - coreOp && failed(resetUnResetCore(deviceModel, tileLoc))) { - return failure(); - } - } - - // Set locks with explicit initializers - WalkResult r; - r = device.walk([&](LockOp lockOp) { - if (lockOp.getLockID() && lockOp.getInit()) { - TileOp t = xilinx::AIE::getTileOp(*lockOp.getOperation()); - TileLoc tileLoc = {t.getCol(), t.getRow()}; - Lock lock{tileLoc, static_cast(*lockOp.getLockID()), - static_cast(*lockOp.getInit())}; - if (failed(initializeLock(deviceModel, lock))) - return WalkResult::interrupt(); - } - return WalkResult::advance(); - }); - if (r.wasInterrupted()) return failure(); - - auto memOps = llvm::to_vector_of(device.getOps()); - llvm::append_range(memOps, device.getOps()); - for (Operation *memOp : memOps) { - TileOp t = xilinx::AIE::getTileOp(*memOp); - TileLoc tileLoc = {t.getCol(), t.getRow()}; - if (deviceModel.isShimNOCorPLTile(tileLoc.col, tileLoc.row)) { - continue; - } - - // handle DMA ops separately - for (Block &block : memOp->getRegion(0)) { - if (block.getOps().empty()) continue; - if (failed(configureLocksAndBd(block, tileLoc, deviceModel))) - return failure(); - } - - for (Block &block : memOp->getRegion(0)) { - for (auto op : block.getOps()) { - DMABDOp bd = *op.getDest()->getOps().begin(); - int chNum = op.getChannelIndex(); - auto channelDir = static_cast(op.getChannelDir()); - bool issueToken = tileLoc.row == 0 && channelDir == DMAChannelDir::MM2S; - bool setChannelEnable = true; - if (failed(configurePushToBdQueue( - deviceModel, tileLoc, chNum, channelDir, bd.getBdId().value(), - op.getRepeatCount(), issueToken, setChannelEnable))) - return failure(); - } - } - } - - // StreamSwitch (switchbox) configuration - for (auto switchboxOp : device.getOps()) { - TileOp t = xilinx::AIE::getTileOp(*switchboxOp.getOperation()); - TileLoc tileLoc = {t.getCol(), t.getRow()}; - std::vector connects; - for (auto connectOp : switchboxOp.getOps()) { - connects.emplace_back( - Port{connectOp.getSourceBundle(), connectOp.getSourceChannel()}, - Port{connectOp.getDestBundle(), connectOp.getDestChannel()}, - Connect::Interconnect::SWB, tileLoc.col, tileLoc.row); - } - if (failed(configureStreamSwitch(deviceModel, tileLoc, connects))) { - return failure(); - } - - Block &b = switchboxOp.getConnections().front(); - for (auto masterSetOp : b.getOps()) { - std::vector amSels; - for (auto val : masterSetOp.getAmsels()) { - AMSelOp amsel = cast(val.getDefiningOp()); - amSels.push_back({static_cast(amsel.getArbiterID()), - static_cast(amsel.getMsel())}); - } - if (failed(configureSwitchPacketMasters( - deviceModel, tileLoc, masterSetOp.getDestBundle(), - masterSetOp.getDestChannel(), amSels, - masterSetOp->hasAttr("keep_pkt_header")))) - return failure(); - } - - for (auto packetRulesOp : b.getOps()) { - int slot = 0; - Block &block = packetRulesOp.getRules().front(); - for (auto packetRuleOp : block.getOps()) { - AMSelOp amselOp = - cast(packetRuleOp.getAmsel().getDefiningOp()); - if (failed(configureSwitchPacketSlaves( - deviceModel, tileLoc, packetRulesOp.getSourceBundle(), - packetRulesOp.getSourceChannel(), - AMSel{amselOp.getArbiterID(), amselOp.getMsel()}, - packetRuleOp.getValue(), packetRuleOp.getMask(), slot))) - return failure(); - slot++; - } - } - } - - for (auto muxOp : device.getOps()) { - TileOp t = xilinx::AIE::getTileOp(*muxOp.getOperation()); - TileLoc tileLoc = {t.getCol(), t.getRow()}; - std::vector connects; - for (auto connectOp : muxOp.getOps()) { - connects.emplace_back( - Port{connectOp.getSourceBundle(), connectOp.getSourceChannel()}, - Port{connectOp.getDestBundle(), connectOp.getDestChannel()}, - Connect::Interconnect::SHIMMUX, tileLoc.col, tileLoc.row); - } - if (failed(configureStreamSwitch(deviceModel, tileLoc, connects))) { - return failure(); - } - } - - return success(); -} - -LogicalResult addCoreEnableToCDO(const AMDAIEDeviceModel &deviceModel, - DeviceOp &device) { - // Start execution of all the cores. - for (auto tileOp : device.getOps()) { - TileLoc tileLoc = {tileOp.getCol(), tileOp.getRow()}; - if (auto coreOp = getCoreOp(tileOp); - coreOp && failed(coreEnable(deviceModel, tileLoc))) - return failure(); - } - return success(); -} - LogicalResult generateCDOBinariesSeparately( const AMDAIEDeviceModel &deviceModel, const Path &workDirPath, DeviceOp &device, bool aieSim, bool enableCores) { if (failed(generateCDOBinary(workDirPath / "aie_cdo_elfs.bin", [&deviceModel, &device, &workDirPath, &aieSim] { - return addAieElfsToCDO(deviceModel, device, - workDirPath, aieSim); + return addAllAieElfs(deviceModel, device, + workDirPath, aieSim); }))) return failure(); if (failed(generateCDOBinary(workDirPath / "aie_cdo_init.bin", [&deviceModel, &device] { - return addInitConfigToCDO(deviceModel, device); + return addInitConfig(deviceModel, device); }))) return failure(); if (enableCores && !device.getOps().empty() && failed(generateCDOBinary(workDirPath / "aie_cdo_enable.bin", [&deviceModel, &device] { - return addCoreEnableToCDO(deviceModel, device); + return addAllCoreEnable(deviceModel, device); }))) return failure(); diff --git a/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/CMakeLists.txt b/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/CMakeLists.txt index 63a38950a..6da73d9fa 100644 --- a/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/CMakeLists.txt +++ b/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/CMakeLists.txt @@ -6,6 +6,17 @@ iree_add_all_subdirs() +iree_cc_library( + NAME + AMDAIERT + HDRS + "AMDAIERT.h" + SRCS + "AMDAIERT.cpp" + DEPS + iree-amd-aie::aie_runtime::iree_aie_runtime_static +) + iree_cc_library( NAME AIETargets @@ -15,6 +26,7 @@ iree_cc_library( "AMDAIETargetLdScript.cpp" "XCLBinGen.cpp" DEPS + ::AMDAIERT iree-amd-aie::aie_runtime::iree_aie_runtime_static iree::target::amd-aie::Transforms iree-aie-bootgen @@ -33,6 +45,7 @@ iree_cc_library( "AIETarget.cpp" DEPS ::AIETargets + ::AMDAIERT iree-amd-aie::schemas::xrt_executable_def_c_fbs iree-amd-aie::schemas::pdi_executable_def_c_fbs iree::base::internal::flatcc::building