From 3914bf44be6c6b4e0a2a0b95464406533c3b20c3 Mon Sep 17 00:00:00 2001 From: Jyotheeswar Ganne Date: Wed, 10 Jun 2026 08:56:37 -0600 Subject: [PATCH 1/3] xdp: add detailed_ddr_read_bandwidth and detailed_ddr_write_bandwidth metric sets for AIE dtrace Add two VE2 aie_dtrace interface-tile metric sets that program 4 shim performance counters with direct NoC0 DMA events for a single MM2S/S2MM channel selected via the metric's ":" suffix: PC0 start_task -> finished_task, PC1 stalled_lock, PC2 starvation, PC3 backpressure. - getInterfaceTiles: match the new metric names so interface tiles get configured - aie_profile_metadata: accept the names in dtrace bandwidth mode - CT writer: generate per-channel DMA-event counter config (no stream-switch port selection) and thread the channel through - aie_dtrace_ve2: pass the configured channel to the CT writer Co-authored-by: Cursor --- .../filetypes/aie_control_config_filetype.cpp | 4 +- .../plugin/aie_dtrace/aie_dtrace_metadata.cpp | 3 +- .../plugin/aie_dtrace/aie_dtrace_metadata.h | 4 + .../aie_dtrace/ve2/aie_dtrace_ct_writer.cpp | 112 ++++++++++++++++-- .../aie_dtrace/ve2/aie_dtrace_ct_writer.h | 14 ++- .../plugin/aie_dtrace/ve2/aie_dtrace_ve2.cpp | 16 ++- 6 files changed, 138 insertions(+), 15 deletions(-) diff --git a/profile/database/static_info/filetypes/aie_control_config_filetype.cpp b/profile/database/static_info/filetypes/aie_control_config_filetype.cpp index 3626c878..a23f519c 100644 --- a/profile/database/static_info/filetypes/aie_control_config_filetype.cpp +++ b/profile/database/static_info/filetypes/aie_control_config_filetype.cpp @@ -379,7 +379,9 @@ AIEControlConfigFiletype::getInterfaceTiles(const std::string& graphName, (metricStr != "read_bandwidth") && (metricStr != "write_bandwidth") && (metricStr != "peak_read_bandwidth") && - (metricStr != "peak_write_bandwidth")) + (metricStr != "peak_write_bandwidth") && + (metricStr != "detailed_ddr_read_bandwidth") && + (metricStr != "detailed_ddr_write_bandwidth")) continue; } diff --git a/profile/plugin/aie_dtrace/aie_dtrace_metadata.cpp b/profile/plugin/aie_dtrace/aie_dtrace_metadata.cpp index 3d86fbab..0013e511 100644 --- a/profile/plugin/aie_dtrace/aie_dtrace_metadata.cpp +++ b/profile/plugin/aie_dtrace/aie_dtrace_metadata.cpp @@ -24,7 +24,8 @@ namespace xdp { { static const std::set metrics = { "ddr_bandwidth", "read_bandwidth", "write_bandwidth", - "peak_read_bandwidth", "peak_write_bandwidth", "off"}; + "peak_read_bandwidth", "peak_write_bandwidth", + "detailed_ddr_read_bandwidth", "detailed_ddr_write_bandwidth", "off"}; return metrics; } diff --git a/profile/plugin/aie_dtrace/aie_dtrace_metadata.h b/profile/plugin/aie_dtrace/aie_dtrace_metadata.h index 0b4c4103..f75f99c6 100644 --- a/profile/plugin/aie_dtrace/aie_dtrace_metadata.h +++ b/profile/plugin/aie_dtrace/aie_dtrace_metadata.h @@ -55,6 +55,10 @@ class AieDtraceMetadata { std::vector> getConfigMetricsVec(int module); + // DMA channel selected by each interface tile metric's ":" suffix; + // used by detailed_ddr_*_bandwidth to pick the MM2S/S2MM channel to monitor. + std::map getConfigChannel0() { return configChannel0; } + int getHardwareGen() const { return metadataReader == nullptr ? 0 : metadataReader->getHardwareGeneration(); } 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 dd6553cd..2bfcaccc 100644 --- a/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.cpp +++ b/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.cpp @@ -27,6 +27,16 @@ namespace xdp { namespace { +// detailed_ddr_read_bandwidth / detailed_ddr_write_bandwidth program 4 shim +// performance counters with direct NoC0 DMA events (task/lock/starvation/ +// backpressure) for a single DMA channel, instead of stream-switch port events. +bool +isDetailedBandwidth(const std::string& metricSet) +{ + return (metricSet == "detailed_ddr_read_bandwidth") || + (metricSet == "detailed_ddr_write_bandwidth"); +} + // Order UCs by aiebu min column; each UC's width is [colStart, nextUcStart - 1] (last UC ends at opLocMaxCol). void applyUcSpansFromOpLoc(std::vector& asmFileInfoList) @@ -690,8 +700,24 @@ std::vector AieDtraceCTWriter::getShimTileColumns(void* hwctx) } std::vector AieDtraceCTWriter::getBandwidthCounterConfigs( - const std::string& metricSet) + const std::string& metricSet, uint8_t channel) { + // detailed_ddr_read_bandwidth / detailed_ddr_write_bandwidth: 4 counters all on + // the same DMA channel, each measuring a different aspect via direct NoC0 DMA + // events. dmaPortIndex is unused (no stream-switch port monitoring). + if (isDetailedBandwidth(metricSet)) { + bool isWrite = (metricSet == "detailed_ddr_write_bandwidth"); + bool isMaster = isWrite; // S2MM=master/output, MM2S=slave/input + std::string dir = isWrite ? "output" : "input"; + uint8_t ch = (channel <= 1) ? channel : 0; + return { + {0, ch, 0, isMaster, dir, "task"}, // Counter 0: start_task -> finished_task + {1, ch, 0, isMaster, dir, "lock"}, // Counter 1: stalled_lock + {2, ch, 0, isMaster, dir, "starvation"}, // Counter 2: starvation + {3, ch, 0, isMaster, dir, "backpressure"} // Counter 3: backpressure + }; + } + // VE2 shim tile DMA port indices for stream switch event monitoring // These port indices are architecture-specific and map to the physical // stream switch ports that connect to the DMA channels. @@ -751,6 +777,10 @@ std::vector AieDtraceCTWriter::generateStreamSwitchPortConfig( { std::vector writes; + // detailed_ddr_*_bandwidth use direct DMA events; no stream-switch port selection. + if (isDetailedBandwidth(metricSet)) + return writes; + uint64_t tileAddress = (static_cast(column) << columnShift) | (static_cast(SHIM_ROW) << rowShift); uint64_t regAddr = tileAddress + STREAM_SWITCH_EVENT_PORT_SEL_OFFSET; @@ -814,7 +844,7 @@ std::vector AieDtraceCTWriter::generateStreamSwitchPortConfig( } std::vector AieDtraceCTWriter::generatePerfCounterConfig( - uint8_t column, const std::string& metricSet) + uint8_t column, const std::string& metricSet, uint8_t channel) { std::vector writes; @@ -840,6 +870,71 @@ std::vector AieDtraceCTWriter::generatePerfCounterConfig( constexpr uint64_t PERF_CTRL0_OFFSET = 0x00031000; constexpr uint64_t PERF_CTRL2_OFFSET = 0x0003100C; + // detailed_ddr_read_bandwidth (MM2S) / detailed_ddr_write_bandwidth (S2MM): + // 4 counters on a single DMA channel using direct NoC0 PL-tile DMA events + // (XAIE2PS_EVENTS_PL_NOC0_DMA_*). Channel selects ch0/ch1 of MM2S or S2MM. + // PC0: start = START_TASK, stop = FINISHED_TASK + // PC1: start = stop = STALLED_LOCK + // PC2: start = stop = STARVATION (MM2S: memory, S2MM: stream) + // PC3: start = stop = BACKPRESSURE (MM2S: stream, S2MM: memory) + if (isDetailedBandwidth(metricSet)) { + uint8_t ch = (channel <= 1) ? channel : 0; + uint8_t startTask, finishedTask, stalledLock, starvation, backpressure; + + if (metricSet == "detailed_ddr_read_bandwidth") { + // MM2S channel ch + startTask = (ch == 0) ? 16 : 17; // PL_NOC0_DMA_MM2S_{0,1}_START_TASK + finishedTask = (ch == 0) ? 24 : 25; // PL_NOC0_DMA_MM2S_{0,1}_FINISHED_TASK + stalledLock = (ch == 0) ? 28 : 29; // PL_NOC0_DMA_MM2S_{0,1}_STALLED_LOCK + starvation = (ch == 0) ? 36 : 37; // PL_NOC0_DMA_MM2S_{0,1}_MEMORY_STARVATION + backpressure = (ch == 0) ? 32 : 33; // PL_NOC0_DMA_MM2S_{0,1}_STREAM_BACKPRESSURE + } + else { + // detailed_ddr_write_bandwidth: S2MM channel ch + startTask = (ch == 0) ? 14 : 15; // PL_NOC0_DMA_S2MM_{0,1}_START_TASK + finishedTask = (ch == 0) ? 22 : 23; // PL_NOC0_DMA_S2MM_{0,1}_FINISHED_TASK + stalledLock = (ch == 0) ? 26 : 27; // PL_NOC0_DMA_S2MM_{0,1}_STALLED_LOCK + starvation = (ch == 0) ? 30 : 31; // PL_NOC0_DMA_S2MM_{0,1}_STREAM_STARVATION + backpressure = (ch == 0) ? 34 : 35; // PL_NOC0_DMA_S2MM_{0,1}_MEMORY_BACKPRESSURE + } + + std::string dir = (metricSet == "detailed_ddr_read_bandwidth") ? "mm2s" : "s2mm"; + + // PerfCtrl0: [7:0]=Cnt0_Start, [15:8]=Cnt0_Stop, [23:16]=Cnt1_Start, [31:24]=Cnt1_Stop + { + uint32_t regValue = 0; + regValue |= (static_cast(startTask) & 0xFF) << 0; // Cnt0 start = start_task + regValue |= (static_cast(finishedTask) & 0xFF) << 8; // Cnt0 stop = finished_task + regValue |= (static_cast(stalledLock) & 0xFF) << 16; // Cnt1 start = stalled_lock + regValue |= (static_cast(stalledLock) & 0xFF) << 24; // Cnt1 stop = stalled_lock + + CTRegisterWrite write; + write.address = tileAddress + PERF_CTRL0_OFFSET; + write.value = regValue; + write.comment = "PerfCtrl0 @ col " + std::to_string(column) + " (" + dir + " ch" + + std::to_string(ch) + ": task,lock)"; + writes.push_back(write); + } + + // PerfCtrl2: [7:0]=Cnt2_Start, [15:8]=Cnt2_Stop, [23:16]=Cnt3_Start, [31:24]=Cnt3_Stop + { + uint32_t regValue = 0; + regValue |= (static_cast(starvation) & 0xFF) << 0; // Cnt2 start = starvation + regValue |= (static_cast(starvation) & 0xFF) << 8; // Cnt2 stop = starvation + regValue |= (static_cast(backpressure) & 0xFF) << 16; // Cnt3 start = backpressure + regValue |= (static_cast(backpressure) & 0xFF) << 24; // Cnt3 stop = backpressure + + CTRegisterWrite write; + write.address = tileAddress + PERF_CTRL2_OFFSET; + write.value = regValue; + write.comment = "PerfCtrl2 @ col " + std::to_string(column) + " (" + dir + " ch" + + std::to_string(ch) + ": starvation,backpressure)"; + writes.push_back(write); + } + + return writes; + } + // PORT_RUNNING and PORT_STALLED events for aie2ps shim tile // Port_Running_N events: 134, 138, 142, 146 (decimal) // Port_Stalled_N events: 135, 139, 143, 147 (decimal) @@ -904,10 +999,10 @@ std::vector AieDtraceCTWriter::generatePerfCounterConfig( } std::vector AieDtraceCTWriter::generateBandwidthCounters( - const std::vector& shimColumns, const std::string& metricSet) + const std::vector& shimColumns, const std::string& metricSet, uint8_t channel) { std::vector counters; - auto configs = getBandwidthCounterConfigs(metricSet); + auto configs = getBandwidthCounterConfigs(metricSet, channel); for (uint8_t column : shimColumns) { for (const auto& cfg : configs) { @@ -1072,7 +1167,8 @@ bool AieDtraceCTWriter::generateBandwidthCT( const std::string& outputPath, void* hwctx, const std::vector& opLocations, - const std::string& metricSet) + const std::string& metricSet, + uint8_t channel) { if (opLocations.empty()) { xrt_core::message::send(severity_level::debug, "XRT", @@ -1133,7 +1229,7 @@ bool AieDtraceCTWriter::generateBandwidthCT( applyUcSpansFromOpLoc(asmFileInfoList); - auto allCounters = generateBandwidthCounters(shimColumns, metricSet); + auto allCounters = generateBandwidthCounters(shimColumns, metricSet, channel); if (allCounters.empty()) { xrt_core::message::send(severity_level::warning, "XRT", "AIE dtrace: No bandwidth counters generated"); @@ -1148,10 +1244,12 @@ bool AieDtraceCTWriter::generateBandwidthCT( std::vector beginBlockWrites; for (uint8_t column : shimColumns) { + // Detailed sets use direct DMA events; generateStreamSwitchPortConfig returns + // empty for them, so this is a no-op in that case. auto ssWrites = generateStreamSwitchPortConfig(column, metricSet); beginBlockWrites.insert(beginBlockWrites.end(), ssWrites.begin(), ssWrites.end()); - auto pcWrites = generatePerfCounterConfig(column, metricSet); + auto pcWrites = generatePerfCounterConfig(column, metricSet, channel); beginBlockWrites.insert(beginBlockWrites.end(), pcWrites.begin(), pcWrites.end()); } 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 d3e52770..edccbf4f 100644 --- a/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.h +++ b/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.h @@ -156,12 +156,15 @@ class AieDtraceCTWriter { * @param hwctx Hardware context handle for partition info access * @param opLocations Vector of op_loc from aiebu_assembler::get_op_locations * @param metricSet The metric set name (ddr_bandwidth, peak_read_bandwidth, etc.) + * @param channel DMA channel (0 or 1) selected by the metric's channel suffix; + * only used by the detailed_ddr_*_bandwidth metric sets * @return true if CT file was generated successfully, false otherwise */ bool generateBandwidthCT(const std::string& outputPath, void* hwctx, const std::vector& opLocations, - const std::string& metricSet = "ddr_bandwidth"); + const std::string& metricSet = "ddr_bandwidth", + uint8_t channel = 0); private: /** @@ -260,27 +263,30 @@ class AieDtraceCTWriter { * @brief Generate performance counter configuration for 4 counters per shim tile * @param column Shim tile column * @param metricSet The metric set name (ddr_bandwidth, peak_read_bandwidth, etc.) + * @param channel DMA channel (0 or 1); only used by detailed_ddr_*_bandwidth sets * @return Vector of register writes to configure performance counters */ std::vector generatePerfCounterConfig(uint8_t column, - const std::string& metricSet = "ddr_bandwidth"); + const std::string& metricSet = "ddr_bandwidth", uint8_t channel = 0); /** * @brief Get bandwidth counter configurations for a shim tile based on metric set * @param metricSet The metric set name (ddr_bandwidth, peak_read_bandwidth, etc.) + * @param channel DMA channel (0 or 1); only used by detailed_ddr_*_bandwidth sets * @return Vector of BandwidthCounterConfig for the 4 counters */ std::vector getBandwidthCounterConfigs( - const std::string& metricSet = "ddr_bandwidth"); + const std::string& metricSet = "ddr_bandwidth", uint8_t channel = 0); /** * @brief Generate bandwidth counters for all shim tiles in the partition * @param shimColumns Vector of shim tile columns * @param metricSet The metric set name (ddr_bandwidth, peak_read_bandwidth, etc.) + * @param channel DMA channel (0 or 1); only used by detailed_ddr_*_bandwidth sets * @return Vector of CTCounterInfo for all bandwidth counters */ std::vector generateBandwidthCounters(const std::vector& shimColumns, - const std::string& metricSet = "ddr_bandwidth"); + const std::string& metricSet = "ddr_bandwidth", uint8_t channel = 0); /** * @brief Write the bandwidth CT file content with register configuration diff --git a/profile/plugin/aie_dtrace/ve2/aie_dtrace_ve2.cpp b/profile/plugin/aie_dtrace/ve2/aie_dtrace_ve2.cpp index 786e1d2b..cfab9211 100644 --- a/profile/plugin/aie_dtrace/ve2/aie_dtrace_ve2.cpp +++ b/profile/plugin/aie_dtrace/ve2/aie_dtrace_ve2.cpp @@ -109,17 +109,29 @@ namespace xdp { AieDtraceCTWriter ctWriter(db, metadata, deviceID, partitionStartCol); std::string bandwidthMetricSet = "peak_read_bandwidth"; + uint8_t bandwidthChannel = 0; auto shimConfigMetrics = metadata->getConfigMetricsVec(SHIM_MODULE_IDX); if (!shimConfigMetrics.empty()) { bandwidthMetricSet = shimConfigMetrics.front().second; + // The detailed_ddr_*_bandwidth metric sets carry a DMA channel in their + // ":" suffix (stored in configChannel0). Match by column/row. + auto configChannel0 = metadata->getConfigChannel0(); + const auto& shimTile = shimConfigMetrics.front().first; + for (const auto& tc : configChannel0) { + if ((tc.first.col == shimTile.col) && (tc.first.row == shimTile.row)) { + bandwidthChannel = tc.second; + break; + } + } xrt_core::message::send(severity_level::info, "XRT", - "AIE dtrace: Using metric set '" + bandwidthMetricSet + "' from configuration"); + "AIE dtrace: Using metric set '" + bandwidthMetricSet + "' (channel " + + std::to_string(bandwidthChannel) + ") from configuration"); } else { xrt_core::message::send(severity_level::info, "XRT", "AIE dtrace: No interface tile metrics configured, using default 'peak_read_bandwidth'"); } - if (!ctWriter.generateBandwidthCT(outputPath, hwctx, it->second, bandwidthMetricSet)) + if (!ctWriter.generateBandwidthCT(outputPath, hwctx, it->second, bandwidthMetricSet, bandwidthChannel)) return; xrt_core::message::send(severity_level::debug, "XRT", From 3ab978159e57466ed04be1f32b65dd71f4cdfb42 Mon Sep 17 00:00:00 2001 From: Jyotheeswar Ganne Date: Fri, 19 Jun 2026 03:46:37 -0600 Subject: [PATCH 2/3] xdp: count PORT_RUNNING on performance counter 0 for detailed_ddr_*_bandwidth Performance counter 0 for detailed_ddr_read_bandwidth and detailed_ddr_write_bandwidth now measures PORT_RUNNING_0 on the channel's stream-switch port instead of start_task -> finished_task. - getBandwidthCounterConfigs: counter 0 eventType "running" with the DMA stream-switch port index for the selected channel/direction - generatePerfCounterConfig: PC0 start/stop = PORT_RUNNING_0_PL - generateStreamSwitchPortConfig: route logical SS port 0 to the channel's DMA port (add channel param); no longer skipped for detailed sets Co-authored-by: Cursor --- .../aie_dtrace/ve2/aie_dtrace_ct_writer.cpp | 61 +++++++++++-------- .../aie_dtrace/ve2/aie_dtrace_ct_writer.h | 3 +- 2 files changed, 38 insertions(+), 26 deletions(-) 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 2bfcaccc..ea518be0 100644 --- a/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.cpp +++ b/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.cpp @@ -710,11 +710,17 @@ std::vector AieDtraceCTWriter::getBandwidthCounterConfig bool isMaster = isWrite; // S2MM=master/output, MM2S=slave/input std::string dir = isWrite ? "output" : "input"; uint8_t ch = (channel <= 1) ? channel : 0; + // Counter 0 monitors PORT_RUNNING on the stream-switch port that connects to + // the selected DMA channel (same VE2 port mapping as ddr_bandwidth): + // S2MM ch0 master South1 => 3, S2MM ch1 master South3 => 5 + // MM2S ch0 slave South3 => 5, MM2S ch1 slave South7 => 9 + uint8_t runPortIndex = isWrite ? ((ch == 0) ? 3 : 5) + : ((ch == 0) ? 5 : 9); return { - {0, ch, 0, isMaster, dir, "task"}, // Counter 0: start_task -> finished_task - {1, ch, 0, isMaster, dir, "lock"}, // Counter 1: stalled_lock - {2, ch, 0, isMaster, dir, "starvation"}, // Counter 2: starvation - {3, ch, 0, isMaster, dir, "backpressure"} // Counter 3: backpressure + {0, ch, runPortIndex, isMaster, dir, "running"}, // Counter 0: PORT_RUNNING (stream-switch port) + {1, ch, 0, isMaster, dir, "lock"}, // Counter 1: stalled_lock + {2, ch, 0, isMaster, dir, "starvation"}, // Counter 2: starvation + {3, ch, 0, isMaster, dir, "backpressure"} // Counter 3: backpressure }; } @@ -773,19 +779,15 @@ std::vector AieDtraceCTWriter::getBandwidthCounterConfig } std::vector AieDtraceCTWriter::generateStreamSwitchPortConfig( - uint8_t column, const std::string& metricSet) + uint8_t column, const std::string& metricSet, uint8_t channel) { std::vector writes; - // detailed_ddr_*_bandwidth use direct DMA events; no stream-switch port selection. - if (isDetailedBandwidth(metricSet)) - return writes; - uint64_t tileAddress = (static_cast(column) << columnShift) | (static_cast(SHIM_ROW) << rowShift); uint64_t regAddr = tileAddress + STREAM_SWITCH_EVENT_PORT_SEL_OFFSET; - auto configs = getBandwidthCounterConfigs(metricSet); + auto configs = getBandwidthCounterConfigs(metricSet, channel); // Build the per-counter list into the SS event-port slots that the perf // counter events actually reference. Each Port_Running_N / Port_Stalled_N @@ -803,7 +805,12 @@ std::vector AieDtraceCTWriter::generateStreamSwitchPortConfig( // sits at configs[2] in the per-counter list) goes into slot 1; slots 2 // and 3 are not consumed by any event and are left zero. std::vector slotConfigs; - if (metricSet == "peak_read_bandwidth" || metricSet == "peak_write_bandwidth") { + if (isDetailedBandwidth(metricSet)) { + // Only counter 0 (PORT_RUNNING_0) reads a stream-switch port; counters 1-3 + // use direct DMA events. Route logical SS port 0 to the channel's DMA port. + if (!configs.empty()) + slotConfigs.push_back(configs[0]); + } else if (metricSet == "peak_read_bandwidth" || metricSet == "peak_write_bandwidth") { if (configs.size() >= 3) { slotConfigs.push_back(configs[0]); slotConfigs.push_back(configs[2]); @@ -831,6 +838,9 @@ std::vector AieDtraceCTWriter::generateStreamSwitchPortConfig( comment << " (MM2S ch0,ch1 x2 for running+stall)"; else if (metricSet == "peak_write_bandwidth") comment << " (S2MM ch0,ch1 x2 for running+stall)"; + else if (isDetailedBandwidth(metricSet)) + comment << " (" << ((metricSet == "detailed_ddr_read_bandwidth") ? "mm2s" : "s2mm") + << " ch" << static_cast((channel <= 1) ? channel : 0) << " port_running)"; else comment << " (MM2S ch0,ch1; S2MM ch0,ch1)"; @@ -871,28 +881,29 @@ std::vector AieDtraceCTWriter::generatePerfCounterConfig( constexpr uint64_t PERF_CTRL2_OFFSET = 0x0003100C; // detailed_ddr_read_bandwidth (MM2S) / detailed_ddr_write_bandwidth (S2MM): - // 4 counters on a single DMA channel using direct NoC0 PL-tile DMA events - // (XAIE2PS_EVENTS_PL_NOC0_DMA_*). Channel selects ch0/ch1 of MM2S or S2MM. - // PC0: start = START_TASK, stop = FINISHED_TASK + // 4 counters on a single DMA channel. Counter 0 measures PORT_RUNNING on the + // channel's stream-switch port (routed via generateStreamSwitchPortConfig); + // the rest use direct NoC0 PL-tile DMA events (XAIE2PS_EVENTS_PL_NOC0_DMA_*). + // Channel selects ch0/ch1 of MM2S or S2MM. + // PC0: start = stop = PORT_RUNNING_0 // PC1: start = stop = STALLED_LOCK // PC2: start = stop = STARVATION (MM2S: memory, S2MM: stream) // PC3: start = stop = BACKPRESSURE (MM2S: stream, S2MM: memory) if (isDetailedBandwidth(metricSet)) { + // Counter 0 reads stream-switch logical port 0 (PORT_RUNNING_0_PL). + constexpr uint8_t PORT_RUNNING_0_PL_EVENT = 0x86; // 134 + uint8_t ch = (channel <= 1) ? channel : 0; - uint8_t startTask, finishedTask, stalledLock, starvation, backpressure; + uint8_t stalledLock, starvation, backpressure; if (metricSet == "detailed_ddr_read_bandwidth") { // MM2S channel ch - startTask = (ch == 0) ? 16 : 17; // PL_NOC0_DMA_MM2S_{0,1}_START_TASK - finishedTask = (ch == 0) ? 24 : 25; // PL_NOC0_DMA_MM2S_{0,1}_FINISHED_TASK stalledLock = (ch == 0) ? 28 : 29; // PL_NOC0_DMA_MM2S_{0,1}_STALLED_LOCK starvation = (ch == 0) ? 36 : 37; // PL_NOC0_DMA_MM2S_{0,1}_MEMORY_STARVATION backpressure = (ch == 0) ? 32 : 33; // PL_NOC0_DMA_MM2S_{0,1}_STREAM_BACKPRESSURE } else { // detailed_ddr_write_bandwidth: S2MM channel ch - startTask = (ch == 0) ? 14 : 15; // PL_NOC0_DMA_S2MM_{0,1}_START_TASK - finishedTask = (ch == 0) ? 22 : 23; // PL_NOC0_DMA_S2MM_{0,1}_FINISHED_TASK stalledLock = (ch == 0) ? 26 : 27; // PL_NOC0_DMA_S2MM_{0,1}_STALLED_LOCK starvation = (ch == 0) ? 30 : 31; // PL_NOC0_DMA_S2MM_{0,1}_STREAM_STARVATION backpressure = (ch == 0) ? 34 : 35; // PL_NOC0_DMA_S2MM_{0,1}_MEMORY_BACKPRESSURE @@ -903,8 +914,8 @@ std::vector AieDtraceCTWriter::generatePerfCounterConfig( // PerfCtrl0: [7:0]=Cnt0_Start, [15:8]=Cnt0_Stop, [23:16]=Cnt1_Start, [31:24]=Cnt1_Stop { uint32_t regValue = 0; - regValue |= (static_cast(startTask) & 0xFF) << 0; // Cnt0 start = start_task - regValue |= (static_cast(finishedTask) & 0xFF) << 8; // Cnt0 stop = finished_task + regValue |= (static_cast(PORT_RUNNING_0_PL_EVENT) & 0xFF) << 0; // Cnt0 start = port_running_0 + regValue |= (static_cast(PORT_RUNNING_0_PL_EVENT) & 0xFF) << 8; // Cnt0 stop = port_running_0 regValue |= (static_cast(stalledLock) & 0xFF) << 16; // Cnt1 start = stalled_lock regValue |= (static_cast(stalledLock) & 0xFF) << 24; // Cnt1 stop = stalled_lock @@ -912,7 +923,7 @@ std::vector AieDtraceCTWriter::generatePerfCounterConfig( write.address = tileAddress + PERF_CTRL0_OFFSET; write.value = regValue; write.comment = "PerfCtrl0 @ col " + std::to_string(column) + " (" + dir + " ch" - + std::to_string(ch) + ": task,lock)"; + + std::to_string(ch) + ": port_running,lock)"; writes.push_back(write); } @@ -1244,9 +1255,9 @@ bool AieDtraceCTWriter::generateBandwidthCT( std::vector beginBlockWrites; for (uint8_t column : shimColumns) { - // Detailed sets use direct DMA events; generateStreamSwitchPortConfig returns - // empty for them, so this is a no-op in that case. - auto ssWrites = generateStreamSwitchPortConfig(column, metricSet); + // For detailed sets, counter 0 monitors PORT_RUNNING on the channel's + // stream-switch port, so the SS event port selection must be programmed. + auto ssWrites = generateStreamSwitchPortConfig(column, metricSet, channel); beginBlockWrites.insert(beginBlockWrites.end(), ssWrites.begin(), ssWrites.end()); auto pcWrites = generatePerfCounterConfig(column, metricSet, channel); 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 edccbf4f..d353b165 100644 --- a/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.h +++ b/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.h @@ -254,10 +254,11 @@ class AieDtraceCTWriter { * @brief Generate stream switch port configuration for DMA channels per shim tile * @param column Shim tile column * @param metricSet The metric set name (ddr_bandwidth, peak_read_bandwidth, etc.) + * @param channel DMA channel (0 or 1); only used by detailed_ddr_*_bandwidth sets * @return Vector of register writes to configure stream switch ports */ std::vector generateStreamSwitchPortConfig(uint8_t column, - const std::string& metricSet = "ddr_bandwidth"); + const std::string& metricSet = "ddr_bandwidth", uint8_t channel = 0); /** * @brief Generate performance counter configuration for 4 counters per shim tile From b3514fd70344b13ce4d24f0727a40242bbff0f18 Mon Sep 17 00:00:00 2001 From: Jyotheeswar Ganne Date: Mon, 22 Jun 2026 00:57:30 -0600 Subject: [PATCH 3/3] xdp: distinguish memory vs stream in starvation/backpressure event metadata For detailed_ddr_*_bandwidth, counter 2 and 3 event labels now encode the memory- vs stream-side so the generated CT counter metadata "event" field is unambiguous: detailed_ddr_read_bandwidth (MM2S): memory_starvation, stream_backpressure detailed_ddr_write_bandwidth (S2MM): stream_starvation, memory_backpressure Co-authored-by: Cursor --- .../plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) 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 ea518be0..a5f313fa 100644 --- a/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.cpp +++ b/profile/plugin/aie_dtrace/ve2/aie_dtrace_ct_writer.cpp @@ -716,11 +716,16 @@ std::vector AieDtraceCTWriter::getBandwidthCounterConfig // MM2S ch0 slave South3 => 5, MM2S ch1 slave South7 => 9 uint8_t runPortIndex = isWrite ? ((ch == 0) ? 3 : 5) : ((ch == 0) ? 5 : 9); + // Starvation/backpressure are memory- vs stream-side depending on direction: + // MM2S (read): memory_starvation, stream_backpressure + // S2MM (write): stream_starvation, memory_backpressure + std::string starvationType = isWrite ? "stream_starvation" : "memory_starvation"; + std::string backpressureType = isWrite ? "memory_backpressure" : "stream_backpressure"; return { - {0, ch, runPortIndex, isMaster, dir, "running"}, // Counter 0: PORT_RUNNING (stream-switch port) - {1, ch, 0, isMaster, dir, "lock"}, // Counter 1: stalled_lock - {2, ch, 0, isMaster, dir, "starvation"}, // Counter 2: starvation - {3, ch, 0, isMaster, dir, "backpressure"} // Counter 3: backpressure + {0, ch, runPortIndex, isMaster, dir, "running"}, // Counter 0: PORT_RUNNING (stream-switch port) + {1, ch, 0, isMaster, dir, "lock"}, // Counter 1: stalled_lock + {2, ch, 0, isMaster, dir, starvationType}, // Counter 2: starvation (memory/stream) + {3, ch, 0, isMaster, dir, backpressureType} // Counter 3: backpressure (memory/stream) }; }