AQLprofile SQTT double buffer support (#1787)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
cf536a8c1a
Коммит
07a563c475
@@ -29,6 +29,7 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include "pm4/cmd_config.h"
|
||||
#include "trace_decoder_instrument.h"
|
||||
|
||||
#define SQTT_PERFCOUNTER_TOKEN (1u << 14)
|
||||
#define SQTT_PERFCOUNTER_SIMD_MASK 24
|
||||
@@ -37,36 +38,6 @@ namespace pm4_builder {
|
||||
class CmdBuffer;
|
||||
class CmdBuilder;
|
||||
|
||||
enum ATT_OPCODES {
|
||||
ATT_CODEOBJ_OPCODE = 4,
|
||||
ATT_TIMESTAMP_OPCODE,
|
||||
ATT_AGENT_INFO_OPCODE,
|
||||
};
|
||||
|
||||
enum ATT_AGENT_INFO_TYPE {
|
||||
ATT_AGENT_INFO_TYPE_RT_FREQUENCY_KHZ = 0,
|
||||
ATT_AGENT_INFO_TYPE_COUNTER_FREQUENCY,
|
||||
};
|
||||
|
||||
union att_decoder_packet_header_t {
|
||||
struct {
|
||||
unsigned int opcode : 8;
|
||||
unsigned int type : 4;
|
||||
unsigned int data20 : 20;
|
||||
};
|
||||
unsigned int u32All;
|
||||
};
|
||||
|
||||
union att_decoder_rocm_header_t {
|
||||
struct {
|
||||
unsigned int char1 : 8; //!< '\0'
|
||||
unsigned int char2 : 8; //!< 'R'
|
||||
unsigned int char3 : 8; //!< 'O'
|
||||
unsigned int char4 : 8; //!< 'C'
|
||||
};
|
||||
unsigned int u32All;
|
||||
};
|
||||
|
||||
/* Class responsible for locking PM4 packets to a specific XCC (mask).
|
||||
Starts locking future packets on constructor.
|
||||
Stops locking when the destructor is called.
|
||||
@@ -116,9 +87,10 @@ struct TraceControl
|
||||
uint32_t status{0};
|
||||
uint32_t cntr{0};
|
||||
uint32_t wptr{0};
|
||||
uint32_t _reserved{0};
|
||||
uint32_t status2{0};
|
||||
uint64_t gpu_clock_cnt_start{0};
|
||||
uint64_t gpu_clock_cnt_end{0};
|
||||
uint32_t status_double_buffer{0};
|
||||
};
|
||||
|
||||
// Encapsulates the various Api and structures that are used to enable
|
||||
@@ -139,6 +111,10 @@ class SqttBuilder {
|
||||
// Builds Pm4 command stream to program hardware registers that
|
||||
// inserts "data" into the SQTT buffer as USERDATA_2 (data_lo) and USERDATA_3 (data_hi)
|
||||
virtual hsa_status_t InsertCodeobjMarker(CmdBuffer* cmd_buffer, uint32_t data, unsigned channel) = 0;
|
||||
// Builds PM4 command stream to swap SQTT buffer to the next
|
||||
virtual void Swapbuffer(CmdBuffer* cmd_buffer, TraceConfig* config, void* addr, void* prev, int se_id, bool buf1) = 0;
|
||||
// Builds PM4 command stream to query status bit
|
||||
virtual void GetStatusPacket(CmdBuffer* cmd_buffer, TraceConfig* config, TraceControl& control, int se_id) = 0;
|
||||
|
||||
virtual void InsertTimestampMarker(CmdBuffer* cmd_buffer, uint64_t* addr) {};
|
||||
|
||||
@@ -146,6 +122,8 @@ class SqttBuilder {
|
||||
virtual size_t GetUTCErrorMask() const = 0;
|
||||
// Returns TT_CONTROL_FULL_MASK
|
||||
virtual size_t GetBufferFullMask() const = 0;
|
||||
// Returns TT_LOCKDOWN_FAIL for double buffering
|
||||
virtual size_t GetLockDownFailMask() const = 0;
|
||||
// Returns TT_WRITE_PTR_MASK
|
||||
virtual size_t GetWritePtrMask() const = 0;
|
||||
// Returns size of block in bytes per increment in WPTR
|
||||
@@ -176,6 +154,7 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
virtual size_t GetUTCErrorMask() const override { return Primitives::TT_CONTROL_UTC_ERR_MASK; };
|
||||
// Returns TT_CONTROL_FULL_MASK
|
||||
virtual size_t GetBufferFullMask() const override { return Primitives::TT_CONTROL_FULL_MASK; };
|
||||
virtual size_t GetLockDownFailMask() const override { return Primitives::TT_LOCKDOWN_FAIL; };
|
||||
// Returns TT_WRITE_PTR_MASK
|
||||
virtual size_t GetWritePtrMask() const override { return Primitives::TT_WRITE_PTR_MASK; };
|
||||
// Returns size of block in bytes per increment in WPTR
|
||||
@@ -237,7 +216,10 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
// to 4KB per thread trace specification
|
||||
const uint64_t se_number_xcc = se_number_total / GetXCCNumber();
|
||||
uint64_t base_addr = reinterpret_cast<uint64_t>(config->data_buffer_ptr);
|
||||
const uint64_t base_step = GetBaseStep(config->data_buffer_size, config->se_mask);
|
||||
if (Primitives::GFXIP_LEVEL == 10 || Primitives::GFXIP_LEVEL == 11)
|
||||
config->capacity_per_disabled_se = 1 << Primitives::TT_BUFF_ALIGN_SHIFT;
|
||||
|
||||
const uint64_t base_step = GetBaseStep(config);
|
||||
|
||||
// Old v1 API calls this with buffer == 0 first
|
||||
if (config->data_buffer_size > 0)
|
||||
@@ -248,10 +230,7 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
else if (base_step < (1ul<<17))
|
||||
throw std::runtime_error("SQTT Buffer size too low");
|
||||
}
|
||||
|
||||
|
||||
config->capacity_per_se = base_step;
|
||||
config->capacity_per_disabled_se = 1 << Primitives::TT_BUFF_ALIGN_SHIFT;
|
||||
|
||||
const bool legacy_mode =
|
||||
config->deprecated_mask && config->deprecated_tokenMask && config->deprecated_tokenMask2;
|
||||
@@ -334,12 +313,24 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
Primitives::sqtt_buffer_size_value(base_step, 0));
|
||||
// Program the thread trace ctrl register
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_CTRL_ADDR,
|
||||
Primitives::sqtt_ctrl_value(true));
|
||||
Primitives::sqtt_ctrl_value(true, false));
|
||||
// Issue a CSPartialFlush cmd including cache flush
|
||||
if (config->concurrent == 0) builder.BuildWriteWaitIdlePacket(cmd_buffer);
|
||||
builder.BuildWriteWaitIdlePacket(cmd_buffer);
|
||||
// Program the thread trace mode register, mode ON
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_MODE_ADDR,
|
||||
Primitives::sqtt_mode_on_value());
|
||||
Primitives::sqtt_mode_on_value(!config->buffer_data.empty()));
|
||||
|
||||
// If we are in double buffer mode
|
||||
if (!config->buffer_data.empty())
|
||||
{
|
||||
builder.BuildWriteWaitIdlePacket(cmd_buffer);
|
||||
uint64_t buf2_addr = reinterpret_cast<uint64_t>(config->buffer_data.at(se_index).at(0));
|
||||
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_BASE_ADDR,
|
||||
Primitives::sqtt_base_value_lo(buf2_addr));
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_BASE2_ADDR,
|
||||
Primitives::sqtt_base_value_hi(buf2_addr));
|
||||
}
|
||||
base_addr += base_step;
|
||||
}
|
||||
// Reset the GRBM to broadcast mode
|
||||
@@ -360,7 +351,9 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
const unsigned baddr_lo = Low32(base_addr >> Primitives::TT_BUFF_ALIGN_SHIFT);
|
||||
const unsigned baddr_hi = High32(base_addr >> Primitives::TT_BUFF_ALIGN_SHIFT);
|
||||
const uint64_t sqtt_size = bMaskedIn ? base_step : config->capacity_per_disabled_se;
|
||||
const uint32_t ctrl_val = Primitives::sqtt_ctrl_value(true);
|
||||
if (sqtt_size == 0) continue;
|
||||
|
||||
uint32_t ctrl_val = Primitives::sqtt_ctrl_value(true, !config->buffer_data.empty());
|
||||
|
||||
Select_GRBM_SE_SH0(cmd_buffer, index);
|
||||
builder.BuildPrimeL2(cmd_buffer, base_addr);
|
||||
@@ -395,7 +388,20 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
WriteConfigPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_TOKEN_MASK_ADDR, token_mask);
|
||||
// Program the thread trace ctrl register
|
||||
WriteConfigPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_CTRL_ADDR, ctrl_val);
|
||||
// If we are in double buffer mode
|
||||
if (!config->buffer_data.empty())
|
||||
{
|
||||
if (Primitives::GFXIP_LEVEL != 12) throw std::runtime_error("Not supported");
|
||||
|
||||
uint64_t buf1_addr = reinterpret_cast<uint64_t>(config->buffer_data.at(index).at(0));
|
||||
unsigned buff1_lo = Low32(buf1_addr >> Primitives::TT_BUFF_ALIGN_SHIFT);
|
||||
unsigned buff1_hi = High32(buf1_addr >> Primitives::TT_BUFF_ALIGN_SHIFT);
|
||||
|
||||
WriteConfigPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_BUF1_SIZE_ADDR, Primitives::sqtt_buffer0_size_value(sqtt_size));
|
||||
WriteConfigPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_BUF1_BASE_LO_ADDR, buff1_lo);
|
||||
builder.BuildWriteWaitIdlePacket(cmd_buffer);
|
||||
WriteConfigPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_BUF1_BASE_HI_ADDR, buff1_hi);
|
||||
}
|
||||
base_addr += sqtt_size;
|
||||
}
|
||||
for (uint64_t index = 0; index < se_number_total; index++) {
|
||||
@@ -408,7 +414,7 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
}
|
||||
builder.BuildWriteWaitIdlePacket(cmd_buffer);
|
||||
|
||||
att_decoder_rocm_header_t header{};
|
||||
rocprof_trace_decoder_instrument_enable_t header{};
|
||||
header.char1 = '\0';
|
||||
header.char2 = 'R';
|
||||
header.char3 = 'O';
|
||||
@@ -418,18 +424,18 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, userdata_channel, header.u32All);
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, userdata_channel, 524801);
|
||||
|
||||
att_decoder_packet_header_t packet{};
|
||||
packet.opcode = ATT_AGENT_INFO_OPCODE;
|
||||
rocprof_trace_decoder_packet_header_t packet{};
|
||||
packet.opcode = ROCPROF_TRACE_DECODER_PACKET_OPCODE_AGENT_INFO;
|
||||
|
||||
if (config->enable_rt_timestamp)
|
||||
{
|
||||
packet.type = ATT_AGENT_INFO_TYPE_RT_FREQUENCY_KHZ;
|
||||
packet.type = ROCPROF_TRACE_DECODER_AGENT_INFO_TYPE_RT_FREQUENCY_KHZ;
|
||||
packet.data20 = this->timestamp_freq / 1000;
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, userdata_channel, packet.u32All);
|
||||
}
|
||||
if (Primitives::GFXIP_LEVEL == 9 && config->perfcounters.size())
|
||||
{
|
||||
packet.type = ATT_AGENT_INFO_TYPE_COUNTER_FREQUENCY;
|
||||
packet.type = ROCPROF_TRACE_DECODER_AGENT_INFO_TYPE_COUNTER_INTERVAL;
|
||||
packet.data20 = (1 + cu_per_se) * ((config->perfcounters.size() + 3) & ~3) * config->perfPeriod;
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, userdata_channel, packet.u32All);
|
||||
}
|
||||
@@ -505,14 +511,12 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
// Initialize cache flush request object
|
||||
builder.BuildCacheFlushPacket(cmd_buffer, size_t(config->control_buffer_ptr),
|
||||
config->control_buffer_size);
|
||||
builder.BuildCacheFlushPacket(cmd_buffer, size_t(config->data_buffer_ptr),
|
||||
config->data_buffer_size);
|
||||
// Program zero size of thread trace buffer
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_SIZE_ADDR,
|
||||
Primitives::sqtt_zero_size_value());
|
||||
// Program the thread trace ctrl register
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_CTRL_ADDR,
|
||||
Primitives::sqtt_ctrl_value(true));
|
||||
Primitives::sqtt_ctrl_value(true, false));
|
||||
// Issue a CSPartialFlush cmd including cache flush
|
||||
builder.BuildWriteWaitIdlePacket(cmd_buffer);
|
||||
} else {
|
||||
@@ -529,7 +533,7 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
}
|
||||
|
||||
// Program the thread trace ctrl register to set mode to 0
|
||||
const uint32_t ctrl_val = Primitives::sqtt_ctrl_value(false);
|
||||
const uint32_t ctrl_val = Primitives::sqtt_ctrl_value(false, false);
|
||||
WriteConfigPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_CTRL_ADDR, ctrl_val);
|
||||
|
||||
{
|
||||
@@ -566,6 +570,10 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
|
||||
builder.BuildCopyRegDataPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_WPTR_ADDR, &control.wptr,
|
||||
Primitives::COPY_DATA_SEL_COUNT_1DW_PRM, true);
|
||||
|
||||
if (Primitives::GFXIP_LEVEL >= 12)
|
||||
builder.BuildCopyRegDataPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_STATUS2_ADDR,
|
||||
&control.status2, Primitives::COPY_DATA_SEL_COUNT_1DW_PRM, true);
|
||||
}
|
||||
|
||||
uint32_t GetXCCNumber() const { return xcc_number_; }
|
||||
@@ -579,33 +587,33 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
return std::max<uint64_t>(num_enabled, 1u);
|
||||
}
|
||||
|
||||
uint64_t GetBaseStep(uint64_t buffersize, uint64_t se_mask) const {
|
||||
// Get selected
|
||||
uint64_t num_enabled = PopCount(se_mask);
|
||||
int64_t num_disabled = (64 - num_enabled) << 12;
|
||||
uint64_t GetBaseStep(TraceConfig* config) const {
|
||||
// Get number of selected shader engines
|
||||
uint64_t num_enabled = PopCount(config->se_mask);
|
||||
int64_t size_disabled = (64 - num_enabled) * config->capacity_per_disabled_se;
|
||||
|
||||
// Make sure num divides buffersize
|
||||
int64_t buffer_per_se = std::max<int64_t>(0, buffersize - num_disabled) / num_enabled;
|
||||
int64_t buffer_per_se = (config->data_buffer_size - size_disabled) / num_enabled;
|
||||
return uint64_t(buffer_per_se) & ~((1 << Primitives::TT_BUFF_ALIGN_SHIFT) - 1);
|
||||
}
|
||||
|
||||
virtual hsa_status_t InsertCodeobjMarker(CmdBuffer* cmd_buffer, uint32_t data,
|
||||
unsigned channel) override {
|
||||
att_decoder_packet_header_t header{};
|
||||
header.opcode = ATT_CODEOBJ_OPCODE;
|
||||
rocprof_trace_decoder_packet_header_t header{};
|
||||
header.opcode = ROCPROF_TRACE_DECODER_PACKET_OPCODE_CODEOBJ;
|
||||
header.type = channel;
|
||||
header.data20 = 0;
|
||||
auto userdata_channel = Primitives::SQ_THREAD_TRACE_USERDATA_2;
|
||||
|
||||
SetGRBMToBroadcast(cmd_buffer);
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, userdata_channel, 4 | (channel << 8));
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, userdata_channel, header.u32All);
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, userdata_channel, data);
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
virtual void InsertTimestampMarker(CmdBuffer* cmd_buffer, uint64_t* addr) override
|
||||
{
|
||||
att_decoder_packet_header_t header{};
|
||||
header.opcode = ATT_TIMESTAMP_OPCODE;
|
||||
rocprof_trace_decoder_packet_header_t header{};
|
||||
header.opcode = ROCPROF_TRACE_DECODER_PACKET_OPCODE_RT_TIMESTAMP;
|
||||
header.type = 0;
|
||||
header.data20 = 0;
|
||||
|
||||
@@ -621,6 +629,50 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
builder.BuildWritePConfigRegPacket(cmdbuf, reg, value);
|
||||
}
|
||||
|
||||
void GetStatusPacket(CmdBuffer* cmd_buffer, TraceConfig* config, TraceControl& control, int se_id) override
|
||||
{
|
||||
int se_per_xcc = se_number_total / GetXCCNumber();
|
||||
XCC_Packet_Lock<Builder> lock(builder, cmd_buffer, GetXCCNumber(), se_id / se_per_xcc);
|
||||
Select_GRBM_SE_SH0(cmd_buffer, se_id % se_per_xcc);
|
||||
|
||||
auto status_addr = (Primitives::GFXIP_LEVEL >= 12) ? Primitives::SQ_THREAD_TRACE_STATUS2_ADDR : Primitives::SQ_THREAD_TRACE_STATUS_ADDR;
|
||||
builder.BuildCopyRegDataPacket(cmd_buffer, status_addr, &control.status_double_buffer, Primitives::COPY_DATA_SEL_COUNT_1DW_PRM, false);
|
||||
|
||||
builder.BuildWriteWaitIdlePacket(cmd_buffer);
|
||||
builder.BuildCacheFlushPacket(cmd_buffer, size_t(&control), sizeof(TraceControl));
|
||||
SetGRBMToBroadcast(cmd_buffer);
|
||||
}
|
||||
|
||||
void Swapbuffer(CmdBuffer* cmd_buffer, TraceConfig* config, void* addr, void* prev, int se_id, bool buf1) override
|
||||
{
|
||||
int se_per_xcc = se_number_total / GetXCCNumber();
|
||||
uint64_t base_addr = reinterpret_cast<uint64_t>(addr);
|
||||
|
||||
XCC_Packet_Lock<Builder> lock(builder, cmd_buffer, GetXCCNumber(), se_id / se_per_xcc);
|
||||
Select_GRBM_SE_SH0(cmd_buffer, se_id % se_per_xcc);
|
||||
|
||||
if (Primitives::GFXIP_LEVEL == 9)
|
||||
{
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_BASE_ADDR, Primitives::sqtt_base_value_lo(base_addr));
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_BASE2_ADDR, Primitives::sqtt_base_value_hi(base_addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned buff1_lo = Low32(base_addr >> Primitives::TT_BUFF_ALIGN_SHIFT);
|
||||
unsigned buff1_hi = High32(base_addr >> Primitives::TT_BUFF_ALIGN_SHIFT) & 0x3FFFu;
|
||||
|
||||
auto reg_lo = buf1 ? Primitives::SQ_THREAD_TRACE_BUF1_BASE_LO_ADDR : Primitives::SQ_THREAD_TRACE_BUF0_BASE_LO_ADDR;
|
||||
auto reg_hi = buf1 ? Primitives::SQ_THREAD_TRACE_BUF1_BASE_HI_ADDR : Primitives::SQ_THREAD_TRACE_BUF0_BASE_HI_ADDR;
|
||||
|
||||
WriteConfigPacket(cmd_buffer, reg_lo, buff1_lo);
|
||||
builder.BuildWriteWaitIdlePacket(cmd_buffer);
|
||||
WriteConfigPacket(cmd_buffer, reg_hi, buff1_hi);
|
||||
}
|
||||
builder.BuildCacheFlushPacket(cmd_buffer, size_t(prev), config->data_buffer_size);
|
||||
|
||||
SetGRBMToBroadcast(cmd_buffer);
|
||||
}
|
||||
|
||||
size_t se_number_total{};
|
||||
size_t xcc_number_{};
|
||||
uint32_t timestamp_freq{};
|
||||
|
||||
@@ -62,8 +62,11 @@ struct TraceConfig {
|
||||
// SE mask for tracing; note -> replicated for all XCCs
|
||||
uint64_t se_mask = 0x11;
|
||||
|
||||
// Maps shader engine IDs to list of buffers
|
||||
std::unordered_map<int, std::vector<void*>> buffer_data{};
|
||||
|
||||
uint64_t capacity_per_se = 0x1000;
|
||||
uint64_t capacity_per_disabled_se = 0x1000;
|
||||
uint64_t capacity_per_disabled_se = 0;
|
||||
std::unordered_map<int, int> target_cu_per_se{};
|
||||
std::unordered_map<int, uint64_t> se_base_addresses{};
|
||||
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2024-2025 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* This file describes the instrumentation format for rocprof trace decoder 0.1.5.
|
||||
* Instrumentation is optional for decoding, with the exception of rocprof_trace_decoder_gfx9_header_t.
|
||||
* Unless specified, all instrumentation packets are written to the USERDATA2 register.
|
||||
* This is an experimental feature, and as such the instrumentation may be changed without notice.
|
||||
*
|
||||
* It is recommended to use code object instrumentation for long traces, to avoid overlapping address spaces
|
||||
* if code objects are loaded/unloaded during the trace.
|
||||
* When an ID is found, callbacks involving _trace_decoder_pc_t will return {id, vaddr} instead of {0, memory_address}.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief For gfx9, must be first 8 bytes of the trace binary buffer. Not added in gfx10+.
|
||||
*/
|
||||
typedef union rocprof_trace_decoder_gfx9_header_t
|
||||
{
|
||||
struct {
|
||||
uint64_t legacy_version : 13; ///< Must be 0x0 or 0x11
|
||||
uint64_t gfx9_version2 : 3; ///< 4: MI200 or earlier - 5: MI300 - 6: MI350
|
||||
uint64_t DSIMDM : 4; ///< Bitmask of SIMDs active
|
||||
uint64_t DCU : 5; ///< Target CU
|
||||
uint64_t DSA : 1; ///< Must be zero
|
||||
uint64_t SEID : 6; ///< Optional: Shader engine ID
|
||||
uint64_t double_buffer : 1; ///< Double buffering mode enabled
|
||||
uint64_t reserved2 : 31;
|
||||
};
|
||||
uint64_t raw;
|
||||
} rocprof_trace_decoder_gfx9_header_t;
|
||||
|
||||
/**
|
||||
* @brief Must be first packet on userdata2. Activates instrumentation.
|
||||
* The 4 characters must be defined as ASCII '\0ROC'. Instrumentation ignored otherwise.
|
||||
* Optionally, a subsequent write can be sent with version number 524801
|
||||
*/
|
||||
typedef union rocprof_trace_decoder_instrument_enable_t
|
||||
{
|
||||
struct {
|
||||
unsigned int char1 : 8; ///< '\0'
|
||||
unsigned int char2 : 8; ///< 'R'
|
||||
unsigned int char3 : 8; ///< 'O'
|
||||
unsigned int char4 : 8; ///< 'C'
|
||||
};
|
||||
unsigned int u32All;
|
||||
} rocprof_trace_decoder_instrument_enable_t;
|
||||
|
||||
/**
|
||||
* @brief Header packet for instrumentation.
|
||||
* Opcode defines the kind of instrumentation, and type (sometimes) defines a subtype.
|
||||
* Header packets are expected to be followed by a 32-bit payload on the same register, except where especified.
|
||||
*/
|
||||
typedef union rocprof_trace_decoder_packet_header_t
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned int opcode : 8; ///< one of rocprof_trace_decoder_packet_opcode_t
|
||||
unsigned int type : 4; ///< one of rocprof_trace_decoder_agent_info_type_t or rocprof_trace_decoder_codeobj_marker_type_t
|
||||
unsigned int data20 : 20; ///< Agent data, if rocprof_trace_decoder_agent_info_type_t.
|
||||
};
|
||||
unsigned int u32All;
|
||||
} rocprof_trace_decoder_packet_header_t;
|
||||
|
||||
typedef enum rocprof_trace_decoder_packet_opcode_t
|
||||
{
|
||||
ROCPROF_TRACE_DECODER_PACKET_OPCODE_CODEOBJ = 4,
|
||||
ROCPROF_TRACE_DECODER_PACKET_OPCODE_RT_TIMESTAMP,
|
||||
ROCPROF_TRACE_DECODER_PACKET_OPCODE_AGENT_INFO ///< Agent info, passed in data20. No payload.
|
||||
|
||||
/// @var ROCPROF_TRACE_DECODER_PACKET_OPCODE_CODEOBJ
|
||||
/// @brief Followed by several rocprof_trace_decoder_codeobj_marker_t
|
||||
/// Once relevant data is sent, finalize with rocprof_trace_decoder_codeobj_marker_tail_t
|
||||
|
||||
/// @var ROCPROF_TRACE_DECODER_PACKET_OPCODE_RT_TIMESTAMP
|
||||
/// @brief Realtime timestamp to correlate the trace with outside information.
|
||||
/// Notes: userdata--3--. Gfx9 only. Not necessary for gfx10+.
|
||||
/// Instead of a single payload, must be followed by 3x USERDATA3 writes, in order:
|
||||
/// 1) Timestamp low 64bits
|
||||
/// 2) Timestamp high 64bits
|
||||
/// 3) Instant sync timestamp, low 32 bits.
|
||||
} rocprof_trace_decoder_packet_opcode_t;
|
||||
|
||||
typedef enum rocprof_trace_decoder_agent_info_type_t
|
||||
{
|
||||
ROCPROF_TRACE_DECODER_AGENT_INFO_TYPE_RT_FREQUENCY_KHZ = 0, ///< Realtime TS frequency in Khz
|
||||
ROCPROF_TRACE_DECODER_AGENT_INFO_TYPE_COUNTER_INTERVAL, ///< (gfx9) SQTT counter interval in cycles
|
||||
ROCPROF_TRACE_DECODER_AGENT_INFO_TYPE_LAST
|
||||
} rocprof_trace_decoder_agent_info_type_t;
|
||||
|
||||
/**
|
||||
* @brief Applies code object instrumentation. Sent as the last code object instrumentation packet.
|
||||
* Instead of _ID_LO and _ID_HI, the legacy_id field can be used for setting the ID.
|
||||
* IDs can be any (nonzero) user defined number, and will be used in callbacks involving _trace_decoder_pc_t.
|
||||
* The combination {id, offset} instead of {0, memory_address} is used to avoid overlapping
|
||||
* addresses when code objects are loaded/unloaded during the trace.
|
||||
*/
|
||||
typedef union rocprof_trace_decoder_codeobj_marker_tail_t
|
||||
{
|
||||
struct {
|
||||
uint32_t isUnload : 1; // 0 if code object is being loaded, 1 for unload
|
||||
uint32_t bFromStart : 1; // Has this code object been loaded before thread trace started?
|
||||
uint32_t legacy_id : 30; // Nonzero: Code object ID, if it fits in 30 bits.
|
||||
};
|
||||
uint32_t raw;
|
||||
} rocprof_trace_decoder_codeobj_marker_tail_t;
|
||||
|
||||
/**
|
||||
* @brief Defines the type of code object marker. Followed by 32-bit payload.
|
||||
* Send ADDR/SIZE with _LO/_HI combinations, followed by _TAIL to apply the instrumentation.
|
||||
*/
|
||||
typedef enum rocprof_trace_decoder_codeobj_marker_type_t
|
||||
{
|
||||
ROCPROF_TRACE_DECODER_CODEOBJ_MARKER_TYPE_TAIL = 0, ///< Payload is a rocprof_trace_decoder_codeobj_marker_tail_t
|
||||
ROCPROF_TRACE_DECODER_CODEOBJ_MARKER_TYPE_SIZE_LO,
|
||||
ROCPROF_TRACE_DECODER_CODEOBJ_MARKER_TYPE_ADDR_LO,
|
||||
ROCPROF_TRACE_DECODER_CODEOBJ_MARKER_TYPE_ADDR_HI,
|
||||
ROCPROF_TRACE_DECODER_CODEOBJ_MARKER_TYPE_SIZE_HI,
|
||||
ROCPROF_TRACE_DECODER_CODEOBJ_MARKER_TYPE_ID_LO,
|
||||
ROCPROF_TRACE_DECODER_CODEOBJ_MARKER_TYPE_ID_HI,
|
||||
ROCPROF_TRACE_DECODER_CODEOBJ_MARKER_TYPE_LAST
|
||||
} rocprof_trace_decoder_codeobj_marker_type_t;
|
||||
Ссылка в новой задаче
Block a user