diff --git a/profile/plugin/aie_dtrace/aie_dtrace_metadata.cpp b/profile/plugin/aie_dtrace/aie_dtrace_metadata.cpp index 0013e511..c4d50de4 100644 --- a/profile/plugin/aie_dtrace/aie_dtrace_metadata.cpp +++ b/profile/plugin/aie_dtrace/aie_dtrace_metadata.cpp @@ -15,6 +15,7 @@ #include "core/common/message.h" #include "xdp/profile/database/database.h" #include "xdp/profile/database/static_info/aie_util.h" +#include "xdp/profile/plugin/aie_dtrace/util/aie_dtrace_util.h" #include "xdp/profile/plugin/vp_base/profiling_runtime_config.h" namespace xdp { @@ -29,6 +30,21 @@ namespace xdp { return metrics; } + static constexpr const char* L2L2_TRANSFER_METRIC_SET = "l2_l2_transfer"; + + bool settingsRequestL2L2Transfer(const std::vector& metricsSettings) + { + for (const auto& setting : metricsSettings) { + std::vector parts; + boost::split(parts, setting, boost::is_any_of(":")); + for (const auto& part : parts) { + if (part == L2L2_TRANSFER_METRIC_SET) + return true; + } + } + return false; + } + AieDtraceMetadata::AieDtraceMetadata(uint64_t deviceID, void* handle) : deviceID(deviceID) , handle(handle) @@ -54,9 +70,27 @@ namespace xdp { + "' 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."); + if (*ci.mem_tile == L2L2_TRANSFER_METRIC_SET) { + l2L2TransferEnabled = true; + xrt_core::message::send(severity_level::info, "XRT", + "AIE dtrace: enabling L2-L2 via mem_tile metric '" + *ci.mem_tile + + "' from Debug.profiling_runtime_config."); + } else { + 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."); + } + } + } + + if (l2L2TransferEnabled) { + const auto designPoints = aie::dtrace::parseL2L2DesignPoints( + xrt_core::config::get_aie_dtrace_settings_l2_l2_design_points()); + if (designPoints.empty()) { + xrt_core::message::send(severity_level::warning, "XRT", + "AIE dtrace: L2-L2 is enabled but AIE_dtrace_settings.l2_l2_design_points is " + "empty or invalid (expected {column,row:port} entries). " + "L2-L2 counters will not be appended to the CT."); } } @@ -86,6 +120,8 @@ namespace xdp { using boost::property_tree::ptree; const std::set validSettings { "tile_based_interface_tile_metrics", + "tile_based_memory_tile_metrics", + "l2_l2_design_points", "configure_aie_hardware", "config_one_partition", }; @@ -94,6 +130,12 @@ namespace xdp { if (auto val = tree.get_optional("config_one_partition")) configOnePartition = *val; + l2L2TransferEnabled = false; + const std::string memTileSettings = + xrt_core::config::get_aie_dtrace_settings_tile_based_memory_tile_metrics(); + if (!memTileSettings.empty()) + l2L2TransferEnabled = settingsRequestL2L2Transfer(getSettingsVector(memTileSettings)); + for (ptree::iterator pos = tree.begin(); pos != tree.end(); pos++) { if (validSettings.find(pos->first) == validSettings.end()) { std::stringstream msg; diff --git a/profile/plugin/aie_dtrace/aie_dtrace_metadata.h b/profile/plugin/aie_dtrace/aie_dtrace_metadata.h index f75f99c6..7928b9e8 100644 --- a/profile/plugin/aie_dtrace/aie_dtrace_metadata.h +++ b/profile/plugin/aie_dtrace/aie_dtrace_metadata.h @@ -24,6 +24,7 @@ class AieDtraceMetadata { double clockFreqMhz = 0.0; void* handle = nullptr; bool configOnePartition = false; + bool l2L2TransferEnabled = false; std::vector> configMetrics; std::map configChannel0; @@ -49,6 +50,8 @@ class AieDtraceMetadata { bool isConfigOnePartition() const { return configOnePartition; } + bool isL2L2Enabled() const { return l2L2TransferEnabled; } + bool aieMetadataEmpty() { return metadataReader == nullptr; } std::vector getSettingsVector(std::string settingsString); diff --git a/profile/plugin/aie_dtrace/util/aie_dtrace_util.cpp b/profile/plugin/aie_dtrace/util/aie_dtrace_util.cpp index 93352107..7e117eb1 100644 --- a/profile/plugin/aie_dtrace/util/aie_dtrace_util.cpp +++ b/profile/plugin/aie_dtrace/util/aie_dtrace_util.cpp @@ -5,8 +5,69 @@ #include "xdp/profile/plugin/aie_dtrace/util/aie_dtrace_util.h" +#include "core/common/config_reader.h" +#include "core/common/message.h" + +#include +#include +#include + namespace xdp::aie::dtrace { + namespace { + using severity_level = xrt_core::message::severity_level; + + static constexpr unsigned int DEFAULT_COALESCE_RESULT_MEMORY_MB = 256; + + void addPortCounterPair(std::vector& points, + uint8_t column, + uint8_t portIndex, + uint8_t runningCounter, + uint8_t stalledCounter) + { + L2L2CounterPoint running; + running.column = column; + running.row = MEM_TILE_ROW_START; + running.portIndex = portIndex; + running.counterNumber = runningCounter; + running.eventType = "running"; + points.push_back(running); + + L2L2CounterPoint stalled; + stalled.column = column; + stalled.row = MEM_TILE_ROW_START; + stalled.portIndex = portIndex; + stalled.counterNumber = stalledCounter; + stalled.eventType = "stalled"; + points.push_back(stalled); + } + + } // namespace + + void + initDtraceOutputConfig() + { + static std::once_flag once; + std::call_once(once, []() { + try { + xrt_core::config::detail::set("Debug.dtrace_output_json_format", "true"); + xrt_core::config::detail::set("Debug.dtrace_coalesce_result", "true"); + xrt_core::config::detail::set("Debug.dtrace_coalesce_result_memory_mb", + std::to_string(DEFAULT_COALESCE_RESULT_MEMORY_MB)); + } + catch (const std::exception& e) { + xrt_core::message::send(severity_level::warning, "XRT", + std::string("AIE dtrace: could not apply default dtrace output settings: ") + + e.what()); + return; + } + + xrt_core::message::send(severity_level::info, "XRT", + "AIE dtrace: enabled JSON dtrace_dump output with coalesced results " + "(dtrace_dump_ctx__.json on hw context teardown)"); + }); + } + std::map> getBandwidthInterfaceTileEventSets(int hwGen) { @@ -26,4 +87,81 @@ namespace xdp::aie::dtrace { }; } + std::vector parseL2L2DesignPoints(const std::string& spec) + { + std::vector points; + if (spec.empty()) + return points; + + // Format: {column,row:port} — row is accepted for INI readability only (ignored). + static const std::regex pointRegex(R"(\{\s*(\d+)\s*,\s*(\d+)\s*:\s*(\d+)\s*\})"); + const auto begin = std::sregex_iterator(spec.begin(), spec.end(), pointRegex); + const auto end = std::sregex_iterator(); + for (auto it = begin; it != end; ++it) { + try { + const unsigned long column = std::stoul((*it)[1].str()); + const unsigned long dstPort = std::stoul((*it)[3].str()); + if (column > 255 || (dstPort != 1 && dstPort != 2)) + continue; + + L2L2InstrumentPoint point; + point.column = static_cast(column); + point.dstPort = static_cast(dstPort); + points.push_back(point); + } + catch (const std::exception&) { + continue; + } + } + return points; + } + + std::vector getL2L2CounterPoints( + uint32_t startCol, + uint32_t numCols, + const std::vector& instrumentPoints) + { + if (numCols == 0 || instrumentPoints.empty()) + return {}; + + const uint32_t endCol = startCol + numCols; + std::vector points; + points.reserve(instrumentPoints.size() * 2); + +/*=================old hardcoded values========================== +// Stamp 0 edge (col 1): one dst path -> ctr 0,1 -> PerfCtrl0 only +addPortCounterPair(points, 1, 2, 0, 1); + +// Stamps 1-4 middle (cols 5, 9, 13, 17): two dst paths -> ctr 0-3 -> PerfCtrl0 + PerfCtrl1 +addPortCounterPair(points, 5, 1, 0, 1); +addPortCounterPair(points, 5, 2, 2, 3); +addPortCounterPair(points, 9, 1, 0, 1); +addPortCounterPair(points, 9, 2, 2, 3); +addPortCounterPair(points, 13, 1, 0, 1); +addPortCounterPair(points, 13, 2, 2, 3); +addPortCounterPair(points, 17, 1, 0, 1); +addPortCounterPair(points, 17, 2, 2, 3); +// Stamp 5 edge (col 21): one dst path -> ctr 0,1 -> PerfCtrl0 only +addPortCounterPair(points, 21, 1, 0, 1); +=============================================================== */ + + // Assign counters 0-1 for the first dst path on a tile, 2-3 for the second. + std::map nextCounterByColumn; + for (const auto& instrumentPoint : instrumentPoints) { + const uint32_t column = instrumentPoint.column; + if (column < startCol || column >= endCol) + continue; + + uint8_t& nextCounter = nextCounterByColumn[instrumentPoint.column]; + if (nextCounter >= L2L2_MAX_DST_PATHS_PER_COLUMN * 2) + continue; + + addPortCounterPair(points, instrumentPoint.column, instrumentPoint.dstPort, + nextCounter, static_cast(nextCounter + 1)); + nextCounter = static_cast(nextCounter + 2); + } + + return points; + } + } // namespace xdp::aie::dtrace diff --git a/profile/plugin/aie_dtrace/util/aie_dtrace_util.h b/profile/plugin/aie_dtrace/util/aie_dtrace_util.h index 2a49a334..7f5392fb 100644 --- a/profile/plugin/aie_dtrace/util/aie_dtrace_util.h +++ b/profile/plugin/aie_dtrace/util/aie_dtrace_util.h @@ -4,6 +4,7 @@ #ifndef AIE_DTRACE_UTIL_DOT_H #define AIE_DTRACE_UTIL_DOT_H +#include #include #include #include @@ -17,6 +18,44 @@ namespace xdp::aie::dtrace { // Shim bandwidth metric sets used for Debug.aie_dtrace (not part of standard aie_profile ini). std::map> getBandwidthInterfaceTileEventSets(int hwGen); + // ===========================L2L2 transfer metrics ========================================== + + // Inter-stamp memtile halo dst paths; design points come from xrt.ini. + // Max dst halo paths per memtile column (4 perf counters, running+stalled per path). + static constexpr uint8_t L2L2_MAX_DST_PATHS_PER_COLUMN = 2; + // Memtile row 0 (absolute array row 1; row 0 = shim/interface tile). + static constexpr uint8_t MEM_TILE_ROW_START = 1; + + struct L2L2InstrumentPoint { + uint8_t column = 0; + uint8_t dstPort = 1; + }; + + // One perf counter at a memtile dst halo path (running or stalled). + struct L2L2CounterPoint { + uint8_t column = 0; + uint8_t row = 0; + uint8_t portIndex = 1; // halo dst port (1 = from left neighbor, 2 = from right) + uint8_t counterNumber = 0; // memtile perf counter 0-3 on this tile + std::string eventType; // "running" or "stalled" + }; + + // Parses AIE_dtrace_settings.l2_l2_design_points, e.g. "{1,1:2},{5,1:1},{5,1:2}". + // INI uses {column,row:port} for readability; row is ignored — counters use MEM_TILE_ROW_START. + std::vector parseL2L2DesignPoints(const std::string& spec); + + // Builds running+stalled counter pairs from xrt.ini design points within the partition. + std::vector getL2L2CounterPoints( + uint32_t startCol, + uint32_t numCols, + const std::vector& instrumentPoints); + + // ======================================================================================== + + // Enable JSON dtrace_dump output with coalesced results by default. + // Must run before XRT creates the first dtrace module (config keys lock on first read). + void initDtraceOutputConfig(); + } // namespace xdp::aie::dtrace #endif diff --git a/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.cpp b/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.cpp index a5f313fa..8a9086bc 100644 --- a/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.cpp +++ b/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.cpp @@ -9,6 +9,7 @@ #include "xdp/profile/database/static_info/aie_constructs.h" #include "xdp/profile/database/static_info/aie_util.h" +#include "core/common/config_reader.h" #include "core/common/message.h" #include @@ -87,6 +88,35 @@ extendLastUcToMaxConfiguredColumn(std::vector& asmFileInfoList, last.colEnd = std::max(last.colEnd, maxCfgCol); } +void +writeBandwidthMetadataCounterLine(std::ostream& out, const CTCounterInfo& ctr) +{ + out << "# {\"col\": " << static_cast(ctr.column) + << ", \"row\": " << static_cast(ctr.row) + << ", \"ctr\": " << static_cast(ctr.counterNumber) + << ", \"ch\": " << static_cast(ctr.channel); + + out << ", \"dir\": "; + if (ctr.portDirection == "input") + out << "\"i\""; + else if (ctr.portDirection == "output") + out << "\"o\""; + else + out << "null"; + + if (!ctr.eventType.empty()) { + out << ", \"event\": "; + if (ctr.eventType == "running") + out << "\"r\""; + else if (ctr.eventType == "stalled") + out << "\"s\""; + else + out << "\"" << ctr.eventType << "\""; + } + + out << "}"; +} + } // namespace using severity_level = xrt_core::message::severity_level; @@ -1043,7 +1073,9 @@ bool AieDtraceCTWriter::writeBandwidthCTFile( const std::vector& asmFileInfoList, const std::vector& allCounters, const std::vector& beginBlockWrites, - const std::string& outputPath) + const std::string& outputPath, + const std::vector& l2l2BeginBlockWrites, + const std::vector& allL2l2Counters) { std::ofstream ctFile(outputPath); @@ -1057,7 +1089,10 @@ bool AieDtraceCTWriter::writeBandwidthCTFile( ctFile << "# Auto-generated CT file for AIE bandwidth monitoring\n"; ctFile << "# Generated by XRT AIE Dtrace Plugin (simplified bandwidth mode)\n"; ctFile << "# Fixed 4 counters per shim tile: S2MM ch0,ch1 + MM2S ch0,ch1\n"; - ctFile << "# Post-processing filters by metric: read_bandwidth, write_bandwidth, ddr_bandwidth\n\n"; + ctFile << "# Post-processing filters by metric: read_bandwidth, write_bandwidth, ddr_bandwidth\n"; + if (!allL2l2Counters.empty()) + ctFile << "# Memtile L2-L2 inter-stamp halo counters appended when tile_based_memory_tile_metrics includes l2_l2_transfer\n"; + ctFile << "\n"; ctFile << "begin\n"; ctFile << "{\n"; @@ -1075,55 +1110,58 @@ bool AieDtraceCTWriter::writeBandwidthCTFile( ctFile << "\n"; } + if (!l2l2BeginBlockWrites.empty()) { + ctFile << " # Hardware configuration for memtile L2-L2 counters (counter reset + perf ctrl)\n"; + for (const auto& write : l2l2BeginBlockWrites) { + if (!write.comment.empty()) + ctFile << " # " << write.comment << "\n"; + ctFile << " write_reg(" << formatAddress(write.address) + << ", 0x" << std::hex << std::setfill('0') << std::setw(8) + << write.value << std::dec << ")\n"; + } + ctFile << "\n"; + } + ctFile << "@blockopen\n"; ctFile << "# COUNTER_METADATA_BEGIN\n"; ctFile << "# {\n"; - // Per-UC counter metadata groupings only + // Per-UC counter metadata: shim bandwidth + memtile L2-L2 merged by column within each stamp. std::vector metaGroups; for (const auto& asmFileInfo : asmFileInfoList) { - if (!asmFileInfo.counters.empty()) + if (!asmFileInfo.counters.empty() || !asmFileInfo.l2l2Counters.empty()) metaGroups.push_back(&asmFileInfo); } for (size_t g = 0; g < metaGroups.size(); g++) { const auto& asmFileInfo = *metaGroups[g]; - ctFile << "# \"" << asmFileInfo.asmId << "\": [\n"; + std::vector mergedMetadata; + mergedMetadata.reserve(asmFileInfo.counters.size() + asmFileInfo.l2l2Counters.size()); + for (const auto& ctr : asmFileInfo.counters) + mergedMetadata.push_back(&ctr); + for (const auto& ctr : asmFileInfo.l2l2Counters) + mergedMetadata.push_back(&ctr); + + std::sort(mergedMetadata.begin(), mergedMetadata.end(), + [](const CTCounterInfo* a, const CTCounterInfo* b) { + if (a->column != b->column) + return a->column < b->column; + if (a->row != b->row) + return a->row < b->row; + return a->counterNumber < b->counterNumber; + }); - for (size_t c = 0; c < asmFileInfo.counters.size(); c++) { - const auto& ctr = asmFileInfo.counters[c]; - ctFile << "# {\"col\": " << static_cast(ctr.column) - << ", \"row\": " << static_cast(ctr.row) - << ", \"ctr\": " << static_cast(ctr.counterNumber) - << ", \"ch\": " << static_cast(ctr.channel) - << ", \"dir\": "; - - if (ctr.portDirection == "input") - ctFile << "\"i\""; - else if (ctr.portDirection == "output") - ctFile << "\"o\""; - else - ctFile << "null"; - - // Add event type for peak bandwidth metrics - if (!ctr.eventType.empty()) { - ctFile << ", \"event\": "; - if (ctr.eventType == "running") - ctFile << "\"r\""; - else if (ctr.eventType == "stalled") - ctFile << "\"s\""; - else - ctFile << "\"" << ctr.eventType << "\""; - } + ctFile << "# \"" << asmFileInfo.asmId << "\": [\n"; - ctFile << "}"; - if (c < asmFileInfo.counters.size() - 1) + for (size_t c = 0; c < mergedMetadata.size(); c++) { + writeBandwidthMetadataCounterLine(ctFile, *mergedMetadata[c]); + if (c + 1 < mergedMetadata.size()) ctFile << ","; ctFile << "\n"; } ctFile << "# ]"; - if (g < metaGroups.size() - 1) + if (g + 1 < metaGroups.size()) ctFile << ","; ctFile << "\n"; } @@ -1134,7 +1172,8 @@ bool AieDtraceCTWriter::writeBandwidthCTFile( ctFile << "}\n\n"; for (const auto& asmFileInfo : asmFileInfoList) { - if (asmFileInfo.timestamps.empty() || asmFileInfo.counters.empty()) + if (asmFileInfo.timestamps.empty() + || (asmFileInfo.counters.empty() && asmFileInfo.l2l2Counters.empty())) continue; std::string basename = fs::path(asmFileInfo.filename).filename().string(); @@ -1156,10 +1195,23 @@ bool AieDtraceCTWriter::writeBandwidthCTFile( ctFile << "{\n"; ctFile << " ts_" << asmFileInfo.asmId << " = timestamp32()\n"; - for (size_t i = 0; i < asmFileInfo.counters.size(); i++) { - const auto& ctr = asmFileInfo.counters[i]; - ctFile << " _ = read_reg(" << formatAddress(ctr.address) << ")\n"; - } + std::vector mergedProbes; + mergedProbes.reserve(asmFileInfo.counters.size() + asmFileInfo.l2l2Counters.size()); + for (const auto& ctr : asmFileInfo.counters) + mergedProbes.push_back(&ctr); + for (const auto& ctr : asmFileInfo.l2l2Counters) + mergedProbes.push_back(&ctr); + std::sort(mergedProbes.begin(), mergedProbes.end(), + [](const CTCounterInfo* a, const CTCounterInfo* b) { + if (a->column != b->column) + return a->column < b->column; + if (a->row != b->row) + return a->row < b->row; + return a->counterNumber < b->counterNumber; + }); + + for (const CTCounterInfo* ctr : mergedProbes) + ctFile << " _ = read_reg(" << formatAddress(ctr->address) << ")\n"; ctFile << "}\n\n"; } @@ -1173,7 +1225,10 @@ bool AieDtraceCTWriter::writeBandwidthCTFile( std::stringstream msg; msg << "Generated bandwidth CT file: " << outputPath - << " (" << allCounters.size() << " counters)"; + << " (" << allCounters.size() << " shim counters"; + if (!allL2l2Counters.empty()) + msg << ", " << allL2l2Counters.size() << " memtile L2-L2 counters"; + msg << ")"; xrt_core::message::send(severity_level::info, "XRT", msg.str()); return true; @@ -1252,10 +1307,71 @@ bool AieDtraceCTWriter::generateBandwidthCT( return false; } - extendLastUcToMaxConfiguredColumn(asmFileInfoList, allCounters); + // ========================================= L2-L2 transfer metrics ========================================== + std::vector allL2l2Counters; + std::vector l2l2BeginBlockWrites; + if (metadata && metadata->isL2L2Enabled()) { + boost::property_tree::ptree aiePartitionPt = xdp::aie::getAIEPartitionInfo(hwctx); + const uint32_t numCols = aiePartitionPt.empty() ? 0 + : static_cast(aiePartitionPt.back().second.get("num_cols", 0)); + + const auto instrumentPoints = aie::dtrace::parseL2L2DesignPoints( + xrt_core::config::get_aie_dtrace_settings_l2_l2_design_points()); + if (!instrumentPoints.empty()) { + auto counterPoints = aie::dtrace::getL2L2CounterPoints( + partitionStartCol, numCols, instrumentPoints); + if (counterPoints.size() == instrumentPoints.size() * 2) { + std::map> pointsByColumn; + for (const auto& point : counterPoints) + pointsByColumn[point.column].push_back(point); + + for (const auto& entry : pointsByColumn) { + auto pcWrites = generateMemtilePerfCounterConfig(entry.first, entry.second); + l2l2BeginBlockWrites.insert(l2l2BeginBlockWrites.end(), + pcWrites.begin(), pcWrites.end()); + } + + for (const auto& point : counterPoints) { + CTCounterInfo info; + info.column = point.column; + info.row = point.row; + info.counterNumber = point.counterNumber; + info.channel = point.portIndex; + info.module = "memory_tile"; + info.address = calculateCounterAddress(point.column, point.row, point.counterNumber, + "memory_tile"); + info.metricSet = "l2_l2_transfer"; + info.portDirection = "input"; + info.eventType = point.eventType; + allL2l2Counters.push_back(info); + } + + std::stringstream l2Msg; + l2Msg << "AIE dtrace: Appending " << allL2l2Counters.size() + << " inter-stamp memtile L2-L2 counters to bandwidth CT (start_col=" + << static_cast(partitionStartCol) << ", num_cols=" << numCols << ")"; + xrt_core::message::send(severity_level::info, "XRT", l2Msg.str()); + } else { + std::stringstream l2Msg; + l2Msg << "AIE dtrace: L2-L2 design points are invalid for this partition (start_col=" + << static_cast(partitionStartCol) << ", num_cols=" << numCols + << "). Check l2_l2_design_points {column,row:dstPort} entries per memtile (max " + << static_cast(aie::dtrace::L2L2_MAX_DST_PATHS_PER_COLUMN) + << "). Skipping L2-L2 CT append."; + xrt_core::message::send(severity_level::warning, "XRT", l2Msg.str()); + } + } + } + // ========================================= L2-L2 transfer metrics ========================================== + + if (!allL2l2Counters.empty()) + extendLastUcToMaxConfiguredColumn(asmFileInfoList, allL2l2Counters); + if (!allCounters.empty()) + extendLastUcToMaxConfiguredColumn(asmFileInfoList, allCounters); for (auto& asmFileInfo : asmFileInfoList) { asmFileInfo.counters = filterCountersByColumn(allCounters, asmFileInfo.colStart, asmFileInfo.colEnd); + asmFileInfo.l2l2Counters = filterCountersByColumn(allL2l2Counters, asmFileInfo.colStart, asmFileInfo.colEnd); } std::vector beginBlockWrites; @@ -1269,7 +1385,76 @@ bool AieDtraceCTWriter::generateBandwidthCT( beginBlockWrites.insert(beginBlockWrites.end(), pcWrites.begin(), pcWrites.end()); } - return writeBandwidthCTFile(asmFileInfoList, allCounters, beginBlockWrites, outputPath); + return writeBandwidthCTFile(asmFileInfoList, allCounters, beginBlockWrites, outputPath, + l2l2BeginBlockWrites, allL2l2Counters); +} + +// ===========================L2L2 transfer metrics ========================================== +std::vector AieDtraceCTWriter::generateMemtilePerfCounterConfig( + uint8_t column, + const std::vector& counterPoints) +{ + std::vector writes; + if (counterPoints.empty()) + return writes; + + const uint8_t row = counterPoints.front().row; + uint64_t tileAddress = (static_cast(column) << columnShift) | + (static_cast(row) << rowShift); + + uint8_t counterEvents[4] = {0, 0, 0, 0}; + bool counterUsed[4] = {false, false, false, false}; + for (const auto& point : counterPoints) { + if (point.counterNumber > 3) + continue; + if (point.eventType == "stalled") + counterEvents[point.counterNumber] = + static_cast(PORT_STALLED_0_MEM_TILE_EVENT + (point.portIndex * 4)); + else + counterEvents[point.counterNumber] = + static_cast(PORT_RUNNING_0_MEM_TILE_EVENT + (point.portIndex * 4)); + counterUsed[point.counterNumber] = true; + } + + for (uint8_t ctr = 0; ctr < 4; ++ctr) { + if (!counterUsed[ctr]) + continue; + + CTRegisterWrite resetWrite; + resetWrite.address = tileAddress + MEM_TILE_BASE_OFFSET + (ctr * 4); + resetWrite.value = 0; + resetWrite.comment = "Reset memtile PerfCounter" + std::to_string(ctr) + + " @ col " + std::to_string(column); + writes.push_back(resetWrite); + } + + // Outer stamps use counters 0-1 only (PerfCtrl0); inner stamps use 0-3 (PerfCtrl0 + PerfCtrl1). + if (counterUsed[0] || counterUsed[1]) { + CTRegisterWrite ctrlWrite; + ctrlWrite.address = tileAddress + MEM_TILE_PERF_CTRL0_OFFSET; + ctrlWrite.value = (static_cast(counterEvents[0]) << 0) + | (static_cast(counterEvents[0]) << 8) + | (static_cast(counterEvents[1]) << 16) + | (static_cast(counterEvents[1]) << 24); + ctrlWrite.comment = "Memtile PerfCtrl0 @ col " + std::to_string(column) + + " (PORT_RUNNING/STALLED on dst halo ports)"; + writes.push_back(ctrlWrite); + } + + // Inner stamps only: counters 2-3 and PerfCtrl1 @ 0x91004. + if (counterUsed[2] || counterUsed[3]) { + CTRegisterWrite ctrlWrite; + ctrlWrite.address = tileAddress + MEM_TILE_PERF_CTRL1_OFFSET; + ctrlWrite.value = (static_cast(counterEvents[2]) << 0) + | (static_cast(counterEvents[2]) << 8) + | (static_cast(counterEvents[3]) << 16) + | (static_cast(counterEvents[3]) << 24); + ctrlWrite.comment = "Memtile PerfCtrl1 @ col " + std::to_string(column) + + " (PORT_RUNNING/STALLED on dst halo ports)"; + writes.push_back(ctrlWrite); + } + + return writes; } } // namespace xdp diff --git a/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.h b/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.h index d353b165..06b98519 100644 --- a/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.h +++ b/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.h @@ -13,6 +13,7 @@ #include #include "aiebu/aiebu_assembler.h" +#include "xdp/profile/plugin/aie_dtrace/util/aie_dtrace_util.h" namespace xdp { @@ -57,7 +58,8 @@ struct ASMFileInfo { uint32_t opLocMinCol = UINT32_MAX; uint32_t opLocMaxCol = 0; std::vector timestamps; // SAVE_TIMESTAMPS lines - std::vector counters; // Filtered counters for this ASM + std::vector counters; // Filtered shim counters for this ASM + std::vector l2l2Counters; // Filtered memtile L2-L2 counters for this ASM }; /** @@ -113,9 +115,9 @@ class AieDtraceCTWriter { * hardware addresses regardless of where XRT placed the partition */ AieDtraceCTWriter(VPDatabase* database, - std::shared_ptr metadata, - uint64_t deviceId, - uint8_t startCol); + std::shared_ptr metadata, + uint64_t deviceId, + uint8_t startCol); /** * @brief Destructor @@ -300,7 +302,13 @@ class AieDtraceCTWriter { bool writeBandwidthCTFile(const std::vector& asmFileInfoList, const std::vector& allCounters, const std::vector& beginBlockWrites, - const std::string& outputPath); + const std::string& outputPath, + const std::vector& l2l2BeginBlockWrites = {}, + const std::vector& allL2l2Counters = {}); + + std::vector generateMemtilePerfCounterConfig( + uint8_t column, + const std::vector& counterPoints); private: VPDatabase* db; @@ -320,8 +328,13 @@ class AieDtraceCTWriter { // Stream switch and performance counter configuration offsets static constexpr uint64_t STREAM_SWITCH_EVENT_PORT_SEL_OFFSET = 0x0003FF00; + static constexpr uint64_t MEM_TILE_PERF_CTRL0_OFFSET = 0x00091000; + static constexpr uint64_t MEM_TILE_PERF_CTRL1_OFFSET = 0x00091004; static constexpr uint64_t PERF_CTRL_OFFSET = 0x00031000; + static constexpr uint8_t PORT_RUNNING_0_MEM_TILE_EVENT = 80; // PORT_RUNNING_N = 80 + 4*N + static constexpr uint8_t PORT_STALLED_0_MEM_TILE_EVENT = 81; // PORT_STALLED_N = 81 + 4*N + // Bandwidth monitoring constants static constexpr uint8_t NUM_BANDWIDTH_COUNTERS = 4; static constexpr uint8_t SHIM_ROW = 0; diff --git a/profile/plugin/aie_dtrace/ve2/aie_dtrace_ve2.cpp b/profile/plugin/aie_dtrace/ve2/aie_dtrace_ve2.cpp index cfab9211..7d261e05 100644 --- a/profile/plugin/aie_dtrace/ve2/aie_dtrace_ve2.cpp +++ b/profile/plugin/aie_dtrace/ve2/aie_dtrace_ve2.cpp @@ -6,6 +6,7 @@ #include "xdp/profile/plugin/aie_dtrace/ve2/aie_dtrace_ve2.h" #include "xdp/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.h" #include "xdp/profile/plugin/aie_dtrace/ve2/elf_helper.h" +#include "xdp/profile/plugin/aie_dtrace/util/aie_dtrace_util.h" #include "core/common/api/hw_context_int.h" #include "core/common/api/kernel_int.h" @@ -134,8 +135,11 @@ namespace xdp { if (!ctWriter.generateBandwidthCT(outputPath, hwctx, it->second, bandwidthMetricSet, bandwidthChannel)) return; + aie::dtrace::initDtraceOutputConfig(); + + const std::string ctMode = metadata->isL2L2Enabled() ? "bandwidth+L2-L2" : "bandwidth"; xrt_core::message::send(severity_level::debug, "XRT", - "AIE dtrace: Bandwidth CT generated for kernel '" + kernel_name + "AIE dtrace: " + ctMode + " CT generated for kernel '" + kernel_name + "' with metric set '" + bandwidthMetricSet + "'"); auto* run_impl = static_cast(run_impl_ptr);