diff --git a/projects/rocr-runtime/runtime/hsa-runtime/core/driver/xdna/amd_xdna_driver.cpp b/projects/rocr-runtime/runtime/hsa-runtime/core/driver/xdna/amd_xdna_driver.cpp index 8df55e05e9..5fd399b7ec 100644 --- a/projects/rocr-runtime/runtime/hsa-runtime/core/driver/xdna/amd_xdna_driver.cpp +++ b/projects/rocr-runtime/runtime/hsa-runtime/core/driver/xdna/amd_xdna_driver.cpp @@ -47,6 +47,10 @@ #include #include +#include +#include +#include +#include #include #include @@ -63,6 +67,37 @@ static_assert((sizeof(core::ShareableHandle::handle) >= sizeof(uint32_t)) && (alignof(core::ShareableHandle::handle) >= alignof(uint32_t)), "ShareableHandle cannot store a XDNA handle"); +/// @brief XDNA device type. +enum class XDNADeviceType { + Phx, + Stx, // Strix Halo / Krackan + Unknown // Unknown device +}; + +/// @brief XDNA device ID. +struct XDNADeviceId { + uint16_t device; + + bool operator<(const XDNADeviceId& other) const { return device < other.device; } +}; + +/// @brief Supported XDNA devices. +static const std::map supported_xdna_devices = { + {{0x1502}, XDNADeviceType::Phx}, // Phoenix + {{0x17f0}, XDNADeviceType::Stx}, // Strix Halo / Krackan +}; + +namespace fs = std::filesystem; + +/// @brief Devnode path for XDNA devices. +static const fs::path devnodes_path = "/dev/accel"; +/// @brief Sysfs path for XDNA devices. +static const fs::path sysfs_path = "/sys/class/accel"; +/// @brief Devnode prefix for XDNA devices. +static const std::string devnode_prefix = "accel"; +/// @brief Maximum devnode minor number for XDNA devices. +static const uint32_t devnode_max_minor_num = 64; + /// @brief Index of the first operand in a command. /// /// Before the operands there are: @@ -103,14 +138,12 @@ XdnaDriver::XdnaDriver(std::string devnode_name) : core::Driver(core::DriverType::XDNA, std::move(devnode_name)) {} hsa_status_t XdnaDriver::DiscoverDriver(std::unique_ptr& driver) { - const int max_minor_num(64); - static const std::string devnode_prefix("/dev/accel/accel"); - - for (int i = 0; i < max_minor_num; ++i) { - auto tmp_driver = std::unique_ptr(new XdnaDriver(devnode_prefix + std::to_string(i))); + for (uint32_t i = 0; i < devnode_max_minor_num; ++i) { + auto tmp_driver = std::make_unique(devnode_prefix + std::to_string(i)); if (tmp_driver->Open() == HSA_STATUS_SUCCESS) { if (tmp_driver->QueryKernelModeDriver(core::DriverQuery::GET_DRIVER_VERSION) == HSA_STATUS_SUCCESS) { + // XDNADriver supports only one XDNA device. Once found, the driver is initialized. driver = std::move(tmp_driver); return HSA_STATUS_SUCCESS; } else { @@ -147,7 +180,8 @@ hsa_status_t XdnaDriver::QueryKernelModeDriver(core::DriverQuery query) { } hsa_status_t XdnaDriver::Open() { - fd_ = open(devnode_name_.c_str(), O_RDWR | O_CLOEXEC); + const auto devnode_path = devnodes_path / devnode_name_; + fd_ = open(devnode_path.c_str(), O_RDWR | O_CLOEXEC); if (fd_ < 0) { return HSA_STATUS_ERROR_OUT_OF_RESOURCES; } @@ -182,13 +216,78 @@ hsa_status_t XdnaDriver::GetNodeProperties(HsaNodeProperties& node_props, uint32 return HSA_STATUS_ERROR; } - // Right now can only target N-1 columns as that is the number of shim DMAs - // in NPU1 devices. - node_props.NumNeuralCores = (aie_metadata.cols - 1) * aie_metadata.core.row_count; + const auto sysfs_device_path = sysfs_path / devnode_name_ / "device"; + + // Find device type. + XDNADeviceType device_type = XDNADeviceType::Unknown; + { + const auto device_id_file = sysfs_device_path / "device"; + if (!fs::exists(device_id_file)) { + assert(false && "Device file not found in sysfs."); + return HSA_STATUS_ERROR; + } + + XDNADeviceId device_id = {}; + std::ifstream is(device_id_file); + // Device ID is in hex. + if (!(is >> std::hex >> device_id.device)) { + assert(false && "Failed to read device ID from sysfs."); + return HSA_STATUS_ERROR; + } + + const auto device_type_it = supported_xdna_devices.find(device_id); + if (device_type_it == supported_xdna_devices.end()) { + assert(false && "Unsupported XDNA device."); + return HSA_STATUS_ERROR; + } + device_type = device_type_it->second; + } + + // Fill in node properties that depend on device type. + std::fill_n(node_props.AMDName, HSA_PUBLIC_NAME_SIZE, 0); + switch (device_type) { + case XDNADeviceType::Phx: { + constexpr std::string_view name("aie2"); + assert(name.size() < HSA_PUBLIC_NAME_SIZE); + std::copy(name.begin(), name.end(), node_props.AMDName); + // Only target N-1 columns as that is the number of shim DMAs in NPU1 devices. + node_props.NumNeuralCores = (aie_metadata.cols - 1) * aie_metadata.core.row_count; + } break; + + case XDNADeviceType::Stx: { + constexpr std::string_view name("aie2p"); + assert(name.size() < HSA_PUBLIC_NAME_SIZE); + std::copy(name.begin(), name.end(), node_props.AMDName); + node_props.NumNeuralCores = aie_metadata.cols * aie_metadata.core.row_count; + } break; + + default: + assert(false && "Unsupported XDNA device."); + return HSA_STATUS_ERROR; + } + + // Read device name from sysfs. + { + const auto device_name_file = sysfs_device_path / "vbnv"; + if (!fs::exists(device_name_file)) { + assert(false && "Device file name not found in sysfs."); + return HSA_STATUS_ERROR; + } + std::array device_name = {}; + std::ifstream is(device_name_file); + if (!is.getline(device_name.data(), device_name.size() - 1)) { + assert(false && "Failed to read device name from sysfs."); + return HSA_STATUS_ERROR; + } + // Convert device name from ASCII to UTF-16 for MarketingName. + std::copy(device_name.begin(), device_name.end(), node_props.MarketingName); + } + /// @todo XDNA driver currently only supports single-node AIE /// devices over PCIe. Update this once we can get topology /// information dynamically from the sysfs. node_props.NumIOLinks = 0; + return HSA_STATUS_SUCCESS; } diff --git a/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/amd_aie_agent.cpp b/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/amd_aie_agent.cpp index 628bcbb6f6..c66273ebb8 100644 --- a/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/amd_aie_agent.cpp +++ b/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/amd_aie_agent.cpp @@ -42,9 +42,11 @@ #include "core/inc/amd_aie_agent.h" +#include #include #include -#include +#include +#include #include "core/inc/amd_aie_aql_queue.h" #include "core/inc/amd_memory_region.h" @@ -111,153 +113,146 @@ hsa_status_t AieAgent::GetInfo(hsa_agent_info_t attribute, void *value) const { const size_t attribute_ = static_cast(attribute); switch (attribute_) { - case HSA_AGENT_INFO_NAME: { - const std::string name_info_("aie2"); - assert(name_info_.size() < HSA_PUBLIC_NAME_SIZE); - std::memset(value, 0, HSA_PUBLIC_NAME_SIZE); - std::strncat(reinterpret_cast(value), name_info_.c_str(), - name_info_.size()); - break; - } - case HSA_AGENT_INFO_VENDOR_NAME: { - const std::string vendor_name_info_("AMD"); - assert(vendor_name_info_.size() < HSA_PUBLIC_NAME_SIZE); - std::memset(value, 0, HSA_PUBLIC_NAME_SIZE); - std::strncat(reinterpret_cast(value), vendor_name_info_.c_str(), - vendor_name_info_.size()); - break; - } - case HSA_AGENT_INFO_FEATURE: - *((hsa_agent_feature_t *)value) = HSA_AGENT_FEATURE_AGENT_DISPATCH; - break; - case HSA_AGENT_INFO_MACHINE_MODEL: - *reinterpret_cast(value) = HSA_MACHINE_MODEL_LARGE; - break; - case HSA_AGENT_INFO_BASE_PROFILE_DEFAULT_FLOAT_ROUNDING_MODES: - case HSA_AGENT_INFO_DEFAULT_FLOAT_ROUNDING_MODE: - // TODO: validate if this is true. - *reinterpret_cast(value) = - HSA_DEFAULT_FLOAT_ROUNDING_MODE_NEAR; - break; - case HSA_AGENT_INFO_PROFILE: - *reinterpret_cast(value) = profile_; - break; - case HSA_AGENT_INFO_WAVEFRONT_SIZE: - *reinterpret_cast(value) = 0; - break; - case HSA_AGENT_INFO_WORKGROUP_MAX_DIM: - std::memset(value, 0, sizeof(uint16_t) * 3); - break; - case HSA_AGENT_INFO_WORKGROUP_MAX_SIZE: - *reinterpret_cast(value) = 0; - break; - case HSA_AGENT_INFO_GRID_MAX_DIM: - std::memset(value, 0, sizeof(uint16_t) * 3); - break; - case HSA_AGENT_INFO_GRID_MAX_SIZE: - *reinterpret_cast(value) = 0; - break; - case HSA_AGENT_INFO_FBARRIER_MAX_SIZE: - *reinterpret_cast(value) = 0; - break; - case HSA_AGENT_INFO_QUEUES_MAX: - *reinterpret_cast(value) = max_queues_; - break; - case HSA_AGENT_INFO_QUEUE_MIN_SIZE: - *reinterpret_cast(value) = min_aql_size_; - break; - case HSA_AGENT_INFO_QUEUE_MAX_SIZE: - *reinterpret_cast(value) = max_aql_size_; - break; - case HSA_AGENT_INFO_QUEUE_TYPE: - *reinterpret_cast(value) = HSA_QUEUE_TYPE_SINGLE; - break; - case HSA_AGENT_INFO_NODE: - *reinterpret_cast(value) = node_id(); - break; - case HSA_AGENT_INFO_DEVICE: - *reinterpret_cast(value) = HSA_DEVICE_TYPE_AIE; - break; - case HSA_AGENT_INFO_CACHE_SIZE: - *reinterpret_cast(value) = 0; - break; - case HSA_AGENT_INFO_VERSION_MAJOR: - *reinterpret_cast(value) = 1; - break; - case HSA_AGENT_INFO_VERSION_MINOR: - *reinterpret_cast(value) = 0; - break; - case HSA_AMD_AGENT_INFO_CHIP_ID: - *reinterpret_cast(value) = 0; - break; - case HSA_AMD_AGENT_INFO_CACHELINE_SIZE: - *reinterpret_cast(value) = 0; - break; - case HSA_AMD_AGENT_INFO_COMPUTE_UNIT_COUNT: - *reinterpret_cast(value) = 0; - break; - case HSA_AMD_AGENT_INFO_MAX_CLOCK_FREQUENCY: - *reinterpret_cast(value) = 0; - break; - case HSA_AMD_AGENT_INFO_DRIVER_NODE_ID: - *reinterpret_cast(value) = node_id(); - break; - case HSA_AMD_AGENT_INFO_MAX_ADDRESS_WATCH_POINTS: - *reinterpret_cast(value) = 0; - break; - case HSA_AMD_AGENT_INFO_BDFID: - *reinterpret_cast(value) = 0; - break; - case HSA_AMD_AGENT_INFO_NUM_SIMDS_PER_CU: - *reinterpret_cast(value) = 0; - break; - case HSA_AMD_AGENT_INFO_NUM_SHADER_ENGINES: - *reinterpret_cast(value) = 0; - break; - case HSA_AMD_AGENT_INFO_NUM_SHADER_ARRAYS_PER_SE: - *reinterpret_cast(value) = 0; - break; - case HSA_EXT_AGENT_INFO_IMAGE_1D_MAX_ELEMENTS: - case HSA_EXT_AGENT_INFO_IMAGE_1DA_MAX_ELEMENTS: - case HSA_EXT_AGENT_INFO_IMAGE_1DB_MAX_ELEMENTS: - case HSA_EXT_AGENT_INFO_IMAGE_2D_MAX_ELEMENTS: - case HSA_EXT_AGENT_INFO_IMAGE_2DA_MAX_ELEMENTS: - case HSA_EXT_AGENT_INFO_IMAGE_2DDEPTH_MAX_ELEMENTS: - case HSA_EXT_AGENT_INFO_IMAGE_2DADEPTH_MAX_ELEMENTS: - case HSA_EXT_AGENT_INFO_IMAGE_3D_MAX_ELEMENTS: - case HSA_EXT_AGENT_INFO_IMAGE_ARRAY_MAX_LAYERS: - *reinterpret_cast(value) = 0; - break; - case HSA_AMD_AGENT_INFO_PRODUCT_NAME: { - const std::string product_name_info_("AIE-ML"); - assert(product_name_info_.size() < HSA_PUBLIC_NAME_SIZE); - std::memset(value, 0, HSA_PUBLIC_NAME_SIZE); - std::strncat(reinterpret_cast(value), product_name_info_.c_str(), - product_name_info_.size()); - break; - } - case HSA_AMD_AGENT_INFO_UUID: { - // At this point AIE devices do not support UUID's. - char uuid_tmp[] = "AIE-XX"; - snprintf((char *)value, sizeof(uuid_tmp), "%s", uuid_tmp); - break; - } - case HSA_AMD_AGENT_INFO_ASIC_REVISION: - *reinterpret_cast(value) = 0; - break; - case HSA_AMD_AGENT_INFO_SVM_DIRECT_HOST_ACCESS: - assert(regions_.size() != 0 && "No device local memory found!"); - *reinterpret_cast(value) = true; - break; - case HSA_AMD_AGENT_INFO_MEMORY_PROPERTIES: - std::memset(value, 0, sizeof(uint8_t) * 8); - break; - case HSA_AMD_AGENT_INFO_CLOCK_COUNTERS: - std::memset(value, 0, sizeof(hsa_amd_clock_counters_t)); - break; - default: - *reinterpret_cast(value) = 0; - return HSA_STATUS_ERROR_INVALID_ARGUMENT; + case HSA_AGENT_INFO_NAME: + std::copy_n(node_props_.AMDName, HSA_PUBLIC_NAME_SIZE, static_cast(value)); + break; + case HSA_AGENT_INFO_VENDOR_NAME: { + constexpr std::string_view vendor_name_info("AMD"); + assert(vendor_name_info.size() < HSA_PUBLIC_NAME_SIZE); + auto ptr = static_cast(value); + std::copy(vendor_name_info.begin(), vendor_name_info.end(), ptr); + std::fill(std::next(ptr, vendor_name_info.size()), std::next(ptr, HSA_PUBLIC_NAME_SIZE), 0); + break; + } + case HSA_AGENT_INFO_FEATURE: + *static_cast(value) = HSA_AGENT_FEATURE_AGENT_DISPATCH; + break; + case HSA_AGENT_INFO_MACHINE_MODEL: + *static_cast(value) = HSA_MACHINE_MODEL_LARGE; + break; + case HSA_AGENT_INFO_BASE_PROFILE_DEFAULT_FLOAT_ROUNDING_MODES: + case HSA_AGENT_INFO_DEFAULT_FLOAT_ROUNDING_MODE: + // TODO: validate if this is true. + *static_cast(value) = + HSA_DEFAULT_FLOAT_ROUNDING_MODE_NEAR; + break; + case HSA_AGENT_INFO_PROFILE: + *static_cast(value) = profile_; + break; + case HSA_AGENT_INFO_WAVEFRONT_SIZE: + *static_cast(value) = 0; + break; + case HSA_AGENT_INFO_WORKGROUP_MAX_DIM: + std::memset(value, 0, sizeof(uint16_t) * 3); + break; + case HSA_AGENT_INFO_WORKGROUP_MAX_SIZE: + *static_cast(value) = 0; + break; + case HSA_AGENT_INFO_GRID_MAX_DIM: + std::memset(value, 0, sizeof(uint16_t) * 3); + break; + case HSA_AGENT_INFO_GRID_MAX_SIZE: + *static_cast(value) = 0; + break; + case HSA_AGENT_INFO_FBARRIER_MAX_SIZE: + *static_cast(value) = 0; + break; + case HSA_AGENT_INFO_QUEUES_MAX: + *static_cast(value) = max_queues_; + break; + case HSA_AGENT_INFO_QUEUE_MIN_SIZE: + *static_cast(value) = min_aql_size_; + break; + case HSA_AGENT_INFO_QUEUE_MAX_SIZE: + *static_cast(value) = max_aql_size_; + break; + case HSA_AGENT_INFO_QUEUE_TYPE: + *static_cast(value) = HSA_QUEUE_TYPE_SINGLE; + break; + case HSA_AGENT_INFO_NODE: + *static_cast(value) = node_id(); + break; + case HSA_AGENT_INFO_DEVICE: + *static_cast(value) = HSA_DEVICE_TYPE_AIE; + break; + case HSA_AGENT_INFO_CACHE_SIZE: + *static_cast(value) = 0; + break; + case HSA_AGENT_INFO_VERSION_MAJOR: + *static_cast(value) = 1; + break; + case HSA_AGENT_INFO_VERSION_MINOR: + *static_cast(value) = 0; + break; + case HSA_AMD_AGENT_INFO_CHIP_ID: + *static_cast(value) = 0; + break; + case HSA_AMD_AGENT_INFO_CACHELINE_SIZE: + *static_cast(value) = 0; + break; + case HSA_AMD_AGENT_INFO_COMPUTE_UNIT_COUNT: + *static_cast(value) = 0; + break; + case HSA_AMD_AGENT_INFO_MAX_CLOCK_FREQUENCY: + *static_cast(value) = 0; + break; + case HSA_AMD_AGENT_INFO_DRIVER_NODE_ID: + *static_cast(value) = node_id(); + break; + case HSA_AMD_AGENT_INFO_MAX_ADDRESS_WATCH_POINTS: + *static_cast(value) = 0; + break; + case HSA_AMD_AGENT_INFO_BDFID: + *static_cast(value) = 0; + break; + case HSA_AMD_AGENT_INFO_NUM_SIMDS_PER_CU: + *static_cast(value) = 0; + break; + case HSA_AMD_AGENT_INFO_NUM_SHADER_ENGINES: + *static_cast(value) = 0; + break; + case HSA_AMD_AGENT_INFO_NUM_SHADER_ARRAYS_PER_SE: + *static_cast(value) = 0; + break; + case HSA_EXT_AGENT_INFO_IMAGE_1D_MAX_ELEMENTS: + case HSA_EXT_AGENT_INFO_IMAGE_1DA_MAX_ELEMENTS: + case HSA_EXT_AGENT_INFO_IMAGE_1DB_MAX_ELEMENTS: + case HSA_EXT_AGENT_INFO_IMAGE_2D_MAX_ELEMENTS: + case HSA_EXT_AGENT_INFO_IMAGE_2DA_MAX_ELEMENTS: + case HSA_EXT_AGENT_INFO_IMAGE_2DDEPTH_MAX_ELEMENTS: + case HSA_EXT_AGENT_INFO_IMAGE_2DADEPTH_MAX_ELEMENTS: + case HSA_EXT_AGENT_INFO_IMAGE_3D_MAX_ELEMENTS: + case HSA_EXT_AGENT_INFO_IMAGE_ARRAY_MAX_LAYERS: + *static_cast(value) = 0; + break; + case HSA_AMD_AGENT_INFO_PRODUCT_NAME: + // Copy MarketingName which is 7-bit ASCII stored in UTF-16 array + std::copy_n(node_props_.MarketingName, HSA_PUBLIC_NAME_SIZE, static_cast(value)); + break; + case HSA_AMD_AGENT_INFO_UUID: { + // At this point AIE devices do not support UUID's. + constexpr std::string_view uuid = "AIE-XX"; + auto ptr = static_cast(value); + std::copy(uuid.begin(), uuid.end(), ptr); + *std::next(ptr, uuid.size()) = '\0'; + break; + } + case HSA_AMD_AGENT_INFO_ASIC_REVISION: + *static_cast(value) = 0; + break; + case HSA_AMD_AGENT_INFO_SVM_DIRECT_HOST_ACCESS: + assert(regions_.size() != 0 && "No device local memory found!"); + *static_cast(value) = true; + break; + case HSA_AMD_AGENT_INFO_MEMORY_PROPERTIES: + std::memset(value, 0, sizeof(uint8_t) * 8); + break; + case HSA_AMD_AGENT_INFO_CLOCK_COUNTERS: + std::memset(value, 0, sizeof(hsa_amd_clock_counters_t)); + break; + default: + *static_cast(value) = 0; + return HSA_STATUS_ERROR_INVALID_ARGUMENT; } return HSA_STATUS_SUCCESS;