Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

350 lines
13 KiB
C++

// MIT License
//
// Copyright (c) 2017-2025 Advanced Micro Devices, Inc.
//
// 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.
// Header file for CmdBuilder and CmdBuffer interfaces
#ifndef SRC_PM4_CMD_BUILDER_H_
#define SRC_PM4_CMD_BUILDER_H_
#include <stdint.h>
#include <string.h>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <type_traits>
#include <vector>
#include <atomic>
#include "lib/aqlprofile/util/reg_offsets.h"
#define APPEND_COMMAND_WRAPPER(cmdbuf, ...) \
do \
{ \
PrintCommand(__FUNCTION__, __VA_ARGS__); \
cmdbuf->Append(__VA_ARGS__); \
} while(false);
namespace pm4_builder
{
namespace
{
#if defined(DEBUG_TRACE)
template <typename T, typename std::enable_if<sizeof(T) % sizeof(uint32_t) == 0, int>::type = 0>
constexpr size_t
PacketsSize(T&& packet)
{
return sizeof(packet) / sizeof(uint32_t);
}
template <typename T, typename... Ts>
constexpr size_t
PacketsSize(T&& packet, Ts&&... rest)
{
return PacketsSize(std::forward<T>(packet)) + PacketsSize(std::forward<Ts>(rest)...);
}
template <typename T, typename std::enable_if<sizeof(T) % sizeof(uint32_t) == 0, int>::type = 0>
void
PrintPackets(std::ostream& stream, T&& packet)
{
for(size_t i = 0; i < sizeof(packet) / sizeof(uint32_t); ++i)
stream << " " << std::hex << std::right << std::setw(8) << std::setfill('0')
<< reinterpret_cast<const uint32_t*>(&packet)[i];
}
template <typename T, typename... Ts>
void
PrintPackets(std::ostream& stream, T&& packet, Ts&&... rest)
{
PrintPackets(stream, std::forward<T>(packet));
PrintPackets(stream, std::forward<Ts>(rest)...);
}
#endif
template <typename... Ts>
void
PrintCommand(const char* function_name, Ts&&... packets)
{
#if defined(DEBUG_TRACE)
std::ostringstream oss;
oss << "'" << function_name << "' size(" << std::dec
<< PacketsSize(std::forward<Ts>(packets)...) << ")";
std::clog << std::setw(40) << std::left << oss.str() << ":";
PrintPackets(std::clog, std::forward<Ts>(packets)...);
std::clog << std::setfill(' ') << std::endl;
#endif
}
} // namespace
/// @brief Implements the interface CmdBuffer and thus can be used to
/// translate various Gpu commands as byte stream.
/// @note: The Api does not require implementations to be thread safe.
/// Users are therefore required to be access in a serialized manner.
class CmdBuffer
{
public:
/// @brief Append the command into the underlying buffer
/// @param packet Buffer containing one or more instances of Gpu commands
template <typename T, typename std::enable_if<sizeof(T) % sizeof(uint32_t) == 0, int>::type = 0>
void Append(T&& packet)
{
size_t pos = data_.size();
data_.resize(pos + sizeof(packet) / sizeof(uint32_t));
memcpy(&data_[pos], &packet, sizeof(T));
}
template <typename... Ts>
void Append(Ts&&... packets)
{
using expander = int[];
(void) expander{0, (Append(std::forward<Ts>(packets)), 0)...};
}
/// @brief Append num_dwords of data to the buffer
/// @param data_pointer points to the data to append
/// @param num_dwords number of dwords
void Append(uint32_t* data_pointer, uint32_t num_dwords)
{
size_t pos = data_.size();
data_.resize(pos + num_dwords);
memcpy(&data_[pos], data_pointer, num_dwords);
}
/// @brief Return size of Gpu commands in bytes in the underlying buffer
size_t Size() const { return data_.size() * sizeof(data_[0]); }
/// @brief Return size of Gpu commands in DWord in the underlying buffer
size_t DwSize() const { return data_.size(); }
void Assign(uint32_t index, uint32_t value) { data_[index] = value; }
/// @brief Return address of the start of accumulated commands.
const void* Data() const { return &data_[0]; }
/// @brief Clear buffer.
void Clear() { return data_.clear(); }
private:
/// @brief Defines Gpu command buffer as a vector of uint32_t
std::vector<uint32_t> data_;
};
enum ChipletId
{
CHIPLET_XCD0 = 0,
CHIPLET_XCD1 = 1,
CHIPLET_XCD2 = 2,
CHIPLET_XCD3 = 3,
CHIPLET_XCD4 = 4,
CHIPLET_XCD5 = 5,
CHIPLET_XCD6 = 6,
CHIPLET_XCD7 = 7,
CHIPLET_AID0 = 8,
CHIPLET_AID1 = 9,
CHIPLET_AID2 = 10,
CHIPLET_AID3 = 11,
CHIPLET_MID0 = 12,
CHIPLET_MID1 = 13,
};
/// @brief Specifies the public interface of CmdBuilder for use by
/// clients to build Gpu command streams.
class CmdBuilder
{
public:
CmdBuilder(const reg_base_offset_table* _table)
: ip_offset_table(_table)
{}
/// @brief Build and copy a WaitIdle Gpu command into command buffer
/// @param cmdbuf Pointer to command buffer to be appended
virtual void BuildWriteWaitIdlePacket(CmdBuffer* cmdbuf) = 0;
/// @brief Builds a Gpu command to wait until condition is realized
/// @param cmdbuf command buffer to be appended with launch command
/// @param mem_space if the address is in memory or is a register offset
/// @param wait_addr address to wait on
/// @param func_eq true means equal, false means not-equal
/// @param mask_val Mask to apply on value from addr in comparison
/// @param wait_val value to apply for the func given above
virtual void BuildWaitRegMemCommand(CmdBuffer* cmdbuf,
bool mem_space,
uint64_t wait_addr,
bool func_eq,
uint32_t mask_val,
uint32_t wait_val) = 0;
/// @brief Build CP command to program a Gpu register
/// @param cmdbuf Pointer to command buffer to be appended
/// @param addr Register to be programmed
/// @param value Value to write into register
virtual void BuildWriteUConfigRegPacket(CmdBuffer* cmdbuf, uint32_t addr, uint32_t value) = 0;
/// @brief Build and copy WriteShReg command
/// @param cmdbuf Pointer to command buffer to be appended
/// @param addr Offset of the register
/// @param value Value to write into register
virtual void BuildWriteShRegPacket(CmdBuffer* cmdbuf, uint32_t addr, uint32_t value) = 0;
/// @brief Build a Gpu command that copies data from a specified
/// source register to destination
/// @param cmdbuf Pointer to command buffer to be appended
/// @param src_sel Source register selector
/// @param src_reg_add 32-bit Source register address of the data to read from
/// @param dst_addr Destination address for the data to be written to
/// @param size Size of the data to be written
/// @param wait True if Gpu command should confirm the write operation
/// operation has completed successfully
virtual void BuildCopyRegDataPacket(CmdBuffer* cmdbuf,
uint32_t src_reg_addr,
const void* dst_addr,
uint32_t size,
bool wait) = 0;
/// @brief Same as the above function but with 64-bit src_reg_addr.
virtual void BuildCopyRegDataPacket(CmdBuffer* cmdbuf,
uint64_t src_reg_addr,
const void* dst_addr,
uint32_t size,
bool wait)
{
BuildCopyRegDataPacket(cmdbuf, uint32_t(src_reg_addr), dst_addr, size, wait);
}
/// @brief Builds the Gpu command to reference indirectly a stream
/// of other Gpu commands. The launch command is then copied into
/// the command buffer parameter.
/// @param cmdBuf command buffer to be appended with launch command
/// @param cmd_addr Address of command buffer carrying command stream
/// @param cmd_size Size of dispatch command stream in bytes
virtual void BuildIndirectBufferCmd(CmdBuffer* cmdbuf,
const void* cmd_addr,
std::size_t cmd_size) = 0;
virtual void BuildMutexAcquirePacket(CmdBuffer* cmdbuf, size_t addr) = 0;
virtual void BuildMutexReleasePacket(CmdBuffer* cmdbuf, size_t addr) = 0;
virtual uint32_t MakeMutexSlot()
{
static std::atomic<size_t> slot{1};
return uint32_t(slot.fetch_add(1)) | (1u << 31);
}
/// @brief Builds a NOP packet
/// @param cmdBuf command buffer to be appended with launch command
/// @param num_dwords number of dwords of the whole NOP packet, including the Header
virtual void BuildNopPacket(CmdBuffer* cmdbuf, uint32_t num_dwords) = 0;
/// @brief Builds a TT Finish Event
/// @param cmdBuf command buffer to be appended with launch command
virtual void BuildThreadTraceEventFinish(CmdBuffer* cmdBuf) = 0;
/// @brief Prime pages of ATCL2
/// @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(){};
bool bUsePerfCounterMode{true};
// is this an MI300 command builder?
uint32_t get_addr(const Register& reg)
{
if(!ip_offset_table)
{
std::cerr << "CmdBuilder::get_addr(): IP offset table is NULL!" << std::endl;
std::abort();
}
return (*ip_offset_table)[reg];
}
virtual void BuildWriteConfigRegPacket(CmdBuffer* cmdbuf, uint32_t addr, uint32_t value) = 0;
virtual void BuildWritePConfigRegPacketToChiplet(CmdBuffer* cmdbuf,
uint32_t addr,
uint32_t value,
ChipletId chiplet,
bool write_to_aid = true)
{}
virtual void BuildWritePConfigRegPacketToChiplet(CmdBuffer* cmdbuf,
const Register& reg,
uint32_t value,
ChipletId chiplet,
bool write_to_aid = true)
{}
virtual uint32_t BuildCopyCounterDataPacketFromChiplet(CmdBuffer* cmdbuf,
const Register& reg_lo,
const Register& reg_hi,
const void* dst_addr,
uint32_t dw_mask,
ChipletId chiplet,
bool copy_from_aid = true)
{
return 0;
}
private:
const reg_base_offset_table* const ip_offset_table;
};
/// @brief Returns the lower 32-bits of a value
constexpr uint32_t
Low32(uint64_t u)
{
return static_cast<uint32_t>(u);
}
/// @brief Returns the upper 32-bits of a value
constexpr uint32_t
High32(uint64_t u)
{
return static_cast<uint32_t>(u >> 32);
}
/// @brief Returns the lower 32-bits of an address
inline uint32_t
PtrLow32(const void* p)
{
return Low32(reinterpret_cast<uintptr_t>(p));
}
/// @brief Returns the upper 32-bits of an address
inline uint32_t
PtrHigh32(const void* p)
{
return High32(reinterpret_cast<uintptr_t>(p));
}
} // namespace pm4_builder
#endif // SRC_PM4_CMD_BUILDER_H_