Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions profile/plugin/aie_halt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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})

Expand Down
130 changes: 125 additions & 5 deletions profile/plugin/aie_halt/ve2/aie_halt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,22 @@

#define XDP_PLUGIN_SOURCE

#include <sstream>

#include <boost/property_tree/ptree.hpp>

#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"

Expand All @@ -34,21 +40,135 @@ namespace xdp {
AIEHaltVE2Impl::AIEHaltVE2Impl(VPDatabase*dB)
: AIEHaltImpl(dB)
{
tranxHandler = std::make_unique<xdp::aie::VE2Transaction>();
}

void AIEHaltVE2Impl::updateDevice(void* hwCtxImpl)
{
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<uint64_t>("start_col");
numCols = e.second.get<uint64_t>("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<uint8_t>(startCol); c < static_cast<uint8_t>(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 {
Expand All @@ -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();
}
Expand Down
23 changes: 22 additions & 1 deletion profile/plugin/aie_halt/ve2/aie_halt.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,19 @@
#ifndef XDP_PLUGIN_AIE_HALT_VE2_IMPL_H
#define XDP_PLUGIN_AIE_HALT_VE2_IMPL_H

#include <memory>

#include "xdp/config.h"
#include "xdp/profile/plugin/aie_halt/aie_halt_impl.h"

#include "xrt/xrt_hw_context.h"

extern "C" {
#include <aie_codegen.h>
#include <aie_codegen_inc/xaie2psgbl_params.h>
#include "xdp/profile/device/common/ve2/ve2_transaction.h"
}

namespace xdp {

class AIEHaltVE2Impl : public AIEHaltImpl
Expand All @@ -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<xdp::aie::VE2Transaction> tranxHandler;
};

}

#endif
#endif
Loading