Skip to content
Open
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
9 changes: 5 additions & 4 deletions profile/plugin/aie_dtrace/aie_dtrace_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "xdp/profile/device/utility.h"
#include "xdp/profile/device/xdp_base_device.h"
#include "xdp/profile/plugin/vp_base/info.h"
#include "xdp/profile/plugin/vp_base/profiling_runtime_config.h"

#if defined(XDP_VE2_BUILD)
#include "xdp/profile/plugin/aie_dtrace/ve2/aie_dtrace_ve2.h"
Expand Down Expand Up @@ -65,7 +66,7 @@ namespace xdp {
{
xrt_core::message::send(severity_level::info, "XRT", "AIE dtrace: update device.");

if (!xrt_core::config::get_aie_dtrace())
if (!profiling_runtime_config::aie_dtrace_enabled())
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jyothees99 We want to keep supporting enabling dtrace with xrt.ini for non-VAIML flow. So, we need to include the xrt ini config check too.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@IshitaGhosh I am using xrt.ini value also to determine aie_dtrace_enabled. It's OR of xrt.ini and profile_runtime_config.

return;

if (!handle)
Expand Down Expand Up @@ -189,7 +190,7 @@ namespace xdp {
void AieDtracePlugin::runConstructorHook(void* run_impl_ptr, void* hwctx, uint32_t run_uid,
const std::string& kernel_name, void* elf_handle)
{
if (!xrt_core::config::get_aie_dtrace())
if (!profiling_runtime_config::aie_dtrace_enabled())
return;

auto itr = handleToAIEDtraceImpl.find(hwctx);
Expand All @@ -204,7 +205,7 @@ namespace xdp {
void AieDtracePlugin::runStartHook(void* run_impl_ptr, void* hwctx, uint32_t run_uid,
const std::string& kernel_name)
{
if (!xrt_core::config::get_aie_dtrace())
if (!profiling_runtime_config::aie_dtrace_enabled())
return;

(void)run_impl_ptr;
Expand All @@ -216,7 +217,7 @@ namespace xdp {
void AieDtracePlugin::runWaitHook(void* run_impl_ptr, void* hwctx, uint32_t run_uid,
const std::string& kernel_name, int ert_cmd_state)
{
if (!xrt_core::config::get_aie_dtrace())
if (!profiling_runtime_config::aie_dtrace_enabled())
return;

(void)run_impl_ptr;
Expand Down
3 changes: 2 additions & 1 deletion profile/plugin/aie_dtrace/ve2/aie_dtrace_ve2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "xdp/profile/database/static_info/aie_util.h"
#include "xdp/profile/database/static_info/aie_constructs.h"
#include "xdp/profile/database/static_info/pl_constructs.h"
#include "xdp/profile/plugin/vp_base/profiling_runtime_config.h"

#include <boost/algorithm/string.hpp>
#include <cmath>
Expand Down Expand Up @@ -226,7 +227,7 @@ namespace xdp {
const std::string& kernel_name,
void* elf_handle)
{
if (!xrt_core::config::get_aie_dtrace())
if (!profiling_runtime_config::aie_dtrace_enabled())
return;

auto ctx = xrt_core::hw_context_int::create_hw_context_from_implementation(hwctx);
Expand Down
54 changes: 49 additions & 5 deletions profile/plugin/aie_profile/aie_profile_metadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "core/common/device.h"
#include "core/common/message.h"
#include "xdp/profile/database/database.h"
#include "xdp/profile/plugin/vp_base/profiling_runtime_config.h"
#include "xdp/profile/plugin/vp_base/vp_base_plugin.h"
#include "xdp/profile/database/parser/metrics.h"
#include "xdp/profile/database/parser/json_parser.h"
Expand Down Expand Up @@ -179,7 +180,7 @@ namespace xdp {
, m_dtraceBandwidthMode(true)
{
xrt_core::message::send(severity_level::info,
"XRT", "Parsing AIE dtrace metadata (AIE_dtrace_settings).");
"XRT", "Parsing AIE dtrace metadata.");
VPDatabase* db = VPDatabase::Instance();

metadataReader = (db->getStaticInfo()).getAIEmetadataReader(deviceID);
Expand All @@ -195,18 +196,61 @@ namespace xdp {

clockFreqMhz = (db->getStaticInfo()).getClockRateMHz(deviceID, false);

// Polling interval and the "start" control always come from xrt.ini.
pollingInterval = xrt_core::config::get_aie_dtrace_settings_interval_us();

setProfileStartControl(compilerOptions.graph_iterator_event, false, nullptr);

// Metric-set source precedence:
// 1. If Debug.profiling_runtime_config carries a control_instrumentation
// section, it wins. Only interface_tile is wired today; aie_tile and
// mem_tile entries are logged for a follow-up.
// 2. Otherwise fall back to the legacy AIE_dtrace_settings.* xrt.ini
// options.
const bool usingBlob = profiling_runtime_config::has_control_instrumentation();
const auto& ci = profiling_runtime_config::control_instrumentation();

if (usingBlob) {
xrt_core::message::send(severity_level::info, "XRT",
"AIE dtrace: using control_instrumentation from "
"Debug.profiling_runtime_config; AIE_dtrace_settings.* will be ignored "
"for metric sets.");

if (ci.aie_tile.has_value() && !ci.aie_tile->empty()) {
xrt_core::message::send(severity_level::info, "XRT",
"AIE dtrace: core tile metric '" + *ci.aie_tile
+ "' from profiling_runtime_config will be supported in a follow-up.");
}
if (ci.mem_tile.has_value() && !ci.mem_tile->empty()) {
xrt_core::message::send(severity_level::info, "XRT",
"AIE dtrace: mem tile metric '" + *ci.mem_tile
+ "' from profiling_runtime_config will be supported in a follow-up.");
}
}

for (int module = 0; module < NUM_MODULES; ++module) {
if (moduleTypes[module] != module_type::shim)
continue;

auto metricsSettings =
getSettingsVector(xrt_core::config::get_aie_dtrace_settings_tile_based_interface_tile_metrics());
auto graphMetricsSettings =
getSettingsVector(xrt_core::config::get_aie_dtrace_settings_graph_based_interface_tile_metrics());
std::vector<std::string> metricsSettings;
std::vector<std::string> graphMetricsSettings;

if (usingBlob) {
if (ci.interface_tile.has_value() && !ci.interface_tile->empty()) {
// Blob carries a bare metric name (e.g. "ddr_bandwidth"). Synthesize
// an "all:<metric>" tile-based selection so the existing parser
// applies it to every interface tile.
metricsSettings = getSettingsVector("all:" + *ci.interface_tile);
}
// If interface_tile is unset/empty in the blob, the blob wins and
// leaves shim tiles unconfigured (no xrt.ini fallback for this knob).
}
else {
metricsSettings =
getSettingsVector(xrt_core::config::get_aie_dtrace_settings_tile_based_interface_tile_metrics());
graphMetricsSettings =
getSettingsVector(xrt_core::config::get_aie_dtrace_settings_graph_based_interface_tile_metrics());
}

getConfigMetricsForInterfaceTiles(module, metricsSettings, graphMetricsSettings);
}
Expand Down
156 changes: 156 additions & 0 deletions profile/plugin/vp_base/profiling_runtime_config.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved

#define XDP_CORE_SOURCE

#include <set>
#include <sstream>
#include <string>

#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>

#include "core/common/config_reader.h"
#include "core/common/message.h"

#include "xdp/profile/plugin/vp_base/profiling_runtime_config.h"

namespace xdp::profiling_runtime_config {

using severity_level = xrt_core::message::severity_level;
namespace pt = boost::property_tree;

namespace {

struct parsed_blob_t {
bool is_set = false;
bool has_ci = false;
control_instrumentation_t ci{};
};

// These helpers are only called from inside get_parsed()'s cached static
// initializer, so every message they emit fires at most once per process.
void
warn(const std::string& msg)
{
xrt_core::message::send(severity_level::warning, "XRT", msg);
}

void
info(const std::string& msg)
{
xrt_core::message::send(severity_level::info, "XRT", msg);
}

// Parse the control_instrumentation subtree: copy known string keys into
// the returned struct and warn about any unknown keys.
control_instrumentation_t
parse_control_instrumentation(const pt::ptree& ci_tree)
{
static const std::set<std::string> known_keys{
"aie_tile", "mem_tile", "interface_tile"
};

control_instrumentation_t ci;

for (const auto& kv : ci_tree) {
const auto& key = kv.first;
const auto value = kv.second.get_value<std::string>("");

if (key == "aie_tile") {
ci.aie_tile = value;
if (!value.empty())
info("profiling_runtime_config.control_instrumentation.aie_tile='" + value + "'");
}
else if (key == "mem_tile") {
ci.mem_tile = value;
if (!value.empty())
info("profiling_runtime_config.control_instrumentation.mem_tile='" + value + "'");
}
else if (key == "interface_tile") {
ci.interface_tile = value;
if (!value.empty())
info("profiling_runtime_config.control_instrumentation.interface_tile='" + value + "'");
}
else {
std::stringstream msg;
msg << "Unknown key 'profiling_runtime_config.control_instrumentation."
<< key << "' ignored. Supported keys:";
const char* sep = " ";
for (const auto& k : known_keys) {
msg << sep << k;
sep = ", ";
}
warn(msg.str());
}
}

return ci;
}

// Parse the root blob exactly once.
const parsed_blob_t&
get_parsed()
{
static const parsed_blob_t cached = [] {
parsed_blob_t out;

const std::string raw = xrt_core::config::get_profiling_runtime_config();
if (raw.empty())
return out;

try {
pt::ptree root;
std::istringstream is(raw);
pt::read_json(is, root);

out.is_set = true;

if (const auto ci_opt = root.get_child_optional("control_instrumentation")) {
out.ci = parse_control_instrumentation(*ci_opt);
out.has_ci = out.ci.aie_tile.has_value()
|| out.ci.mem_tile.has_value()
|| out.ci.interface_tile.has_value();
}
}
catch (const std::exception& ex) {
warn(std::string("Failed to parse Debug.profiling_runtime_config "
"as JSON; ignoring runtime config. Details: ")
+ ex.what());
return parsed_blob_t{};
}

return out;
}();

return cached;
}

} // anonymous namespace

bool
is_set()
{
return get_parsed().is_set;
}

bool
has_control_instrumentation()
{
return get_parsed().has_ci;
}

const control_instrumentation_t&
control_instrumentation()
{
return get_parsed().ci;
}

bool
aie_dtrace_enabled()
{
static bool value = xrt_core::config::get_aie_dtrace() || has_control_instrumentation();
return value;
}

} // namespace xdp::profiling_runtime_config
51 changes: 51 additions & 0 deletions profile/plugin/vp_base/profiling_runtime_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved

#ifndef PROFILING_RUNTIME_CONFIG_DOT_H
#define PROFILING_RUNTIME_CONFIG_DOT_H

#include <optional>
#include <string>

#include "xdp/config.h"

// Parser for the XRT INI option Debug.profiling_runtime_config which holds
// an inline JSON blob describing XDP runtime configuration. Only the
// control_instrumentation section is consumed by this change; other top-level
// keys (event_trace, etc.) are accepted but ignored and may be wired up in a
// follow-up.
//
// The parser lives on the XDP side (xdp_core) so this code can evolve quickly
// without churning the stable xrt_coreutil interface. core/common/xdp/profile.cpp
// keeps a minimal independent probe for the load-time gate.
//
// Example blob:
// {"control_instrumentation":{"aie_tile":"func_stalls","mem_tile":"","interface_tile":"ddr_bandwidth"},"event_trace":{}}

namespace xdp::profiling_runtime_config {

struct control_instrumentation_t {
std::optional<std::string> aie_tile; // maps to "core" module internally
std::optional<std::string> mem_tile; // maps to "mem_tile" module internally
std::optional<std::string> interface_tile; // maps to "shim" module internally
};

// True when the xrt.ini value is non-empty and parsed successfully.
XDP_CORE_EXPORT bool is_set();

// True when is_set() and the blob contained a control_instrumentation object
// with at least one recognized key (aie_tile / mem_tile / interface_tile).
XDP_CORE_EXPORT bool has_control_instrumentation();

// Returns the cached control_instrumentation view. Safe to call even when
// has_control_instrumentation() is false (all members will be empty).
XDP_CORE_EXPORT const control_instrumentation_t& control_instrumentation();

// True if aie_dtrace should be active: either Debug.aie_dtrace is set in
// xrt.ini, or the runtime config blob carries a control_instrumentation
// section. Intended as the single gate for the aie_dtrace plugin guards.
XDP_CORE_EXPORT bool aie_dtrace_enabled();

} // namespace xdp::profiling_runtime_config

#endif
Loading