From 073c963d447065b2ef3df1817352a795370a7b55 Mon Sep 17 00:00:00 2001 From: Nishant Mysore Date: Wed, 10 May 2023 11:53:18 -0700 Subject: [PATCH] Added Skeleton for AIE Profiling Plugin on Windows Devices (#7530) --- .../xdp/profile/plugin/CMakeLists.txt | 1 + .../profile/plugin/aie_profile/CMakeLists.txt | 17 +- .../aie_profile/aie_profile_metadata.cpp | 488 +++++++++--------- .../plugin/aie_profile/aie_profile_plugin.cpp | 90 ++-- .../plugin/aie_profile/win/aie_profile.cpp | 91 ++++ .../plugin/aie_profile/win/aie_profile.h | 60 +++ .../plugin/aie_profile/x86/aie_profile.cpp | 97 ++-- .../x86/aie_profile_kernel_config.h | 191 ++++--- .../profile/writer/aie_profile/aie_writer.cpp | 2 +- .../profile/writer/aie_profile/aie_writer.h | 2 +- 10 files changed, 605 insertions(+), 434 deletions(-) create mode 100644 src/runtime_src/xdp/profile/plugin/aie_profile/win/aie_profile.cpp create mode 100644 src/runtime_src/xdp/profile/plugin/aie_profile/win/aie_profile.h diff --git a/src/runtime_src/xdp/profile/plugin/CMakeLists.txt b/src/runtime_src/xdp/profile/plugin/CMakeLists.txt index c52b9182413..0ae2dfb06da 100644 --- a/src/runtime_src/xdp/profile/plugin/CMakeLists.txt +++ b/src/runtime_src/xdp/profile/plugin/CMakeLists.txt @@ -6,6 +6,7 @@ if (XDP_MINIMAL_BUILD STREQUAL "yes") add_subdirectory(native) add_subdirectory(user) + add_subdirectory(aie_profile) else() diff --git a/src/runtime_src/xdp/profile/plugin/aie_profile/CMakeLists.txt b/src/runtime_src/xdp/profile/plugin/aie_profile/CMakeLists.txt index 48142c5d40a..6d1032072ff 100644 --- a/src/runtime_src/xdp/profile/plugin/aie_profile/CMakeLists.txt +++ b/src/runtime_src/xdp/profile/plugin/aie_profile/CMakeLists.txt @@ -7,7 +7,9 @@ # on both Edge and x86 platforms that support AIE. # ==================================================================== -if (${XRT_NATIVE_BUILD} STREQUAL "yes") +if (XDP_MINIMAL_BUILD STREQUAL "yes") + set(IMPL_DIR "${PROFILE_DIR}/plugin/aie_profile/win") +elseif (${XRT_NATIVE_BUILD} STREQUAL "yes") set(IMPL_DIR "${PROFILE_DIR}/plugin/aie_profile/x86") elseif (DEFINED XRT_AIE_BUILD AND ${XRT_NATIVE_BUILD} STREQUAL "no") set(IMPL_DIR "${PROFILE_DIR}/plugin/aie_profile/edge") @@ -22,8 +24,19 @@ file(GLOB AIE_PROFILE_PLUGIN_FILES "${IMPL_DIR}/*.cpp" ) -if (${XRT_NATIVE_BUILD} STREQUAL "yes") +if (XDP_MINIMAL_BUILD STREQUAL "yes") + add_library(xdp_aie_profile_plugin MODULE ${AIE_PROFILE_PLUGIN_FILES}) + add_dependencies(xdp_aie_profile_plugin xdp_core xrt_coreutil) + target_link_libraries(xdp_aie_profile_plugin PRIVATE xdp_core xrt_coreutil) + + set_target_properties(xdp_aie_profile_plugin PROPERTIES VERSION ${XRT_VERSION_STRING} SOVERSION ${XRT_SOVERSION}) + + install (TARGETS xdp_aie_profile_plugin + LIBRARY DESTINATION ${XDP_PLUGIN_INSTALL_DIR} + ) + +elseif (${XRT_NATIVE_BUILD} STREQUAL "yes") add_library(xdp_aie_profile_plugin MODULE ${AIE_PROFILE_PLUGIN_FILES}) add_dependencies(xdp_aie_profile_plugin xdp_core xrt_coreutil) target_link_libraries(xdp_aie_profile_plugin PRIVATE xdp_core xrt_coreutil) diff --git a/src/runtime_src/xdp/profile/plugin/aie_profile/aie_profile_metadata.cpp b/src/runtime_src/xdp/profile/plugin/aie_profile/aie_profile_metadata.cpp index ef650f8d6e6..927dced74e9 100644 --- a/src/runtime_src/xdp/profile/plugin/aie_profile/aie_profile_metadata.cpp +++ b/src/runtime_src/xdp/profile/plugin/aie_profile/aie_profile_metadata.cpp @@ -16,12 +16,12 @@ #define XDP_SOURCE +#include "aie_profile_metadata.h" + #include #include #include -#include "aie_profile_metadata.h" - #include "core/common/config_reader.h" #include "core/common/device.h" #include "core/common/message.h" @@ -33,8 +33,7 @@ namespace xdp { using severity_level = xrt_core::message::severity_level; namespace pt = boost::property_tree; - AieProfileMetadata::AieProfileMetadata(uint64_t deviceID, void* handle) - : deviceID(deviceID), handle(handle) + AieProfileMetadata::AieProfileMetadata(uint64_t deviceID, void* handle) : deviceID(deviceID), handle(handle) { // Verify settings from xrt.ini checkSettings(); @@ -46,7 +45,7 @@ namespace xdp { // Setup Config Metrics // Get AIE clock frequency VPDatabase* db = VPDatabase::Instance(); - clockFreqMhz = (db->getStaticInfo()).getClockRateMHz(deviceID,false); + clockFreqMhz = (db->getStaticInfo()).getClockRateMHz(deviceID, false); // Tile-based metrics settings std::vector metricsConfig; @@ -60,7 +59,7 @@ namespace xdp { graphMetricsConfig.push_back(xrt_core::config::get_aie_profile_settings_graph_based_aie_metrics()); graphMetricsConfig.push_back(xrt_core::config::get_aie_profile_settings_graph_based_aie_memory_metrics()); // Uncomment to support graph-based metrics for Interface Tiles - //graphMetricsConfig.push_back(xrt_core::config::get_aie_profile_settings_graph_based_interface_tile_metrics()); + // graphMetricsConfig.push_back(xrt_core::config::get_aie_profile_settings_graph_based_interface_tile_metrics()); graphMetricsConfig.push_back(""); graphMetricsConfig.push_back(xrt_core::config::get_aie_profile_settings_graph_based_memory_tile_metrics()); @@ -69,7 +68,7 @@ namespace xdp { auto type = moduleTypes[module]; auto metricsSettings = getSettingsVector(metricsConfig[module]); auto graphMetricsSettings = getSettingsVector(graphMetricsConfig[module]); - + if (type == module_type::shim) getConfigMetricsForInterfaceTiles(module, metricsSettings, graphMetricsSettings); else @@ -77,7 +76,7 @@ namespace xdp { } } - bool tileCompare(tile_type tile1, tile_type tile2) + bool tileCompare(tile_type tile1, tile_type tile2) { return ((tile1.col == tile2.col) && (tile1.row == tile2.row)); } @@ -85,23 +84,20 @@ namespace xdp { void AieProfileMetadata::checkSettings() { using boost::property_tree::ptree; - const std::set validSettings { - "graph_based_aie_metrics", "graph_based_aie_memory_metrics", - "graph_based_memory_tile_metrics", "tile_based_aie_metrics", - "tile_based_aie_memory_metrics", "tile_based_memory_tile_metrics", - "tile_based_interface_tile_metrics", "interval_us" - }; - const std::map deprecatedSettings { - {"aie_profile_core_metrics", - "AIE_profile_settings.graph_based_aie_metrics or tile_based_aie_metrics"}, - {"aie_profile_memory_metrics", - "AIE_profile_settings.graph_based_aie_memory_metrics or tile_based_aie_memory_metrics"}, - {"aie_profile_interface_metrics", - "AIE_profile_settings.tile_based_interface_tile_metrics"}, - {"aie_profile_interval_us", - "AIE_profile_settings.interval_us"} - }; - + const std::set validSettings{"graph_based_aie_metrics", "graph_based_aie_memory_metrics", + "graph_based_memory_tile_metrics", "tile_based_aie_metrics", + "tile_based_aie_memory_metrics", "tile_based_memory_tile_metrics", + "tile_based_interface_tile_metrics", "interval_us"}; + const std::map deprecatedSettings{ + {"aie_profile_core_metrics", + "AIE_profile_settings.graph_based_aie_metrics or " + "tile_based_aie_metrics"}, + {"aie_profile_memory_metrics", + "AIE_profile_settings.graph_based_aie_memory_metrics or " + "tile_based_aie_memory_metrics"}, + {"aie_profile_interface_metrics", "AIE_profile_settings.tile_based_interface_tile_metrics"}, + {"aie_profile_interval_us", "AIE_profile_settings.interval_us"}}; + // Verify settings in AIE_profile_settings section auto tree1 = xrt_core::config::detail::get_ptree_value("AIE_profile_settings"); for (ptree::iterator pos = tree1.begin(); pos != tree1.end(); pos++) { @@ -166,8 +162,7 @@ namespace xdp { return rowOffset; } - std::vector - AieProfileMetadata::getSettingsVector(std::string settingsString) + std::vector AieProfileMetadata::getSettingsVector(std::string settingsString) { if (settingsString.empty()) return {}; @@ -175,7 +170,8 @@ namespace xdp { // For 2023.1 only: support both *_bandwidths and *_throughputs if (settingsString.find("bandwidths") != std::string::npos) { xrt_core::message::send(severity_level::warning, "XRT", - "All metric sets named *_bandwidths will be renamed *_throughputs in 2023.2. Please use the new settings."); + "All metric sets named *_bandwidths will be renamed *_throughputs " + "in 2023.2. Please use the new settings."); boost::replace_all(settingsString, "bandwidths", "throughputs"); } @@ -186,8 +182,7 @@ namespace xdp { return settingsVector; } - std::unordered_map - AieProfileMetadata::get_plios(const xrt_core::device* device) + std::unordered_map AieProfileMetadata::get_plios(const xrt_core::device* device) { auto data = device->get_axlf_section(AIE_METADATA); if (!data.first || !data.second) @@ -213,10 +208,9 @@ namespace xdp { return plios; } - std::vector - AieProfileMetadata::get_interface_tiles(const xrt_core::device* device, const std::string &metricStr, - int16_t channelId, bool useColumn, uint32_t minCol, - uint32_t maxCol) + std::vector AieProfileMetadata::get_interface_tiles(const xrt_core::device* device, + const std::string& metricStr, int16_t channelId, + bool useColumn, uint32_t minCol, uint32_t maxCol) { std::vector tiles; @@ -225,7 +219,7 @@ namespace xdp { for (auto& plio : plios) { auto isMaster = plio.second.slaveOrMaster; auto streamId = plio.second.streamId; - auto shimCol = plio.second.shimColumn; + auto shimCol = plio.second.shimColumn; // If looking for specific ID, make sure it matches if ((channelId >= 0) && (channelId != streamId)) @@ -234,14 +228,12 @@ namespace xdp { // Make sure it's desired polarity // NOTE: input = slave (data flowing from PLIO) // output = master (data flowing to PLIO) - if ((isMaster && (metricStr == "input_throughputs")) - || (!isMaster && (metricStr == "output_throughputs"))) + if ((isMaster && (metricStr == "input_throughputs")) || (!isMaster && (metricStr == "output_throughputs"))) continue; plioCount++; - if (useColumn - && !( (minCol <= (uint32_t)shimCol) && ((uint32_t)shimCol <= maxCol) )) { + if (useColumn && !((minCol <= (uint32_t)shimCol) && ((uint32_t)shimCol <= maxCol))) { // shimCol is not within minCol:maxCol range. So skip. continue; } @@ -254,10 +246,10 @@ namespace xdp { tile.itr_mem_row = streamId; tiles.push_back(tile); } - + if ((plioCount == 0) && (channelId >= 0)) { - std::string msg = "No tiles used channel ID " + std::to_string(channelId) - + ". Please specify a valid channel ID."; + std::string msg = + "No tiles used channel ID " + std::to_string(channelId) + ". Please specify a valid channel ID."; xrt_core::message::send(severity_level::warning, "XRT", msg); } return tiles; @@ -266,11 +258,11 @@ namespace xdp { // Find all MEM tiles associated with a graph and kernel // kernel_name = all : all tiles in graph // kernel_name = : only tiles used by that specific kernel - std::vector - AieProfileMetadata::get_mem_tiles(const xrt_core::device* device, const std::string& graph_name, - const std::string& kernel_name) + std::vector AieProfileMetadata::get_mem_tiles(const xrt_core::device* device, + const std::string& graph_name, + const std::string& kernel_name) { - if (getHardwareGen() == 1) + if (getHardwareGen() == 1) return {}; auto data = device->get_axlf_section(AIE_METADATA); @@ -291,10 +283,9 @@ namespace xdp { uint16_t rowOffset = 1; // Now parse all shared buffers - for (auto const &shared_buffer : sharedBufferTree.get()) { + for (auto const& shared_buffer : sharedBufferTree.get()) { auto currGraph = shared_buffer.second.get("graph"); - if ((currGraph.find(graph_name) == std::string::npos) - && (graph_name.compare("all") != 0)) + if ((currGraph.find(graph_name) == std::string::npos) && (graph_name.compare("all") != 0)) continue; if (kernel_name.compare("all") != 0) { std::vector names; @@ -313,16 +304,15 @@ namespace xdp { std::unique_copy(allTiles.begin(), allTiles.end(), std::back_inserter(memTiles), tileCompare); return memTiles; } - + inline void throw_if_error(bool err, const char* msg) { if (err) throw std::runtime_error(msg); } - std::vector - AieProfileMetadata::get_event_tiles(const xrt_core::device* device, const std::string& graph_name, - module_type type) + std::vector AieProfileMetadata::get_event_tiles(const xrt_core::device* device, + const std::string& graph_name, module_type type) { auto data = device->get_axlf_section(AIE_METADATA); if (!data.first || !data.second) @@ -335,7 +325,7 @@ namespace xdp { return {}; const char* col_name = (type == module_type::core) ? "core_columns" : "dma_columns"; - const char* row_name = (type == module_type::core) ? "core_rows" : "dma_rows"; + const char* row_name = (type == module_type::core) ? "core_rows" : "dma_rows"; std::vector tiles; auto rowOffset = getAIETileRowOffset(); @@ -343,21 +333,20 @@ namespace xdp { for (auto& graph : aie_meta.get_child("aie_metadata.EventGraphs")) { auto currGraph = graph.second.get("name"); - if ((currGraph.find(graph_name) == std::string::npos) - && (graph_name.compare("all") != 0)) + if ((currGraph.find(graph_name) == std::string::npos) && (graph_name.compare("all") != 0)) continue; int count = startCount; for (auto& node : graph.second.get_child(col_name)) { tiles.push_back(tile_type()); auto& t = tiles.at(count++); - t.col = std::stoul(node.second.data()); + t.col = static_cast(std::stoul(node.second.data())); } int num_tiles = count; count = startCount; for (auto& node : graph.second.get_child(row_name)) - tiles.at(count++).row = std::stoul(node.second.data()) + rowOffset; + tiles.at(count++).row = static_cast(std::stoul(node.second.data())) + rowOffset; throw_if_error(count < num_tiles, "rows < num_tiles"); startCount = count; } @@ -366,9 +355,8 @@ namespace xdp { } // Find all AIE tiles associated with a graph and module type (kernel_name = all) - std::vector - AieProfileMetadata::get_aie_tiles(const xrt_core::device* device, - const std::string& graph_name, module_type type) + std::vector AieProfileMetadata::get_aie_tiles(const xrt_core::device* device, + const std::string& graph_name, module_type type) { std::vector tiles; tiles = get_event_tiles(device, graph_name, module_type::core); @@ -379,9 +367,8 @@ namespace xdp { return tiles; } - std::vector - AieProfileMetadata::get_tiles(const xrt_core::device* device, const std::string& graph_name, - module_type type, const std::string& kernel_name) + std::vector AieProfileMetadata::get_tiles(const xrt_core::device* device, const std::string& graph_name, + module_type type, const std::string& kernel_name) { if (type == module_type::mem_tile) return get_mem_tiles(device, graph_name, kernel_name); @@ -404,10 +391,9 @@ namespace xdp { std::vector tiles; auto rowOffset = getAIETileRowOffset(); - for (auto const &mapping : kernelToTileMapping.get()) { + for (auto const& mapping : kernelToTileMapping.get()) { auto currGraph = mapping.second.get("graph"); - if ((currGraph.find(graph_name) == std::string::npos) - && (graph_name.compare("all") != 0)) + if ((currGraph.find(graph_name) == std::string::npos) && (graph_name.compare("all") != 0)) continue; if (kernel_name.compare("all") != 0) { std::vector names; @@ -426,46 +412,45 @@ namespace xdp { } // Resolve metrics for AIE or MEM tiles - void - AieProfileMetadata::getConfigMetricsForTiles(int moduleIdx, - const std::vector& metricsSettings, - const std::vector& graphMetricsSettings, - const module_type mod) + void AieProfileMetadata::getConfigMetricsForTiles(int moduleIdx, const std::vector& metricsSettings, + const std::vector& graphMetricsSettings, + const module_type mod) { - if ((metricsSettings.empty()) && (graphMetricsSettings.empty())) + if ((metricsSettings.empty()) && (graphMetricsSettings.empty())) return; if ((getHardwareGen() == 1) && (mod == module_type::mem_tile)) { xrt_core::message::send(severity_level::warning, "XRT", - "MEM tiles are not available in AIE1. Profile settings will be ignored."); + "MEM tiles are not available in AIE1. Profile " + "settings will be ignored."); return; } std::shared_ptr device = xrt_core::get_userpf_device(handle); uint16_t rowOffset = (mod == module_type::mem_tile) ? 1 : getAIETileRowOffset(); - auto modName = (mod == module_type::core) ? "aie" - : ((mod == module_type::dma) ? "aie_memory" - : "memory_tile"); + auto modName = (mod == module_type::core) ? "aie" : ((mod == module_type::dma) ? "aie_memory" : "memory_tile"); auto allValidKernels = get_kernels(device.get()); auto allValidGraphs = get_graphs(device.get()); std::set allValidTiles; auto validTilesVec = get_tiles(device.get(), "all", mod); - std::unique_copy(validTilesVec.begin(), validTilesVec.end(), std::inserter(allValidTiles, allValidTiles.end()), tileCompare); + std::unique_copy(validTilesVec.begin(), validTilesVec.end(), std::inserter(allValidTiles, allValidTiles.end()), + tileCompare); // STEP 1 : Parse per-graph or per-kernel settings - /* AIE_profile_settings config format ; Multiple values can be specified for a metric separated with ';' - * AI Engine Tiles - * graph_based_aie_metrics = :: - * graph_based_aie_memory_metrics = :: - * MEM Tiles - * graph_based_memory_tile_metrics = ::[:] + /* AIE_profile_settings config format ; Multiple values can be specified for + * a metric separated with ';' AI Engine Tiles graph_based_aie_metrics = :: + * graph_based_aie_memory_metrics = :: MEM Tiles + * graph_based_memory_tile_metrics = ::[:] */ std::vector> graphMetrics(graphMetricsSettings.size()); - // Graph Pass 1 : process only "all" metric setting + // Graph Pass 1 : process only "all" metric setting for (size_t i = 0; i < graphMetricsSettings.size(); ++i) { // Split done only in Pass 1 boost::split(graphMetrics[i], graphMetricsSettings[i], boost::is_any_of(":")); @@ -473,74 +458,74 @@ namespace xdp { // Check if graph is not all or if invalid kernel if (graphMetrics[i][0].compare("all") != 0) continue; - if ((graphMetrics[i][1].compare("all") != 0) - && (std::find(allValidKernels.begin(), allValidKernels.end(), graphMetrics[i][1]) == allValidKernels.end())) { + if ((graphMetrics[i][1].compare("all") != 0) && + (std::find(allValidKernels.begin(), allValidKernels.end(), graphMetrics[i][1]) == allValidKernels.end())) { std::stringstream msg; - msg << "Kernel " << graphMetrics[i][1] << " not found. The graph_based_" << modName - << "_metrics setting " << graphMetricsSettings[i] << " will be ignored."; + msg << "Kernel " << graphMetrics[i][1] << " not found. The graph_based_" << modName << "_metrics setting " + << graphMetricsSettings[i] << " will be ignored."; xrt_core::message::send(severity_level::warning, "XRT", msg.str()); continue; } auto tiles = get_tiles(device.get(), graphMetrics[i][0], mod, graphMetrics[i][1]); - for (auto &e : tiles) { + for (auto& e : tiles) { configMetrics[moduleIdx][e] = graphMetrics[i][2]; } // Grab channel numbers (if specified; MEM tiles only) if (graphMetrics[i].size() == 5) { try { - for (auto &e : tiles) { - configChannel0[e] = std::stoi(graphMetrics[i][3]); - configChannel1[e] = std::stoi(graphMetrics[i][4]); + for (auto& e : tiles) { + configChannel0[e] = static_cast(std::stoul(graphMetrics[i][3])); + configChannel1[e] = static_cast(std::stoul(graphMetrics[i][4])); } - } catch (...) { + } + catch (...) { std::stringstream msg; - msg << "Channel specifications in graph_based_" << modName - << "_metrics are not valid and hence ignored."; + msg << "Channel specifications in graph_based_" << modName << "_metrics are not valid and hence ignored."; xrt_core::message::send(severity_level::warning, "XRT", msg.str()); } } } // Graph Pass 1 - // Graph Pass 2 : process per graph metric setting + // Graph Pass 2 : process per graph metric setting for (size_t i = 0; i < graphMetricsSettings.size(); ++i) { // Check if already processed or if invalid if (graphMetrics[i][0].compare("all") == 0) continue; if (std::find(allValidGraphs.begin(), allValidGraphs.end(), graphMetrics[i][0]) == allValidGraphs.end()) { std::stringstream msg; - msg << "Graph " << graphMetrics[i][0] << " not found. The graph_based_" << modName - << "_metrics setting " << graphMetricsSettings[i] << " will be ignored."; + msg << "Graph " << graphMetrics[i][0] << " not found. The graph_based_" << modName << "_metrics setting " + << graphMetricsSettings[i] << " will be ignored."; xrt_core::message::send(severity_level::warning, "XRT", msg.str()); continue; } - if ((graphMetrics[i][1].compare("all") != 0) - && (std::find(allValidKernels.begin(), allValidKernels.end(), graphMetrics[i][1]) == allValidKernels.end())) { + if ((graphMetrics[i][1].compare("all") != 0) && + (std::find(allValidKernels.begin(), allValidKernels.end(), graphMetrics[i][1]) == allValidKernels.end())) { std::stringstream msg; - msg << "Kernel " << graphMetrics[i][1] << " not found. The graph_based_" << modName - << "_metrics setting " << graphMetricsSettings[i] << " will be ignored."; + msg << "Kernel " << graphMetrics[i][1] << " not found. The graph_based_" << modName << "_metrics setting " + << graphMetricsSettings[i] << " will be ignored."; xrt_core::message::send(severity_level::warning, "XRT", msg.str()); continue; } // Capture all tiles in given graph auto tiles = get_tiles(device.get(), graphMetrics[i][0], mod, graphMetrics[i][1]); - for (auto &e : tiles) { + for (auto& e : tiles) { configMetrics[moduleIdx][e] = graphMetrics[i][2]; } // Grab channel numbers (if specified; MEM tiles only) if (graphMetrics[i].size() == 5) { try { - for (auto &e : tiles) { - configChannel0[e] = std::stoi(graphMetrics[i][3]); - configChannel1[e] = std::stoi(graphMetrics[i][4]); + for (auto& e : tiles) { + configChannel0[e] = static_cast(std::stoul(graphMetrics[i][3])); + configChannel1[e] = static_cast(std::stoul(graphMetrics[i][4])); } - } catch (...) { + } + catch (...) { std::stringstream msg; - msg << "Channel specifications in graph_based_" << modName - << "_metrics are not valid and hence ignored."; + msg << "Channel specifications in graph_based_" << modName << "_metrics are not valid and hence ignored."; xrt_core::message::send(severity_level::warning, "XRT", msg.str()); } } @@ -548,25 +533,30 @@ namespace xdp { // STEP 2 : Parse per-tile settings: all, bounding box, and/or single tiles - /* AIE_profile_settings config format ; Multiple values can be specified for a metric separated with ';' - * AI Engine Tiles - * Single or all tiles - * tile_based_aie_metrics = [[{,}|all>:] - * tile_based_aie_memory_metrics = [[<{,}|all>:] + /* AIE_profile_settings config format ; Multiple values can be specified for + * a metric separated with ';' AI Engine Tiles Single or all tiles + * tile_based_aie_metrics = + * [[{,}|all>:] + * tile_based_aie_memory_metrics = + * [[<{,}|all>:] * Range of tiles - * tile_based_aie_metrics = [{}:{,}:]] - * tile_based_aie_memory_metrics = [{}:{,}:]] - * + * tile_based_aie_metrics = + * [{}:{,}:]] + * tile_based_aie_memory_metrics = + * [{}:{,}:]] + * * MEM Tiles (AIE2 and beyond) * Single or all tiles - * tile_based_memory_tile_metrics = [[<{,}|all>:[:]] + * tile_based_memory_tile_metrics = + * [[<{,}|all>:[:]] * Range of tiles - * tile_based_memory_tile_metrics = [{}:{,}:[:]]] + * tile_based_memory_tile_metrics = + * [{}:{,}:[:]]] */ std::vector> metrics(metricsSettings.size()); - // Pass 1 : process only "all" metric setting + // Pass 1 : process only "all" metric setting for (size_t i = 0; i < metricsSettings.size(); ++i) { // Split done only in Pass 1 boost::split(metrics[i], metricsSettings[i], boost::is_any_of(":")); @@ -575,31 +565,31 @@ namespace xdp { continue; auto tiles = get_tiles(device.get(), metrics[i][0], mod); - for (auto &e : tiles) { + for (auto& e : tiles) { configMetrics[moduleIdx][e] = metrics[i][1]; } // Grab channel numbers (if specified; MEM tiles only) if (metrics[i].size() == 4) { try { - for (auto &e : tiles) { - configChannel0[e] = std::stoi(metrics[i][2]); - configChannel1[e] = std::stoi(metrics[i][3]); + for (auto& e : tiles) { + configChannel0[e] = static_cast(std::stoul(metrics[i][2])); + configChannel1[e] = static_cast(std::stoul(metrics[i][3])); } - } catch (...) { + } + catch (...) { std::stringstream msg; - msg << "Channel specifications in tile_based_" << modName - << "_metrics are not valid and hence ignored."; + msg << "Channel specifications in tile_based_" << modName << "_metrics are not valid and hence ignored."; xrt_core::message::send(severity_level::warning, "XRT", msg.str()); } } - } // Pass 1 + } // Pass 1 - // Pass 2 : process only range of tiles metric setting + // Pass 2 : process only range of tiles metric setting for (size_t i = 0; i < metricsSettings.size(); ++i) { if ((metrics[i].size() != 3) && (metrics[i].size() != 5)) continue; - + uint16_t minRow = 0, minCol = 0; uint16_t maxRow = 0, maxCol = 0; @@ -611,23 +601,25 @@ namespace xdp { std::vector minTile; boost::split(minTile, metrics[i][0], boost::is_any_of(",")); - minCol = std::stoi(minTile[0]); - minRow = std::stoi(minTile[1]) + rowOffset; + minCol = static_cast(std::stoul(minTile[0])); + minRow = static_cast(std::stoul(minTile[1])) + rowOffset; std::vector maxTile; boost::split(maxTile, metrics[i][1], boost::is_any_of(",")); - maxCol = std::stoi(maxTile[0]); - maxRow = std::stoi(maxTile[1]) + rowOffset; - } catch (...) { - xrt_core::message::send(severity_level::warning, "XRT", - "Tile range specification in tile_based_aie_[memory}_metrics is not of valid format and hence skipped."); + maxCol = static_cast(std::stoul(maxTile[0])); + maxRow = static_cast(std::stoul(maxTile[1])) + rowOffset; + } + catch (...) { + xrt_core::message::send(severity_level::warning, "XRT", + "Tile range specification in tile_based_aie_[memory}_metrics " + "is not of valid format and hence skipped."); continue; } - // Ensure range is valid + // Ensure range is valid if ((minCol > maxCol) || (minRow > maxRow)) { std::stringstream msg; - msg << "Tile range specification in tile_based_" << modName + msg << "Tile range specification in tile_based_" << modName << "_metrics is not of valid format and hence skipped."; xrt_core::message::send(severity_level::warning, "XRT", msg.str()); continue; @@ -637,12 +629,12 @@ namespace xdp { uint8_t channel1 = 1; if (metrics[i].size() == 5) { try { - channel0 = std::stoi(metrics[i][3]); - channel1 = std::stoi(metrics[i][4]); - } catch (...) { + channel0 = static_cast(std::stoul(metrics[i][3])); + channel1 = static_cast(std::stoul(metrics[i][4])); + } + catch (...) { std::stringstream msg; - msg << "Channel specifications in tile_based_" << modName - << "_metrics are not valid and hence ignored."; + msg << "Channel specifications in tile_based_" << modName << "_metrics are not valid and hence ignored."; xrt_core::message::send(severity_level::warning, "XRT", msg.str()); } } @@ -656,12 +648,12 @@ namespace xdp { // Make sure tile is used if (allValidTiles.find(tile) == allValidTiles.end()) { std::stringstream msg; - msg << "Specified Tile {" << std::to_string(tile.col) << "," - << std::to_string(tile.row) << "} is not active. Hence skipped."; + msg << "Specified Tile {" << std::to_string(tile.col) << "," << std::to_string(tile.row) + << "} is not active. Hence skipped."; xrt_core::message::send(severity_level::warning, "XRT", msg.str()); continue; } - + configMetrics[moduleIdx][tile] = metrics[i][2]; // Grab channel numbers (if specified; MEM tiles only) @@ -671,13 +663,12 @@ namespace xdp { } } } - } // Pass 2 + } // Pass 2 - // Pass 3 : process only single tile metric setting + // Pass 3 : process only single tile metric setting for (size_t i = 0; i < metricsSettings.size(); ++i) { // Check if already processed - if ((metrics[i][0].compare("all") == 0) || (metrics[i].size() == 3) - || (metrics[i].size() == 5)) + if ((metrics[i][0].compare("all") == 0) || (metrics[i].size() == 3) || (metrics[i].size() == 5)) continue; uint16_t col = 0; @@ -689,12 +680,12 @@ namespace xdp { std::vector tilePos; boost::split(tilePos, metrics[i][0], boost::is_any_of(",")); - col = std::stoi(tilePos[0]); - row = std::stoi(tilePos[1]) + rowOffset; - } catch (...) { + col = static_cast(std::stoul(tilePos[0])); + row = static_cast(std::stoul(tilePos[1])) + rowOffset; + } + catch (...) { std::stringstream msg; - msg << "Tile specification in tile_based_" << modName - << "_metrics is not valid format and hence skipped."; + msg << "Tile specification in tile_based_" << modName << "_metrics is not valid format and hence skipped."; xrt_core::message::send(severity_level::warning, "XRT", msg.str()); continue; } @@ -706,47 +697,48 @@ namespace xdp { // Make sure tile is used if (allValidTiles.find(tile) == allValidTiles.end()) { std::stringstream msg; - msg << "Specified Tile {" << std::to_string(tile.col) << "," - << std::to_string(tile.row) << "} is not active. Hence skipped."; + msg << "Specified Tile {" << std::to_string(tile.col) << "," << std::to_string(tile.row) + << "} is not active. Hence skipped."; xrt_core::message::send(severity_level::warning, "XRT", msg.str()); continue; } configMetrics[moduleIdx][tile] = metrics[i][1]; - + // Grab channel numbers (if specified; MEM tiles only) if (metrics[i].size() == 4) { try { - configChannel0[tile] = std::stoi(metrics[i][2]); - configChannel1[tile] = std::stoi(metrics[i][3]); - } catch (...) { + configChannel0[tile] = static_cast(std::stoul(metrics[i][2])); + configChannel1[tile] = static_cast(std::stoul(metrics[i][3])); + } + catch (...) { std::stringstream msg; - msg << "Channel specifications in tile_based_" << modName - << "_metrics are not valid and hence ignored."; + msg << "Channel specifications in tile_based_" << modName << "_metrics are not valid and hence ignored."; xrt_core::message::send(severity_level::warning, "XRT", msg.str()); } } - } // Pass 3 + } // Pass 3 // Set default, check validity, and remove "off" tiles auto defaultSet = defaultSets[moduleIdx]; - //for (auto &e : allValidTiles) { - // if (configMetrics[moduleIdx].find(e) == configMetrics[moduleIdx].end()) - // configMetrics[moduleIdx][e] = defaultSet; - //} + // for (auto &e : allValidTiles) { + // if (configMetrics[moduleIdx].find(e) == configMetrics[moduleIdx].end()) + // configMetrics[moduleIdx][e] = defaultSet; + // } bool showWarning = true; std::vector offTiles; - for (auto &tileMetric : configMetrics[moduleIdx]) { + for (auto& tileMetric : configMetrics[moduleIdx]) { // Save list of "off" tiles if (tileMetric.second.empty() || (tileMetric.second.compare("off") == 0)) { offTiles.push_back(tileMetric.first); continue; } - + // Ensure requested metric set is supported (if not, use default) - if (std::find(metricStrings[mod].begin(), metricStrings[mod].end(), tileMetric.second) == metricStrings[mod].end()) { + if (std::find(metricStrings[mod].begin(), metricStrings[mod].end(), tileMetric.second) == + metricStrings[mod].end()) { if (showWarning) { std::stringstream msg; msg << "Unable to find " << moduleNames[moduleIdx] << " metric set " << tileMetric.second @@ -755,40 +747,41 @@ namespace xdp { showWarning = false; } tileMetric.second = defaultSet; - } + } } // Remove all the "off" tiles - for (auto &t : offTiles) { + for (auto& t : offTiles) { configMetrics[moduleIdx].erase(t); } } - // Resolve Interface metrics - void - AieProfileMetadata::getConfigMetricsForInterfaceTiles(int moduleIdx, - const std::vector& metricsSettings, - const std::vector graphMetricsSettings) + // Resolve Interface metrics + void AieProfileMetadata::getConfigMetricsForInterfaceTiles(int moduleIdx, + const std::vector& metricsSettings, + const std::vector graphMetricsSettings) { - if ((metricsSettings.empty()) && (graphMetricsSettings.empty())) + if ((metricsSettings.empty()) && (graphMetricsSettings.empty())) return; std::shared_ptr device = xrt_core::get_userpf_device(handle); // TODO: Add support for graph metrics - + // STEP 2 : Parse per-tile settings: all, bounding box, and/or single tiles - /* AIE_profile_settings config format ; Multiple values can be specified for a metric separated with ';' - * Single or all tiles - * tile_based_interface_tile_metrics = [[:[:]] + /* AIE_profile_settings config format ; Multiple values can be specified for + * a metric separated with ';' Single or all tiles + * tile_based_interface_tile_metrics = + * [[:[:]] * Range of tiles - * tile_based_interface_tile_metrics = [::[:]]] + * tile_based_interface_tile_metrics = + * [::[:]]] */ std::vector> metrics(metricsSettings.size()); - // Pass 1 : process only "all" metric setting + // Pass 1 : process only "all" metric setting for (size_t i = 0; i < metricsSettings.size(); ++i) { // Split done only in Pass 1 boost::split(metrics[i], metricsSettings[i], boost::is_any_of(":")); @@ -796,15 +789,15 @@ namespace xdp { if (metrics[i][0].compare("all") != 0) continue; - int16_t channelId = (metrics[i].size() < 3) ? -1 : std::stoi(metrics[i][2]); + int16_t channelId = (metrics[i].size() < 3) ? -1 : static_cast(std::stoul(metrics[i][2])); auto tiles = get_interface_tiles(device.get(), metrics[i][1], channelId); - for (auto &e : tiles) { + for (auto& e : tiles) { configMetrics[moduleIdx][e] = metrics[i][1]; } - } // Pass 1 + } // Pass 1 - // Pass 2 : process only range of tiles metric setting + // Pass 2 : process only range of tiles metric setting for (size_t i = 0; i < metricsSettings.size(); ++i) { if ((metrics[i][0].compare("all") == 0) || (metrics[i].size() < 3)) continue; @@ -812,95 +805,108 @@ namespace xdp { uint32_t maxCol = 0; try { maxCol = std::stoi(metrics[i][1]); - } catch (std::invalid_argument const &e) { + } + catch (std::invalid_argument const&) { // maxColumn is not an integer i.e either 1st style or wrong format, skip for now continue; } uint32_t minCol = 0; try { minCol = std::stoi(metrics[i][0]); - } catch (std::invalid_argument const &e) { - // 2nd style but expected min column is not an integer, give warning and skip - xrt_core::message::send(severity_level::warning, "XRT", - "Minimum column specification in tile_based_interface_tile_metrics is not an integer and hence skipped."); + } + catch (std::invalid_argument const&) { + // 2nd style but expected min column is not an integer, give warning and skip + xrt_core::message::send(severity_level::warning, "XRT", + "Minimum column specification in " + "tile_based_interface_tile_metrics is not " + "an integer and hence skipped."); continue; } int16_t channelId = 0; if (metrics[i].size() == 4) { try { - channelId = std::stoi(metrics[i][3]); - } catch (std::invalid_argument const &e) { - // Expected channel Id is not an integer, give warning and ignore channelId - xrt_core::message::send(severity_level::warning, "XRT", - "Channel ID specification in tile_based_interface_tile_metrics is not an integer and hence ignored."); + channelId = static_cast(std::stoul(metrics[i][3])); + } + catch (std::invalid_argument const&) { + // Expected channel Id is not an integer, give warning and + // ignore channelId + xrt_core::message::send(severity_level::warning, "XRT", + "Channel ID specification in " + "tile_based_interface_tile_metrics is " + "not an integer and hence ignored."); channelId = -1; } } - - auto tiles = get_interface_tiles(device.get(), metrics[i][2], channelId, - true, minCol, maxCol); - for (auto &t : tiles) { + auto tiles = get_interface_tiles(device.get(), metrics[i][2], channelId, true, minCol, maxCol); + + for (auto& t : tiles) { configMetrics[moduleIdx][t] = metrics[i][2]; } - } // Pass 2 + } // Pass 2 - // Pass 3 : process only single tile metric setting + // Pass 3 : process only single tile metric setting for (size_t i = 0; i < metricsSettings.size(); ++i) { // Skip range specification, invalid format, or already processed - if ((metrics[i].size() == 4) || (metrics[i].size() < 2) - || (metrics[i][0].compare("all") == 0)) + if ((metrics[i].size() == 4) || (metrics[i].size() < 2) || (metrics[i][0].compare("all") == 0)) continue; - + uint32_t col = 0; try { col = std::stoi(metrics[i][1]); - } catch (std::invalid_argument const &e) { + } + catch (std::invalid_argument const&) { // max column is not a number, so the expected single column specification. Handle this here try { col = std::stoi(metrics[i][0]); - } catch (std::invalid_argument const &e) { + } + catch (std::invalid_argument const&) { // Expected column specification is not a number. Give warning and skip - xrt_core::message::send(severity_level::warning, "XRT", - "Column specification in tile_based_interface_tile_metrics is not an integer and hence skipped."); + xrt_core::message::send(severity_level::warning, "XRT", + "Column specification in tile_based_interface_tile_metrics " + "is not an integer and hence skipped."); continue; } int16_t channelId = -1; if (metrics[i].size() == 3) { try { - channelId = std::stoi(metrics[i][2]); - } catch (std::invalid_argument const &e) { - // Expected channel Id is not an integer, give warning and ignore channelId - xrt_core::message::send(severity_level::warning, "XRT", - "Channel ID specification in tile_based_interface_tile_metrics is not an integer and hence ignored."); + channelId = static_cast(std::stoul(metrics[i][2])); + } + catch (std::invalid_argument const&) { + // Expected channel Id is not an integer, give warning and + // ignore channelId + xrt_core::message::send(severity_level::warning, "XRT", + "Channel ID specification in " + "tile_based_interface_tile_metrics is not an integer " + "and hence ignored."); channelId = -1; } } - auto tiles = get_interface_tiles(device.get(), metrics[i][1], channelId, - true, col, col); + auto tiles = get_interface_tiles(device.get(), metrics[i][1], channelId, true, col, col); - for (auto &t : tiles) { + for (auto& t : tiles) { configMetrics[moduleIdx][t] = metrics[i][1]; } } - } // Pass 3 + } // Pass 3 // Set default, check validity, and remove "off" tiles auto defaultSet = defaultSets[moduleIdx]; - //auto totalTiles = get_interface_tiles(device.get(), defaultSet, -1); - //for (auto &e : totalTiles) { - // if (configMetrics[moduleIdx].find(e) == configMetrics[moduleIdx].end()) { - // configMetrics[moduleIdx][e] = defaultSet; - // } - //} + // auto totalTiles = get_interface_tiles(device.get(), defaultSet, -1); + // for (auto &e : totalTiles) { + // if (configMetrics[moduleIdx].find(e) == configMetrics[moduleIdx].end()) + // { + // configMetrics[moduleIdx][e] = defaultSet; + // } + // } bool showWarning = true; std::vector offTiles; - for (auto &tileMetric : configMetrics[moduleIdx]) { + for (auto& tileMetric : configMetrics[moduleIdx]) { // Save list of "off" tiles if (tileMetric.second.empty() || (tileMetric.second.compare("off") == 0)) { offTiles.push_back(tileMetric.first); @@ -911,8 +917,8 @@ namespace xdp { auto metricVec = metricStrings[module_type::shim]; if (std::find(metricVec.begin(), metricVec.end(), tileMetric.second) == metricVec.end()) { if (showWarning) { - std::string msg = "Unable to find interface_tile metric set " + tileMetric.second - + ". Using default of " + defaultSet + ". "; + std::string msg = "Unable to find interface_tile metric set " + tileMetric.second + ". Using default of " + + defaultSet + ". "; xrt_core::message::send(severity_level::warning, "XRT", msg); showWarning = false; } @@ -921,7 +927,7 @@ namespace xdp { } // Remove all the "off" tiles - for (auto &t : offTiles) { + for (auto& t : offTiles) { configMetrics[moduleIdx].erase(t); } } @@ -929,8 +935,8 @@ namespace xdp { void AieProfileMetadata::read_aie_metadata(const char* data, size_t size, pt::ptree& aie_project) { std::stringstream aie_stream; - aie_stream.write(data,size); - pt::read_json(aie_stream,aie_project); + aie_stream.write(data, size); + pt::read_json(aie_stream, aie_project); } std::vector AieProfileMetadata::get_graphs(const xrt_core::device* device) @@ -950,7 +956,7 @@ namespace xdp { return graphs; } - + std::vector AieProfileMetadata::get_kernels(const xrt_core::device* device) { auto data = device->get_axlf_section(AIE_METADATA); @@ -966,7 +972,7 @@ namespace xdp { if (!kernelToTileMapping) return {}; - for (auto const &mapping : kernelToTileMapping.get()) { + for (auto const& mapping : kernelToTileMapping.get()) { std::vector names; std::string functionStr = mapping.second.get("function"); boost::split(names, functionStr, boost::is_any_of(".")); @@ -979,12 +985,12 @@ namespace xdp { uint8_t AieProfileMetadata::getMetricSetIndex(std::string metricString, module_type mod) { auto stringVector = metricStrings[mod]; - + auto itr = std::find(stringVector.begin(), stringVector.end(), metricString); - if (itr != stringVector.cend()){ + if (itr != stringVector.cend()) { return 0; } else { - return std::distance(stringVector.begin(), itr); + return static_cast(std::distance(stringVector.begin(), itr)); } } -} +} // namespace xdp diff --git a/src/runtime_src/xdp/profile/plugin/aie_profile/aie_profile_plugin.cpp b/src/runtime_src/xdp/profile/plugin/aie_profile/aie_profile_plugin.cpp index 71b02ec611c..e190b07666b 100644 --- a/src/runtime_src/xdp/profile/plugin/aie_profile/aie_profile_plugin.cpp +++ b/src/runtime_src/xdp/profile/plugin/aie_profile/aie_profile_plugin.cpp @@ -16,6 +16,8 @@ #define XDP_SOURCE +#include "xdp/profile/plugin/aie_profile/aie_profile_plugin.h" + #include #include #include @@ -31,15 +33,17 @@ #include "xdp/profile/device/device_intf.h" #include "xdp/profile/device/hal_device/xdp_hal_device.h" #include "xdp/profile/device/utility.h" -#include "xdp/profile/plugin/aie_profile/aie_profile_plugin.h" #include "xdp/profile/plugin/vp_base/info.h" #include "xdp/profile/writer/aie_profile/aie_writer.h" -#ifdef XRT_X86_BUILD - #include "x86/aie_profile.h" +#ifdef _WIN32 +#include "win/aie_profile.h" +// #include "shim.h" +#elif defined(XRT_X86_BUILD) +#include "x86/aie_profile.h" #else - #include "edge/aie_profile.h" - #include "core/edge/user/shim.h" +#include "core/edge/user/shim.h" +#include "edge/aie_profile.h" #endif namespace xdp { @@ -47,8 +51,7 @@ namespace xdp { bool AieProfilePlugin::live = false; - AieProfilePlugin::AieProfilePlugin() - : XDPPlugin() + AieProfilePlugin::AieProfilePlugin() : XDPPlugin() { AieProfilePlugin::live = true; @@ -85,17 +88,21 @@ namespace xdp { if (itr != handleToAIEData.end()) return itr->second.deviceID; +#ifdef _WIN32 + return 0; +#else char pathBuf[PATH_LENGTH]; memset(pathBuf, 0, PATH_LENGTH); + xclGetDebugIPlayoutPath(handle, pathBuf, PATH_LENGTH); std::string sysfspath(pathBuf); - uint64_t deviceID = db->addDevice(sysfspath); // Get the unique device Id + uint64_t deviceID = db->addDevice(sysfspath); // Get the unique device Id return deviceID; +#endif } void AieProfilePlugin::updateAIEDevice(void* handle) { - // Don't update if no profiling is requested if (!xrt_core::config::get_aie_profile()) return; @@ -108,66 +115,77 @@ namespace xdp { // Update the static database with information from xclbin (db->getStaticInfo()).updateDevice(deviceID, handle); { +#ifdef _WIN32 + (db->getStaticInfo()).setDeviceName(deviceID, "win_device"); +#else struct xclDeviceInfo2 info; - if(xclGetDeviceInfo2(handle, &info) == 0) { + if (xclGetDeviceInfo2(handle, &info) == 0) { (db->getStaticInfo()).setDeviceName(deviceID, std::string(info.mName)); } +#endif } - + // delete old data if (handleToAIEData.find(handle) != handleToAIEData.end()) - handleToAIEData.erase(handle); + handleToAIEData.erase(handle); auto& AIEData = handleToAIEData[handle]; AIEData.deviceID = deviceID; AIEData.metadata = std::make_shared(deviceID, handle); - #ifdef XRT_X86_BUILD - AIEData.implementation = std::make_unique(db, AIEData.metadata); - #else - AIEData.implementation = std::make_unique(db, AIEData.metadata); - #endif +#ifdef _WIN32 + AIEData.implementation = std::make_unique(db, AIEData.metadata); +#elif defined(XRT_X86_BUILD) + AIEData.implementation = std::make_unique(db, AIEData.metadata); +#else + AIEData.implementation = std::make_unique(db, AIEData.metadata); +#endif auto& implementation = AIEData.implementation; // Ensure we only read/configure once per xclbin if (!(db->getStaticInfo()).isAIECounterRead(deviceID)) { - - //Sets up and calls the PS kernel on x86 implementation - //Sets up and the hardware on the edge implementation + // Sets up and calls the PS kernel on x86 implementation + // Sets up and the hardware on the edge implementation implementation->updateDevice(); (db->getStaticInfo()).setIsAIECounterRead(deviceID, true); } // Open the writer for this device + auto time = std::time(nullptr); + +#ifdef _WIN32 + std::tm tm{}; + localtime_s(&tm, &time); + std::string deviceName = "win_device"; +#else + auto tm = *std::localtime(&time); struct xclDeviceInfo2 info; xclGetDeviceInfo2(handle, &info); std::string deviceName = std::string(info.mName); - - // Get current time - auto time = std::time(nullptr); - auto tm = *std::localtime(&time); +#endif + std::ostringstream timeOss; timeOss << std::put_time(&tm, "_%Y_%m_%d_%H%M%S"); std::string timestamp = timeOss.str(); std::string outputFile = "aie_profile_" + deviceName + timestamp + ".csv"; - - VPWriter* writer = new AIEProfilingWriter(outputFile.c_str(), - deviceName.c_str(), mIndex); + + VPWriter* writer = new AIEProfilingWriter(outputFile.c_str(), deviceName.c_str(), mIndex); writers.push_back(writer); db->getStaticInfo().addOpenedFile(writer->getcurrentFileName(), "AIE_PROFILE"); // Start the AIE profiling thread - AIEData.threadCtrlBool = true; + AIEData.threadCtrlBool = true; auto device_thread = std::thread(&AieProfilePlugin::pollAIECounters, this, mIndex, handle); - // auto device_thread = std::thread(&AieProfileImpl::pollAIECounters, implementation.get(), mIndex, handle); + // auto device_thread = std::thread(&AieProfileImpl::pollAIECounters, + // implementation.get(), mIndex, handle); AIEData.thread = std::move(device_thread); ++mIndex; } - void AieProfilePlugin::pollAIECounters(uint32_t index, void* handle) + void AieProfilePlugin::pollAIECounters(uint32_t index, void* handle) { auto it = handleToAIEData.find(handle); if (it == handleToAIEData.end()) @@ -177,9 +195,9 @@ namespace xdp { while (should_continue) { handleToAIEData[handle].implementation->poll(index, handle); - std::this_thread::sleep_for(std::chrono::microseconds(handleToAIEData[handle].metadata->getPollingIntervalVal())); + std::this_thread::sleep_for(std::chrono::microseconds(handleToAIEData[handle].metadata->getPollingIntervalVal())); } - //Final Polling Operation + // Final Polling Operation handleToAIEData[handle].implementation->poll(index, handle); } @@ -198,13 +216,11 @@ namespace xdp { void AieProfilePlugin::endPoll() { // Ask all threads to end - for (auto& p : handleToAIEData) - p.second.threadCtrlBool = false; + for (auto& p : handleToAIEData) p.second.threadCtrlBool = false; - for (auto& p : handleToAIEData) - p.second.thread.join(); + for (auto& p : handleToAIEData) p.second.thread.join(); handleToAIEData.clear(); } -} // end namespace xdp +} // end namespace xdp diff --git a/src/runtime_src/xdp/profile/plugin/aie_profile/win/aie_profile.cpp b/src/runtime_src/xdp/profile/plugin/aie_profile/win/aie_profile.cpp new file mode 100644 index 00000000000..9f6972d3489 --- /dev/null +++ b/src/runtime_src/xdp/profile/plugin/aie_profile/win/aie_profile.cpp @@ -0,0 +1,91 @@ +/** + * Copyright (C) 2022-2023 Advanced Micro Devices, Inc. - All rights reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may + * not use this file except in compliance with the License. A copy of the + * License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#define XDP_SOURCE + +#include "aie_profile.h" + +#include +#include +#include +#include + +#include "core/common/message.h" +#include "core/common/time.h" +#include "core/common/xrt_profiling.h" +#include "core/include/xrt/xrt_kernel.h" +#include "xdp/profile/database/database.h" +#include "xdp/profile/database/static_info/aie_constructs.h" +#include "xdp/profile/database/static_info/pl_constructs.h" + +namespace xdp { + + AieProfile_WinImpl::AieProfile_WinImpl(VPDatabase* database, std::shared_ptr metadata) + : AieProfileImpl(database, metadata) + { + // auto spdevice = xrt_core::get_userpf_device(metadata->getHandle()); + // device = xrt::device(spdevice); + + // auto uuid = device.get_xclbin_uuid(); + + // if (metadata->getHardwareGen() == 1) + // aie_profile_kernel = xrt::kernel(device, uuid.get(), + // "aie_profile_config"); + // else + // aie_profile_kernel = xrt::kernel(device, uuid.get(), + // "aie2_profile_config"); + } + + void AieProfile_WinImpl::updateDevice() + { + setMetricsSettings(metadata->getDeviceID(), metadata->getHandle()); + } + + void setupAIEProfiler(uint8_t col, uint8_t row, uint32_t start, uint32_t end) + { + std::cout << col << " " << row << " " << start << " " << end << std::endl; + // aiegraph_handle_.clearTransactionBuffer(); + // buffers_.clear(); + // inputs_.clear(); + // outputs_.clear(); + // bufferidx_to_xrt_subbo_.clear(); + // buffer_to_xrt_bo_.clear(); + + // std::vectorpc_list; + // pc_list.push_back(start); + // pc_list.push_back(end); + } + + bool AieProfile_WinImpl::setMetricsSettings(uint64_t deviceId, void* handle) + { + std::cout << deviceId << handle << std::endl; + return true; + } + + void AieProfile_WinImpl::poll(uint32_t index, void* handle) + { + std::cout << index << handle << std::endl; + // For now, we are waiting for a way to retreive polling information from + // the AIE. + return; + } + + void AieProfile_WinImpl::freeResources() + { + // TODO - if there are any resources we need to free after the application + // is complete, it must be done here. + } +} // namespace xdp diff --git a/src/runtime_src/xdp/profile/plugin/aie_profile/win/aie_profile.h b/src/runtime_src/xdp/profile/plugin/aie_profile/win/aie_profile.h new file mode 100644 index 00000000000..3dec1552327 --- /dev/null +++ b/src/runtime_src/xdp/profile/plugin/aie_profile/win/aie_profile.h @@ -0,0 +1,60 @@ +/** + * Copyright (C) 2022-2023 Advanced Micro Devices, Inc. - All rights reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may + * not use this file except in compliance with the License. A copy of the + * License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#ifndef AIE_PROFILE_H +#define AIE_PROFILE_H + +#include + +#include "core/include/xrt/xrt_kernel.h" +// #include "aiegraph.hpp" + +#include "xdp/profile/plugin/aie_profile/aie_profile_impl.h" + +namespace xdp { + + class AieProfile_WinImpl : public AieProfileImpl { + public: + AieProfile_WinImpl(VPDatabase* database, std::shared_ptr metadata); + ~AieProfile_WinImpl() = default; + + void updateDevice(); + void poll(uint32_t index, void* handle); + void freeResources(); + bool setMetricsSettings(uint64_t deviceId, void* handle); + + private: + xrt::device device; + // xrt::kernel aie_profile_kernel; + + // //inpu specific private members + // std::string name; + + // AIEGraphHandle aiegraph_handle; + // XrtContext &xrt_context_ + // std::vector bd_bundles; + // xrt::bo bo_fm; + // xrt::bo bo_instr; + // std::vector bufferidx_to_xrt_subbo; + + // std::unordered_set inputs; + // std::unordered_set outputs; + // std::unordered_set buffers; + }; + +} // namespace xdp + +#endif diff --git a/src/runtime_src/xdp/profile/plugin/aie_profile/x86/aie_profile.cpp b/src/runtime_src/xdp/profile/plugin/aie_profile/x86/aie_profile.cpp index 9a495e88bdd..a85dbd7763e 100644 --- a/src/runtime_src/xdp/profile/plugin/aie_profile/x86/aie_profile.cpp +++ b/src/runtime_src/xdp/profile/plugin/aie_profile/x86/aie_profile.cpp @@ -14,14 +14,14 @@ * under the License. */ -#define XDP_SOURCE +#define XDP_SOURCE + +#include "aie_profile.h" #include #include -#include #include - -#include "aie_profile.h" +#include #include "core/common/message.h" #include "core/common/time.h" @@ -33,11 +33,10 @@ #include "xdp/profile/plugin/aie_profile/aie_profile_metadata.h" #include "xdp/profile/plugin/aie_profile/x86/aie_profile_kernel_config.h" - constexpr uint32_t ALIGNMENT_SIZE = 4096; -constexpr uint64_t OUTPUT_SIZE = ALIGNMENT_SIZE * 22; //Calculated maximum output size for all 400 tiles -constexpr uint64_t INPUT_SIZE = ALIGNMENT_SIZE * 2; // input/output must be aligned to 4096 +constexpr uint64_t OUTPUT_SIZE = ALIGNMENT_SIZE * 22; // Calculated maximum output size for all 400 tiles +constexpr uint64_t INPUT_SIZE = ALIGNMENT_SIZE * 2; // input/output must be aligned to 4096 namespace xdp { using ProfileInputConfiguration = xdp::built_in::ProfileInputConfiguration; @@ -47,65 +46,62 @@ namespace xdp { using severity_level = xrt_core::message::severity_level; AieProfile_x86Impl::AieProfile_x86Impl(VPDatabase* database, std::shared_ptr metadata) - : AieProfileImpl(database, metadata) + : AieProfileImpl(database, metadata) { auto spdevice = xrt_core::get_userpf_device(metadata->getHandle()); device = xrt::device(spdevice); - + auto uuid = device.get_xclbin_uuid(); if (metadata->getHardwareGen() == 1) aie_profile_kernel = xrt::kernel(device, uuid.get(), "aie_profile_config"); - else + else aie_profile_kernel = xrt::kernel(device, uuid.get(), "aie2_profile_config"); } void AieProfile_x86Impl::updateDevice() { - setMetricsSettings(metadata->getDeviceID(), metadata->getHandle()); - } bool AieProfile_x86Impl::setMetricsSettings(uint64_t deviceId, void* handle) { - int NUM_MODULES = metadata->getNumModules(); - //Create the Configuration PS kernel - // Calculate number of tiles per module + // Create the Configuration PS kernel + // Calculate number of tiles per module int numTiles = 0; - for(int module = 0; module < NUM_MODULES; ++module) { + for (int module = 0; module < NUM_MODULES; ++module) { numTiles += metadata->getConfigMetrics(module).size(); } - std::size_t total_size = sizeof(ProfileInputConfiguration) + sizeof(ProfileTileType[numTiles-1]); + std::size_t total_size = sizeof(ProfileInputConfiguration) + sizeof(ProfileTileType[numTiles - 1]); ProfileInputConfiguration* input_params = (ProfileInputConfiguration*)malloc(total_size); input_params->numTiles = numTiles; input_params->offset = metadata->getAIETileRowOffset(); - - - //Create the Profile Tile Struct with All Tiles + // Create the Profile Tile Struct with All Tiles ProfileTileType profileTiles[numTiles]; int tile_idx = 0; auto configChannel0 = metadata->getConfigChannel0(); auto configChannel1 = metadata->getConfigChannel1(); - for(int module = 0; module < NUM_MODULES; ++module) { + for (int module = 0; module < NUM_MODULES; ++module) { auto configMetrics = metadata->getConfigMetrics(module); - for (auto &tileMetric : configMetrics){ + for (auto& tileMetric : configMetrics) { profileTiles[tile_idx].col = tileMetric.first.col; profileTiles[tile_idx].row = tileMetric.first.row; profileTiles[tile_idx].itr_mem_row = tileMetric.first.itr_mem_row; profileTiles[tile_idx].itr_mem_col = tileMetric.first.itr_mem_col; profileTiles[tile_idx].itr_mem_addr = tileMetric.first.itr_mem_addr; profileTiles[tile_idx].is_trigger = tileMetric.first.is_trigger; - profileTiles[tile_idx].metricSet = metadata->getMetricSetIndex(tileMetric.second, metadata->getModuleType(module)); + profileTiles[tile_idx].metricSet = + metadata->getMetricSetIndex(tileMetric.second, metadata->getModuleType(module)); profileTiles[tile_idx].tile_mod = module; - //If the tile is a memtile, check if any channel specification is present + // If the tile is a memtile, check if any channel specification is + // present if (configChannel0.count(tileMetric.first)) profileTiles[tile_idx].channel0 = configChannel0[tileMetric.first]; if (configChannel1.count(tileMetric.first)) @@ -119,13 +115,12 @@ namespace xdp { uint8_t* input = reinterpret_cast(input_params); try { - - //input bo + // input bo auto inbo = xrt::bo(device, INPUT_SIZE, 2); auto inbo_map = inbo.map(); std::fill(inbo_map, inbo_map + INPUT_SIZE, 0); - - //output bo + + // output bo auto outbo = xrt::bo(device, OUTPUT_SIZE, 2); auto outbo_map = outbo.map(); memset(outbo_map, 0, OUTPUT_SIZE); @@ -138,16 +133,18 @@ namespace xdp { outbo.sync(XCL_BO_SYNC_BO_FROM_DEVICE, OUTPUT_SIZE, 0); ProfileOutputConfiguration* cfg = reinterpret_cast(outbo_map); - - for (uint32_t i = 0; i < cfg->numCounters; i++){ + + for (uint32_t i = 0; i < cfg->numCounters; i++) { // Store counter info in database auto& counter = cfg->counters[i]; std::string counterName = "AIE Counter " + std::to_string(counter.counterId); - (db->getStaticInfo()).addAIECounter(deviceId, counter.counterId, counter.col, counter.row, counter.counterNum, - counter.startEvent, counter.endEvent, counter.resetEvent, counter.payload, metadata->getClockFreqMhz() , - metadata->getModuleName(counter.moduleName), counterName); + (db->getStaticInfo()) + .addAIECounter(deviceId, counter.counterId, counter.col, counter.row, counter.counterNum, + counter.startEvent, counter.endEvent, counter.resetEvent, counter.payload, + metadata->getClockFreqMhz(), metadata->getModuleName(counter.moduleName), counterName); } - } catch (...) { + } + catch (...) { std::string msg = "The aie_profile_config PS kernel was not found."; xrt_core::message::send(xrt_core::message::severity_level::warning, "XRT", msg); free(input_params); @@ -164,16 +161,15 @@ namespace xdp { void AieProfile_x86Impl::poll(uint32_t index, void* handle) { - try { - //input bo - // We Don't need to pass data from the db for polling since - // the counters are stored locally in PS memory after setup + // input bo + // We Don't need to pass data from the db for polling since + // the counters are stored locally in PS memory after setup auto inbo = xrt::bo(device, INPUT_SIZE, 2); auto inbo_map = inbo.map(); - memset(inbo_map, 0, INPUT_SIZE); - - //output bo + memset(inbo_map, 0, INPUT_SIZE); + + // output bo auto outbo = xrt::bo(device, OUTPUT_SIZE, 2); auto outbo_map = outbo.map(); memset(outbo_map, 0, OUTPUT_SIZE); @@ -183,7 +179,7 @@ namespace xdp { outbo.sync(XCL_BO_SYNC_BO_FROM_DEVICE, OUTPUT_SIZE, 0); ProfileOutputConfiguration* cfg = reinterpret_cast(outbo_map); - for (uint32_t i = 0; i < cfg->numCounters; i++){ + for (uint32_t i = 0; i < cfg->numCounters; i++) { std::vector values; auto& counter = cfg->counters[i]; values.push_back(counter.col); @@ -196,9 +192,9 @@ namespace xdp { values.push_back(counter.payload); double timestamp = xrt_core::time_ns() / 1.0e6; db->getDynamicInfo().addAIESample(index, timestamp, values); - } - - } catch (...) { + } + } + catch (...) { std::string msg = "The aie_profile polling failed."; xrt_core::message::send(xrt_core::message::severity_level::warning, "XRT", msg); return; @@ -210,19 +206,20 @@ namespace xdp { try { auto inbo = xrt::bo(device, INPUT_SIZE, 2); auto inbo_map = inbo.map(); - memset(inbo_map, 0, INPUT_SIZE); - - //output bo + memset(inbo_map, 0, INPUT_SIZE); + + // output bo auto outbo = xrt::bo(device, OUTPUT_SIZE, 2); auto outbo_map = outbo.map(); memset(outbo_map, 0, OUTPUT_SIZE); auto run = aie_profile_kernel(inbo, outbo, 2 /*cleanup iteration*/); run.wait(); - } catch (...) { + } + catch (...) { std::string msg = "The aie_profile cleanup failed."; xrt_core::message::send(xrt_core::message::severity_level::warning, "XRT", msg); return; } } -} +} // namespace xdp diff --git a/src/runtime_src/xdp/profile/plugin/aie_profile/x86/aie_profile_kernel_config.h b/src/runtime_src/xdp/profile/plugin/aie_profile/x86/aie_profile_kernel_config.h index f13c9c4738a..9637485502a 100644 --- a/src/runtime_src/xdp/profile/plugin/aie_profile/x86/aie_profile_kernel_config.h +++ b/src/runtime_src/xdp/profile/plugin/aie_profile/x86/aie_profile_kernel_config.h @@ -18,107 +18,94 @@ #define AIE_PROFILE_CONFIG_DOT_H namespace xdp { -namespace built_in { - - - - enum class CoreMetrics : uint8_t - { - HEAT_MAP = 0, - STALLS = 1, - EXECUTION = 2, - FLOATING_POINT = 3, - STREAM_PUT_GET = 4, - WRITE_BANDWIDTHS = 5, - READ_BANDWIDTHS = 6, - AIE_TRACE = 7, - EVENTS = 8 - }; - - enum class MemoryMetrics : uint8_t - { - CONFLICTS = 0, - DMA_LOCKS = 1, - DMA_STALLS_S2MM = 2, - DMA_STALLS_MM2S = 3, - WRITE_BANDWIDTHS = 4, - READ_BANDWIDTHS = 5 - }; - - enum class InterfaceMetrics : uint8_t - { - INPUT_BANDWIDTHS = 0, - OUTPUT_BANDWIDTHS = 1, - PACKETS = 2 - }; - - enum class MemTileMetrics : uint8_t - { - INPUT_CHANNELS = 0, - INPUT_CHANNELS_DETAILS = 1, - OUTPUT_CHANNELS = 2, - OUTPUT_CHANNELS_DETAILS = 3, - MEMORY_STATS = 4, - MEM_TRACE = 5 - }; - - // This struct is used for input for the PS kernel. It contains all of - // the information gathered from the user controls in the xrt.ini file - // and the information we can infer from the debug ip layout file. - // The struct should be constructed and then transferred via a buffer object. - // - // Since this is transferred from host to device, it should have - // a C-Style interface. - - struct ProfileTileType { - uint16_t row; - uint16_t col; - uint16_t itr_mem_row; - uint16_t itr_mem_col; - uint64_t itr_mem_addr; - bool is_trigger; - uint8_t metricSet; - uint8_t tile_mod; - uint8_t channel0 = -1; - uint8_t channel1 = -1; - }; - - struct ProfileInputConfiguration - { - static constexpr auto NUM_CORE_COUNTERS = 4; - static constexpr auto NUM_MEMORY_COUNTERS = 2; - static constexpr auto NUM_SHIM_COUNTERS = 2; - static constexpr auto NUM_MEM_TILE_COUNTERS = 4; - - uint16_t numTiles; - uint8_t offset; - - // uint16_t numTiles[NUM_MODULES]; // Make unique variab - ProfileTileType tiles[1]; //flexible array member - }; - - struct PSCounterInfo - { - uint8_t moduleName; - uint16_t col; - uint16_t row; - uint16_t startEvent; - uint16_t endEvent; - uint32_t counterValue; - uint32_t payload; - uint32_t counterNum; //.Counter number in the tile - uint32_t counterId; // Counter ID in list of all possible counters - uint64_t resetEvent; - uint64_t timerValue; - }; - - struct ProfileOutputConfiguration - { - uint32_t numCounters; - PSCounterInfo counters[1]; - }; - -} // end namespace built_in -} // end namespace xdp + namespace built_in { + + enum class CoreMetrics : uint8_t { + HEAT_MAP = 0, + STALLS = 1, + EXECUTION = 2, + FLOATING_POINT = 3, + STREAM_PUT_GET = 4, + WRITE_BANDWIDTHS = 5, + READ_BANDWIDTHS = 6, + AIE_TRACE = 7, + EVENTS = 8 + }; + + enum class MemoryMetrics : uint8_t { + CONFLICTS = 0, + DMA_LOCKS = 1, + DMA_STALLS_S2MM = 2, + DMA_STALLS_MM2S = 3, + WRITE_BANDWIDTHS = 4, + READ_BANDWIDTHS = 5 + }; + + enum class InterfaceMetrics : uint8_t { INPUT_BANDWIDTHS = 0, OUTPUT_BANDWIDTHS = 1, PACKETS = 2 }; + + enum class MemTileMetrics : uint8_t { + INPUT_CHANNELS = 0, + INPUT_CHANNELS_DETAILS = 1, + OUTPUT_CHANNELS = 2, + OUTPUT_CHANNELS_DETAILS = 3, + MEMORY_STATS = 4, + MEM_TRACE = 5 + }; + + // This struct is used for input for the PS kernel. It contains all of + // the information gathered from the user controls in the xrt.ini file + // and the information we can infer from the debug ip layout file. + // The struct should be constructed and then transferred via a buffer object. + // + // Since this is transferred from host to device, it should have + // a C-Style interface. + + struct ProfileTileType { + uint16_t row; + uint16_t col; + uint16_t itr_mem_row; + uint16_t itr_mem_col; + uint64_t itr_mem_addr; + bool is_trigger; + uint8_t metricSet; + uint8_t tile_mod; + int8_t channel0 = -1; + int8_t channel1 = -1; + }; + + struct ProfileInputConfiguration { + static constexpr auto NUM_CORE_COUNTERS = 4; + static constexpr auto NUM_MEMORY_COUNTERS = 2; + static constexpr auto NUM_SHIM_COUNTERS = 2; + static constexpr auto NUM_MEM_TILE_COUNTERS = 4; + + uint16_t numTiles; + uint16_t offset; + + // uint16_t numTiles[NUM_MODULES]; // Make unique variab + ProfileTileType tiles[1]; // flexible array member + }; + + struct PSCounterInfo { + uint8_t moduleName; + uint16_t col; + uint16_t row; + uint16_t startEvent; + uint16_t endEvent; + uint32_t counterValue; + uint32_t payload; + uint8_t counterNum; //.Counter number in the tile + uint32_t counterId; // Counter ID in list of all possible counters + uint8_t resetEvent; + uint64_t timerValue; + }; + + struct ProfileOutputConfiguration { + uint32_t numCounters; + PSCounterInfo counters[1]; + }; + + } // end namespace built_in +} // end namespace xdp #endif diff --git a/src/runtime_src/xdp/profile/writer/aie_profile/aie_writer.cpp b/src/runtime_src/xdp/profile/writer/aie_profile/aie_writer.cpp index 79a737f8d55..d40a70b6b5d 100644 --- a/src/runtime_src/xdp/profile/writer/aie_profile/aie_writer.cpp +++ b/src/runtime_src/xdp/profile/writer/aie_profile/aie_writer.cpp @@ -35,7 +35,7 @@ namespace xdp { { } - bool AIEProfilingWriter::write(bool openNewFile) + bool AIEProfilingWriter::write(bool) { // Report HW generation to inform analysis how to interpret event IDs auto aieGeneration = (db->getStaticInfo()).getAIEGeneration(mDeviceIndex); diff --git a/src/runtime_src/xdp/profile/writer/aie_profile/aie_writer.h b/src/runtime_src/xdp/profile/writer/aie_profile/aie_writer.h index fa79b738b23..5e9c072d979 100644 --- a/src/runtime_src/xdp/profile/writer/aie_profile/aie_writer.h +++ b/src/runtime_src/xdp/profile/writer/aie_profile/aie_writer.h @@ -29,7 +29,7 @@ namespace xdp { uint64_t deviceIndex); ~AIEProfilingWriter(); - virtual bool write(bool openNewFile); + virtual bool write(bool openNewFile = true); private: std::string mDeviceName;