rocr/aie: AIE Queue Processing

Change-Id: I681c971ba7229037ca85d5529838aa7bbe5820e2


[ROCm/ROCR-Runtime commit: e9cc839b2b]
This commit is contained in:
Eddie Richter
2024-12-06 18:16:26 +00:00
committed by David Yat Sin
parent a317650289
commit 8ea388af92
8 changed files with 538 additions and 141 deletions
@@ -100,6 +100,9 @@ public:
return system_allocator_;
}
/// @brief Getter for the AIE system deallocator.
const std::function<void(void*)>& system_deallocator() const { return system_deallocator_; }
// AIE agent methods.
/// @brief Get the number of columns on this AIE agent.
uint32_t GetNumCols() const { return num_cols_; }
@@ -124,6 +127,9 @@ private:
core::MemoryRegion::AllocateFlags flags)>
system_allocator_;
std::function<void(void*)> system_deallocator_;
const hsa_profile_t profile_ = HSA_PROFILE_BASE;
const uint32_t min_aql_size_ = 0x40;
const uint32_t max_aql_size_ = 0x40;
@@ -49,7 +49,6 @@
#include "core/inc/queue.h"
#include "core/inc/runtime.h"
#include "core/inc/signal.h"
#include "core/util/locks.h"
namespace rocr {
namespace AMD {
@@ -131,6 +130,12 @@ private:
/// @brief Base of the queue's ring buffer storage.
void *ring_buf_ = nullptr;
/// @brief Called when the doorbell is rung to iterate over
/// all packets and submit them. Submissions is done by
// calling into the XdnaDriver.
hsa_status_t SubmitCmd(XdnaDriver& driver, void* queue_base, uint64_t read_dispatch_id,
uint64_t write_dispatch_id);
/// @brief Handle for an application context on the AIE device.
///
/// Each user queue will have an associated context. This handle is assigned
@@ -154,4 +159,4 @@ private:
} // namespace AMD
} // namespace rocr
#endif // header guard
#endif // HSA_RUNTIME_CORE_INC_AMD_HW_AQL_AIE_COMMAND_PROCESSOR_H_
@@ -45,9 +45,46 @@
#include <memory>
#include <unordered_map>
#include "core/driver/xdna/uapi/amdxdna_accel.h"
#include "core/inc/amd_aie_agent.h"
#include "core/inc/driver.h"
#include "core/inc/memory_region.h"
/// @brief struct amdxdna_cmd_chain - Interpretation of data payload for
/// ERT_CMD_CHAIN
struct amdxdna_cmd_chain {
/// Number of commands in chain
__u32 command_count;
/// Index of last successfully submitted command in chain
__u32 submit_index;
/// Index of failing command if cmd status is not completed
__u32 error_index;
__u32 reserved[3];
/// Address of each command in chain
__u64 data[] __counted_by(command_count);
};
/// @brief struct amdxdna_cmd - Exec buffer command header format
struct amdxdna_cmd {
union {
struct {
/// Current state of a command
__u32 state : 4;
__u32 unused : 6;
/// Extra CU masks in addition to mandatory mask
__u32 extra_cu_masks : 2;
/// Number of words in payload (data)
__u32 count : 11;
/// Opcode identifying specific command
__u32 opcode : 5;
__u32 reserved : 4;
};
__u32 header;
};
/// Count number of words representing packet payload
__u32 data[] __counted_by(count);
};
namespace rocr {
namespace core {
class Queue;
@@ -55,6 +92,40 @@ class Queue;
namespace AMD {
/// @brief: The number of arguments in the packet payload before we start passing operands
constexpr uint32_t NON_OPERAND_COUNT = 6;
// @brief: Used to transform an address into a device address
constexpr uint32_t DEV_ADDR_BASE = 0x04000000;
constexpr uint32_t DEV_ADDR_OFFSET_MASK = 0x02FFFFFF;
/// @brief: The driver places a structure before each command in a command chain.
/// Need to increase the size of the command by the size of this structure.
/// In the following xdna driver source can see where this is implemented:
/// Commit hash: eddd92c0f61592c576a500f16efa24eb23667c23
/// https://github.com/amd/xdna-driver/blob/main/src/driver/amdxdna/aie2_msg_priv.h#L387-L391
/// https://github.com/amd/xdna-driver/blob/main/src/driver/amdxdna/aie2_message.c#L637
constexpr uint32_t CMD_COUNT_SIZE_INCREASE = 3;
/// @brief: The size of an instruction in bytes
constexpr uint32_t INSTR_SIZE_BYTES = 4;
/// @brief: Index of command payload where the instruction sequence
/// address is located
constexpr uint32_t CMD_PKT_PAYLOAD_INSTRUCTION_SEQUENCE_IDX = 2;
constexpr uint32_t CMD_PKT_PAYLOAD_INSTRUCTION_SEQUENCE_SIZE_IDX = 4;
/// @brief Environment variable to define job submission timeout
constexpr uint32_t DEFAULT_TIMEOUT_VAL = 50;
/// @brief: Calculates the number of operands in a packet
/// given the number of arguments in the packet
/// @param: arg_count(Input), Number of arguments in the packet
/// @return: uint32_t, The number of operands in the packet
inline uint32_t GetOperandCount(uint32_t arg_count) {
return ((arg_count - NON_OPERAND_COUNT) / 2);
}
class XdnaDriver final : public core::Driver {
public:
XdnaDriver(std::string devnode_name);
@@ -68,6 +139,9 @@ public:
hsa_status_t Init() override;
hsa_status_t QueryKernelModeDriver(core::DriverQuery query) override;
std::unordered_map<uint32_t, void*>& GetHandleMappings();
std::unordered_map<void*, uint32_t>& GetAddrMappings();
hsa_status_t GetAgentProperties(core::Agent &agent) const override;
hsa_status_t
GetMemoryProperties(uint32_t node_id,
@@ -84,7 +158,11 @@ public:
hsa_status_t CreateQueue(core::Queue &queue) const override;
hsa_status_t DestroyQueue(core::Queue &queue) const override;
private:
// @brief Submits num_pkts packets in a command chain to the XDNA driver
hsa_status_t SubmitCmdChain(hsa_amd_aie_ert_packet_t* first_pkt, uint32_t num_pkts,
uint32_t num_operands, uint32_t hw_ctx_handle);
private:
hsa_status_t QueryDriverVersion();
/// @brief Allocate device accesible heap space.
///
@@ -92,27 +170,55 @@ private:
hsa_status_t InitDeviceHeap();
hsa_status_t FreeDeviceHeap();
/// @brief Creates a command BO and returns a pointer to the memory and
// the corresponding handle
///
/// @param size size of memory to allocate
/// @param handle A pointer to the BO handle
/// @param cmd A pointer to the buffer
hsa_status_t CreateCmd(uint32_t size, uint32_t* handle, amdxdna_cmd** cmd);
/// @brief Adds all BOs in a command packet payload to a vector
/// and replaces the handles with a virtual address
///
/// @param count Number of entries in the command
/// @param bo_args A pointer to a vector that contains all bo handles
/// @param cmd_pkt_payload A pointer to the payload of the command
hsa_status_t RegisterCmdBOs(uint32_t count, std::vector<uint32_t>& bo_args,
std::vector<uint32_t>& bo_sizes, std::vector<uint64_t>& bo_addrs,
hsa_amd_aie_ert_start_kernel_data_t* cmd_pkt_payload,
const std::unordered_map<void*, uint32_t>& vmem_addr_mappings);
/// @brief Syncs all BOs referenced in bo_args
///
/// @param bo_args vector containing handles of BOs to sync
hsa_status_t SyncBos(const std::vector<uint64_t>& bo_args, const std::vector<uint32_t>& bo_sizes);
/// @brief Executes a command and waits for its completion
///
/// @param exec_cmd Structure containing the details of the command to execute
/// @param hw_ctx_handle the handle of the hardware context to run this
/// command
hsa_status_t ExecCmdAndWait(amdxdna_drm_exec_cmd* exec_cmd, uint32_t hw_ctx_handle);
/// TODO: Remove this in the future and rely on the core Runtime
/// object to track handle allocations. Using the VMEM API for mapping XDNA
/// driver handles requires a bit more refactoring. So rely on the XDNA driver
/// to manage some of this for now.
std::unordered_map<uint32_t, void *> vmem_handle_mappings;
std::unordered_map<void*, uint32_t> vmem_addr_mappings;
/// @brief Virtual address range allocated for the device heap.
///
/// Allocate a large enough space so we can carve out the device heap in
/// this range and ensure it is aligned to 64MB. Currently, AIE2 supports
/// 48MB device heap and it must be aligned to 64MB.
/// this range and ensure it is aligned to 64MB. Currently, npu1 supports
/// 64MB device heap and it must be aligned to 64MB.
void *dev_heap_parent = nullptr;
/// @brief The aligned device heap.
void *dev_heap_aligned = nullptr;
static constexpr size_t dev_heap_size = 48 * 1024 * 1024;
static constexpr size_t dev_heap_size = 64 * 1024 * 1024;
static constexpr size_t dev_heap_align = 64 * 1024 * 1024;
/// @brief DRM buffer object handle for the device heap. Assigned by the
/// kernel-mode driver.
uint32_t dev_heap_handle = 0;
};
} // namespace AMD