diff --git a/src/runtime_src/core/common/api/kernel_int.h b/src/runtime_src/core/common/api/kernel_int.h index e69f414d857..31d67d83a85 100644 --- a/src/runtime_src/core/common/api/kernel_int.h +++ b/src/runtime_src/core/common/api/kernel_int.h @@ -124,10 +124,14 @@ get_kernel_from_impl(const xrt::kernel_impl* kernel_impl); xrt::run get_run_from_impl(const xrt::run_impl*); -// Fill XDP kernel data from a run_impl pointer for profiling hooks +// Fill XDP kernel data from a run_impl pointer for profiling hooks. +// include_state controls whether run_impl->state() is queried; that polls the +// command and is only valid after submission, so callers that run before the +// command is submitted (run_constructor/run_start hooks) must leave it false. XRT_CORE_COMMON_EXPORT void -get_xdp_kernel_data(const xrt::run_impl* run_impl, xrt_core::xdp::xrt_kernel_data* data); +get_xdp_kernel_data(const xrt::run_impl* run_impl, xrt_core::xdp::xrt_kernel_data* data, + bool include_state = false); // Set dtrace control file on a run_impl handle // This is used by XDP profiling to set the CT file without requiring xrt::run diff --git a/src/runtime_src/core/common/api/xrt_kernel.cpp b/src/runtime_src/core/common/api/xrt_kernel.cpp index 0457de53e89..8dc81381c8a 100644 --- a/src/runtime_src/core/common/api/xrt_kernel.cpp +++ b/src/runtime_src/core/common/api/xrt_kernel.cpp @@ -4580,14 +4580,20 @@ get_run_from_impl(const xrt::run_impl* run_impl) } void -get_xdp_kernel_data(const xrt::run_impl* run_impl, xrt_core::xdp::xrt_kernel_data* data) +get_xdp_kernel_data(const xrt::run_impl* run_impl, xrt_core::xdp::xrt_kernel_data* data, + bool include_state) { auto kernel = run_impl->get_kernel(); data->uid = run_impl->get_uid(); data->name = kernel->get_name(); data->hwctx = kernel->get_hw_context(); data->mod = kernel->get_module(); - data->ert_state = static_cast(run_impl->state()); + // run_impl->state() polls the command's ERT packet. That is only valid once + // the command has been submitted; calling it earlier (e.g. from the + // run_constructor / run_start hooks, which fire before submission) throws + // "Cannot poll a command that has not been submitted". Only the run_wait + // hook actually consumes ert_state, so query it only when explicitly asked. + data->ert_state = include_state ? static_cast(run_impl->state()) : 0; } void diff --git a/src/runtime_src/core/common/xdp/profile.cpp b/src/runtime_src/core/common/xdp/profile.cpp index f1600cecc5e..d259bcdd772 100644 --- a/src/runtime_src/core/common/xdp/profile.cpp +++ b/src/runtime_src/core/common/xdp/profile.cpp @@ -10,16 +10,11 @@ #include "core/common/dlfcn.h" #include "core/common/module_loader.h" #include "core/common/message.h" +#include "core/common/utils.h" #include "core/include/xrt/xrt_kernel.h" -#include #include #include -#include - -#ifdef _WIN32 -#pragma warning( disable : 4996 ) /* Disable warning for getenv */ -#endif // An anonymous namespace to hold a common set of blank functions // for all modules that don't require specialization and the common @@ -64,8 +59,7 @@ namespace { #if !defined(XDP_CLIENT_BUILD) && !defined(XDP_VE2_BUILD) static bool is_hw_emulation() { - static auto xem = std::getenv("XCL_EMULATION_MODE"); - static bool hwem = xem ? (std::strcmp(xem, "hw_emu") == 0) : false; + static bool hwem = (xrt_core::utils::getenv("XCL_EMULATION_MODE") == "hw_emu"); return hwem; } #endif @@ -79,7 +73,7 @@ namespace xrt_core::xdp::core { void load_core() { - if (std::getenv("AMD_XDP_NPU3")) { + if (xrt_core::utils::is_env("AMD_XDP_NPU3")) { static xrt_core::sdk_loader xdp_core_loader("xdp_core_npu3", register_callbacks_empty, @@ -114,12 +108,12 @@ load() { #if defined(XDP_CLIENT_BUILD) && defined(_WIN32) static xrt_core::sdk_loader - xdp_aie_loader(std::getenv("AMD_XDP_NPU3") ? "xdp_aie_profile_plugin_npu3" : "xdp_aie_profile_plugin", + xdp_aie_loader(xrt_core::utils::is_env("AMD_XDP_NPU3") ? "xdp_aie_profile_plugin_npu3" : "xdp_aie_profile_plugin", register_callbacks, warning_callbacks_empty); #else static xrt_core::module_loader - xdp_aie_loader(std::getenv("AMD_XDP_NPU3") ? "xdp_aie_profile_plugin_npu3" : "xdp_aie_profile_plugin", + xdp_aie_loader(xrt_core::utils::is_env("AMD_XDP_NPU3") ? "xdp_aie_profile_plugin_npu3" : "xdp_aie_profile_plugin", register_callbacks, warning_callbacks_empty); #endif @@ -185,7 +179,17 @@ load_xdna() void load() { - load_xdna(); +#if defined(XDP_CLIENT_BUILD) && defined(_WIN32) + static xrt_core::sdk_loader + xdp_aie_dtrace_loader(xrt_core::utils::is_env("AMD_XDP_NPU3") ? "xdp_aie_dtrace_plugin_npu3" : "xdp_aie_dtrace_plugin", + register_callbacks, + warning_callbacks_empty); +#else + static xrt_core::module_loader + xdp_aie_dtrace_loader(xrt_core::utils::is_env("AMD_XDP_NPU3") ? "xdp_aie_dtrace_plugin_npu3" : "xdp_aie_dtrace_plugin", + register_callbacks, + warning_callbacks_empty); +#endif } void @@ -205,7 +209,14 @@ end_poll(void* handle) void run_constructor(xrt::run_impl* run_impl) { - if (run_constructor_cb) { + if (!run_constructor_cb) + return; + + // The dtrace run hooks are best-effort profiling instrumentation. They must + // never affect the run lifecycle: an exception escaping here would propagate + // out of the run_impl constructor and corrupt the caller's run object (e.g. + // leaving FlexMLRT polling a command that was never submitted). + try { xrt_kernel_data data{}; xrt_core::kernel_int::get_xdp_kernel_data(run_impl, &data); auto elf_hdl = data.mod ? xrt_core::module_int::get_elf_handle(data.mod) : nullptr; @@ -215,31 +226,63 @@ run_constructor(xrt::run_impl* run_impl) data.name.c_str(), elf_hdl.get()); } + catch (const std::exception& e) { + xrt_core::message::send(xrt_core::message::severity_level::debug, "XRT", + std::string{"AIE dtrace run_constructor hook failed (ignored): "} + e.what()); + } + catch (...) { + xrt_core::message::send(xrt_core::message::severity_level::debug, "XRT", + "AIE dtrace run_constructor hook failed (ignored): unknown exception"); + } } void run_start(const xrt::run_impl* run_impl) { - if (run_start_cb) { + if (!run_start_cb) + return; + + try { xrt_kernel_data data{}; xrt_core::kernel_int::get_xdp_kernel_data(run_impl, &data); run_start_cb(nullptr, data.hwctx.get_handle().get(), data.uid, data.name.c_str()); } + catch (const std::exception& e) { + xrt_core::message::send(xrt_core::message::severity_level::debug, "XRT", + std::string{"AIE dtrace run_start hook failed (ignored): "} + e.what()); + } + catch (...) { + xrt_core::message::send(xrt_core::message::severity_level::debug, "XRT", + "AIE dtrace run_start hook failed (ignored): unknown exception"); + } } void run_wait(const xrt::run_impl* run_impl) { - if (run_wait_cb) { + if (!run_wait_cb) + return; + + try { xrt_kernel_data data{}; - xrt_core::kernel_int::get_xdp_kernel_data(run_impl, &data); + // run_wait fires after the command has completed, so polling state() here + // is valid and ert_state is the value this hook needs. + xrt_core::kernel_int::get_xdp_kernel_data(run_impl, &data, true); run_wait_cb(nullptr, data.hwctx.get_handle().get(), data.uid, data.name.c_str(), data.ert_state); } + catch (const std::exception& e) { + xrt_core::message::send(xrt_core::message::severity_level::debug, "XRT", + std::string{"AIE dtrace run_wait hook failed (ignored): "} + e.what()); + } + catch (...) { + xrt_core::message::send(xrt_core::message::severity_level::debug, "XRT", + "AIE dtrace run_wait hook failed (ignored): unknown exception"); + } } } // end namespace xrt_core::xdp::aie::dtrace @@ -267,7 +310,7 @@ void load() { static xrt_core::module_loader - xdp_aie_debug_loader(std::getenv("AMD_XDP_NPU3") ? "xdp_aie_debug_plugin_npu3" : "xdp_aie_debug_plugin", + xdp_aie_debug_loader(xrt_core::utils::is_env("AMD_XDP_NPU3") ? "xdp_aie_debug_plugin_npu3" : "xdp_aie_debug_plugin", register_callbacks, warning_callbacks_empty); } @@ -355,7 +398,7 @@ void load() { static xrt_core::module_loader - xdp_ml_timeline_loader(std::getenv("AMD_XDP_NPU3") ? "xdp_ml_timeline_plugin_npu3" : "xdp_ml_timeline_plugin", + xdp_ml_timeline_loader(xrt_core::utils::is_env("AMD_XDP_NPU3") ? "xdp_ml_timeline_plugin_npu3" : "xdp_ml_timeline_plugin", register_callbacks, warning_callbacks_empty); } @@ -443,12 +486,12 @@ load() { #if defined(XDP_CLIENT_BUILD) && defined(_WIN32) static xrt_core::sdk_loader - xdp_aie_trace_loader(std::getenv("AMD_XDP_NPU3") ? "xdp_aie_trace_plugin_npu3" : "xdp_aie_trace_plugin", + xdp_aie_trace_loader(xrt_core::utils::is_env("AMD_XDP_NPU3") ? "xdp_aie_trace_plugin_npu3" : "xdp_aie_trace_plugin", register_callbacks, warning_callbacks_empty); #else static xrt_core::module_loader - xdp_aie_trace_loader(std::getenv("AMD_XDP_NPU3") ? "xdp_aie_trace_plugin_npu3" : "xdp_aie_trace_plugin", + xdp_aie_trace_loader(xrt_core::utils::is_env("AMD_XDP_NPU3") ? "xdp_aie_trace_plugin_npu3" : "xdp_aie_trace_plugin", register_callbacks, warning_callbacks_empty); #endif @@ -502,12 +545,12 @@ load() { #if defined(XDP_CLIENT_BUILD) && defined(_WIN32) static xrt_core::sdk_loader - xdp_aie_halt_loader(std::getenv("AMD_XDP_NPU3") ? "xdp_aie_halt_plugin_npu3" : "xdp_aie_halt_plugin", + xdp_aie_halt_loader(xrt_core::utils::is_env("AMD_XDP_NPU3") ? "xdp_aie_halt_plugin_npu3" : "xdp_aie_halt_plugin", register_callbacks, warning_callbacks_empty); #else static xrt_core::module_loader - xdp_aie_halt_loader(std::getenv("AMD_XDP_NPU3") ? "xdp_aie_halt_plugin_npu3" : "xdp_aie_halt_plugin", + xdp_aie_halt_loader(xrt_core::utils::is_env("AMD_XDP_NPU3") ? "xdp_aie_halt_plugin_npu3" : "xdp_aie_halt_plugin", register_callbacks, warning_callbacks_empty); #endif @@ -687,6 +730,14 @@ update_device(void* handle, bool hw_context_flow) "Failed to setup for AIE Debug. Caught exception ", handle); + load_once_and_update(xrt_core::config::get_aie_dtrace, + xrt_core::xdp::aie::dtrace::load, + xrt_core::xdp::aie::dtrace::update_device, + "Failed to load AIE dtrace library. Caught exception ", + "Failed to setup for AIE dtrace. Caught exception ", + handle, + hw_context_flow); + #elif defined(XDP_VE2_BUILD) load_once_and_update(xrt_core::config::get_ml_timeline, @@ -773,7 +824,7 @@ update_device(void* handle, bool hw_context_flow) load_once_and_update( []() { return xrt_core::config::get_pl_deadlock_detection() && - nullptr == std::getenv("XCL_EMULATION_MODE"); + !xrt_core::utils::is_env("XCL_EMULATION_MODE"); }, xrt_core::xdp::pl_deadlock::load, xrt_core::xdp::pl_deadlock::update_device, @@ -875,7 +926,7 @@ finish_flush_device(void* handle) #else if (xrt_core::config::get_pl_deadlock_detection() - && nullptr == std::getenv("XCL_EMULATION_MODE")) { + && !xrt_core::utils::is_env("XCL_EMULATION_MODE")) { xrt_core::xdp::pl_deadlock::finish_flush_device(handle); } if (xrt_core::config::get_aie_trace())