diff --git a/profile/plugin/aie_halt/CMakeLists.txt b/profile/plugin/aie_halt/CMakeLists.txt index d4392771..89f0a639 100644 --- a/profile/plugin/aie_halt/CMakeLists.txt +++ b/profile/plugin/aie_halt/CMakeLists.txt @@ -42,14 +42,28 @@ if (XDP_CLIENT_BUILD_CMAKE STREQUAL "yes") ) elseif (XDP_VE2_BUILD_CMAKE STREQUAL "yes") - add_library(xdp_aie_halt_plugin SHARED ${XDP_AIE_HALT_PLUGIN_FILES}) + # For ve2 the halt control code is generated on the fly using aie-codegen + # (with a prebuilt elf loaded as a fallback), so the aie-codegen library and + # the shared device/common transaction helpers are required. Note the + # XDP_DEVICE_COMMON_FILES glob does not recurse into device/common/ve2, so + # ve2_transaction.cpp must be added explicitly. + add_library(xdp_aie_halt_plugin SHARED ${XDP_AIE_HALT_PLUGIN_FILES} ${XDP_DEVICE_COMMON_FILES} + "${PROFILE_DIR}/device/common/ve2/ve2_transaction.cpp") add_dependencies(xdp_aie_halt_plugin xdp_core xrt_coreutil) - - # Note: For ve2, a prebuilt elf is loaded so aie-codegen library is not needed - #target_include_directories(xdp_aie_halt_plugin PRIVATE ${AIE_CODEGEN_DIR}/include) - #target_link_libraries(xdp_aie_halt_plugin PRIVATE xdp_core xrt_coreutil aie_codegen) - target_link_libraries(xdp_aie_halt_plugin PRIVATE xdp_core xrt_coreutil) - target_compile_definitions(xdp_aie_halt_plugin PRIVATE XDP_VE2_BUILD=1 XDP_USE_AIE_CODEGEN=1) + + target_link_libraries(xdp_aie_halt_plugin PRIVATE xdp_core xrt_coreutil aie_codegen aiebu_library_objects) + # -Bsymbolic: ensures XAie_* calls within this plugin resolve to the + # statically-linked aie_codegen rather than being interposed by the + # system libxaiengine.so.3 (required by libxrt_core.so.2) + target_link_options(xdp_aie_halt_plugin PRIVATE -Wl,-Bsymbolic) + target_compile_definitions(xdp_aie_halt_plugin PRIVATE XDP_VE2_BUILD=1 XDP_USE_AIE_CODEGEN=1 FAL_LINUX="on") + target_include_directories(xdp_aie_halt_plugin PRIVATE + ${CMAKE_SOURCE_DIR}/src + ${AIEFAL_DIR} + ${AIEBU_SOURCE_DIR}/src/cpp/include + ${AIE_CODEGEN_DIR}/include + ${XRT_SOURCE_DIR}/runtime_src/core/common/elf + ) set_target_properties(xdp_aie_halt_plugin PROPERTIES VERSION ${XRT_VERSION_STRING} SOVERSION ${XRT_SOVERSION}) diff --git a/profile/plugin/aie_halt/ve2/aie_halt.cpp b/profile/plugin/aie_halt/ve2/aie_halt.cpp index 183b005e..363c6a80 100644 --- a/profile/plugin/aie_halt/ve2/aie_halt.cpp +++ b/profile/plugin/aie_halt/ve2/aie_halt.cpp @@ -16,16 +16,22 @@ #define XDP_PLUGIN_SOURCE +#include + +#include + #include "core/common/api/hw_context_int.h" +#include "core/common/api/xclbin_int.h" #include "core/common/device.h" #include "core/common/message.h" +#include "core/include/xclbin.h" #include "core/include/xrt/experimental/xrt_elf.h" #include "core/include/xrt/experimental/xrt_ext.h" #include "core/include/xrt/experimental/xrt_module.h" - #include "core/include/xrt/xrt_kernel.h" +#include "xdp/profile/database/static_info/aie_util.h" #include "xdp/profile/plugin/aie_halt/ve2/aie_halt.h" #include "xdp/profile/plugin/vp_base/utility.h" @@ -34,6 +40,7 @@ namespace xdp { AIEHaltVE2Impl::AIEHaltVE2Impl(VPDatabase*dB) : AIEHaltImpl(dB) { + tranxHandler = std::make_unique(); } void AIEHaltVE2Impl::updateDevice(void* hwCtxImpl) @@ -41,14 +48,127 @@ namespace xdp { xrt_core::message::send(xrt_core::message::severity_level::debug, "XRT", "In AIEHaltVE2Impl::updateDevice"); + xrt::hw_context hwContext = + xrt_core::hw_context_int::create_hw_context_from_implementation(hwCtxImpl); + + // Primary path: generate the halt control code on the fly using aie-codegen. + if (generateHaltControlCode(hwCtxImpl, hwContext)) + return; + + // Fallback path: load a prebuilt control code ELF from disk. + xrt_core::message::send(xrt_core::message::severity_level::debug, "XRT", + "Could not generate AIE Halt control code. Falling back to prebuilt control code ELF."); + loadHaltElf(hwContext); + } + + bool AIEHaltVE2Impl::generateHaltControlCode(void* hwCtxImpl, xrt::hw_context hwContext) + { + using severity_level = xrt_core::message::severity_level; + + // Get the xclbin via the hw context uuid (device->get_xclbin_uuid() reads + // the sysfs xclbinid file, which is absent on the XDNA path). AIE info is + // in AIE_TRACE_METADATA, falling back to AIE_METADATA. + xdp::aie::driver_config meta_config; + try { + auto device = xrt_core::hw_context_int::get_core_device(hwContext); + xrt::xclbin xrtXclbin = device->get_xclbin(hwContext.get_xclbin_uuid()); + + auto data = xrt_core::xclbin_int::get_axlf_section(xrtXclbin, AIE_TRACE_METADATA); + if (!data.first || !data.second) + data = xrt_core::xclbin_int::get_axlf_section(xrtXclbin, AIE_METADATA); + + if (!data.first || !data.second) { + xrt_core::message::send(severity_level::warning, "XRT", "Empty AIE Metadata in xclbin"); + return false; + } + + boost::property_tree::ptree aieMetadata; + auto metadataReader = xdp::aie::readAIEMetadata(data.first, data.second, aieMetadata); + if (!metadataReader) { + xrt_core::message::send(severity_level::warning, "XRT", "Failed to parse AIE Metadata from xclbin."); + return false; + } + meta_config = metadataReader->getDriverConfig(); + } catch (const std::exception& e) { + std::string msg("AIE Metadata could not be read/processed from xclbin: "); + msg += e.what(); + xrt_core::message::send(severity_level::warning, "XRT", msg); + return false; + } + + XAie_Config cfg { + meta_config.hw_gen, + meta_config.base_address, + meta_config.column_shift, + meta_config.row_shift, + meta_config.num_rows, + meta_config.num_columns, + meta_config.shim_row, + meta_config.mem_row_start, + meta_config.mem_num_rows, + meta_config.aie_tile_row_start, + meta_config.aie_tile_num_rows, + {0} // PartProp + }; + + auto RC = XAie_CfgInitialize(&aieDevInst, &cfg); + if (RC != XAIE_OK) { + xrt_core::message::send(severity_level::warning, "XRT", "AIE Driver Initialization Failed."); + return false; + } + + uint64_t startCol = 0, numCols = 0; + boost::property_tree::ptree aiePartitionPt = xdp::aie::getAIEPartitionInfo(hwCtxImpl); + for (const auto& e : aiePartitionPt) { + startCol = e.second.get("start_col"); + numCols = e.second.get("num_cols"); + // Currently, assuming only one Hw Context is alive at a time + break; + } + + std::stringstream msg; + msg << "Set AIE Core breakpoint at Lock Acquire Req Instr, Start col " + << startCol << ", Num col " << numCols; + xrt_core::message::send(severity_level::info, "XRT", msg.str()); + + // Record driver calls into the control code ASM. + if (!tranxHandler->initializeTransaction(&aieDevInst, "AieHalt")) { + xrt_core::message::send(severity_level::warning, "XRT", "AIE Halt transaction initialization failed."); + return false; + } + + // Halt each AIE core on the Lock Acquire Request instruction (event 0x2C). + constexpr uint32_t AIE_EVENT_INSTR_LOCK_ACQ_REQ = 0x2C; + uint32_t dbg_ctrl_1_reg = + AIE_EVENT_INSTR_LOCK_ACQ_REQ << XAIE2PSGBL_CORE_MODULE_DEBUG_CONTROL1_DEBUG_HALT_CORE_EVENT0_LSB; + + for (uint8_t c = static_cast(startCol); c < static_cast(startCol + numCols); c++) { + for (uint8_t r = meta_config.aie_tile_row_start; r < meta_config.num_rows; r++) { + auto tileOffset = XAie_GetTileAddr(&aieDevInst, r, c); + XAie_Write32(&aieDevInst, tileOffset + XAIE2PSGBL_CORE_MODULE_DEBUG_CONTROL1, dbg_ctrl_1_reg); + } + } + + // Assemble the recorded ASM into an ELF and run it on XDP_KERNEL. + if (!tranxHandler->submitTransaction(&aieDevInst, hwContext)) { + xrt_core::message::send(severity_level::warning, "XRT", + "Failed to generate/submit AIE Halt control code."); + return false; + } + + xrt_core::message::send(severity_level::info, "XRT", + "Successfully generated and scheduled AIE Halt control code."); + return true; + } + + void AIEHaltVE2Impl::loadHaltElf(xrt::hw_context hwContext) + { std::string inputCtrlCode = xrt_core::config::get_aie_halt_settings_control_code(); if (inputCtrlCode.empty()) { xrt_core::message::send(xrt_core::message::severity_level::debug, "XRT", "No input control code file for AIE Halt provided. Defaulting to \"aieHalt4x4.elf\"."); inputCtrlCode = "aieHalt4x4.elf"; } - - xrt::hw_context hwContext = xrt_core::hw_context_int::create_hw_context_from_implementation(hwCtxImpl); xrt::elf haltElf; try { @@ -70,12 +190,12 @@ namespace xdp { } xrt_core::message::send(xrt_core::message::severity_level::debug, "XRT", - "In AIEHaltVE2Impl New Kernel Object for XDP_KERNEL created for running control code Elf"); + "In AIEHaltVE2Impl New Kernel Object for XDP_KERNEL created for running control code Elf"); xrt::run rn{krnl}; rn.start(); xrt_core::message::send(xrt_core::message::severity_level::debug, "XRT", - "In AIEHaltVE2Impl run start, going to wait"); + "In AIEHaltVE2Impl run start, going to wait"); rn.wait2(); } diff --git a/profile/plugin/aie_halt/ve2/aie_halt.h b/profile/plugin/aie_halt/ve2/aie_halt.h index cdd00792..2fd4eea2 100644 --- a/profile/plugin/aie_halt/ve2/aie_halt.h +++ b/profile/plugin/aie_halt/ve2/aie_halt.h @@ -17,9 +17,19 @@ #ifndef XDP_PLUGIN_AIE_HALT_VE2_IMPL_H #define XDP_PLUGIN_AIE_HALT_VE2_IMPL_H +#include + #include "xdp/config.h" #include "xdp/profile/plugin/aie_halt/aie_halt_impl.h" +#include "xrt/xrt_hw_context.h" + +extern "C" { +#include +#include +#include "xdp/profile/device/common/ve2/ve2_transaction.h" +} + namespace xdp { class AIEHaltVE2Impl : public AIEHaltImpl @@ -38,8 +48,19 @@ namespace xdp { void updateDevice(void* hwCtxImpl) override; void finishflushDevice(void* hwCtxImpl) override; + + private: + // Primary path: generate the halt control code on the fly via aie-codegen. + // Returns true if it was generated and scheduled successfully. + bool generateHaltControlCode(void* hwCtxImpl, xrt::hw_context hwContext); + + // Fallback path: load and run a prebuilt control code ELF from disk. + void loadHaltElf(xrt::hw_context hwContext); + + XAie_DevInst aieDevInst = {0}; + std::unique_ptr tranxHandler; }; } -#endif \ No newline at end of file +#endif