diff --git a/CMakeLists.txt b/CMakeLists.txt index 0268455..79e0ba1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,17 +7,18 @@ project(gpufetch CXX) set(SRC_DIR "src") set(COMMON_DIR "${SRC_DIR}/common") set(CUDA_DIR "${SRC_DIR}/cuda") +set(HSA_DIR "${SRC_DIR}/hsa") set(INTEL_DIR "${SRC_DIR}/intel") +# Enable Intel backend by default if(NOT DEFINED ENABLE_INTEL_BACKEND) set(ENABLE_INTEL_BACKEND true) endif() -if(NOT DEFINED ENABLE_CUDA_BACKEND OR ENABLE_CUDA_BACKEND) +if(ENABLE_CUDA_BACKEND) check_language(CUDA) if(CMAKE_CUDA_COMPILER) enable_language(CUDA) - set(ENABLE_CUDA_BACKEND true) # Must link_directories early so add_executable(gpufetch ...) gets the right directories link_directories(cuda_backend ${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/targets/x86_64-linux/lib) else() @@ -25,6 +26,34 @@ if(NOT DEFINED ENABLE_CUDA_BACKEND OR ENABLE_CUDA_BACKEND) endif() endif() +if(ENABLE_HSA_BACKEND) + # TODO: Needs rocm-cmake, what if its not insalled? + find_package(ROCmCMakeBuildTools) + if (ROCmCMakeBuildTools_FOUND) + find_package(hsa-runtime64 1.0 REQUIRED) + link_directories(hsa_backend hsa-runtime64::hsa-runtime64) + + # Find HSA headers + # ROCm does not seem to provide this, which is quite frustrating. + find_path(HSA_INCLUDE_DIR + NAMES hsa/hsa.h + HINTS + $ENV{ROCM_PATH}/include # allow users override via env variable + /opt/rocm/include # common default path + /usr/include + /usr/local/include + ) + + if(NOT HSA_INCLUDE_DIR) + message(STATUS "${BoldYellow}HSA not found, disabling HSA backend${ColorReset}") + set(ENABLE_HSA_BACKEND false) + endif() + else() + set(ENABLE_HSA_BACKEND false) + message(STATUS "${BoldYellow}ROCm not found${ColorReset}") + endif() +endif() + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") find_package(PCIUTILS) if(NOT ${PCIUTILS_FOUND}) @@ -50,8 +79,9 @@ else() endif() add_executable(gpufetch ${COMMON_DIR}/main.cpp ${COMMON_DIR}/args.cpp ${COMMON_DIR}/gpu.cpp ${COMMON_DIR}/pci.cpp ${COMMON_DIR}/sort.cpp ${COMMON_DIR}/global.cpp ${COMMON_DIR}/printer.cpp ${COMMON_DIR}/master.cpp ${COMMON_DIR}/uarch.cpp) -set(SANITY_FLAGS "-Wfloat-equal -Wshadow -Wpointer-arith") -set(CMAKE_CXX_FLAGS "${SANITY_FLAGS} -Wall -Wextra -pedantic -fstack-protector-all -pedantic -std=c++11") +set(SANITY_FLAGS -Wfloat-equal -Wshadow -Wpointer-arith -Wall -Wextra -pedantic -fstack-protector-all -pedantic) +target_compile_features(gpufetch PRIVATE cxx_std_11) +target_compile_options(gpufetch PRIVATE ${SANITY_FLAGS}) if(ENABLE_INTEL_BACKEND) target_compile_definitions(gpufetch PUBLIC BACKEND_INTEL) @@ -94,6 +124,22 @@ if(ENABLE_CUDA_BACKEND) target_link_libraries(gpufetch cuda_backend) endif() +if(ENABLE_HSA_BACKEND) + target_compile_definitions(gpufetch PUBLIC BACKEND_HSA) + + add_library(hsa_backend STATIC ${HSA_DIR}/hsa.cpp) + + if(NOT ${PCIUTILS_FOUND}) + add_dependencies(hsa_backend pciutils) + endif() + + target_include_directories(hsa_backend PRIVATE "${HSA_INCLUDE_DIR}") + message(STATUS "Found HSA: ${HSA_INCLUDE_DIR}") + + target_link_libraries(hsa_backend PRIVATE hsa-runtime64::hsa-runtime64) + target_link_libraries(gpufetch hsa_backend) +endif() + target_link_libraries(gpufetch pci z) install(TARGETS gpufetch DESTINATION bin) @@ -115,6 +161,11 @@ if(ENABLE_CUDA_BACKEND) else() message(STATUS "CUDA backend: ${BoldRed}OFF${ColorReset}") endif() +if(ENABLE_HSA_BACKEND) + message(STATUS "HSA backend: ${BoldGreen}ON${ColorReset}") +else() + message(STATUS "HSA backend: ${BoldRed}OFF${ColorReset}") +endif() if(ENABLE_INTEL_BACKEND) message(STATUS "Intel backend: ${BoldGreen}ON${ColorReset}") else() diff --git a/README.md b/README.md index 9e6e827..7859462 100644 --- a/README.md +++ b/README.md @@ -33,15 +33,16 @@ gpufetch is a command-line tool written in C++ that displays the GPU information -- [1. Support](#1-support) -- [2. Backends](#2-backends) - - [2.1 CUDA backend is not enabled. Why?](#21-cuda-backend-is-not-enabled-why) - - [2.2 The backend is enabled, but gpufetch is unable to detect my GPU](#22-the-backend-is-enabled-but-gpufetch-is-unable-to-detect-my-gpu) -- [3. Installation (building from source)](#3-installation-building-from-source) -- [4. Colors](#4-colors) - - [4.1 Specifying a name](#41-specifying-a-name) - - [4.2 Specifying the colors in RGB format](#42-specifying-the-colors-in-rgb-format) -- [5. Bugs or improvements](#5-bugs-or-improvements) +- [Table of contents](#table-of-contents) + - [1. Support](#1-support) + - [2. Backends](#2-backends) + - [2.1 CUDA backend is not enabled. Why?](#21-cuda-backend-is-not-enabled-why) + - [2.2 The backend is enabled, but gpufetch is unable to detect my GPU](#22-the-backend-is-enabled-but-gpufetch-is-unable-to-detect-my-gpu) + - [3. Installation (building from source)](#3-installation-building-from-source) + - [4. Colors](#4-colors) + - [4.1 Specifying a name](#41-specifying-a-name) + - [4.2 Specifying the colors in RGB format](#42-specifying-the-colors-in-rgb-format) + - [5. Bugs or improvements](#5-bugs-or-improvements) @@ -49,14 +50,16 @@ gpufetch is a command-line tool written in C++ that displays the GPU information gpufetch supports the following GPUs: - **NVIDIA** GPUs (Compute Capability >= 2.0) +- **AMD** GPUs (Experimental) (RDNA 3.0, CDNA 3.0) - **Intel** iGPUs (Generation >= Gen6) Only compilation under **Linux** is supported. ## 2. Backends -gpufetch is made up of two backends: +gpufetch is made up of three backends: - CUDA backend +- HSA backend - Intel backend Backends are enabled and disabled at **compile time**. When compiling gpufetch, check the CMake output to see which backends are enabled. @@ -111,6 +114,7 @@ By default, `gpufetch` will print the GPU logo with the system color scheme. How By specifying a name, gpufetch will use the specific colors of each manufacture. Valid values are: - intel +- amd - nvidia ``` diff --git a/build.sh b/build.sh index ee2d075..a37806c 100755 --- a/build.sh +++ b/build.sh @@ -23,6 +23,8 @@ fi # In case you want to explicitely disable a backend, you can: # Disable CUDA backend: # cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DENABLE_CUDA_BACKEND=OFF .. +# Disable HSA backend: +# cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DENABLE_HSA_BACKEND=OFF .. # Disable Intel backend: # cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DENABLE_INTEL_BACKEND=OFF .. diff --git a/src/common/args.cpp b/src/common/args.cpp index 6e1aa85..3e34cbb 100644 --- a/src/common/args.cpp +++ b/src/common/args.cpp @@ -13,12 +13,14 @@ #define NUM_COLORS 4 #define COLOR_STR_NVIDIA "nvidia" +#define COLOR_STR_AMD "amd" #define COLOR_STR_INTEL "intel" // +-----------------------+-----------------------+ // | Color logo | Color text | // | Color 1 | Color 2 | Color 1 | Color 2 | #define COLOR_DEFAULT_NVIDIA "118,185,000:255,255,255:255,255,255:118,185,000" +#define COLOR_DEFAULT_AMD "250,250,250:250,250,250:200,200,200:255,255,255" #define COLOR_DEFAULT_INTEL "015,125,194:230,230,230:040,150,220:230,230,230" struct args_struct { @@ -168,6 +170,7 @@ bool parse_color(char* optarg_str, struct color*** cs) { bool free_ptr = true; if(strcmp(optarg_str, COLOR_STR_NVIDIA) == 0) color_to_copy = COLOR_DEFAULT_NVIDIA; + else if(strcmp(optarg_str, COLOR_STR_AMD) == 0) color_to_copy = COLOR_DEFAULT_AMD; else if(strcmp(optarg_str, COLOR_STR_INTEL) == 0) color_to_copy = COLOR_DEFAULT_INTEL; else { str_to_parse = optarg_str; diff --git a/src/common/ascii.hpp b/src/common/ascii.hpp index 00a8254..058a5b4 100644 --- a/src/common/ascii.hpp +++ b/src/common/ascii.hpp @@ -34,6 +34,23 @@ $C2## ## ## ## ## ## ## ## #: :# \ $C2## ## ## ## ## ## ## ## ####### \ $C2## ## ### ## ###### ## ## ## " +#define ASCII_AMD \ +"$C2 '############### \ +$C2 ,############# \ +$C2 .#### \ +$C2 #. .#### \ +$C2 :##. .#### \ +$C2 :###. .#### \ +$C2 #########. :## \ +$C2 #######. ; \ +$C1 \ +$C1 ### ### ### ####### \ +$C1 ## ## ##### ##### ## ## \ +$C1 ## ## ### #### ### ## ## \ +$C1 ######### ### ## ### ## ## \ +$C1## ## ### ### ## ## \ +$C1## ## ### ### ####### " + #define ASCII_INTEL \ "$C1 .#################. \ $C1 .#### ####. \ @@ -68,6 +85,27 @@ $C1 olcc::; ,:ccloMMMMMMMMM \ $C1 :......oMMMMMMMMMMMMMMMMMMMMMM \ $C1 :lllMMMMMMMMMMMMMMMMMMMMMMMMMM " +#define ASCII_AMD_L \ +"$C1 \ +$C1 \ +$C1 \ +$C1 \ +$C1 \ +$C1 \ +$C1 @@@@ @@@ @@@ @@@@@@@@ $C2 ############ \ +$C1 @@@@@@ @@@@@ @@@@@ @@@ @@@ $C2 ########## \ +$C1 @@@ @@@ @@@@@@@@@@@@@ @@@ @@ $C2 # ##### \ +$C1 @@@ @@@ @@@ @@@ @@@ @@@ @@ $C2 ### ##### \ +$C1 @@@@@@@@@@@@ @@@ @@@ @@@ @@@ $C2######### ### \ +$C1 @@@ @@@ @@@ @@@ @@@@@@@@@ $C2######## ## \ +$C1 \ +$C1 \ +$C1 \ +$C1 \ +$C1 \ +$C1 \ +$C1 " + #define ASCII_INTEL_L \ "$C1 ###############@ \ $C1 ######@ ######@ \ @@ -94,11 +132,13 @@ typedef struct ascii_logo asciiL; // ------------------------------------------------------------------------------------------ // | LOGO | W | H | REPLACE | COLORS LOGO | COLORS TEXT | // ------------------------------------------------------------------------------------------ -asciiL logo_nvidia = { ASCII_NVIDIA, 45, 19, false, {C_FG_GREEN, C_FG_WHITE}, {C_FG_WHITE, C_FG_GREEN} }; -asciiL logo_intel = { ASCII_INTEL, 48, 14, false, {C_FG_CYAN}, {C_FG_CYAN, C_FG_WHITE} }; +asciiL logo_nvidia = { ASCII_NVIDIA, 45, 19, false, {C_FG_GREEN, C_FG_WHITE}, {C_FG_WHITE, C_FG_GREEN} }; +asciiL logo_amd = { ASCII_AMD, 39, 15, false, {C_FG_WHITE, C_FG_GREEN}, {C_FG_WHITE, C_FG_GREEN} }; +asciiL logo_intel = { ASCII_INTEL, 48, 14, false, {C_FG_CYAN}, {C_FG_CYAN, C_FG_WHITE} }; // Long variants | ---------------------------------------------------------------------------------------| -asciiL logo_nvidia_l = { ASCII_NVIDIA_L, 50, 15, false, {C_FG_GREEN, C_FG_WHITE}, {C_FG_WHITE, C_FG_GREEN} }; -asciiL logo_intel_l = { ASCII_INTEL_L, 62, 19, true, {C_BG_CYAN, C_BG_WHITE}, {C_FG_CYAN, C_FG_WHITE} }; -asciiL logo_unknown = { NULL, 0, 0, false, {C_NONE}, {C_NONE, C_NONE} }; +asciiL logo_nvidia_l = { ASCII_NVIDIA_L, 50, 15, false, {C_FG_GREEN, C_FG_WHITE}, {C_FG_WHITE, C_FG_GREEN} }; +asciiL logo_amd_l = { ASCII_AMD_L, 62, 19, true, {C_BG_WHITE, C_BG_WHITE}, {C_FG_CYAN, C_FG_B_WHITE} }; +asciiL logo_intel_l = { ASCII_INTEL_L, 62, 19, true, {C_BG_CYAN, C_BG_WHITE}, {C_FG_CYAN, C_FG_WHITE} }; +asciiL logo_unknown = { NULL, 0, 0, false, {C_NONE}, {C_NONE, C_NONE} }; #endif diff --git a/src/common/gpu.hpp b/src/common/gpu.hpp index 53092c7..c63fd3e 100644 --- a/src/common/gpu.hpp +++ b/src/common/gpu.hpp @@ -9,6 +9,7 @@ enum { GPU_VENDOR_NVIDIA, + GPU_VENDOR_AMD, GPU_VENDOR_INTEL }; @@ -44,6 +45,11 @@ struct topology_c { int32_t tensor_cores; }; +// HSA topology +struct topology_h { + int32_t compute_units; +}; + // Intel topology struct topology_i { int32_t slices; @@ -72,6 +78,8 @@ struct gpu_info { struct memory* mem; struct cache* cach; struct topology_c* topo_c; + // HSA specific + struct topology_h* topo_h; // Intel specific struct topology_i* topo_i; }; diff --git a/src/common/main.cpp b/src/common/main.cpp index f10e215..5d12b27 100644 --- a/src/common/main.cpp +++ b/src/common/main.cpp @@ -8,7 +8,7 @@ #include "../cuda/cuda.hpp" #include "../cuda/uarch.hpp" -static const char* VERSION = "0.25"; +static const char* VERSION = "0.30"; void print_help(char *argv[]) { const char **t = args_str; diff --git a/src/common/master.cpp b/src/common/master.cpp index a5694f3..9353630 100644 --- a/src/common/master.cpp +++ b/src/common/master.cpp @@ -7,6 +7,7 @@ #include "master.hpp" #include "args.hpp" #include "../cuda/cuda.hpp" +#include "../hsa/hsa.hpp" #include "../intel/intel.hpp" #define MAX_GPUS 1000 @@ -35,6 +36,18 @@ struct gpu_list* get_gpu_list() { list->num_gpus += idx; #endif +#ifdef BACKEND_HSA + bool valid = true; + + while(valid) { + list->gpus[idx] = get_gpu_info_hsa(devices, idx); + if(list->gpus[idx] != NULL) idx++; + else valid = false; + } + + list->num_gpus += idx; +#endif + #ifdef BACKEND_INTEL list->gpus[idx] = get_gpu_info_intel(devices); if(list->gpus[idx] != NULL) list->num_gpus++; @@ -51,6 +64,11 @@ bool print_gpus_list(struct gpu_list* list) { print_gpu_cuda(list->gpus[i]); #endif } + else if(list->gpus[i]->vendor == GPU_VENDOR_AMD) { + #ifdef BACKEND_AMD + print_gpu_hsa(list->gpus[i]); + #endif + } else if(list->gpus[i]->vendor == GPU_VENDOR_INTEL) { #ifdef BACKEND_INTEL print_gpu_intel(list->gpus[i]); @@ -69,6 +87,13 @@ void print_enabled_backends() { printf("%sOFF%s\n", C_FG_RED, C_RESET); #endif + printf("- HSA backend: "); +#ifdef BACKEND_HSA + printf("%sON%s\n", C_FG_GREEN, C_RESET); +#else + printf("%sOFF%s\n", C_FG_RED, C_RESET); +#endif + printf("- Intel backend: "); #ifdef BACKEND_INTEL printf("%sON%s\n", C_FG_GREEN, C_RESET); diff --git a/src/common/printer.cpp b/src/common/printer.cpp index e182d5a..e255e57 100644 --- a/src/common/printer.cpp +++ b/src/common/printer.cpp @@ -10,6 +10,7 @@ #include "../intel/uarch.hpp" #include "../intel/intel.hpp" +#include "../hsa/hsa.hpp" #include "../cuda/cuda.hpp" #include "../cuda/uarch.hpp" @@ -233,6 +234,9 @@ void choose_ascii_art(struct ascii* art, struct color** cs, struct terminal* ter if(art->vendor == GPU_VENDOR_NVIDIA) { art->art = choose_ascii_art_aux(&logo_nvidia_l, &logo_nvidia, term, lf); } + else if(art->vendor == GPU_VENDOR_AMD) { + art->art = choose_ascii_art_aux(&logo_amd_l, &logo_amd, term, lf); + } else if(art->vendor == GPU_VENDOR_INTEL) { art->art = choose_ascii_art_aux(&logo_intel_l, &logo_intel, term, lf); } @@ -478,6 +482,42 @@ bool print_gpufetch_cuda(struct gpu_info* gpu, STYLE s, struct color** cs, struc } #endif +#ifdef BACKEND_HSA +bool print_gpufetch_amd(struct gpu_info* gpu, STYLE s, struct color** cs, struct terminal* term) { + struct ascii* art = set_ascii(get_gpu_vendor(gpu), s); + + if(art == NULL) + return false; + + char* gpu_name = get_str_gpu_name(gpu); + char* sms = get_str_cu(gpu); + char* max_frequency = get_str_freq(gpu); + + setAttribute(art, ATTRIBUTE_NAME, gpu_name); + setAttribute(art, ATTRIBUTE_FREQUENCY, max_frequency); + setAttribute(art, ATTRIBUTE_STREAMINGMP, sms); + + const char** attribute_fields = ATTRIBUTE_FIELDS; + uint32_t longest_attribute = longest_attribute_length(art, attribute_fields); + uint32_t longest_field = longest_field_length(art, longest_attribute); + choose_ascii_art(art, cs, term, longest_field); + + if(!ascii_fits_screen(term->w, *art->art, longest_field)) { + // Despite of choosing the smallest logo, the output does not fit + // Choose the shorter field names and recalculate the longest attr + attribute_fields = ATTRIBUTE_FIELDS_SHORT; + longest_attribute = longest_attribute_length(art, attribute_fields); + } + + print_ascii_generic(art, longest_attribute, term->w - art->art->width, attribute_fields); + + free(art->attributes); + free(art); + + return true; +} +#endif + struct terminal* get_terminal_size() { struct terminal* term = (struct terminal*) emalloc(sizeof(struct terminal)); @@ -517,11 +557,22 @@ bool print_gpufetch(struct gpu_info* gpu, STYLE s, struct color** cs) { return false; #endif } - else { + else if(gpu->vendor == GPU_VENDOR_AMD) { + #ifdef BACKEND_HSA + return print_gpufetch_amd(gpu, s, cs, term); + #else + return false; + #endif + } + else if(gpu->vendor == GPU_VENDOR_INTEL) { #ifdef BACKEND_INTEL return print_gpufetch_intel(gpu, s, cs, term); #else return false; #endif } + else { + printErr("Invalid GPU vendor: %d", gpu->vendor); + return false; + } } diff --git a/src/hsa/hsa.cpp b/src/hsa/hsa.cpp new file mode 100644 index 0000000..6e13506 --- /dev/null +++ b/src/hsa/hsa.cpp @@ -0,0 +1,130 @@ +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "hsa.hpp" +#include "../common/pci.hpp" +#include "../common/global.hpp" +#include "../common/uarch.hpp" + +struct agent_info { + unsigned deviceId; // ID of the target GPU device + char gpu_name[64]; + char vendor_name[64]; + char device_mkt_name[64]; + uint32_t max_clock_freq; + uint32_t compute_unit; +}; + +#define RET_IF_HSA_ERR(err) { \ + if ((err) != HSA_STATUS_SUCCESS) { \ + char err_val[12]; \ + char* err_str = NULL; \ + if (hsa_status_string(err, \ + (const char**)&err_str) != HSA_STATUS_SUCCESS) { \ + snprintf(&(err_val[0]), sizeof(err_val), "%#x", (uint32_t)err); \ + err_str = &(err_val[0]); \ + } \ + printErr("HSA failure at: %s:%d\n", \ + __FILE__, __LINE__); \ + printErr("Call returned %s\n", err_str); \ + return (err); \ + } \ +} + +hsa_status_t agent_callback(hsa_agent_t agent, void *data) { + struct agent_info* info = reinterpret_cast(data); + + hsa_device_type_t type; + hsa_status_t err = hsa_agent_get_info(agent, HSA_AGENT_INFO_DEVICE, &type); + RET_IF_HSA_ERR(err); + + if (type == HSA_DEVICE_TYPE_GPU) { + err = hsa_agent_get_info(agent, HSA_AGENT_INFO_NAME, info->gpu_name); + RET_IF_HSA_ERR(err); + + // TODO: What if vendor_name is not AMD? + err = hsa_agent_get_info(agent, HSA_AGENT_INFO_VENDOR_NAME, info->vendor_name); + RET_IF_HSA_ERR(err); + + err = hsa_agent_get_info(agent, (hsa_agent_info_t) HSA_AMD_AGENT_INFO_PRODUCT_NAME, &info->device_mkt_name); + RET_IF_HSA_ERR(err); + + err = hsa_agent_get_info(agent, (hsa_agent_info_t) HSA_AMD_AGENT_INFO_MAX_CLOCK_FREQUENCY, &info->max_clock_freq); + RET_IF_HSA_ERR(err); + + err = hsa_agent_get_info(agent, (hsa_agent_info_t) HSA_AMD_AGENT_INFO_COMPUTE_UNIT_COUNT, &info->compute_unit); + RET_IF_HSA_ERR(err); + } + + return HSA_STATUS_SUCCESS; +} + +struct topology_h* get_topology_info(struct agent_info info) { + struct topology_h* topo = (struct topology_h*) emalloc(sizeof(struct topology_h)); + + topo->compute_units = info.compute_unit; + + return topo; +} + +struct gpu_info* get_gpu_info_hsa(struct pci_dev *devices, int gpu_idx) { + struct gpu_info* gpu = (struct gpu_info*) emalloc(sizeof(struct gpu_info)); + gpu->pci = NULL; + gpu->idx = gpu_idx; + + if(gpu->idx < 0) { + printErr("GPU index must be equal or greater than zero"); + return NULL; + } + + if(gpu->idx > 0) { + // Currently we only support fetching GPU 0. + return NULL; + } + + hsa_status_t status; + + // Initialize the HSA runtime + status = hsa_init(); + if (status != HSA_STATUS_SUCCESS) { + printErr("Failed to initialize HSA runtime"); + return NULL; + } + + struct agent_info info; + info.deviceId = gpu_idx; + + // Iterate over all agents in the system + status = hsa_iterate_agents(agent_callback, &info); + if (status != HSA_STATUS_SUCCESS) { + printErr("Failed to iterate HSA agents"); + hsa_shut_down(); + return NULL; + } + + gpu->freq = info.max_clock_freq; + gpu->vendor = GPU_VENDOR_AMD; + gpu->name = (char *) emalloc(sizeof(char) * (strlen(info.device_mkt_name) + 1)); + strcpy(gpu->name, info.device_mkt_name); + gpu->topo_h = get_topology_info(info); + + // TODO: Use gpu_name for uarch detection + + // Shut down the HSA runtime + hsa_shut_down(); + return gpu; +} + +char* get_str_cu(struct gpu_info* gpu) { + return get_str_generic(gpu->topo_h->compute_units); +} diff --git a/src/hsa/hsa.hpp b/src/hsa/hsa.hpp new file mode 100644 index 0000000..06d1c38 --- /dev/null +++ b/src/hsa/hsa.hpp @@ -0,0 +1,9 @@ +#ifndef __HSA_GPU__ +#define __HSA_GPU__ + +#include "../common/gpu.hpp" + +struct gpu_info* get_gpu_info_hsa(struct pci_dev *devices, int gpu_idx); +char* get_str_cu(struct gpu_info* gpu); + +#endif