Skip to content

Commit 51ac67e

Browse files
authored
[XDP] Support subgraphs profiling graphs and kernel and new metadata handling (#9224)
1 parent 670667f commit 51ac67e

File tree

6 files changed

+353
-23
lines changed

6 files changed

+353
-23
lines changed

src/runtime_src/xdp/profile/database/static_info/aie_util.cpp

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "core/common/query_requests.h"
1313
#include "filetypes/aie_control_config_filetype.h"
1414
#include "filetypes/aie_trace_config_filetype.h"
15+
#include "filetypes/aie_trace_config_v3_filetype.h"
1516

1617
#include "core/common/api/xclbin_int.h"
1718
#include "core/include/xrt/detail/xclbin.h"
@@ -62,7 +63,9 @@ namespace xdp::aie {
6263
// aie_trace_config.json format
6364
try {
6465
int majorVersion = aie_project.get("schema_version.major", 1);
65-
if (majorVersion == 2)
66+
if (majorVersion == 3)
67+
return std::make_unique<xdp::aie::AIETraceConfigV3Filetype>(aie_project);
68+
else if (majorVersion == 2)
6669
return std::make_unique<xdp::aie::AIETraceConfigFiletype>(aie_project);
6770
}
6871
catch(...) {
@@ -210,21 +213,6 @@ namespace xdp::aie {
210213
return *rowOffset;
211214
}
212215

213-
/****************************************************************************
214-
* Get all valid graph names from metadata
215-
***************************************************************************/
216-
std::vector<std::string>
217-
getValidGraphs(const boost::property_tree::ptree& aie_meta,
218-
const std::string& root)
219-
{
220-
std::vector<std::string> graphs;
221-
for (auto& graph : aie_meta.get_child(root)) {
222-
std::string graphName = graph.second.get<std::string>("name");
223-
graphs.push_back(graphName);
224-
}
225-
return graphs;
226-
}
227-
228216
/****************************************************************************
229217
* Read AIE metadata from axlf section
230218
***************************************************************************/

src/runtime_src/xdp/profile/database/static_info/aie_util.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,6 @@ namespace xdp::aie {
6161
getAIETileRowOffset(const boost::property_tree::ptree& aie_meta,
6262
const std::string& location);
6363

64-
XDP_CORE_EXPORT
65-
std::vector<std::string>
66-
getValidGraphs(const boost::property_tree::ptree& aie_meta,
67-
const std::string& root);
68-
6964
XDP_CORE_EXPORT
7065
bool isInfoVerbosity();
7166

src/runtime_src/xdp/profile/database/static_info/filetypes/aie_control_config_filetype.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,12 @@ AIEControlConfigFiletype::getPartitionOverlayStartCols() const {
7878
std::vector<std::string>
7979
AIEControlConfigFiletype::getValidGraphs() const
8080
{
81-
return xdp::aie::getValidGraphs(aie_meta, "aie_metadata.graphs");
81+
std::vector<std::string> graphs;
82+
for (auto& graph : aie_meta.get_child("aie_metadata.graphs")) {
83+
auto graphName = graph.second.get<std::string>("name");
84+
graphs.push_back(graphName);
85+
}
86+
return graphs;
8287
}
8388

8489
std::vector<std::string>
Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved
3+
4+
#define XDP_CORE_SOURCE
5+
6+
#include "aie_trace_config_v3_filetype.h"
7+
#include "core/common/message.h"
8+
#include "xdp/profile/database/static_info/aie_util.h"
9+
#include "xdp/profile/plugin/vp_base/utility.h"
10+
11+
#include <boost/algorithm/string.hpp>
12+
#include <boost/property_tree/json_parser.hpp>
13+
#include <boost/property_tree/ptree.hpp>
14+
#include <set>
15+
#include <algorithm>
16+
17+
namespace xdp::aie {
18+
namespace pt = boost::property_tree;
19+
using severity_level = xrt_core::message::severity_level;
20+
21+
AIETraceConfigV3Filetype::AIETraceConfigV3Filetype(boost::property_tree::ptree& aie_project)
22+
: AIETraceConfigFiletype(aie_project) {}
23+
24+
std::vector<std::string>
25+
AIETraceConfigV3Filetype::getValidKernels() const
26+
{
27+
std::vector<std::string> kernels;
28+
29+
// Collect all kernel to tile mappings
30+
auto kernelToTileMapping = aie_meta.get_child_optional("aie_metadata.TileMapping.AIEKernelToTileMapping");
31+
if (!kernelToTileMapping) {
32+
xrt_core::message::send(severity_level::info, "XRT", getMessage("TileMapping.AIEKernelToTileMapping"));
33+
return {};
34+
}
35+
36+
std::set<std::string> uniqueKernels; // Use set to avoid duplicates
37+
38+
for (auto const &mapping : kernelToTileMapping.get()) {
39+
auto functionStr = mapping.second.get<std::string>("function");
40+
if (functionStr.empty())
41+
continue;
42+
43+
// Extract kernel names from function string
44+
std::vector<std::string> names;
45+
boost::split(names, functionStr, boost::is_any_of("."));
46+
47+
// Add individual kernel components
48+
for (const auto& name : names) {
49+
if (!name.empty())
50+
uniqueKernels.insert(name);
51+
}
52+
53+
// Also store the complete function name
54+
uniqueKernels.insert(functionStr);
55+
}
56+
57+
// Convert set to vector
58+
kernels.assign(uniqueKernels.begin(), uniqueKernels.end());
59+
return kernels;
60+
}
61+
62+
std::vector<std::string>
63+
AIETraceConfigV3Filetype::getValidGraphs() const
64+
{
65+
std::vector<std::string> graphs;
66+
67+
// Collect all kernel to tile mappings
68+
auto kernelToTileMapping = aie_meta.get_child_optional("aie_metadata.TileMapping.AIEKernelToTileMapping");
69+
if (!kernelToTileMapping) {
70+
xrt_core::message::send(severity_level::info, "XRT", getMessage("TileMapping.AIEKernelToTileMapping"));
71+
return {};
72+
}
73+
74+
std::set<std::string> uniqueGraphs; // Use set to avoid duplicates
75+
76+
for (auto const &mapping : kernelToTileMapping.get()) {
77+
auto graphStr = mapping.second.get<std::string>("graph");
78+
if (graphStr.empty())
79+
continue;
80+
81+
// Extract subgraph names from complete graph string
82+
std::vector<std::string> names;
83+
boost::split(names, graphStr, boost::is_any_of("."));
84+
85+
// Add individual subgraph components
86+
for (const auto& name : names) {
87+
if (!name.empty())
88+
uniqueGraphs.insert(name);
89+
}
90+
91+
// Add the complete graph name
92+
uniqueGraphs.insert(graphStr);
93+
}
94+
95+
// Convert set to vector
96+
graphs.assign(uniqueGraphs.begin(), uniqueGraphs.end());
97+
return graphs;
98+
}
99+
100+
// Find all AIE or memory tiles associated with a graph and kernel/buffer
101+
// kernel_name = all : all tiles in graph
102+
// kernel_name = <kernel> : only tiles used by that specific kernel
103+
std::vector<tile_type>
104+
AIETraceConfigV3Filetype::getTiles(const std::string& graph_name,
105+
module_type type,
106+
const std::string& kernel_name) const
107+
{
108+
if (type == module_type::mem_tile)
109+
return getMemoryTiles(graph_name, kernel_name);
110+
111+
auto kernelToTileMapping = aie_meta.get_child_optional("aie_metadata.TileMapping.AIEKernelToTileMapping");
112+
if (!kernelToTileMapping) {
113+
xrt_core::message::send(severity_level::info, "XRT", getMessage("TileMapping.AIEKernelToTileMapping"));
114+
return {};
115+
}
116+
117+
std::map<std::pair<uint8_t, uint8_t>, tile_type> tileMap; // Use map to handle unique tiles by location
118+
auto rowOffset = getAIETileRowOffset();
119+
120+
// Parse all kernel mappings
121+
for (auto const &mapping : kernelToTileMapping.get()) {
122+
auto graphStr = mapping.second.get<std::string>("graph", "");
123+
auto functionStr = mapping.second.get<std::string>("function", "");
124+
125+
if (graphStr.empty() || functionStr.empty())
126+
continue;
127+
128+
// Check if graph matches
129+
bool foundGraph = (graph_name == "all") || (graphStr.find(graph_name) != std::string::npos);
130+
if (!foundGraph)
131+
continue;
132+
133+
// Check if kernel/function matches using precise pattern matching
134+
bool foundKernel = (kernel_name == "all") || matchesKernelPattern(functionStr, kernel_name);
135+
if (!foundGraph || !foundKernel)
136+
continue;
137+
138+
// Get core tile location
139+
auto coreCol = mapping.second.get<uint8_t>("column");
140+
auto coreRow = static_cast<uint8_t>(mapping.second.get<uint8_t>("row") + rowOffset);
141+
142+
// Create or get existing core tile
143+
auto coreKey = std::make_pair(coreCol, coreRow);
144+
if (tileMap.find(coreKey) == tileMap.end()) {
145+
tile_type coreTile;
146+
coreTile.col = coreCol;
147+
coreTile.row = coreRow;
148+
coreTile.active_core = (mapping.second.get<std::string>("tile", "") == "aie");
149+
coreTile.active_memory = false; // Will be set to true if DMA channels exist
150+
tileMap[coreKey] = coreTile;
151+
}
152+
153+
// Process DMA channels
154+
auto dmaChannelsTree = mapping.second.get_child_optional("dmaChannels");
155+
if (dmaChannelsTree) {
156+
for (auto const &channel : dmaChannelsTree.get()) {
157+
uint8_t dmaCol = xdp::aie::convertStringToUint8(channel.second.get<std::string>("column"));
158+
uint8_t dmaRow = static_cast<uint8_t>(xdp::aie::convertStringToUint8(channel.second.get<std::string>("row")) + rowOffset);
159+
160+
// If channel matches core tile location, add to core tile
161+
if (dmaCol == coreCol && dmaRow == coreRow) {
162+
tileMap[coreKey].active_memory = true;
163+
populateDMAChannelNames(tileMap[coreKey], channel.second);
164+
} else {
165+
// Otherwise create/update separate DMA tile
166+
auto dmaKey = std::make_pair(dmaCol, dmaRow);
167+
if (tileMap.find(dmaKey) == tileMap.end()) {
168+
tile_type dmaTile;
169+
dmaTile.col = dmaCol;
170+
dmaTile.row = dmaRow;
171+
dmaTile.active_core = false;
172+
dmaTile.active_memory = true;
173+
tileMap[dmaKey] = dmaTile;
174+
}
175+
populateDMAChannelNames(tileMap[dmaKey], channel.second);
176+
}
177+
}
178+
}
179+
}
180+
181+
// Convert map to vector
182+
std::vector<tile_type> tiles;
183+
for (const auto& pair : tileMap) {
184+
tiles.push_back(pair.second);
185+
}
186+
187+
return tiles;
188+
}
189+
190+
// Helper method to match kernel patterns with ordered substring matching
191+
bool AIETraceConfigV3Filetype::matchesKernelPattern(const std::string& function, const std::string& kernel_name) const
192+
{
193+
if ((kernel_name == "all") || (kernel_name.empty())) {
194+
return true;
195+
}
196+
197+
// Split function and kernel pattern by dots
198+
std::vector<std::string> functionParts;
199+
boost::split(functionParts, function, boost::is_any_of("."));
200+
201+
std::vector<std::string> kernelParts;
202+
boost::split(kernelParts, kernel_name, boost::is_any_of("."));
203+
204+
// Remove empty parts
205+
functionParts.erase(std::remove_if(functionParts.begin(), functionParts.end(),
206+
[](const std::string& s) { return s.empty(); }),
207+
functionParts.end());
208+
kernelParts.erase(std::remove_if(kernelParts.begin(), kernelParts.end(),
209+
[](const std::string& s) { return s.empty(); }),
210+
kernelParts.end());
211+
212+
// If kernel has more parts than function, it can't match
213+
if (kernelParts.size() > functionParts.size()) {
214+
return false;
215+
}
216+
217+
// Look for contiguous subsequence of kernel parts in function parts
218+
for (size_t i = 0; i <= functionParts.size() - kernelParts.size(); ++i) {
219+
bool matches = true;
220+
for (size_t j = 0; j < kernelParts.size(); ++j) {
221+
if (functionParts[i + j] != kernelParts[j]) {
222+
matches = false;
223+
break;
224+
}
225+
}
226+
if (matches) {
227+
return true;
228+
}
229+
}
230+
231+
return false;
232+
}
233+
234+
// Helper method to populate DMA channel names from metadata
235+
void AIETraceConfigV3Filetype::populateDMAChannelNames(tile_type& tile, const boost::property_tree::ptree& channelNode) const
236+
{
237+
auto portName = channelNode.get<std::string>("portName", "");
238+
auto channelNum = channelNode.get<uint8_t>("channel", 0);
239+
auto direction = channelNode.get<std::string>("direction", "");
240+
241+
if (portName.empty() || direction.empty())
242+
return;
243+
244+
if (direction == "s2mm") {
245+
if (channelNum < tile.s2mm_names.size()) {
246+
tile.s2mm_names[channelNum] = portName;
247+
}
248+
} else if (direction == "mm2s") {
249+
if (channelNum < tile.mm2s_names.size()) {
250+
tile.mm2s_names[channelNum] = portName;
251+
}
252+
}
253+
}
254+
255+
// =================================================================
256+
// UNSUPPORTED METHODS - Throw runtime exceptions for V3 format
257+
// =================================================================
258+
259+
std::vector<tile_type>
260+
AIETraceConfigV3Filetype::getAIETiles(const std::string&) const
261+
{
262+
throw std::runtime_error("getAIETiles() is not supported in V3 metadata format. "
263+
"Use getTiles() with module_type::core instead.");
264+
}
265+
266+
std::vector<tile_type>
267+
AIETraceConfigV3Filetype::getAllAIETiles(const std::string&) const
268+
{
269+
throw std::runtime_error("getAllAIETiles() is not supported in V3 metadata format. "
270+
"Use getTiles() with module_type::core instead.");
271+
}
272+
273+
std::vector<tile_type>
274+
AIETraceConfigV3Filetype::getEventTiles(const std::string&, module_type) const
275+
{
276+
throw std::runtime_error("getEventTiles() is not supported in V3 metadata format. "
277+
"Use getTiles() with the appropriate module_type instead.");
278+
}
279+
280+
} // namespace xdp::aie

0 commit comments

Comments
 (0)