Adding timestamp marker into SQTT buffer for gfx9 GPUs (#200)
* Adding TS Marker
* Apply suggestions from code review
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Add option to enable/disable RT
---------
Co-authored-by: Giovanni Baraldi <gbaraldi@amd.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
[ROCm/aqlprofile commit: 926ec4a56f]
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
1157f97224
Коммит
0542860ef8
@@ -211,6 +211,13 @@ class CmdBuilder {
|
||||
/// @param cmdBuf command buffer to be appended with launch command
|
||||
virtual void BuildPrimeL2(CmdBuffer* cmdBuf, uint64_t addr) = 0;
|
||||
|
||||
/// @brief Generates RT packets into thread trace buffer (gfx9 only)
|
||||
/// @param cmdBuf command buffer to be appended with launch command
|
||||
/// @param dst where gpu clock data is r/w. Must persist during packet dispatch
|
||||
/// @param reg userdata register address
|
||||
/// @param header SQTT packet header
|
||||
virtual void BuildGPUClockPacket(CmdBuffer* cmdBuf, uint64_t* dst, const Register& reg, uint32_t header) {};
|
||||
|
||||
/// @brief Release resources used by CmdBuilder
|
||||
virtual ~CmdBuilder(){};
|
||||
|
||||
|
||||
@@ -446,6 +446,83 @@ class Gfx9CmdBuilder : public CmdBuilder {
|
||||
uint32_t size, bool wait) {
|
||||
BuildCopyRegDataPacket(cmd, get_addr(reg), dst_addr, size, wait);
|
||||
}
|
||||
|
||||
std::array<uint32_t, 6> ClockRetrievePacket(uint64_t* dst)
|
||||
{
|
||||
auto addr = reinterpret_cast<uint64_t>(dst);
|
||||
|
||||
uint32_t header = MakePacket3Header(PACKET3_COPY_DATA, 6 * sizeof(uint32_t));
|
||||
|
||||
uint32_t dword2 =
|
||||
PACKET3_COPY_DATA__SRC_SEL(PACKET3_COPY_DATA__SRC_SEL__GPU_CLOCK_COUNT) |
|
||||
PACKET3_COPY_DATA__SRC_CACHE_POLICY(PACKET3_COPY_DATA__SRC_CACHE_POLICY__STREAM) |
|
||||
PACKET3_COPY_DATA__DST_SEL(PACKET3_COPY_DATA__DST_SEL__MEMORY) |
|
||||
PACKET3_COPY_DATA__DST_CACHE_POLICY(PACKET3_COPY_DATA__DST_CACHE_POLICY__STREAM) |
|
||||
PACKET3_COPY_DATA__WR_CONFIRM(PACKET3_COPY_DATA__WR_CONFIRM__WAIT_FOR_CONFIRMATION) |
|
||||
PACKET3_COPY_DATA__COUNT_SEL(PACKET3_COPY_DATA__COUNT_SEL__64_BITS_OF_DATA);
|
||||
|
||||
uint32_t dword5 = PACKET3_COPY_DATA__DST_64B_ADDR_LO(addr >> 3);
|
||||
uint32_t dword6 = PACKET3_COPY_DATA__DST_ADDR_HI(High32(addr));
|
||||
|
||||
return {header, dword2, 0, 0, dword5, dword6};
|
||||
}
|
||||
|
||||
std::array<uint32_t, 6> UserdataLoPacket(uint32_t userdata_addr)
|
||||
{
|
||||
uint32_t header = MakePacket3Header(PACKET3_COPY_DATA, 6 * sizeof(uint32_t));
|
||||
|
||||
uint32_t dword2 =
|
||||
PACKET3_COPY_DATA__SRC_SEL(PACKET3_COPY_DATA__SRC_SEL__GPU_CLOCK_COUNT) |
|
||||
PACKET3_COPY_DATA__SRC_CACHE_POLICY(PACKET3_COPY_DATA__SRC_CACHE_POLICY__STREAM) |
|
||||
PACKET3_COPY_DATA__DST_SEL(PACKET3_COPY_DATA__DST_SEL__MEM_MAPPED_REGISTER) |
|
||||
PACKET3_COPY_DATA__DST_CACHE_POLICY(PACKET3_COPY_DATA__DST_CACHE_POLICY__STREAM) |
|
||||
PACKET3_COPY_DATA__WR_CONFIRM(PACKET3_COPY_DATA__WR_CONFIRM__WAIT_FOR_CONFIRMATION) |
|
||||
PACKET3_COPY_DATA__COUNT_SEL(PACKET3_COPY_DATA__COUNT_SEL__32_BITS_OF_DATA);
|
||||
|
||||
return {header, dword2, 0, 0, userdata_addr, 0};
|
||||
}
|
||||
|
||||
std::array<uint32_t, 6> TraceDataMem32Packet(uint32_t userdata_addr, uint32_t* addr)
|
||||
{
|
||||
uint32_t header = MakePacket3Header(PACKET3_COPY_DATA, 6 * sizeof(uint32_t));
|
||||
uint32_t dword2 = PACKET3_COPY_DATA__SRC_SEL(PACKET3_COPY_DATA__SRC_SEL__MEMORY) |
|
||||
PACKET3_COPY_DATA__SRC_CACHE_POLICY(PACKET3_COPY_DATA__SRC_CACHE_POLICY__STREAM) |
|
||||
PACKET3_COPY_DATA__DST_SEL(PACKET3_COPY_DATA__DST_SEL__MEM_MAPPED_REGISTER) |
|
||||
PACKET3_COPY_DATA__DST_CACHE_POLICY(PACKET3_COPY_DATA__DST_CACHE_POLICY__STREAM) |
|
||||
PACKET3_COPY_DATA__WR_CONFIRM(PACKET3_COPY_DATA__WR_CONFIRM__DO_NOT_WAIT_FOR_CONFIRMATION) |
|
||||
PACKET3_COPY_DATA__COUNT_SEL(PACKET3_COPY_DATA__COUNT_SEL__32_BITS_OF_DATA);
|
||||
uint32_t dword3 = PACKET3_COPY_DATA__SRC_32B_ADDR_LO(PtrLow32(addr) >> 2);
|
||||
uint32_t dword4 = PACKET3_COPY_DATA__SRC_MEMTC_ADDR_HI(PtrHigh32(addr));
|
||||
|
||||
return {header, dword2, dword3, dword4, userdata_addr, 0};
|
||||
};
|
||||
|
||||
void BuildGPUClockPacket(CmdBuffer* cmdBuf, uint64_t* dst, const Register& userdata_addr, uint32_t header) override
|
||||
{
|
||||
uint32_t addr = get_addr(userdata_addr);
|
||||
|
||||
BuildWriteUConfigRegPacket(cmdBuf, addr, header);
|
||||
// Copy to dst
|
||||
{
|
||||
auto copy_data = ClockRetrievePacket(dst);
|
||||
APPEND_COMMAND_WRAPPER(cmdBuf, copy_data);
|
||||
}
|
||||
// Copy low-bits to userdata
|
||||
{
|
||||
auto copy_data = TraceDataMem32Packet(addr, (uint32_t*)dst);
|
||||
APPEND_COMMAND_WRAPPER(cmdBuf, copy_data);
|
||||
}
|
||||
// Copy hi-bits to userdata
|
||||
{
|
||||
auto copy_data = TraceDataMem32Packet(addr, (uint32_t*)dst + 1);
|
||||
APPEND_COMMAND_WRAPPER(cmdBuf, copy_data);
|
||||
}
|
||||
// Send instant clock
|
||||
{
|
||||
auto copy_data = UserdataLoPacket(addr);
|
||||
APPEND_COMMAND_WRAPPER(cmdBuf, copy_data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace pm4_builder
|
||||
|
||||
@@ -38,8 +38,9 @@ class CmdBuffer;
|
||||
class CmdBuilder;
|
||||
|
||||
constexpr size_t ATT_CODEOBJ_OPCODE = 4;
|
||||
constexpr size_t ATT_TIMESTAMP_OPCODE = 5;
|
||||
|
||||
union att_decoder_codeobj_header_t {
|
||||
union att_decoder_packet_header_t {
|
||||
struct {
|
||||
unsigned int opcode : 8;
|
||||
unsigned int type : 4;
|
||||
@@ -102,11 +103,14 @@ class XCC_Packet_Lock {
|
||||
// Thread traces status register indices to determine
|
||||
// status of thread trace run
|
||||
|
||||
struct TraceControl {
|
||||
uint32_t status;
|
||||
uint32_t cntr;
|
||||
uint32_t wptr;
|
||||
uint32_t _reserved;
|
||||
struct TraceControl
|
||||
{
|
||||
uint32_t status{0};
|
||||
uint32_t cntr{0};
|
||||
uint32_t wptr{0};
|
||||
uint32_t _reserved{0};
|
||||
uint64_t gpu_clock_cnt_start{0};
|
||||
uint64_t gpu_clock_cnt_end{0};
|
||||
};
|
||||
|
||||
// Encapsulates the various Api and structures that are used to enable
|
||||
@@ -126,7 +130,9 @@ class SqttBuilder {
|
||||
virtual void End(CmdBuffer* cmd_buffer, TraceConfig* config) = 0;
|
||||
// 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 InsertMarker(CmdBuffer* cmd_buffer, uint32_t data, unsigned channel) = 0;
|
||||
virtual hsa_status_t InsertCodeobjMarker(CmdBuffer* cmd_buffer, uint32_t data, unsigned channel) = 0;
|
||||
|
||||
virtual void InsertTimestampMarker(CmdBuffer* cmd_buffer, uint64_t* addr) {};
|
||||
|
||||
// Returns TT_CONTROL_UTC_ERR_MASK
|
||||
virtual size_t GetUTCErrorMask() const = 0;
|
||||
@@ -326,8 +332,6 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
Primitives::sqtt_mode_on_value());
|
||||
base_addr += base_step;
|
||||
}
|
||||
// Reset the GRBM to broadcast mode
|
||||
SetGRBMToBroadcast(cmd_buffer);
|
||||
} else {
|
||||
SetGRBMToBroadcast(cmd_buffer);
|
||||
builder.BuildWritePConfigRegPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_STATUS_ADDR, 0);
|
||||
@@ -401,6 +405,20 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, userdata_channel, header.u32All);
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, userdata_channel, 524801);
|
||||
|
||||
if (Primitives::GFXIP_LEVEL == 9 && config->enable_rt_timestamp)
|
||||
{
|
||||
for (size_t xcc = 0; xcc < GetXCCNumber(); xcc++)
|
||||
{
|
||||
bool some_se_enabled = false;
|
||||
for (int se = 0; se < se_number_xcc; se++) some_se_enabled |=config->target_cu_per_se.at(se + xcc*se_number_xcc) >= 0;
|
||||
if (!some_se_enabled) continue;
|
||||
|
||||
XCC_Packet_Lock<Builder> lock(builder, cmd_buffer, GetXCCNumber(), xcc);
|
||||
auto& control = reinterpret_cast<TraceControl*>(config->control_buffer_ptr)[xcc];
|
||||
InsertTimestampMarker(cmd_buffer, &control.gpu_clock_cnt_start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void End(CmdBuffer* cmd_buffer, TraceConfig* config) override {
|
||||
@@ -408,9 +426,25 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
// Issue a CSPartialFlush cmd including cache flush
|
||||
builder.BuildWriteWaitIdlePacket(cmd_buffer);
|
||||
|
||||
if (Primitives::GFXIP_LEVEL == 9) {
|
||||
if (Primitives::GFXIP_LEVEL == 9)
|
||||
{
|
||||
const uint32_t se_number_xcc = se_number_total / std::max(1u, GetXCCNumber());
|
||||
|
||||
if (config->enable_rt_timestamp)
|
||||
{
|
||||
for (size_t xcc = 0; xcc < GetXCCNumber(); xcc++)
|
||||
{
|
||||
bool some_se_enabled = false;
|
||||
for (int se = 0; se < se_number_xcc; se++) some_se_enabled |=config->target_cu_per_se.at(se + xcc*se_number_xcc) >= 0;
|
||||
if (!some_se_enabled) continue;
|
||||
|
||||
XCC_Packet_Lock<Builder> lock(builder, cmd_buffer, GetXCCNumber(), xcc);
|
||||
auto& control = reinterpret_cast<TraceControl*>(config->control_buffer_ptr)[xcc];
|
||||
InsertTimestampMarker(cmd_buffer, &control.gpu_clock_cnt_end);
|
||||
}
|
||||
builder.BuildWriteWaitIdlePacket(cmd_buffer);
|
||||
}
|
||||
|
||||
// Program the thread trace mode register to disable thread trace
|
||||
builder.BuildWriteUConfigRegPacket(cmd_buffer, Primitives::SQ_THREAD_TRACE_MODE_ADDR,
|
||||
Primitives::sqtt_mode_off_value());
|
||||
@@ -527,9 +561,9 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
return uint64_t(buffer_per_se) & ~((1 << Primitives::TT_BUFF_ALIGN_SHIFT) - 1);
|
||||
}
|
||||
|
||||
virtual hsa_status_t InsertMarker(CmdBuffer* cmd_buffer, uint32_t data,
|
||||
virtual hsa_status_t InsertCodeobjMarker(CmdBuffer* cmd_buffer, uint32_t data,
|
||||
unsigned channel) override {
|
||||
att_decoder_codeobj_header_t header{};
|
||||
att_decoder_packet_header_t header{};
|
||||
header.opcode = ATT_CODEOBJ_OPCODE;
|
||||
header.type = channel;
|
||||
header.reserved = 0;
|
||||
@@ -540,6 +574,17 @@ class GpuSqttBuilder : public SqttBuilder, protected Primitives {
|
||||
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;
|
||||
header.type = 0;
|
||||
header.reserved = 0;
|
||||
|
||||
SetGRBMToBroadcast(cmd_buffer);
|
||||
builder.BuildGPUClockPacket(cmd_buffer, addr, Primitives::SQ_THREAD_TRACE_USERDATA_3, header.u32All);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void WriteConfigPacket(CmdBuffer* cmdbuf, const T& reg, uint32_t value) {
|
||||
|
||||
@@ -66,6 +66,8 @@ struct TraceConfig {
|
||||
std::unordered_map<int, int> target_cu_per_se{};
|
||||
std::unordered_map<int, uint64_t> se_base_addresses{};
|
||||
|
||||
bool enable_rt_timestamp{false};
|
||||
|
||||
int GetTargetCU(int SE) const { return target_cu_per_se.at(SE); };
|
||||
uint64_t GetSEmask() const { return se_mask; };
|
||||
uint64_t GetSEBaseAddr(int SE) const { return se_base_addresses.at(SE); }
|
||||
|
||||
Ссылка в новой задаче
Block a user