SWDEV-361376 - Add python wrapper
- Add generator for python wrapper
- Add interface, exception and init files
- Add CMake custom targets
Change-Id: I63c1d94fbb587387c22f559a3db79987eb214a2e
Signed-off-by: Dejan Andjelkovic <Dejan.Andjelkovic@amd.com>
[ROCm/amdsmi commit: 6064f160a3]
Этот коммит содержится в:
коммит произвёл
Bill(Shuzhou) Liu
родитель
c68caedcbd
Коммит
14d9160565
@@ -142,6 +142,7 @@ set(CMN_SRC_LIST ${CMN_SRC_LIST} "${AMDSMI_SRC_DIR}/amd_smi_system.cc")
|
||||
set(CMN_SRC_LIST ${CMN_SRC_LIST} "${AMDSMI_SRC_DIR}/amd_smi_drm.cc")
|
||||
set(CMN_SRC_LIST ${CMN_SRC_LIST} "${AMDSMI_SRC_DIR}/amd_smi_lib_loader.cc")
|
||||
set(CMN_SRC_LIST ${CMN_SRC_LIST} "${AMDSMI_SRC_DIR}/amd_smi_utils.cc")
|
||||
set(CMN_SRC_LIST ${CMN_SRC_LIST} "${AMDSMI_SRC_DIR}/amd_smi_uuid.cc")
|
||||
set(CMN_SRC_LIST ${CMN_SRC_LIST} "${AMDSMI_SRC_DIR}/fdinfo.cc")
|
||||
|
||||
set(CMN_INC_LIST "${ROCM_INC_DIR}/rocm_smi_device.h")
|
||||
@@ -210,6 +211,45 @@ else()
|
||||
message("Doxygen or Latex is not found. Will not generate documents.")
|
||||
endif(DOXYGEN_FOUND AND LATEX_FOUND)
|
||||
|
||||
# Generate python_wrapper and package targets
|
||||
find_program(PYTHON3 "python3")
|
||||
find_program(PIP3 "pip3")
|
||||
|
||||
if (PYTHON3 AND PIP3)
|
||||
add_custom_command(OUTPUT clang_tools_extract
|
||||
COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/amdsmi_wrapper
|
||||
COMMAND pip3 download ctypeslib2==2.3.2 -d ${CMAKE_CURRENT_BINARY_DIR}/dl
|
||||
COMMAND pip3 download clang==10.0.1 -d ${CMAKE_CURRENT_BINARY_DIR}/dl
|
||||
COMMAND unzip -o ${CMAKE_CURRENT_BINARY_DIR}/dl/ctypeslib2-2.3.2-py3-none-any.whl -d ${CMAKE_CURRENT_BINARY_DIR}/amdsmi_wrapper
|
||||
COMMAND unzip -o ${CMAKE_CURRENT_BINARY_DIR}/dl/clang-10.0.1-py3-none-any.whl -d ${CMAKE_CURRENT_BINARY_DIR}/amdsmi_wrapper
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_custom_target(python_wrapper DEPENDS clang_tools_extract
|
||||
COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/amdsmi_wrapper
|
||||
COMMAND cp -r ${CMAKE_CURRENT_SOURCE_DIR}/include/amd_smi/amd_smi.h ${CMAKE_CURRENT_BINARY_DIR}/amdsmi_wrapper
|
||||
COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/amdsmi_wrapper/rocm_smi
|
||||
COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/rocm_smi/include/rocm_smi/kfd_ioctl.h ${CMAKE_CURRENT_BINARY_DIR}/amdsmi_wrapper/rocm_smi/
|
||||
COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/tools/generator.py ${CMAKE_CURRENT_BINARY_DIR}/amdsmi_wrapper/amd_smi.h ${CMAKE_CURRENT_BINARY_DIR}/amdsmi_wrapper/ ${CMAKE_CURRENT_BINARY_DIR}/amdsmi_wrapper/
|
||||
COMMAND cp ${CMAKE_CURRENT_BINARY_DIR}/amdsmi_wrapper/amdsmi_wrapper.py ${CMAKE_CURRENT_SOURCE_DIR}/py-interface/
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/amdsmi_wrapper)
|
||||
|
||||
set (PY_INTERFACE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/py-interface")
|
||||
set (PACKAGE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/python_package/amdsmi")
|
||||
|
||||
add_custom_target(python_package DEPENDS python_wrapper
|
||||
COMMAND mkdir -p ${PACKAGE_OUTPUT_DIR}
|
||||
COMMAND cp ${PY_INTERFACE_DIR}/__init__.py ${PACKAGE_OUTPUT_DIR}
|
||||
COMMAND cp ${PY_INTERFACE_DIR}/amdsmi_exception.py ${PACKAGE_OUTPUT_DIR}
|
||||
COMMAND cp ${PY_INTERFACE_DIR}/amdsmi_interface.py ${PACKAGE_OUTPUT_DIR}
|
||||
COMMAND cp ${PY_INTERFACE_DIR}/amdsmi_wrapper.py ${PACKAGE_OUTPUT_DIR}
|
||||
COMMAND cp ${PY_INTERFACE_DIR}/README.md ${PACKAGE_OUTPUT_DIR}
|
||||
COMMAND cp ${CMAKE_CURRENT_BINARY_DIR}/rocm_smi/libamd_smi64.so ${PACKAGE_OUTPUT_DIR}
|
||||
COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE ${PACKAGE_OUTPUT_DIR}
|
||||
COMMAND echo ${PACKAGE_OUTPUT_DIR})
|
||||
|
||||
else()
|
||||
message("Python3 or Pip3 not found.")
|
||||
endif(PYTHON3 AND PIP3)
|
||||
|
||||
#TODO: Should use GNUInstallDirs to match distro standards
|
||||
#This need fix in subdirectory CMakefile as well
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2019-2022 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.
|
||||
|
||||
@@ -118,6 +118,7 @@ int main() {
|
||||
return AMDSMI_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
// Get BDF info
|
||||
amdsmi_bdf_t bdf = {};
|
||||
ret = amdsmi_get_device_bdf(device_handles[j], &bdf);
|
||||
CHK_AMDSMI_RET(ret)
|
||||
@@ -126,6 +127,12 @@ int main() {
|
||||
bdf.domain_number, bdf.bus_number, bdf.device_number,
|
||||
bdf.function_number);
|
||||
|
||||
// Get handle from BDF
|
||||
amdsmi_device_handle dev_handle;
|
||||
ret = amdsmi_get_device_handle_from_bdf(bdf, &device_handles[0], device_count, &dev_handle);
|
||||
CHK_AMDSMI_RET(ret)
|
||||
|
||||
// Get ASIC info
|
||||
amdsmi_asic_info_t asic_info = {};
|
||||
ret = amdsmi_get_asic_info(device_handles[j], &asic_info);
|
||||
CHK_AMDSMI_RET(ret)
|
||||
@@ -149,6 +156,34 @@ int main() {
|
||||
printf("\tVBios Version String: %s\n\n",
|
||||
vbios_info.vbios_version_string);
|
||||
|
||||
// Get power measure
|
||||
amdsmi_power_measure_t power_measure = {};
|
||||
ret = amdsmi_get_power_measure(device_handles[j], &power_measure);
|
||||
CHK_AMDSMI_RET(ret)
|
||||
printf(" Output of amdsmi_get_power_measure:\n");
|
||||
printf("\tCurrent GFX Voltage: %d\n",
|
||||
power_measure.voltage_gfx);
|
||||
printf("\tAverage socket power: %d\n",
|
||||
power_measure.average_socket_power);
|
||||
printf("\tEnergy accumulator: %d\n\n",
|
||||
power_measure.energy_accumulator);
|
||||
|
||||
// Get driver version
|
||||
char version[AMDSMI_MAX_DRIVER_VERSION_LENGTH];
|
||||
int version_length = AMDSMI_MAX_DRIVER_VERSION_LENGTH;
|
||||
ret = amdsmi_get_driver_version(device_handles[j], &version_length, version);
|
||||
CHK_AMDSMI_RET(ret)
|
||||
printf(" Output of amdsmi_get_driver_version:\n");
|
||||
printf("\tDriver version: %s\n\n", version);
|
||||
|
||||
// Get device uuid
|
||||
unsigned int uuid_length = AMDSMI_GPU_UUID_SIZE;
|
||||
char uuid[AMDSMI_GPU_UUID_SIZE];
|
||||
ret = amdsmi_get_device_uuid(device_handles[j], &uuid_length, uuid);
|
||||
CHK_AMDSMI_RET(ret)
|
||||
printf(" Output of amdsmi_get_device_uuid:\n");
|
||||
printf("\tDevice uuid: %s\n\n", uuid);
|
||||
|
||||
// Get engine usage info
|
||||
amdsmi_engine_usage_t engine_usage = {};
|
||||
ret = amdsmi_get_gpu_activity(device_handles[j], &engine_usage);
|
||||
@@ -228,8 +263,8 @@ int main() {
|
||||
printf("\tGPU Power limit: %d\n\n", power_limit.limit);
|
||||
|
||||
// Get GFX clock measurements
|
||||
amdsmi_clock_measure_t gfx_clk_values = {};
|
||||
ret = amdsmi_get_clock_measure(device_handles[j], CLOCK_TYPE_GFX,
|
||||
amdsmi_clk_measure_t gfx_clk_values = {};
|
||||
ret = amdsmi_get_clock_measure(device_handles[j], CLK_TYPE_GFX,
|
||||
&gfx_clk_values);
|
||||
CHK_AMDSMI_RET(ret)
|
||||
printf(" Output of amdsmi_get_clock_measure:\n");
|
||||
@@ -238,14 +273,30 @@ int main() {
|
||||
printf("\tGPU GFX Current Clock: %d\n", gfx_clk_values.cur_clk);
|
||||
|
||||
// Get MEM clock measurements
|
||||
amdsmi_clock_measure_t mem_clk_values = {};
|
||||
ret = amdsmi_get_clock_measure(device_handles[j], CLOCK_TYPE_MEM,
|
||||
amdsmi_clk_measure_t mem_clk_values = {};
|
||||
ret = amdsmi_get_clock_measure(device_handles[j], CLK_TYPE_MEM,
|
||||
&mem_clk_values);
|
||||
CHK_AMDSMI_RET(ret)
|
||||
printf("\tGPU MEM Max Clock: %d\n", mem_clk_values.max_clk);
|
||||
printf("\tGPU MEM Average Clock: %d\n", mem_clk_values.avg_clk);
|
||||
printf("\tGPU MEM Current Clock: %d\n\n", mem_clk_values.cur_clk);
|
||||
|
||||
// Get PCIe status
|
||||
amdsmi_pcie_info_t pcie_info = {};
|
||||
ret = amdsmi_get_pcie_link_status(device_handles[j], &pcie_info);
|
||||
CHK_AMDSMI_RET(ret)
|
||||
printf(" Output of amdsmi_get_pcie_link_status:\n");
|
||||
printf("\tPCIe lanes: %d\n", pcie_info.pcie_lanes);
|
||||
printf("\tPCIe speed: %d\n\n", pcie_info.pcie_speed);
|
||||
|
||||
// Get PCIe caps
|
||||
amdsmi_pcie_info_t pcie_caps_info = {};
|
||||
ret = amdsmi_get_pcie_link_caps(device_handles[j], &pcie_caps_info);
|
||||
CHK_AMDSMI_RET(ret)
|
||||
printf(" Output of amdsmi_get_pcie_link_caps:\n");
|
||||
printf("\tPCIe max lanes: %d\n", pcie_caps_info.pcie_lanes);
|
||||
printf("\tPCIe max speed: %d\n\n", pcie_caps_info.pcie_speed);
|
||||
|
||||
// Get VRAM temperature limit
|
||||
amdsmi_temperature_limit_t mem_temp_limit = {};
|
||||
ret = amdsmi_get_temperature_limit(
|
||||
@@ -294,11 +345,11 @@ int main() {
|
||||
"ENABLED"};
|
||||
amdsmi_ras_err_state_t state = {};
|
||||
int index = 0;
|
||||
printf(" Output of amdsmi_get_ras_features_enabled:\n");
|
||||
printf(" Output of amdsmi_get_ras_block_features_enabled:\n");
|
||||
for (auto block = AMDSMI_GPU_BLOCK_FIRST;
|
||||
block <= AMDSMI_GPU_BLOCK_LAST;
|
||||
block = (amdsmi_gpu_block_t)(block * 2)) {
|
||||
ret = amdsmi_get_ras_features_enabled(device_handles[j], block,
|
||||
ret = amdsmi_get_ras_block_features_enabled(device_handles[j], block,
|
||||
&state);
|
||||
CHK_AMDSMI_RET(ret)
|
||||
printf("\tBlock: %s\n", block_names[index]);
|
||||
@@ -362,7 +413,7 @@ int main() {
|
||||
// Get frequency ranges
|
||||
amdsmi_frequency_range_t freq_ranges = {};
|
||||
ret = amdsmi_get_target_frequency_range(
|
||||
device_handles[j], CLOCK_TYPE_GFX, &freq_ranges);
|
||||
device_handles[j], CLK_TYPE_GFX, &freq_ranges);
|
||||
CHK_AMDSMI_RET(ret)
|
||||
printf(" Output of amdsmi_get_target_frequency_range:\n");
|
||||
printf("\tSupported min freq: %lu\n",
|
||||
|
||||
@@ -45,13 +45,14 @@
|
||||
#define INCLUDE_AMD_SMI_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif // __cplusplus
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initialization flags
|
||||
*
|
||||
@@ -141,20 +142,20 @@ typedef enum amdsmi_status_t {
|
||||
* Clock types
|
||||
*/
|
||||
typedef enum amdsmi_clk_type {
|
||||
CLOCK_TYPE_SYS = 0x0, //!< System clock
|
||||
CLOCK_TYPE_FIRST = CLOCK_TYPE_SYS,
|
||||
CLOCK_TYPE_GFX = CLOCK_TYPE_SYS,
|
||||
CLOCK_TYPE_DF, //!< Data Fabric clock (for ASICs
|
||||
CLK_TYPE_SYS = 0x0, //!< System clock
|
||||
CLK_TYPE_FIRST = CLK_TYPE_SYS,
|
||||
CLK_TYPE_GFX = CLK_TYPE_SYS,
|
||||
CLK_TYPE_DF, //!< Data Fabric clock (for ASICs
|
||||
//!< running on a separate clock)
|
||||
CLOCK_TYPE_DCEF, //!< Display Controller Engine clock
|
||||
CLOCK_TYPE_SOC,
|
||||
CLOCK_TYPE_MEM,
|
||||
CLOCK_TYPE_PCIE,
|
||||
CLOCK_TYPE_VCLK0,
|
||||
CLOCK_TYPE_VCLK1,
|
||||
CLOCK_TYPE_DCLK0,
|
||||
CLOCK_TYPE_DCLK1,
|
||||
CLOCK_TYPE__MAX = CLOCK_TYPE_DCLK1
|
||||
CLK_TYPE_DCEF, //!< Display Controller Engine clock
|
||||
CLK_TYPE_SOC,
|
||||
CLK_TYPE_MEM,
|
||||
CLK_TYPE_PCIE,
|
||||
CLK_TYPE_VCLK0,
|
||||
CLK_TYPE_VCLK1,
|
||||
CLK_TYPE_DCLK0,
|
||||
CLK_TYPE_DCLK1,
|
||||
CLK_TYPE__MAX = CLK_TYPE_DCLK1
|
||||
} amdsmi_clk_type_t;
|
||||
/// \cond Ignore in docs.
|
||||
typedef amdsmi_clk_type_t amdsmi_clk_type;
|
||||
@@ -346,19 +347,19 @@ typedef struct amdsmi_power_limit {
|
||||
} amdsmi_power_limit_t;
|
||||
|
||||
typedef struct amdsmi_power_measure {
|
||||
uint16_t average_socket_power;
|
||||
uint32_t average_socket_power;
|
||||
uint64_t energy_accumulator; // v1 mod. (32->64)
|
||||
uint32_t voltage_gfx; // GFX voltage measurement in mV
|
||||
uint32_t voltage_soc; // SOC voltage measurement in mV
|
||||
uint32_t voltage_mem; // MEM voltage measurement in mV
|
||||
} amdsmi_power_measure_t;
|
||||
|
||||
typedef struct amdsmi_clock_measure {
|
||||
typedef struct amdsmi_clk_measure {
|
||||
uint32_t cur_clk;
|
||||
uint32_t avg_clk;
|
||||
uint32_t min_clk;
|
||||
uint32_t max_clk;
|
||||
} amdsmi_clock_measure_t;
|
||||
} amdsmi_clk_measure_t;
|
||||
|
||||
typedef struct amdsmi_engine_usage {
|
||||
uint32_t average_gfx_activity;
|
||||
@@ -1080,6 +1081,13 @@ typedef struct {
|
||||
uint64_t uncorrectable_count; //!< Accumulated uncorrectable errors
|
||||
} amdsmi_error_count_t;
|
||||
|
||||
/**
|
||||
* @brief This structure holds pcie info.
|
||||
*/
|
||||
typedef struct amdsmi_pcie_info {
|
||||
uint16_t pcie_lanes;
|
||||
uint16_t pcie_speed;
|
||||
} amdsmi_pcie_info_t;
|
||||
/**
|
||||
* @brief This structure contains information specific to a process.
|
||||
*/
|
||||
@@ -1134,8 +1142,8 @@ typedef union amd_id {
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Initialize AMD SMI.
|
||||
*
|
||||
* @brief Initialize AMD SMI.
|
||||
*
|
||||
* @details When called, this initializes internal data structures,
|
||||
* including those corresponding to sources of information that SMI provides.
|
||||
*
|
||||
@@ -1164,7 +1172,7 @@ amdsmi_status_t amdsmi_shut_down(void);
|
||||
|
||||
/*****************************************************************************/
|
||||
/** @defgroup Discovery Queries
|
||||
* These functions provide discovery of the sockets.
|
||||
* These functions provide discovery of the sockets.
|
||||
* @{
|
||||
*/
|
||||
|
||||
@@ -1208,7 +1216,7 @@ amdsmi_status_t amdsmi_get_socket_handles(uint32_t *socket_count,
|
||||
* @param[in] socket_handle a socket handle
|
||||
*
|
||||
* @param[out] name The id of the socket.
|
||||
*
|
||||
*
|
||||
* @param[in] len the length of the caller provided buffer @p name.
|
||||
*
|
||||
* @retval ::AMDSMI_STATUS_SUCCESS call was successful
|
||||
@@ -1275,6 +1283,28 @@ amdsmi_status_t amdsmi_get_device_handles(amdsmi_socket_handle socket_handle,
|
||||
amdsmi_status_t amdsmi_get_device_type(amdsmi_device_handle device_handle,
|
||||
device_type_t* device_type);
|
||||
|
||||
/**
|
||||
* @brief Get device handle with the matching bdf.
|
||||
*
|
||||
* @details Given bdf info @p bdf, this function will get
|
||||
* the device handle with the matching bdf.
|
||||
*
|
||||
* @param[in] bdf The bdf to match with corresponding device handle.
|
||||
*
|
||||
* @param[in] device_handles a list of devices handles on the socket.
|
||||
*
|
||||
* @param[in] device_count a count of handles in device_handles.
|
||||
*
|
||||
* @param[out] device_handle device handle with the matching bdf.
|
||||
*
|
||||
* @retval ::AMDSMI_STATUS_SUCCESS call was successful
|
||||
* @retval ::AMDSMI_STATUS_INVAL the provided arguments are not valid
|
||||
*/
|
||||
amdsmi_status_t amdsmi_get_device_handle_from_bdf(amdsmi_bdf_t bdf,
|
||||
amdsmi_device_handle* device_handles,
|
||||
uint32_t device_count,
|
||||
amdsmi_device_handle* device_handle);
|
||||
|
||||
/** @} */ // end of Discovery
|
||||
|
||||
|
||||
@@ -1868,7 +1898,7 @@ amdsmi_get_bad_page_info(amdsmi_device_handle device_handle, uint32_t *num_pages
|
||||
*
|
||||
*/
|
||||
amdsmi_status_t
|
||||
amdsmi_get_ras_features_enabled(amdsmi_device_handle device_handle, amdsmi_gpu_block block,
|
||||
amdsmi_get_ras_block_features_enabled(amdsmi_device_handle device_handle, amdsmi_gpu_block block,
|
||||
amdsmi_ras_err_state_t *state);
|
||||
/**
|
||||
* @brief Get percentage of time any device memory is being used
|
||||
@@ -2211,6 +2241,42 @@ amdsmi_utilization_count_get(amdsmi_device_handle device_handle,
|
||||
uint32_t count,
|
||||
uint64_t *timestamp);
|
||||
|
||||
/**
|
||||
* @brief Get current PCIE info of the device with provided device handle.
|
||||
*
|
||||
* @details Given a device handle @p dev, this function returns PCIE info of the
|
||||
* given device.
|
||||
*
|
||||
* @param[in] dev a device handle
|
||||
*
|
||||
* @param[out] info amdsmi_pcie_info_t struct which will hold all the extracted PCIE info data.
|
||||
*
|
||||
* @retval ::AMDSMI_STATUS_SUCCESS call was successful
|
||||
* @retval ::AMDSMI_STATUS_NOT_SUPPORTED installed software or hardware does not
|
||||
* support this function with the given arguments
|
||||
* @retval ::AMDSMI_STATUS_INVAL the provided arguments are not valid
|
||||
*
|
||||
*/
|
||||
amdsmi_status_t amdsmi_get_pcie_link_status(amdsmi_device_handle dev, amdsmi_pcie_info_t *info);
|
||||
|
||||
/**
|
||||
* @brief Get max PCIe capabilities of the device with provided device handle.
|
||||
*
|
||||
* @details Given a device handle @p dev, this function returns PCIe caps info of the
|
||||
* given device.
|
||||
*
|
||||
* @param[in] dev a device handle
|
||||
*
|
||||
* @param[out] info amdsmi_pcie_info_t struct which will hold all the extracted PCIe caps data.
|
||||
*
|
||||
* @retval ::AMDSMI_STATUS_SUCCESS call was successful
|
||||
* @retval ::AMDSMI_STATUS_NOT_SUPPORTED installed software or hardware does not
|
||||
* support this function with the given arguments
|
||||
* @retval ::AMDSMI_STATUS_INVAL the provided arguments are not valid
|
||||
*
|
||||
*/
|
||||
amdsmi_status_t amdsmi_get_pcie_link_caps(amdsmi_device_handle dev, amdsmi_pcie_info_t *info);
|
||||
|
||||
/**
|
||||
* @brief Get the performance level of the device with provided
|
||||
* device handle.
|
||||
@@ -3447,7 +3513,7 @@ amdsmi_is_P2P_accessible(amdsmi_device_handle device_handle_src, amdsmi_device_h
|
||||
*
|
||||
* // Get the device handle via amdsmi_get_device_handles()
|
||||
* // ... ...
|
||||
*
|
||||
*
|
||||
* std::cout << "Supported AMDSMI Functions:" << std::endl; *
|
||||
* err = amdsmi_dev_supported_func_iterator_open(device, &iter_handle);
|
||||
*
|
||||
@@ -4033,7 +4099,7 @@ amdsmi_get_power_measure(amdsmi_device_handle dev, amdsmi_power_measure_t *info)
|
||||
* * -::AMDSMI_STATUS_API_FAILED - Other errors
|
||||
*/
|
||||
amdsmi_status_t
|
||||
amdsmi_get_clock_measure(amdsmi_device_handle dev, amdsmi_clk_type_t clk_type, amdsmi_clock_measure_t *info);
|
||||
amdsmi_get_clock_measure(amdsmi_device_handle dev, amdsmi_clk_type_t clk_type, amdsmi_clk_measure_t *info);
|
||||
|
||||
/**
|
||||
* \brief Returns temperature measurements of the GPU.
|
||||
|
||||
@@ -40,5 +40,6 @@ amdsmi_status_t smi_amdgpu_get_ranges(amd::smi::AMDSmiGPUDevice* device, amdsmi_
|
||||
amdsmi_status_t smi_amdgpu_get_enabled_blocks(amd::smi::AMDSmiGPUDevice* device, uint64_t *enabled_blocks);
|
||||
amdsmi_status_t smi_amdgpu_get_bad_page_info(amd::smi::AMDSmiGPUDevice* device, uint32_t *num_pages, amdsmi_retired_page_record_t *info);
|
||||
amdsmi_status_t smi_amdgpu_get_ecc_error_count(amd::smi::AMDSmiGPUDevice* device, amdsmi_error_count_t *err_cnt);
|
||||
amdsmi_status_t smi_amdgpu_get_driver_version(amd::smi::AMDSmiGPUDevice* device, int *length, char *version);
|
||||
|
||||
#endif //
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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.
|
||||
*/
|
||||
|
||||
#ifndef GPUVSMI_UUID_H_
|
||||
#define GPUVSMI_UUID_H_
|
||||
|
||||
/**
|
||||
* \brief Generates uuid for device with specified parameters
|
||||
*
|
||||
* \param [out] str String buffer where to output generated uuid
|
||||
*
|
||||
* \param [in] serial Asic serial
|
||||
*
|
||||
* \param [in] did Device ID
|
||||
*
|
||||
* \param [in] idx PF/VF index
|
||||
*
|
||||
* \return SMI_RET_CODE indicating result.
|
||||
*/
|
||||
amdsmi_status_t amdsmi_uuid_gen(char *str, uint64_t serial, uint16_t did, uint8_t idx);
|
||||
|
||||
#endif
|
||||
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
@@ -0,0 +1,114 @@
|
||||
#
|
||||
# Copyright (C) 2022 Advanced Micro Devices. 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.
|
||||
#
|
||||
|
||||
# Library Initialization
|
||||
from .amdsmi_interface import amdsmi_init
|
||||
from .amdsmi_interface import amdsmi_fini
|
||||
|
||||
# Device Descovery
|
||||
from .amdsmi_interface import amdsmi_get_device_type
|
||||
from .amdsmi_interface import amdsmi_get_device_handles
|
||||
from .amdsmi_interface import amdsmi_get_device_bdf
|
||||
from .amdsmi_interface import amdsmi_get_device_uuid
|
||||
from .amdsmi_interface import amdsmi_get_device_handle_from_bdf
|
||||
|
||||
# # SW Version Information
|
||||
from .amdsmi_interface import amdsmi_get_driver_version
|
||||
|
||||
# # ASIC and Bus Static Information
|
||||
from .amdsmi_interface import amdsmi_get_asic_info
|
||||
from .amdsmi_interface import amdsmi_get_power_info
|
||||
from .amdsmi_interface import amdsmi_get_caps_info
|
||||
|
||||
# # Microcode and VBIOS Information
|
||||
from .amdsmi_interface import amdsmi_get_vbios_info
|
||||
from .amdsmi_interface import amdsmi_get_fw_info
|
||||
|
||||
# # GPU Monitoring
|
||||
from .amdsmi_interface import amdsmi_get_gpu_activity
|
||||
from .amdsmi_interface import amdsmi_get_vram_usage
|
||||
from .amdsmi_interface import amdsmi_get_power_measure
|
||||
from .amdsmi_interface import amdsmi_get_clock_measure
|
||||
from .amdsmi_interface import amdsmi_get_temperature_measure
|
||||
|
||||
from .amdsmi_interface import amdsmi_get_pcie_link_status
|
||||
from .amdsmi_interface import amdsmi_get_pcie_link_caps
|
||||
from .amdsmi_interface import amdsmi_get_power_limit
|
||||
from .amdsmi_interface import amdsmi_get_temperature_limit
|
||||
from .amdsmi_interface import amdsmi_get_bad_page_info
|
||||
|
||||
# # Power Management
|
||||
from .amdsmi_interface import amdsmi_get_target_frequency_range
|
||||
|
||||
# # Process Information
|
||||
from .amdsmi_interface import amdsmi_get_process_list
|
||||
from .amdsmi_interface import amdsmi_get_process_info
|
||||
|
||||
# # ECC Error Information
|
||||
from .amdsmi_interface import amdsmi_get_ecc_error_count
|
||||
|
||||
# # Board Information
|
||||
from .amdsmi_interface import amdsmi_get_board_info
|
||||
|
||||
# # Ras Information
|
||||
from .amdsmi_interface import amdsmi_get_ras_block_features_enabled
|
||||
|
||||
# # Events
|
||||
# from .smi_interface import EventListen
|
||||
|
||||
# # Enums
|
||||
|
||||
from .amdsmi_interface import AmdSmiInitFlags
|
||||
from .amdsmi_interface import AmdSmiContainerTypes
|
||||
from .amdsmi_interface import AmdSmiDeviceType
|
||||
from .amdsmi_interface import AmdSmiMmIp
|
||||
from .amdsmi_interface import AmdSmiFWBlock
|
||||
from .amdsmi_interface import AmdSmiClockType
|
||||
from .amdsmi_interface import AmdSmiTemperatureType
|
||||
from .amdsmi_interface import AmdSmiDevPerfLevel
|
||||
from .amdsmi_interface import AmdSmiSwComponent
|
||||
from .amdsmi_interface import AmdSmiEventGroup
|
||||
from .amdsmi_interface import AmdSmiEventType
|
||||
from .amdsmi_interface import AmdSmiCounterCommand
|
||||
from .amdsmi_interface import AmdSmiEvtNotificationType
|
||||
from .amdsmi_interface import AmdSmiTemperatureMetric
|
||||
from .amdsmi_interface import AmdSmiVoltageMetric
|
||||
from .amdsmi_interface import AmdSmiVoltageType
|
||||
from .amdsmi_interface import AmdSmiPowerProfilePresetMasks
|
||||
from .amdsmi_interface import AmdSmiGpuBlock
|
||||
from .amdsmi_interface import AmdSmiRasErrState
|
||||
from .amdsmi_interface import AmdSmiMemoryType
|
||||
from .amdsmi_interface import AmdSmiFreqInd
|
||||
from .amdsmi_interface import AmdSmiXgmiStatus
|
||||
from .amdsmi_interface import AmdSmiMemoryPageStatus
|
||||
from .amdsmi_interface import AmdSmiIoLinkType
|
||||
from .amdsmi_interface import AmdSmiUtilizationCounterType
|
||||
|
||||
# Exceptions
|
||||
|
||||
from .amdsmi_exception import AmdSmiLibraryException
|
||||
from .amdsmi_exception import AmdSmiRetryException
|
||||
from .amdsmi_exception import AmdSmiParameterException
|
||||
from .amdsmi_exception import AmdSmiKeyException
|
||||
from .amdsmi_exception import AmdSmiBdfFormatException
|
||||
from .amdsmi_exception import AmdSmiTimeoutException
|
||||
from .amdsmi_exception import AmdSmiException
|
||||
from .amdsmi_exception import AmdSmiRetCode
|
||||
@@ -0,0 +1,172 @@
|
||||
#
|
||||
# Copyright (C) 2022 Advanced Micro Devices. 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.
|
||||
#
|
||||
|
||||
from enum import IntEnum
|
||||
from . import amdsmi_wrapper
|
||||
|
||||
|
||||
class AmdSmiRetCode(IntEnum):
|
||||
SUCCESS = amdsmi_wrapper.AMDSMI_STATUS_SUCCESS
|
||||
ERR_INVAL = amdsmi_wrapper.AMDSMI_STATUS_INVAL
|
||||
ERR_NOT_SUPPORTED = amdsmi_wrapper.AMDSMI_STATUS_NOT_SUPPORTED
|
||||
FILE_ERROR = amdsmi_wrapper.AMDSMI_STATUS_FILE_ERROR
|
||||
ERR_NO_PERM = amdsmi_wrapper.AMDSMI_STATUS_NO_PERM
|
||||
ERR_OUT_OF_RESOURCES = amdsmi_wrapper.AMDSMI_STATUS_OUT_OF_RESOURCES
|
||||
INTERNAL_EXCEPTION = amdsmi_wrapper.AMDSMI_STATUS_INTERNAL_EXCEPTION
|
||||
INPUT_OUT_OF_BOUNDS = amdsmi_wrapper.AMDSMI_STATUS_INPUT_OUT_OF_BOUNDS
|
||||
INIT_ERROR = amdsmi_wrapper.AMDSMI_STATUS_INIT_ERROR
|
||||
NOT_IMPLEMENTED = amdsmi_wrapper.AMDSMI_STATUS_NOT_YET_IMPLEMENTED
|
||||
ERR_NOT_FOUND = amdsmi_wrapper.AMDSMI_STATUS_NOT_FOUND
|
||||
INSUFFICIENT_SIZE = amdsmi_wrapper.AMDSMI_STATUS_INSUFFICIENT_SIZE
|
||||
INTERRUPT = amdsmi_wrapper.AMDSMI_STATUS_INTERRUPT
|
||||
UNEXPECTED_SIZE = amdsmi_wrapper.AMDSMI_STATUS_UNEXPECTED_SIZE
|
||||
NO_DATA = amdsmi_wrapper.AMDSMI_STATUS_NO_DATA
|
||||
UNEXPECTED_DATA = amdsmi_wrapper.AMDSMI_STATUS_UNEXPECTED_DATA
|
||||
ERR_BUSY = amdsmi_wrapper.AMDSMI_STATUS_BUSY
|
||||
REFCOUNT_OVERFLOW = amdsmi_wrapper.AMDSMI_STATUS_REFCOUNT_OVERFLOW
|
||||
LIB_START = amdsmi_wrapper.AMDSMI_LIB_START
|
||||
FAIL_LOAD_MODULE = amdsmi_wrapper.AMDSMI_STATUS_FAIL_LOAD_MODULE
|
||||
FAIL_LOAD_SYMBOL = amdsmi_wrapper.AMDSMI_STATUS_FAIL_LOAD_SYMBOL
|
||||
DRM_ERROR = amdsmi_wrapper.AMDSMI_STATUS_DRM_ERROR
|
||||
ERR_IO = amdsmi_wrapper.AMDSMI_STATUS_IO
|
||||
FAULT = amdsmi_wrapper.AMDSMI_STATUS_FAULT
|
||||
API_FAILED = amdsmi_wrapper.AMDSMI_STATUS_API_FAILED
|
||||
TIMEOUT = amdsmi_wrapper.AMDSMI_STATUS_TIMEOUT
|
||||
NO_SLOT = amdsmi_wrapper.AMDSMI_STATUS_NO_SLOT
|
||||
RETRY = amdsmi_wrapper.AMDSMI_STATUS_RETRY
|
||||
NOT_INIT = amdsmi_wrapper.AMDSMI_STATUS_NOT_INIT
|
||||
UNKNOWN_ERROR = amdsmi_wrapper.AMDSMI_STATUS_UNKNOWN_ERROR
|
||||
|
||||
|
||||
class AmdSmiException(Exception):
|
||||
"""Base smi exception class"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class AmdSmiLibraryException(AmdSmiException):
|
||||
def __init__(self, err_code):
|
||||
err_code = abs(err_code)
|
||||
super().__init__(err_code)
|
||||
self.err_code = err_code
|
||||
self.set_err_info()
|
||||
|
||||
def __str__(self):
|
||||
return "An error occured with code: {err_code}({err_info})".format(
|
||||
err_code=self.err_code, err_info=self.err_info
|
||||
)
|
||||
|
||||
def get_error_code(self):
|
||||
return self.err_code
|
||||
|
||||
def set_err_info(self):
|
||||
switch = {
|
||||
AmdSmiRetCode.ERR_INVAL: "AMDSMI_STATUS_INVAL - Invalid parameters",
|
||||
AmdSmiRetCode.ERR_NOT_SUPPORTED: "AMDSMI_STATUS_NOT_SUPPORTED - Feature not supported",
|
||||
AmdSmiRetCode.FILE_ERROR: "AMDSMI_STATUS_FILE_ERROR - Error opening file",
|
||||
AmdSmiRetCode.ERR_OUT_OF_RESOURCES: "AMDSMI_STATUS_OUT_OF_RESOURCES - Not enough memory",
|
||||
AmdSmiRetCode.INTERNAL_EXCEPTION: "AMDSMI_STATUS_INTERNAL_EXCEPTION - Internal error",
|
||||
AmdSmiRetCode.ERR_NO_PERM: "AMDSMI_STATUS_NO_PERM - Permission Denied",
|
||||
AmdSmiRetCode.INPUT_OUT_OF_BOUNDS: "AMDSMI_STATUS_INPUT_OUT_OF_BOUNDS - Out of bounds",
|
||||
AmdSmiRetCode.INIT_ERROR: "AMDSMI_STATUS_INIT_ERROR - Initialization error",
|
||||
AmdSmiRetCode.ERR_BUSY: "AMDSMI_STATUS_BUSY - Device busy",
|
||||
AmdSmiRetCode.ERR_NOT_FOUND: "AMDSMI_STATUS_NOT_FOUND - Device Not found",
|
||||
AmdSmiRetCode.ERR_IO: "AMDSMI_STATUS_IO - I/O Error",
|
||||
AmdSmiRetCode.NOT_IMPLEMENTED: "AMDSMI_STATUS_NOT_YET_IMPLEMENTED - Feature not yet implemented",
|
||||
AmdSmiRetCode.INSUFFICIENT_SIZE: "AMDSMI_STATUS_INSUFFICIENT_SIZE - Insufficient size for operation",
|
||||
AmdSmiRetCode.INTERRUPT: "AMDSMI_STATUS_INTERRUPT - Interrupt ocurred during execution",
|
||||
AmdSmiRetCode.UNEXPECTED_SIZE: "AMDSMI_STATUS_UNEXPECTED_SIZE - unexpected size of data was read",
|
||||
AmdSmiRetCode.NO_DATA: "AMDSMI_STATUS_NO_DATA - No data was found for given input",
|
||||
AmdSmiRetCode.UNEXPECTED_DATA: "AMDSMI_STATUS_UNEXPECTED_DATA - The data read or provided was unexpected",
|
||||
AmdSmiRetCode.REFCOUNT_OVERFLOW: "AMDSMI_STATUS_REFCOUNT_OVERFLOW - Internal reference counter exceeded INT32_MAX",
|
||||
AmdSmiRetCode.LIB_START: "AMDSMI_LIB_START - Lib start status",
|
||||
AmdSmiRetCode.FAIL_LOAD_MODULE: "AMDSMI_STATUS_FAIL_LOAD_MODULE - Fail to load lib",
|
||||
AmdSmiRetCode.FAIL_LOAD_SYMBOL: "AMDSMI_STATUS_FAIL_LOAD_SYMBOL - Fail to load symbol",
|
||||
AmdSmiRetCode.DRM_ERROR: "AMDSMI_STATUS_DRM_ERROR - Error when called libdrm",
|
||||
AmdSmiRetCode.FAULT: "AMDSMI_STATUS_FAULT - Bad address",
|
||||
AmdSmiRetCode.API_FAILED: "AMDSMI_STATUS_API_FAILED - API call failed",
|
||||
AmdSmiRetCode.TIMEOUT: "AMDSMI_STATUS_TIMEOUT - Timeout in API call",
|
||||
AmdSmiRetCode.NO_SLOT: "AMDSMI_STATUS_NO_SLOT - No more free slot",
|
||||
AmdSmiRetCode.RETRY: "AMDSMI_STATUS_RETRY - Retry operation",
|
||||
AmdSmiRetCode.NOT_INIT: "AMDSMI_STATUS_NOT_INIT - Device not initialized",
|
||||
}
|
||||
|
||||
self.err_info = switch.get(self.err_code, "AMDSMI_STATUS_UNKNOWN_ERROR - An unknown error occurred")
|
||||
|
||||
|
||||
class AmdSmiRetryException(AmdSmiLibraryException):
|
||||
def __init__(self):
|
||||
super().__init__(AmdSmiRetCode.RETRY)
|
||||
|
||||
|
||||
class AmdSmiTimeoutException(AmdSmiLibraryException):
|
||||
def __init__(self):
|
||||
super().__init__(AmdSmiRetCode.TIMEOUT)
|
||||
|
||||
|
||||
class AmdSmiParameterException(AmdSmiException):
|
||||
def __init__(self, receivedValue, expectedType, msg=None):
|
||||
super().__init__(msg)
|
||||
self.actualType = type(receivedValue)
|
||||
self.expectedType = expectedType
|
||||
self.set_err_msg()
|
||||
if msg is not None:
|
||||
self.err_msg = msg
|
||||
|
||||
def set_err_msg(self):
|
||||
self.err_msg = (
|
||||
"Invalid parameter:\n"
|
||||
+ "Actual type: {actualType}\n".format(actualType=self.actualType)
|
||||
+ "Expected type: {expectedType}".format(expectedType=self.expectedType)
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.err_msg
|
||||
|
||||
|
||||
class AmdSmiKeyException(AmdSmiException):
|
||||
def __init__(self, key):
|
||||
super().__init__()
|
||||
self.key = key
|
||||
self.set_err_msg()
|
||||
|
||||
def set_err_msg(self):
|
||||
self.err_msg = "Key " + self.key + " is missing from dictionary"
|
||||
|
||||
def __str__(self):
|
||||
return self.err_msg
|
||||
|
||||
|
||||
class AmdSmiBdfFormatException(AmdSmiException):
|
||||
def __init__(self, bdf):
|
||||
super().__init__()
|
||||
self.bdf = bdf
|
||||
|
||||
def __str__(self):
|
||||
return (
|
||||
"Wrong BDF format: {}. \n"
|
||||
+ "BDF string should be: <domain>:<bus>:<device>.<function>\n"
|
||||
+ " or <bus>:<device>.<function> in hexcode format.\n"
|
||||
+ "Where:\n\t<domain> is 4 hex digits long from 0000-FFFF interval\n"
|
||||
+ "\t<bus> is 2 hex digits long from 00-FF interval\n"
|
||||
+ "\t<device> is 2 hex digits long from 00-1F interval\n"
|
||||
+ "\t<function> is 1 hex digit long from 0-7 interval"
|
||||
).format(self.bdf)
|
||||
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
@@ -0,0 +1,16 @@
|
||||
from setuptools import setup
|
||||
|
||||
with open("amdsmi/README.md", "r", encoding="utf-8") as fh:
|
||||
long_description = fh.read()
|
||||
|
||||
setup(
|
||||
name='amdsmi',
|
||||
version='0.1',
|
||||
description="SMI LIB - AMD GPU Monitoring Library",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
packages=['amdsmi'],
|
||||
package_data={'': ['LICENSE']},
|
||||
include_package_data=True,
|
||||
python_requires=">=3.6",
|
||||
)
|
||||
@@ -62,6 +62,7 @@
|
||||
#include "amd_smi/impl/amd_smi_system.h"
|
||||
#include "amd_smi/impl/amd_smi_socket.h"
|
||||
#include "amd_smi/impl/amd_smi_gpu_device.h"
|
||||
#include "amd_smi/impl/amd_smi_uuid.h"
|
||||
#include "rocm_smi/rocm_smi.h"
|
||||
#include "rocm_smi/rocm_smi_common.h"
|
||||
#include "amd_smi/impl/amdgpu_drm.h"
|
||||
@@ -253,7 +254,7 @@ amdsmi_status_t amdsmi_get_board_info(amdsmi_device_handle device_handle, amdsmi
|
||||
static_cast<amd::smi::AMDSmiGPUDevice*>(device_handle);
|
||||
|
||||
if (gpu_device->check_if_drm_is_supported()) {
|
||||
status = smi_amdgpu_get_board_info(gpu_device, board_info);
|
||||
status = smi_amdgpu_get_board_info(gpu_device, board_info);
|
||||
}
|
||||
else {
|
||||
status = rsmi_wrapper(rsmi_dev_name_get, device_handle, board_info->product_name, AMDSMI_PRODUCT_NAME_LENGTH);
|
||||
@@ -492,8 +493,8 @@ amdsmi_get_asic_info(amdsmi_device_handle device_handle, amdsmi_asic_info_t *inf
|
||||
return AMDSMI_STATUS_INVAL;
|
||||
}
|
||||
|
||||
struct drm_amdgpu_info_device dev_info = {};
|
||||
struct drm_amdgpu_info_vbios vbios = {};
|
||||
struct drm_amdgpu_info_device dev_info = {};
|
||||
struct drm_amdgpu_info_vbios vbios = {};
|
||||
char* name;
|
||||
char *tmp;
|
||||
|
||||
@@ -501,7 +502,7 @@ amdsmi_get_asic_info(amdsmi_device_handle device_handle, amdsmi_asic_info_t *inf
|
||||
static_cast<amd::smi::AMDSmiGPUDevice*>(device_handle);
|
||||
amdsmi_status_t status;
|
||||
if (gpu_device->check_if_drm_is_supported()){
|
||||
status = gpu_device->amdgpu_query_info(AMDGPU_INFO_DEV_INFO, sizeof(struct drm_amdgpu_info_device), &dev_info);
|
||||
status = gpu_device->amdgpu_query_info(AMDGPU_INFO_DEV_INFO, sizeof(struct drm_amdgpu_info_device), &dev_info);
|
||||
if (status != AMDSMI_STATUS_SUCCESS) return status;
|
||||
status = gpu_device->amdgpu_query_vbios(&vbios);
|
||||
if (status != AMDSMI_STATUS_SUCCESS) return status;
|
||||
@@ -965,7 +966,7 @@ amdsmi_get_power_cap_info(amdsmi_device_handle device_handle,
|
||||
status = smi_amdgpu_get_power_cap(gpudevice, &power_cap);
|
||||
|
||||
info->power_cap = power_cap;
|
||||
status = smi_amdgpu_get_ranges(gpudevice, CLOCK_TYPE_GFX,
|
||||
status = smi_amdgpu_get_ranges(gpudevice, CLK_TYPE_GFX,
|
||||
NULL, NULL, &dpm);
|
||||
info->dpm_cap = dpm;
|
||||
|
||||
@@ -1059,10 +1060,10 @@ amdsmi_status_t amdsmi_dev_gpu_clk_freq_get(amdsmi_device_handle device_handle,
|
||||
return AMDSMI_STATUS_INVAL;
|
||||
|
||||
// Get from gpu_metrics
|
||||
if (clk_type == CLOCK_TYPE_VCLK0 ||
|
||||
clk_type == CLOCK_TYPE_VCLK1 ||
|
||||
clk_type == CLOCK_TYPE_DCLK0 ||
|
||||
clk_type == CLOCK_TYPE_DCLK1 ) {
|
||||
if (clk_type == CLK_TYPE_VCLK0 ||
|
||||
clk_type == CLK_TYPE_VCLK1 ||
|
||||
clk_type == CLK_TYPE_DCLK0 ||
|
||||
clk_type == CLK_TYPE_DCLK1 ) {
|
||||
amdsmi_gpu_metrics_t metric_info;
|
||||
auto r_status = amdsmi_dev_gpu_metrics_info_get(
|
||||
device_handle, &metric_info);
|
||||
@@ -1070,19 +1071,19 @@ amdsmi_status_t amdsmi_dev_gpu_clk_freq_get(amdsmi_device_handle device_handle,
|
||||
return r_status;
|
||||
|
||||
f->num_supported = 1;
|
||||
if (clk_type == CLOCK_TYPE_VCLK0) {
|
||||
if (clk_type == CLK_TYPE_VCLK0) {
|
||||
f->current = metric_info.current_vclk0;
|
||||
f->frequency[0] = metric_info.average_vclk0_frequency;
|
||||
}
|
||||
if (clk_type == CLOCK_TYPE_VCLK1) {
|
||||
if (clk_type == CLK_TYPE_VCLK1) {
|
||||
f->current = metric_info.current_vclk1;
|
||||
f->frequency[0] = metric_info.average_vclk1_frequency;
|
||||
}
|
||||
if (clk_type == CLOCK_TYPE_DCLK0) {
|
||||
if (clk_type == CLK_TYPE_DCLK0) {
|
||||
f->current = metric_info.current_dclk0;
|
||||
f->frequency[0] = metric_info.average_dclk0_frequency;
|
||||
}
|
||||
if (clk_type == CLOCK_TYPE_DCLK1) {
|
||||
if (clk_type == CLK_TYPE_DCLK1) {
|
||||
f->current = metric_info.current_dclk1;
|
||||
f->frequency[0] = metric_info.average_dclk1_frequency;
|
||||
}
|
||||
@@ -1098,10 +1099,10 @@ amdsmi_status_t amdsmi_dev_gpu_clk_freq_get(amdsmi_device_handle device_handle,
|
||||
amdsmi_status_t amdsmi_dev_gpu_clk_freq_set(amdsmi_device_handle device_handle,
|
||||
amdsmi_clk_type_t clk_type, uint64_t freq_bitmask) {
|
||||
// Not support the clock type read from gpu_metrics
|
||||
if (clk_type == CLOCK_TYPE_VCLK0 ||
|
||||
clk_type == CLOCK_TYPE_VCLK1 ||
|
||||
clk_type == CLOCK_TYPE_DCLK0 ||
|
||||
clk_type == CLOCK_TYPE_DCLK1 ) {
|
||||
if (clk_type == CLK_TYPE_VCLK0 ||
|
||||
clk_type == CLK_TYPE_VCLK1 ||
|
||||
clk_type == CLK_TYPE_DCLK0 ||
|
||||
clk_type == CLK_TYPE_DCLK1 ) {
|
||||
return AMDSMI_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
@@ -1269,12 +1270,12 @@ amdsmi_get_vbios_info(amdsmi_device_handle dev, amdsmi_vbios_info_t *info) {
|
||||
if (info == nullptr) {
|
||||
return AMDSMI_STATUS_INVAL;
|
||||
}
|
||||
struct drm_amdgpu_info_vbios vbios = {};
|
||||
struct drm_amdgpu_info_vbios vbios = {};
|
||||
|
||||
amd::smi::AMDSmiGPUDevice* gpu_device =
|
||||
static_cast<amd::smi::AMDSmiGPUDevice*>(dev);
|
||||
amdsmi_status_t status;
|
||||
if (gpu_device->check_if_drm_is_supported()){
|
||||
if (gpu_device->check_if_drm_is_supported()){
|
||||
status = gpu_device->amdgpu_query_vbios(&vbios);
|
||||
if (status != AMDSMI_STATUS_SUCCESS) {
|
||||
return status;
|
||||
@@ -1290,7 +1291,7 @@ amdsmi_get_vbios_info(amdsmi_device_handle dev, amdsmi_vbios_info_t *info) {
|
||||
return AMDSMI_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return AMDSMI_STATUS_SUCCESS;
|
||||
return AMDSMI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
amdsmi_status_t
|
||||
@@ -1334,13 +1335,13 @@ amdsmi_get_power_limit(amdsmi_device_handle dev, amdsmi_power_limit_t *limit) {
|
||||
}
|
||||
|
||||
amdsmi_status_t
|
||||
amdsmi_get_clock_measure(amdsmi_device_handle dev, amdsmi_clk_type_t clk_type, amdsmi_clock_measure_t *info) {
|
||||
amdsmi_get_clock_measure(amdsmi_device_handle dev, amdsmi_clk_type_t clk_type, amdsmi_clk_measure_t *info) {
|
||||
if (info == nullptr) {
|
||||
return AMDSMI_STATUS_INVAL;
|
||||
}
|
||||
|
||||
if (clk_type >= CLOCK_TYPE__MAX) {
|
||||
printf("Domain value greater or equals CLOCK_TYPE__MAX value. Return code: %d", AMDSMI_STATUS_INVAL);
|
||||
if (clk_type >= CLK_TYPE__MAX) {
|
||||
printf("Domain value greater or equals CLK_TYPE__MAX value. Return code: %d", AMDSMI_STATUS_INVAL);
|
||||
return AMDSMI_STATUS_INVAL;
|
||||
}
|
||||
|
||||
@@ -1362,19 +1363,19 @@ amdsmi_get_clock_measure(amdsmi_device_handle dev, amdsmi_clk_type_t clk_type, a
|
||||
info->max_clk = max_freq;
|
||||
|
||||
switch (clk_type) {
|
||||
case CLOCK_TYPE_GFX:
|
||||
case CLK_TYPE_GFX:
|
||||
info->avg_clk = metrics.average_gfxclk_frequency;
|
||||
info->cur_clk = metrics.current_gfxclk;
|
||||
break;
|
||||
case CLOCK_TYPE_MEM:
|
||||
case CLK_TYPE_MEM:
|
||||
info->avg_clk = metrics.average_uclk_frequency;
|
||||
info->cur_clk = metrics.current_uclk;
|
||||
break;
|
||||
case CLOCK_TYPE_VCLK0:
|
||||
case CLK_TYPE_VCLK0:
|
||||
info->avg_clk = metrics.average_vclk0_frequency;
|
||||
info->cur_clk = metrics.current_vclk0;
|
||||
break;
|
||||
case CLOCK_TYPE_VCLK1:
|
||||
case CLK_TYPE_VCLK1:
|
||||
info->avg_clk = metrics.average_vclk1_frequency;
|
||||
info->cur_clk = metrics.current_vclk1;
|
||||
break;
|
||||
@@ -1485,7 +1486,7 @@ amdsmi_get_temperature_measure(amdsmi_device_handle dev, amdsmi_temperature_type
|
||||
}
|
||||
|
||||
amdsmi_status_t
|
||||
amdsmi_get_ras_features_enabled(amdsmi_device_handle device_handle, amdsmi_gpu_block block, amdsmi_ras_err_state_t *state) {
|
||||
amdsmi_get_ras_block_features_enabled(amdsmi_device_handle device_handle, amdsmi_gpu_block block, amdsmi_ras_err_state_t *state) {
|
||||
if (state == nullptr || block > AMDSMI_GPU_BLOCK_LAST) {
|
||||
return AMDSMI_STATUS_INVAL;
|
||||
}
|
||||
@@ -1610,9 +1611,40 @@ amdsmi_get_process_info(amdsmi_device_handle dev, amdsmi_process_handle process,
|
||||
return AMDSMI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
amdsmi_status_t
|
||||
amdsmi_get_power_measure(amdsmi_device_handle dev, amdsmi_power_measure_t *info) {
|
||||
if (info == nullptr) {
|
||||
return AMDSMI_STATUS_INVAL;
|
||||
}
|
||||
|
||||
amdsmi_gpu_metrics_t metrics = {};
|
||||
amd::smi::AMDSmiGPUDevice* gpu_device =
|
||||
static_cast<amd::smi::AMDSmiGPUDevice*>(dev);
|
||||
amdsmi_status_t status;
|
||||
|
||||
status = amdsmi_dev_gpu_metrics_info_get(dev, &metrics);
|
||||
if (status != AMDSMI_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
int64_t voltage_read = 0;
|
||||
|
||||
status = amdsmi_dev_volt_metric_get(dev, AMDSMI_VOLT_TYPE_VDDGFX, AMDSMI_VOLT_CURRENT, &voltage_read);
|
||||
if (status != AMDSMI_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
info->voltage_gfx = voltage_read;
|
||||
|
||||
info->average_socket_power = metrics.average_socket_power;
|
||||
info->energy_accumulator = metrics.energy_accumulator;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
amdsmi_status_t
|
||||
amdsmi_get_target_frequency_range(amdsmi_device_handle dev, amdsmi_clk_type_t clk_type, amdsmi_frequency_range_t *range) {
|
||||
if (range == nullptr || clk_type > CLOCK_TYPE__MAX) {
|
||||
if (range == nullptr || clk_type > CLK_TYPE__MAX) {
|
||||
return AMDSMI_STATUS_INVAL;
|
||||
}
|
||||
|
||||
@@ -1636,16 +1668,16 @@ amdsmi_get_target_frequency_range(amdsmi_device_handle dev, amdsmi_clk_type_t cl
|
||||
range->supported_freq_range.upper_bound = (long)max;
|
||||
max = 0;
|
||||
switch (clk_type) {
|
||||
case CLOCK_TYPE_GFX:
|
||||
case CLK_TYPE_GFX:
|
||||
max = metrics.current_gfxclk;
|
||||
break;
|
||||
case CLOCK_TYPE_MEM:
|
||||
case CLK_TYPE_MEM:
|
||||
max = metrics.current_uclk;
|
||||
break;
|
||||
case CLOCK_TYPE_VCLK0:
|
||||
case CLK_TYPE_VCLK0:
|
||||
max = metrics.current_vclk0;
|
||||
break;
|
||||
case CLOCK_TYPE_VCLK1:
|
||||
case CLK_TYPE_VCLK1:
|
||||
max = metrics.current_vclk1;
|
||||
break;
|
||||
default:
|
||||
@@ -1655,3 +1687,158 @@ amdsmi_get_target_frequency_range(amdsmi_device_handle dev, amdsmi_clk_type_t cl
|
||||
|
||||
return AMDSMI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
amdsmi_status_t
|
||||
amdsmi_get_driver_version(amdsmi_device_handle dev, int *length, char *version) {
|
||||
if (length == nullptr || version == nullptr) {
|
||||
return AMDSMI_STATUS_INVAL;
|
||||
}
|
||||
amdsmi_status_t status = AMDSMI_STATUS_SUCCESS;
|
||||
amd::smi::AMDSmiGPUDevice* gpu_device =
|
||||
static_cast<amd::smi::AMDSmiGPUDevice*>(dev);
|
||||
status = smi_amdgpu_get_driver_version(gpu_device, length, version);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
amdsmi_status_t
|
||||
amdsmi_get_device_uuid(amdsmi_device_handle dev, unsigned int *uuid_length, char *uuid) {
|
||||
if (uuid_length == nullptr || uuid == nullptr) {
|
||||
return AMDSMI_STATUS_INVAL;
|
||||
}
|
||||
|
||||
amd::smi::AMDSmiGPUDevice* gpu_device =
|
||||
static_cast<amd::smi::AMDSmiGPUDevice*>(dev);
|
||||
amdsmi_status_t status = AMDSMI_STATUS_SUCCESS;
|
||||
SMIGPUDEVICE_MUTEX(gpu_device->get_mutex())
|
||||
|
||||
FILE *fp;
|
||||
size_t len = AMDSMI_GPU_UUID_SIZE;
|
||||
ssize_t nread;
|
||||
amdsmi_asic_info_t asic_info = {};
|
||||
const uint8_t fcn = 0xff;
|
||||
|
||||
std::string path = "/sys/class/drm/" + gpu_device->get_gpu_path() + "/device/uuid_info";
|
||||
status = amdsmi_get_asic_info(dev, &asic_info);
|
||||
if (status != AMDSMI_STATUS_SUCCESS) {
|
||||
printf("Getting asic info failed. Return code: %d", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
fp = fopen(path.c_str(), "rb");
|
||||
if (!fp) {
|
||||
/* generate random UUID */
|
||||
status = amdsmi_uuid_gen(uuid, strtoul(asic_info.asic_serial, nullptr, AMDSMI_NORMAL_STRING_LENGTH), (uint16_t)asic_info.device_id, fcn);
|
||||
return status;
|
||||
}
|
||||
|
||||
nread = getline(&uuid, &len, fp);
|
||||
if (nread <= 0) {
|
||||
/* generate random UUID */
|
||||
status = amdsmi_uuid_gen(uuid, strtoul(asic_info.asic_serial, nullptr, AMDSMI_NORMAL_STRING_LENGTH), (uint16_t)asic_info.device_id, fcn);
|
||||
fclose(fp);
|
||||
return status;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return status;
|
||||
}
|
||||
|
||||
amdsmi_status_t
|
||||
amdsmi_get_pcie_link_status(amdsmi_device_handle dev, amdsmi_pcie_info_t *info){
|
||||
if (info == nullptr) {
|
||||
return AMDSMI_STATUS_INVAL;
|
||||
}
|
||||
amdsmi_status_t status = AMDSMI_STATUS_SUCCESS;
|
||||
amdsmi_gpu_metrics_t metric_info = {};
|
||||
status = amdsmi_dev_gpu_metrics_info_get(
|
||||
dev, &metric_info);
|
||||
if (status != AMDSMI_STATUS_SUCCESS)
|
||||
return status;
|
||||
|
||||
info->pcie_lanes = metric_info.pcie_link_width;
|
||||
info->pcie_speed = metric_info.pcie_link_speed;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
amdsmi_status_t amdsmi_get_pcie_link_caps(amdsmi_device_handle dev, amdsmi_pcie_info_t *info) {
|
||||
if (info == nullptr) {
|
||||
return AMDSMI_STATUS_INVAL;
|
||||
}
|
||||
|
||||
amdsmi_status_t status = AMDSMI_STATUS_SUCCESS;
|
||||
amd::smi::AMDSmiGPUDevice* gpu_device =
|
||||
static_cast<amd::smi::AMDSmiGPUDevice*>(dev);
|
||||
|
||||
SMIGPUDEVICE_MUTEX(gpu_device->get_mutex())
|
||||
|
||||
char buff[AMDSMI_NORMAL_STRING_LENGTH];
|
||||
FILE* fp;
|
||||
double pcie_speed = 0;
|
||||
unsigned pcie_width = 0;
|
||||
amdsmi_asic_info_t asic_info = {};
|
||||
|
||||
memset((void *)info, 0, sizeof(*info));
|
||||
|
||||
std::string path_max_link_width = "/sys/class/drm/" +
|
||||
gpu_device->get_gpu_path() + "/device/max_link_width";
|
||||
fp = fopen(path_max_link_width.c_str(), "r");
|
||||
if (fp) {
|
||||
fscanf(fp, "%d", &pcie_width);
|
||||
fclose(fp);
|
||||
} else {
|
||||
printf("Failed to open file: %s \n", path_max_link_width.c_str());
|
||||
return AMDSMI_STATUS_API_FAILED;
|
||||
}
|
||||
info->pcie_lanes = (uint16_t)pcie_width;
|
||||
|
||||
std::string path_max_link_speed = "/sys/class/drm/" +
|
||||
gpu_device->get_gpu_path() + "/device/max_link_speed";
|
||||
fp = fopen(path_max_link_speed.c_str(), "r");
|
||||
if (fp) {
|
||||
fscanf(fp, "%lf %s", &pcie_speed, buff);
|
||||
fclose(fp);
|
||||
} else {
|
||||
printf("Failed to open file: %s \n", path_max_link_speed.c_str());
|
||||
return AMDSMI_STATUS_API_FAILED;
|
||||
}
|
||||
|
||||
status = amdsmi_get_asic_info(dev, &asic_info);
|
||||
if (status != AMDSMI_STATUS_SUCCESS)
|
||||
return status;
|
||||
|
||||
if (pcie_speed == 0 && asic_info.device_id == 29538)
|
||||
pcie_speed = 16;
|
||||
|
||||
info->pcie_speed = pcie_speed * 1000;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
amdsmi_status_t amdsmi_get_device_handle_from_bdf(amdsmi_bdf_t bdf,
|
||||
amdsmi_device_handle* device_handles,
|
||||
uint32_t device_count,
|
||||
amdsmi_device_handle* device_handle){
|
||||
if (device_handles == nullptr) {
|
||||
return AMDSMI_STATUS_INVAL;
|
||||
}
|
||||
amdsmi_status_t status = AMDSMI_STATUS_SUCCESS;
|
||||
|
||||
for(auto idx = 0; idx < device_count; idx++) {
|
||||
amd::smi::AMDSmiGPUDevice* gpu_device = nullptr;
|
||||
status = get_gpu_device_from_handle(device_handles[idx], &gpu_device);
|
||||
if (status != AMDSMI_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
amdsmi_bdf_t found_bdf = gpu_device->get_bdf();
|
||||
if (bdf.bus_number == found_bdf.bus_number &&
|
||||
bdf.device_number == found_bdf.device_number &&
|
||||
bdf.domain_number == found_bdf.domain_number &&
|
||||
bdf.function_number == found_bdf.function_number) {
|
||||
*device_handle = device_handles[idx];
|
||||
return AMDSMI_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
return AMDSMI_STATUS_API_FAILED;
|
||||
}
|
||||
|
||||
@@ -51,18 +51,18 @@ static bool isAMDGPU(std::string dev_path) {
|
||||
std::string vend_path = dev_path + "/device/vendor";
|
||||
std::string vbios_v_path = dev_path + "/device/vbios_version";
|
||||
if (!amd::smi::FileExists(vend_path.c_str())) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!amd::smi::FileExists(vbios_v_path.c_str())) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::ifstream fs;
|
||||
fs.open(vend_path);
|
||||
|
||||
if (!fs.is_open()) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t vendor_id;
|
||||
@@ -72,7 +72,7 @@ static bool isAMDGPU(std::string dev_path) {
|
||||
fs.close();
|
||||
|
||||
if (vendor_id == kAmdGpuId) {
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -199,16 +199,16 @@ amdsmi_status_t smi_amdgpu_get_ranges(amd::smi::AMDSmiGPUDevice* device, amdsmi_
|
||||
unsigned int max, min, dpm;
|
||||
|
||||
switch (domain) {
|
||||
case CLOCK_TYPE_GFX:
|
||||
case CLK_TYPE_GFX:
|
||||
fullpath += "/pp_dpm_sclk";
|
||||
break;
|
||||
case CLOCK_TYPE_MEM:
|
||||
case CLK_TYPE_MEM:
|
||||
fullpath += "/pp_dpm_mclk";
|
||||
break;
|
||||
case CLOCK_TYPE_VCLK0:
|
||||
case CLK_TYPE_VCLK0:
|
||||
fullpath += "/pp_dpm_vclk";
|
||||
break;
|
||||
case CLOCK_TYPE_VCLK1:
|
||||
case CLK_TYPE_VCLK1:
|
||||
fullpath += "/pp_dpm_vclk1";
|
||||
break;
|
||||
default:
|
||||
@@ -380,3 +380,81 @@ amdsmi_status_t smi_amdgpu_get_ecc_error_count(amd::smi::AMDSmiGPUDevice* device
|
||||
|
||||
return AMDSMI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
amdsmi_status_t smi_amdgpu_get_driver_version(amd::smi::AMDSmiGPUDevice* device, int *length, char *version) {
|
||||
if (!device->check_if_drm_is_supported()) {
|
||||
return AMDSMI_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
SMIGPUDEVICE_MUTEX(device->get_mutex())
|
||||
amdsmi_status_t status = AMDSMI_STATUS_SUCCESS;
|
||||
FILE *fp;
|
||||
char *tmp, *ptr, *token;
|
||||
char *ver = NULL;
|
||||
int i = 0;
|
||||
size_t len;
|
||||
|
||||
if (length)
|
||||
len = *length < AMDSMI_MAX_DRIVER_VERSION_LENGTH ? *length :
|
||||
AMDSMI_MAX_DRIVER_VERSION_LENGTH;
|
||||
else
|
||||
len = AMDSMI_MAX_DRIVER_VERSION_LENGTH;
|
||||
|
||||
std::string path = "/sys/module/amdgpu/version";
|
||||
|
||||
fp = fopen(path.c_str(), "r");
|
||||
if (!fp){
|
||||
fp = fopen("/proc/version", "r");
|
||||
if (!fp) {
|
||||
status = AMDSMI_STATUS_IO;
|
||||
return status;
|
||||
}
|
||||
|
||||
len = 0;
|
||||
if (getline(&ver, &len, fp) <= 0) {
|
||||
status = AMDSMI_STATUS_IO;
|
||||
fclose(fp);
|
||||
free(ver);
|
||||
return status;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
ptr = ver;
|
||||
token = strtok_r(ptr, " ", &tmp);
|
||||
|
||||
if (!token) {
|
||||
free(ver);
|
||||
status = AMDSMI_STATUS_IO;
|
||||
return status;
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
ptr = strtok_r(NULL, " ", &tmp);
|
||||
if (!ptr)
|
||||
break;
|
||||
}
|
||||
if (i != 2 || !ptr) {
|
||||
free(ver);
|
||||
status = AMDSMI_STATUS_IO;
|
||||
return status;
|
||||
}
|
||||
if (length)
|
||||
len = *length < AMDSMI_MAX_DRIVER_VERSION_LENGTH ? *length :
|
||||
AMDSMI_MAX_DRIVER_VERSION_LENGTH;
|
||||
else
|
||||
len = AMDSMI_MAX_DRIVER_VERSION_LENGTH;
|
||||
|
||||
strncpy(version, ptr, len);
|
||||
free(ver);
|
||||
} else {
|
||||
if ((len = getline(&version, &len, fp)) <= 0)
|
||||
status = AMDSMI_STATUS_IO;
|
||||
|
||||
fclose(fp);
|
||||
if (length) {
|
||||
*length = version[len-1] == '\n' ? len - 1 : len;
|
||||
}
|
||||
version[len-1] = version[len-1] == '\n' ? '\0' : version[len-1];
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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.
|
||||
*/
|
||||
|
||||
#include "amd_smi/amd_smi.h"
|
||||
#include "amd_smi/impl/amd_smi_uuid.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <cstdio>
|
||||
|
||||
typedef struct uuid_s {
|
||||
union {
|
||||
struct {
|
||||
uint32_t did : 16;
|
||||
uint32_t fcn : 8;
|
||||
uint32_t asic_7 : 8;
|
||||
};
|
||||
uint32_t time_low;
|
||||
};
|
||||
uint32_t time_mid : 16;
|
||||
uint32_t time_high : 12;
|
||||
uint32_t version : 4;
|
||||
uint8_t clk_seq_hi : 6;
|
||||
uint8_t variant : 2;
|
||||
union {
|
||||
uint8_t clk_seq_low;
|
||||
uint8_t asic_6;
|
||||
};
|
||||
uint16_t asic_4;
|
||||
uint32_t asic_0;
|
||||
} uuid_t;
|
||||
|
||||
static void print_uuid(char *str, uuid_t *uuid)
|
||||
{
|
||||
sprintf(str, "%08x", uuid->time_low);
|
||||
sprintf(str + 8, "-");
|
||||
sprintf(str + 9, "%04x", uuid->time_mid);
|
||||
sprintf(str + 13, "-");
|
||||
sprintf(str + 14, "%04x", (uuid->version << 12) | uuid->time_high);
|
||||
sprintf(str + 18, "-");
|
||||
sprintf(str + 14 + 5, "%02x", (uuid->variant << 6) | uuid->clk_seq_hi);
|
||||
sprintf(str + 16 + 5, "%02x", uuid->clk_seq_low);
|
||||
sprintf(str + 18 + 5, "-");
|
||||
sprintf(str + 19 + 5, "%04x", uuid->asic_4);
|
||||
sprintf(str + 23 + 5, "%08x", uuid->asic_0);
|
||||
str[31 + 5] = 0;
|
||||
}
|
||||
|
||||
static void insert_asic_serial(uuid_t *uuid, uint64_t serial)
|
||||
{
|
||||
uuid->asic_0 = (uint32_t)serial;
|
||||
uuid->asic_4 = (uint16_t)(serial >> 4 * 8) & 0xFFFF;
|
||||
uuid->asic_6 = (uint8_t)(serial >> 6 * 8) & 0xFF;
|
||||
uuid->asic_7 = (uint32_t)(serial >> 7 * 8) & 0xFF;
|
||||
}
|
||||
|
||||
static void insert_did(uuid_t *uuid, uint16_t did)
|
||||
{
|
||||
uuid->did = did;
|
||||
}
|
||||
|
||||
static void insert_fcn(uuid_t *uuid, uint8_t fcn_idx)
|
||||
{
|
||||
uuid->fcn = fcn_idx;
|
||||
}
|
||||
|
||||
static void insert_clk_seq(uuid_t *uuid, uint16_t seq)
|
||||
{
|
||||
uuid->clk_seq_low = (uint8_t)seq;
|
||||
uuid->clk_seq_hi = (seq >> 8) & 0x3fU;
|
||||
}
|
||||
|
||||
amdsmi_status_t amdsmi_uuid_gen(char *str, uint64_t serial, uint16_t did, uint8_t idx)
|
||||
{
|
||||
uuid_t uuid;
|
||||
memset(&uuid, 0, sizeof(uuid_t));
|
||||
|
||||
insert_clk_seq(&uuid, 0);
|
||||
insert_did(&uuid, did);
|
||||
insert_fcn(&uuid, idx);
|
||||
insert_asic_serial(&uuid, serial);
|
||||
|
||||
uuid.version = 1;
|
||||
uuid.variant = 2;
|
||||
|
||||
print_uuid(str, &uuid);
|
||||
|
||||
return AMDSMI_STATUS_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,504 @@
|
||||
#
|
||||
# Copyright (C) 2022 Advanced Micro Devices. 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.
|
||||
#
|
||||
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
from ctypes import *
|
||||
from subprocess import call
|
||||
from subprocess import check_output
|
||||
|
||||
sys.path.append(os.getcwd())
|
||||
|
||||
import ctypeslib
|
||||
from ctypeslib.clang2py import main as clang2py
|
||||
|
||||
INTERFACE_SPECIFICATION = sys.argv[1]
|
||||
OUTPUT_DIRECTORY = sys.argv[2]
|
||||
LIBRARY_BINARY = sys.argv[3]
|
||||
OUTPUT_FILE = "amdsmi_wrapper.py"
|
||||
SMI_LIB_CTYPES = "amdsmi_lib_ctypes.py"
|
||||
SMI_LIB_RET = "amdsmi_lib_ret.py"
|
||||
|
||||
INTERFACE_FUNCTIONS = os.path.join(OUTPUT_DIRECTORY, "amdsmi_functions.h")
|
||||
|
||||
API_REGEX_MATCHER = r"(\w+\s*\w*[\s\*]+)\s*(\w+)\(([^)]*)\);"
|
||||
API_REGEX_TYPEDEF = r"typedef\s*(\w+)\s*(.*);"
|
||||
|
||||
# Pointer statuses
|
||||
NO_POINTER = 0
|
||||
SINGLE_POINTER = 1
|
||||
DOUBLE_POINTER = 2
|
||||
TRIPLE_POINTER = 3
|
||||
|
||||
clang_include_dir = "/usr/include/"
|
||||
try:
|
||||
clang_include_dir = os.path.join(
|
||||
check_output(["clang", "-print-resource-dir"]).decode("utf-8").strip(),
|
||||
"include/",
|
||||
)
|
||||
except Exception as e:
|
||||
print(
|
||||
"Clang not found on the system. The script might not work properly. {}".format(
|
||||
e
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def ParseHeaderFile() -> bool:
|
||||
"""
|
||||
This function will parse the data from the main header file, create separate
|
||||
temporary files which will then be used as arguments for clang2py(). Afterwards,
|
||||
when the generator successfully completes wrapper generation - these temporary
|
||||
files will be removed.
|
||||
|
||||
`Parameters`: None.
|
||||
|
||||
`Returns`:
|
||||
`bool`: True if success, False if failed.
|
||||
"""
|
||||
|
||||
if not os.path.exists(INTERFACE_SPECIFICATION):
|
||||
return False
|
||||
|
||||
lib_types = ""
|
||||
type_read_enablers = [
|
||||
"#include <stdlib.h>",
|
||||
"typedef enum amdsmi_init_flags {",
|
||||
"typedef enum amdsmi_clk_type {",
|
||||
]
|
||||
type_read_disablers = [
|
||||
" * @brief Initialization flags",
|
||||
"} device_type_t;",
|
||||
"} amdsmi_func_id_value_t;",
|
||||
]
|
||||
reader_mask = False
|
||||
|
||||
with open(INTERFACE_SPECIFICATION, "r") as types:
|
||||
for i, line in enumerate(types):
|
||||
if line.strip() in type_read_enablers:
|
||||
reader_mask = True
|
||||
if reader_mask:
|
||||
lib_types += line
|
||||
if line.strip() in type_read_disablers:
|
||||
reader_mask = False
|
||||
|
||||
with open(os.path.join(OUTPUT_DIRECTORY, "amdsmi_lib_types.h"), "w") as file_saver:
|
||||
file_saver.write(lib_types)
|
||||
|
||||
lib_ret_out = ""
|
||||
ret_reader_enablers = ["#include <stdlib.h>", "typedef enum amdsmi_status_t {"]
|
||||
ret_reader_disablers = [" * @brief Initialization flags", "} amdsmi_status_t;"]
|
||||
reader_mask = False
|
||||
with open(INTERFACE_SPECIFICATION, "r") as ret_out:
|
||||
for idx, line in enumerate(ret_out):
|
||||
if line.strip() in ret_reader_enablers:
|
||||
reader_mask = True
|
||||
if reader_mask:
|
||||
lib_ret_out += line
|
||||
if line.strip() in ret_reader_disablers:
|
||||
reader_mask = False
|
||||
with open(os.path.join(OUTPUT_DIRECTORY, "amdsmi_lib_ret.h"), "w") as file_saver:
|
||||
file_saver.write(lib_ret_out)
|
||||
|
||||
functions_out = ""
|
||||
functions_reader_enablers = [
|
||||
"#include <stdlib.h>",
|
||||
"amdsmi_status_t amdsmi_init(uint64_t init_flags);",
|
||||
]
|
||||
functions_reader_disablers = [
|
||||
"typedef enum amdsmi_init_flags {",
|
||||
"amdsmi_get_ecc_error_count(amdsmi_device_handle dev, amdsmi_error_count_t *ec);",
|
||||
]
|
||||
reader_mask = False
|
||||
with open(INTERFACE_SPECIFICATION, "r") as ret_out:
|
||||
for idx, line in enumerate(ret_out):
|
||||
if line.strip() in functions_reader_enablers:
|
||||
reader_mask = True
|
||||
if reader_mask:
|
||||
functions_out += line
|
||||
if line.strip() in functions_reader_disablers:
|
||||
reader_mask = False
|
||||
with open(INTERFACE_FUNCTIONS, "w") as file_saver:
|
||||
file_saver.write(functions_out)
|
||||
|
||||
sys.argv = [
|
||||
"generator.py",
|
||||
"--clang-args=-I" + clang_include_dir,
|
||||
os.path.join(OUTPUT_DIRECTORY, "amdsmi_lib_types.h"),
|
||||
"-o",
|
||||
os.path.join(OUTPUT_DIRECTORY, "amdsmi_lib_ctypes.py"),
|
||||
]
|
||||
clang2py()
|
||||
|
||||
sys.argv = [
|
||||
"generator.py",
|
||||
os.path.join(OUTPUT_DIRECTORY, "amdsmi_lib_ret.h"),
|
||||
"-o",
|
||||
os.path.join(OUTPUT_DIRECTORY, "amdsmi_lib_ret.py"),
|
||||
]
|
||||
clang2py()
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def DeducePointerStatus(variable: str) -> int:
|
||||
"""
|
||||
Function used to deduce pointer status of a specific variable.
|
||||
|
||||
`Parameters`:
|
||||
* variable (`str`): Variable string for which the pointer status
|
||||
is to be deduced.
|
||||
|
||||
`Returns`:
|
||||
`int`: Degree of pointer deduced (0 for no pointer status found
|
||||
and 3 for a triple pointer).
|
||||
"""
|
||||
if ("***" in variable) or ("**" in variable and "[]" in variable):
|
||||
return TRIPLE_POINTER
|
||||
elif ("**" in variable) or ("*" in variable and "[]" in variable):
|
||||
return DOUBLE_POINTER
|
||||
elif "*" in variable or "[]" in variable:
|
||||
return SINGLE_POINTER
|
||||
return NO_POINTER
|
||||
|
||||
|
||||
def TypeCast(cxxtype: str, ptr_status=0) -> str:
|
||||
"""
|
||||
Function used to type cast a cxx type to the corresponding ctypes
|
||||
type.
|
||||
|
||||
`Parameters`:
|
||||
* cxxtype (`str`): String containing the cxx type.
|
||||
* ptr_status (`int`): Integer describing pointer status of the
|
||||
cxx type.
|
||||
|
||||
`Returns`:
|
||||
`str`: String containing the corresponding ctypes type.
|
||||
"""
|
||||
if cxxtype == "void" and ptr_status:
|
||||
return "c_void_p"
|
||||
elif cxxtype == "char" and ptr_status:
|
||||
return "c_char_p"
|
||||
elif cxxtype == "int":
|
||||
return "c_int"
|
||||
elif cxxtype == "unsigned int":
|
||||
return "c_uint"
|
||||
elif cxxtype == "unsigned":
|
||||
return "c_uint"
|
||||
elif cxxtype == "uint8_t":
|
||||
return "c_uint8"
|
||||
elif cxxtype == "uint16_t":
|
||||
return "c_uint16"
|
||||
elif cxxtype == "uint32_t":
|
||||
return "c_uint32"
|
||||
elif cxxtype == "size_t":
|
||||
return "c_uint64"
|
||||
elif cxxtype == "uint64_t":
|
||||
return "c_uint64"
|
||||
elif cxxtype == "int8_t":
|
||||
return "c_int8"
|
||||
elif cxxtype == "int16_t":
|
||||
return "c_int16"
|
||||
elif cxxtype == "int32_t":
|
||||
return "c_int32"
|
||||
elif cxxtype == "int64_t":
|
||||
return "c_int64"
|
||||
elif cxxtype == "float":
|
||||
return "c_float"
|
||||
elif cxxtype == "double":
|
||||
return "c_double"
|
||||
elif cxxtype == "char":
|
||||
return "c_char"
|
||||
elif cxxtype == "bool":
|
||||
return "c_bool"
|
||||
elif cxxtype == "void":
|
||||
return ""
|
||||
else:
|
||||
return cxxtype
|
||||
|
||||
|
||||
def GetType(cxxtype: str, ptr_status=0) -> str:
|
||||
"""
|
||||
Function used to retrieve ctypes type of a cxx type.
|
||||
|
||||
`Parameters`:
|
||||
* cxxtype (`str`): String containing the cxx type.
|
||||
* ptr_status (`int`): Integer representing the pointer
|
||||
status of the cxx type.
|
||||
|
||||
`Returns`:
|
||||
`str`: String of the ctypes type that was retrieved.
|
||||
"""
|
||||
if cxxtype == "void" and ptr_status == 2:
|
||||
return "POINTER(" + TypeCast(cxxtype, ptr_status=1) + ")"
|
||||
elif cxxtype == "void" and ptr_status == 1:
|
||||
return TypeCast(cxxtype, ptr_status)
|
||||
elif cxxtype == "char" and ptr_status == 2:
|
||||
return "POINTER(" + TypeCast(cxxtype, ptr_status=1) + ")"
|
||||
elif cxxtype == "char" and ptr_status == 1:
|
||||
return TypeCast(cxxtype, ptr_status)
|
||||
elif ptr_status == 2:
|
||||
return "POINTER(POINTER(" + TypeCast(cxxtype) + "))"
|
||||
elif ptr_status == 1:
|
||||
return "POINTER(" + TypeCast(cxxtype) + ")"
|
||||
else:
|
||||
return TypeCast(cxxtype)
|
||||
|
||||
|
||||
def DetectOpaquePointer(variable_type: str, variable: str, ptr_status=0) -> bool:
|
||||
"""
|
||||
Function used to check whether a variable is an opaque pointer.
|
||||
|
||||
`Parameters`:
|
||||
* variable_type (`str`): String containing the variable type.
|
||||
* variable (`str`): String containing the variable name.
|
||||
* ptr_status (`int`): Integer representing the pointer status found.
|
||||
|
||||
`Returns`:
|
||||
`bool`: Bool representing whether an opaque pointer was deduced or not.
|
||||
"""
|
||||
if variable_type == "struct" and len(variable.split(" ")) > 1 and ptr_status == 1:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def TypeDefConvert(variable_type: str, variable: str) -> str:
|
||||
"""
|
||||
Function used to break down a typedef down and extract the cxx type.
|
||||
This type will then further be converted to a ctypes type.
|
||||
|
||||
`Parameters`:
|
||||
* variable_type (`str`): String containing the variable type.
|
||||
* variable (`str`): String containing the variable name.
|
||||
|
||||
`Returns`:
|
||||
`str`: Finalized string containing the proper definition with ctypes
|
||||
type.
|
||||
"""
|
||||
ptr_status = DeducePointerStatus(variable)
|
||||
variable = variable.replace("*", " ").strip()
|
||||
cxxtypedef = str()
|
||||
if DetectOpaquePointer(variable_type, variable, ptr_status):
|
||||
variables = variable.split(" ")
|
||||
cxxtypedef = variables[2] + " = ctypes." + GetType(variables[0], ptr_status)
|
||||
else:
|
||||
cxxtypedef = variable + " = ctypes." + GetType(variable_type, ptr_status)
|
||||
|
||||
return cxxtypedef
|
||||
|
||||
|
||||
def ParseParameters(parameters: str) -> list:
|
||||
"""
|
||||
Function that parses function parameters and returns a list containing
|
||||
ctypes types for the given parameters.
|
||||
|
||||
An example return value:
|
||||
[smi_device_handle, POINTER(smi_device_handle), POINTER(smi_vf_config)]
|
||||
|
||||
`Parameters`:
|
||||
* parameters (`str`): String containing the parameters for parsing.
|
||||
|
||||
`Returns`:
|
||||
`list`: List containing ctypes types for the given parameters.
|
||||
"""
|
||||
if parameters == "":
|
||||
return []
|
||||
|
||||
parameter_array = parameters.split(",")
|
||||
|
||||
result = []
|
||||
for param in parameter_array:
|
||||
ptr_status = DeducePointerStatus(param)
|
||||
param = param.strip().split(" ")
|
||||
|
||||
while "const" in param:
|
||||
param.remove("const")
|
||||
|
||||
if param[0] == "unsigned" and len(param) == 3:
|
||||
input = param[0] + " " + param[1]
|
||||
result.append(GetType(input, ptr_status))
|
||||
elif param[0] == "struct" or param[0] == "union" or param[0] == "enum":
|
||||
result.append(GetType(param[1], ptr_status))
|
||||
else:
|
||||
result.append(GetType(param[0], ptr_status))
|
||||
|
||||
return "[{}]".format(",".join(result))
|
||||
|
||||
|
||||
def CleanTempFiles() -> None:
|
||||
"""
|
||||
This function cleans up the temporary files created by the generator.
|
||||
|
||||
`Parameters`: None.
|
||||
|
||||
`Returns`: None.
|
||||
"""
|
||||
os.remove(INTERFACE_FUNCTIONS)
|
||||
os.remove(os.path.join(OUTPUT_DIRECTORY, "amdsmi_lib_ret.h"))
|
||||
os.remove(os.path.join(OUTPUT_DIRECTORY, "amdsmi_lib_types.h"))
|
||||
|
||||
|
||||
def main() -> str:
|
||||
"""
|
||||
Py wrapper generator.
|
||||
|
||||
`Parameters`: None.
|
||||
|
||||
`Returns`:
|
||||
`str`: String containing status message.
|
||||
"""
|
||||
api = []
|
||||
api_expose = []
|
||||
typedef_list = []
|
||||
typedef_expose = []
|
||||
|
||||
if not ParseHeaderFile():
|
||||
return "Error - header file missing."
|
||||
|
||||
format_code = ["clang-format", "-i", INTERFACE_FUNCTIONS]
|
||||
try:
|
||||
ret = call(format_code)
|
||||
if ret < 0:
|
||||
print("Clang-format failed to run")
|
||||
except Exception as e:
|
||||
print(
|
||||
"Clang-format not found on the system. The script might not work properly. {}".format(
|
||||
e
|
||||
)
|
||||
)
|
||||
|
||||
with open(INTERFACE_FUNCTIONS) as specification:
|
||||
file_specification = specification.read()
|
||||
# find all typedefs and construct typedef_list in format [{typedef_name} = {ctypes_type}]
|
||||
# typedef_expose is the list containing only the names of typedefs [{typedef_name}]
|
||||
for variable_type, variable in re.findall(
|
||||
API_REGEX_TYPEDEF, file_specification
|
||||
):
|
||||
typedef_list.append(TypeDefConvert(variable_type, variable))
|
||||
typedef_expose.append(variable.replace("*", ""))
|
||||
|
||||
# Get all components from function declaration(return type, function name, parameters) and
|
||||
# append to api list
|
||||
# api = [{return_type} = {ctypes_type}, {function_name} = {name}, {args} = [{ctypes_type}]]
|
||||
for returnType, functionName, parameters in re.findall(
|
||||
API_REGEX_MATCHER, file_specification
|
||||
):
|
||||
ptr_status = DeducePointerStatus(returnType)
|
||||
|
||||
returnType = returnType.replace("*", " ").strip()
|
||||
returnedType = GetType(returnType, ptr_status)
|
||||
|
||||
api.append(
|
||||
{
|
||||
"return_type": returnedType,
|
||||
"function_name": functionName,
|
||||
"args": ParseParameters(parameters),
|
||||
}
|
||||
)
|
||||
# api_expose is the list of all functions(function names) in the interface
|
||||
api_expose.append(functionName)
|
||||
|
||||
api_string = ""
|
||||
for method in api:
|
||||
api_string += """
|
||||
_lib.{function_name}.argtypes = {argument_array}
|
||||
_lib.{function_name}.restype = {return_type}
|
||||
{function_name} = _lib.{function_name}
|
||||
""".format(
|
||||
function_name=method["function_name"],
|
||||
argument_array=method["args"],
|
||||
return_type=method["return_type"],
|
||||
)
|
||||
|
||||
typedef_list_out = ""
|
||||
for typedef_item in typedef_list:
|
||||
typedef_list_out += typedef_item + "\n"
|
||||
|
||||
smi_lib_ctypes_out = ""
|
||||
with open(os.path.join(OUTPUT_DIRECTORY, SMI_LIB_CTYPES), "r") as smi_lib_ctypes:
|
||||
smi_lib_ctypes_out = smi_lib_ctypes.read()
|
||||
smi_lib_ctypes_out = smi_lib_ctypes_out.replace("struct_", "")
|
||||
smi_lib_ctypes_out = smi_lib_ctypes_out.replace("union_", "")
|
||||
smi_lib_ctypes_out = smi_lib_ctypes_out.replace("POINTER(None)", "c_void_p")
|
||||
|
||||
smi_lib_ret_out = ""
|
||||
with open(os.path.join(OUTPUT_DIRECTORY, SMI_LIB_RET), "r") as smi_lib_ret:
|
||||
smi_lib_ret_out = smi_lib_ret.read()
|
||||
smi_lib_ret_out = smi_lib_ret_out.replace("__all__ =", "__all__ +=")
|
||||
|
||||
with open(os.path.join(OUTPUT_DIRECTORY, OUTPUT_FILE), "w") as out:
|
||||
out.write(
|
||||
"""
|
||||
#
|
||||
# Copyright (C) 2022 Advanced Micro Devices. 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.
|
||||
#
|
||||
|
||||
from ctypes import *
|
||||
from ctypes import POINTER
|
||||
from subprocess import run
|
||||
from subprocess import PIPE
|
||||
import os
|
||||
|
||||
{SMI_LIB_TYPES}
|
||||
{SMI_LIB_RET}
|
||||
{TYPEDEF_LIST}
|
||||
|
||||
__all__ += {API_EXPOSE}
|
||||
__all__ += {TYPEDEF_EXPOSE}
|
||||
|
||||
_lib = CDLL(os.path.join(os.path.dirname(__file__), "libamd_smi64.so"))
|
||||
|
||||
{API}
|
||||
""".format(
|
||||
SMI_LIB_TYPES=smi_lib_ctypes_out,
|
||||
SMI_LIB_RET=smi_lib_ret_out,
|
||||
TYPEDEF_LIST=typedef_list_out,
|
||||
API_EXPOSE=api_expose,
|
||||
TYPEDEF_EXPOSE=typedef_expose,
|
||||
BINARY=LIBRARY_BINARY,
|
||||
API=api_string,
|
||||
)
|
||||
)
|
||||
CleanTempFiles()
|
||||
return "Success - wrapper generated."
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
status = main()
|
||||
print(status)
|
||||
Ссылка в новой задаче
Block a user