6 Commits

Author SHA1 Message Date
Dr-Noob
8021aecb8c Small changes to CMakeLists.txt 2025-10-12 12:31:43 +02:00
Dr-Noob
b788bb7476 Update README 2025-10-12 12:24:40 +02:00
Dr-Noob
b5f8139038 Work on ASCII colors and add AMD color arg 2025-10-12 12:24:21 +02:00
Dr-Noob
60a1ef70d8 Supporting HSA detection of basic features and printing 2025-10-12 12:11:16 +02:00
Dr-Noob
14c745f7cb Working on the skeleton of HSA, fetching name works, need to work on printer next 2025-10-11 16:38:32 +02:00
Dr-Noob
2f5a41a135 Preliminary support via HSA 2025-10-11 16:03:55 +02:00
16 changed files with 183 additions and 842 deletions

View File

@@ -10,10 +10,9 @@ set(CUDA_DIR "${SRC_DIR}/cuda")
set(HSA_DIR "${SRC_DIR}/hsa") set(HSA_DIR "${SRC_DIR}/hsa")
set(INTEL_DIR "${SRC_DIR}/intel") set(INTEL_DIR "${SRC_DIR}/intel")
# Make sure that at least one backend is enabled. # Enable Intel backend by default
# It does not make sense that the user has not specified any backend. if(NOT DEFINED ENABLE_INTEL_BACKEND)
if(NOT ENABLE_INTEL_BACKEND AND NOT ENABLE_CUDA_BACKEND AND NOT ENABLE_HSA_BACKEND) set(ENABLE_INTEL_BACKEND true)
message(FATAL_ERROR "No backend was enabled! Please enable at least one backend with -DENABLE_XXX_BACKEND")
endif() endif()
if(ENABLE_CUDA_BACKEND) if(ENABLE_CUDA_BACKEND)
@@ -28,7 +27,8 @@ if(ENABLE_CUDA_BACKEND)
endif() endif()
if(ENABLE_HSA_BACKEND) if(ENABLE_HSA_BACKEND)
find_package(ROCmCMakeBuildTools QUIET) # TODO: Needs rocm-cmake, what if its not insalled?
find_package(ROCmCMakeBuildTools)
if (ROCmCMakeBuildTools_FOUND) if (ROCmCMakeBuildTools_FOUND)
find_package(hsa-runtime64 1.0 REQUIRED) find_package(hsa-runtime64 1.0 REQUIRED)
link_directories(hsa_backend hsa-runtime64::hsa-runtime64) link_directories(hsa_backend hsa-runtime64::hsa-runtime64)
@@ -48,49 +48,13 @@ if(ENABLE_HSA_BACKEND)
message(STATUS "${BoldYellow}HSA not found, disabling HSA backend${ColorReset}") message(STATUS "${BoldYellow}HSA not found, disabling HSA backend${ColorReset}")
set(ENABLE_HSA_BACKEND false) set(ENABLE_HSA_BACKEND false)
endif() endif()
else()
# rocm-cmake is not installed, try to manually find neccesary files.
message(STATUS "${BoldYellow}Could NOT find HSA automatically, running manual search...${ColorReset}")
if (NOT DEFINED ROCM_PATH)
set(ROCM_PATH "/opt/rocm" CACHE PATH "Path to ROCm")
endif()
find_path(HSA_INCLUDE_DIR hsa/hsa.h HINTS ${ROCM_PATH}/include)
find_library(HSA_LIBRARY hsa-runtime64 HINTS ${ROCM_PATH}/lib ${ROCM_PATH}/lib64)
if (HSA_INCLUDE_DIR AND HSA_LIBRARY)
message(STATUS "${BoldYellow}HSA was found manually${ColorReset}")
else() else()
set(ENABLE_HSA_BACKEND false) set(ENABLE_HSA_BACKEND false)
message(STATUS "${BoldYellow}HSA was not found manually${ColorReset}") message(STATUS "${BoldYellow}ROCm not found${ColorReset}")
endif()
endif() endif()
endif() endif()
set(GPUFECH_COMMON
${COMMON_DIR}/main.cpp
${COMMON_DIR}/args.cpp
${COMMON_DIR}/gpu.cpp
${COMMON_DIR}/global.cpp
${COMMON_DIR}/printer.cpp
${COMMON_DIR}/master.cpp
${COMMON_DIR}/uarch.cpp
)
set(GPUFETCH_LINK_TARGETS z)
if(NOT(ENABLE_HSA_BACKEND AND NOT ENABLE_CUDA_BACKEND AND NOT ENABLE_INTEL_BACKEND))
# Look for pciutils only if not building HSA only.
#
# This has the (intented) secondary effect that if only HSA backend is enabled
# by the user, but ROCm cannot be found, pciutils will still be compiled in
# order to show the list of GPUs available on the system, so that the user will
# get at least some feedback even if HSA is not found.
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
list(APPEND GPUFECH_COMMON ${COMMON_DIR}/pci.cpp ${COMMON_DIR}/sort.cpp)
list(APPEND GPUFETCH_LINK_TARGETS pci)
set(CMAKE_ENABLE_PCIUTILS ON)
find_package(PCIUTILS) find_package(PCIUTILS)
if(NOT ${PCIUTILS_FOUND}) if(NOT ${PCIUTILS_FOUND})
message(STATUS "${BoldYellow}pciutils not found, downloading and building a local copy...${ColorReset}") message(STATUS "${BoldYellow}pciutils not found, downloading and building a local copy...${ColorReset}")
@@ -113,17 +77,12 @@ if(NOT(ENABLE_HSA_BACKEND AND NOT ENABLE_CUDA_BACKEND AND NOT ENABLE_INTEL_BACKE
# Needed for linking libpci in FreeBSD # Needed for linking libpci in FreeBSD
link_directories(/usr/local/lib/) link_directories(/usr/local/lib/)
endif() endif()
endif()
add_executable(gpufetch ${GPUFECH_COMMON}) 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 -Wall -Wextra -pedantic -fstack-protector-all -pedantic) 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_features(gpufetch PRIVATE cxx_std_11)
target_compile_options(gpufetch PRIVATE ${SANITY_FLAGS}) target_compile_options(gpufetch PRIVATE ${SANITY_FLAGS})
if (CMAKE_ENABLE_PCIUTILS)
target_compile_definitions(gpufetch PUBLIC BACKEND_USE_PCI)
endif()
if(ENABLE_INTEL_BACKEND) if(ENABLE_INTEL_BACKEND)
target_compile_definitions(gpufetch PUBLIC BACKEND_INTEL) target_compile_definitions(gpufetch PUBLIC BACKEND_INTEL)
@@ -168,24 +127,20 @@ endif()
if(ENABLE_HSA_BACKEND) if(ENABLE_HSA_BACKEND)
target_compile_definitions(gpufetch PUBLIC BACKEND_HSA) target_compile_definitions(gpufetch PUBLIC BACKEND_HSA)
add_library(hsa_backend STATIC ${HSA_DIR}/hsa.cpp ${HSA_DIR}/uarch.cpp) add_library(hsa_backend STATIC ${HSA_DIR}/hsa.cpp)
if(NOT ${PCIUTILS_FOUND}) if(NOT ${PCIUTILS_FOUND})
add_dependencies(hsa_backend pciutils) add_dependencies(hsa_backend pciutils)
endif() endif()
target_include_directories(hsa_backend PRIVATE "${HSA_INCLUDE_DIR}") target_include_directories(hsa_backend PRIVATE "${HSA_INCLUDE_DIR}")
message(STATUS "Found HSA: ${HSA_INCLUDE_DIR}")
if (HSA_LIBRARY)
target_link_libraries(hsa_backend PRIVATE ${HSA_LIBRARY})
else()
target_link_libraries(hsa_backend PRIVATE hsa-runtime64::hsa-runtime64) target_link_libraries(hsa_backend PRIVATE hsa-runtime64::hsa-runtime64)
endif()
target_link_libraries(gpufetch hsa_backend) target_link_libraries(gpufetch hsa_backend)
endif() endif()
target_link_libraries(gpufetch ${GPUFETCH_LINK_TARGETS}) target_link_libraries(gpufetch pci z)
install(TARGETS gpufetch DESTINATION bin) install(TARGETS gpufetch DESTINATION bin)
if(NOT WIN32) if(NOT WIN32)

View File

@@ -1,24 +1,5 @@
#!/bin/bash #!/bin/bash
print_help() {
cat << EOF
Usage: $0 <backends> [build_type]
<backends> MANDATORY. Comma-separated list of
backends to enable.
Valid options: hsa, intel, cuda
Example: hsa,cuda
[build_type] OPTIONAL. Build type. Valid options:
debug, release (default: release)
Examples:
$0 hsa,intel debug
$0 cuda
$0 hsa,intel,cuda release
EOF
}
# gpufetch build script # gpufetch build script
set -e set -e
@@ -26,79 +7,19 @@ rm -rf build/ gpufetch
mkdir build/ mkdir build/
cd build/ cd build/
if [ "$1" == "--help" ] if [ "$1" == "debug" ]
then then
echo "gpufetch build script" BUILD_TYPE="Debug"
echo
print_help
exit 0
fi
if [[ $# -lt 1 ]]; then
echo "ERROR: At least one backend must be specified."
echo
print_help
exit 1
fi
# Determine if last argument is build type
LAST_ARG="${!#}"
if [[ "$LAST_ARG" == "debug" || "$LAST_ARG" == "release" ]]; then
BUILD_TYPE="$LAST_ARG"
BACKEND_ARG="${1}"
else else
BUILD_TYPE="release" BUILD_TYPE="Release"
BACKEND_ARG="${1}"
fi fi
# Split comma-separated backends into an array
IFS=',' read -r -a BACKENDS <<< "$BACKEND_ARG"
# Validate build type
if [[ "$BUILD_TYPE" != "debug" && "$BUILD_TYPE" != "release" ]]
then
echo "Error: Invalid build type '$BUILD_TYPE'."
echo "Valid options are: debug, release"
exit 1
fi
# From lower to upper case
CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=${BUILD_TYPE^}"
# Validate backends
VALID_BACKENDS=("hsa" "intel" "cuda")
for BACKEND in "${BACKENDS[@]}"; do
case "$BACKEND" in
hsa)
CMAKE_FLAGS+=" -DENABLE_HSA_BACKEND=ON"
;;
intel)
CMAKE_FLAGS+=" -DENABLE_INTEL_BACKEND=ON"
;;
cuda)
CMAKE_FLAGS+=" -DENABLE_CUDA_BACKEND=ON"
;;
*)
echo "ERROR: Invalid backend '$BACKEND'."
echo "Valid options: ${VALID_BACKENDS[*]}"
exit 1
;;
esac
done
# You can also manually specify the compilation flags.
# If you need to, just run the cmake command directly
# instead of using this script.
#
# Here you will find some help:
#
# In case you have CUDA installed but it is not detected, # In case you have CUDA installed but it is not detected,
# - set CMAKE_CUDA_COMPILER to your nvcc binary: # - set CMAKE_CUDA_COMPILER to your nvcc binary:
# - set CMAKE_CUDA_COMPILER_TOOLKIT_ROOT to the CUDA root dir # - set CMAKE_CUDA_COMPILER_TOOLKIT_ROOT to the CUDA root dir
# for example: # for example:
# cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_CUDA_COMPILER=/usr/local/cuda/bin/nvcc -DCMAKE_CUDA_COMPILER_TOOLKIT_ROOT=/usr/local/cuda/ .. # cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_CUDA_COMPILER=/usr/local/cuda/bin/nvcc -DCMAKE_CUDA_COMPILER_TOOLKIT_ROOT=/usr/local/cuda/ ..
#
# In case you want to explicitely disable a backend, you can: # In case you want to explicitely disable a backend, you can:
# Disable CUDA backend: # Disable CUDA backend:
# cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DENABLE_CUDA_BACKEND=OFF .. # cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DENABLE_CUDA_BACKEND=OFF ..
@@ -107,9 +28,7 @@ done
# Disable Intel backend: # Disable Intel backend:
# cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DENABLE_INTEL_BACKEND=OFF .. # cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DENABLE_INTEL_BACKEND=OFF ..
echo "$0: Running cmake $CMAKE_FLAGS" cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
echo
cmake $CMAKE_FLAGS ..
os=$(uname) os=$(uname)
if [ "$os" == 'Linux' ]; then if [ "$os" == 'Linux' ]; then

View File

@@ -101,17 +101,6 @@ char* get_str_bus_width(struct gpu_info* gpu) {
return string; return string;
} }
char* get_str_lds_size(struct gpu_info* gpu) {
// TODO: Show XX KB (XX MB Total) like in cpufetch
uint32_t size = 3+1+3+1;
assert(strlen(STRING_UNKNOWN)+1 <= size);
char* string = (char *) ecalloc(size, sizeof(char));
sprintf(string, "%d KB", gpu->mem->lds_size / 1024);
return string;
}
char* get_str_memory_clock(struct gpu_info* gpu) { char* get_str_memory_clock(struct gpu_info* gpu) {
return get_freq_as_str_mhz(gpu->mem->freq); return get_freq_as_str_mhz(gpu->mem->freq);
} }

View File

@@ -3,6 +3,8 @@
#include <cstdint> #include <cstdint>
#include "../cuda/pci.hpp"
#define UNKNOWN_FREQ -1 #define UNKNOWN_FREQ -1
enum { enum {
@@ -46,10 +48,6 @@ struct topology_c {
// HSA topology // HSA topology
struct topology_h { struct topology_h {
int32_t compute_units; int32_t compute_units;
int32_t num_shader_engines;
int32_t simds_per_cu;
int32_t num_xcc;
int32_t matrix_cores;
}; };
// Intel topology // Intel topology
@@ -65,7 +63,6 @@ struct memory {
int32_t bus_width; int32_t bus_width;
int32_t freq; int32_t freq;
int32_t clk_mul; // clock multiplier int32_t clk_mul; // clock multiplier
int32_t lds_size; // HSA specific for now
}; };
struct gpu_info { struct gpu_info {
@@ -93,7 +90,6 @@ char* get_str_freq(struct gpu_info* gpu);
char* get_str_memory_size(struct gpu_info* gpu); char* get_str_memory_size(struct gpu_info* gpu);
char* get_str_memory_type(struct gpu_info* gpu); char* get_str_memory_type(struct gpu_info* gpu);
char* get_str_bus_width(struct gpu_info* gpu); char* get_str_bus_width(struct gpu_info* gpu);
char* get_str_lds_size(struct gpu_info* gpu);
char* get_str_memory_clock(struct gpu_info* gpu); char* get_str_memory_clock(struct gpu_info* gpu);
char* get_str_l2(struct gpu_info* gpu); char* get_str_l2(struct gpu_info* gpu);
char* get_str_peak_performance(struct gpu_info* gpu); char* get_str_peak_performance(struct gpu_info* gpu);

View File

@@ -8,11 +8,7 @@
#include "../cuda/cuda.hpp" #include "../cuda/cuda.hpp"
#include "../cuda/uarch.hpp" #include "../cuda/uarch.hpp"
#ifdef BACKEND_USE_PCI static const char* VERSION = "0.25";
#include "pci.hpp"
#endif
static const char* VERSION = "0.30";
void print_help(char *argv[]) { void print_help(char *argv[]) {
const char **t = args_str; const char **t = args_str;
@@ -83,12 +79,8 @@ int main(int argc, char* argv[]) {
} }
if(get_num_gpus_available(list) == 0) { if(get_num_gpus_available(list) == 0) {
#ifdef BACKEND_USE_PCI
printErr("No GPU was detected! Available GPUs are:"); printErr("No GPU was detected! Available GPUs are:");
print_gpus_list_pci(); print_gpus_list_pci();
#else
printErr("No GPU was detected!");
#endif
printf("Please, make sure that the appropiate backend is enabled:\n"); printf("Please, make sure that the appropiate backend is enabled:\n");
print_enabled_backends(); print_enabled_backends();
printf("Visit https://github.com/Dr-Noob/gpufetch#2-backends for more information\n"); printf("Visit https://github.com/Dr-Noob/gpufetch#2-backends for more information\n");

View File

@@ -1,10 +1,7 @@
#include <cstdlib> #include <cstdlib>
#include <cstdio> #include <cstdio>
#ifdef BACKEND_USE_PCI
#include "pci.hpp" #include "pci.hpp"
#endif
#include "global.hpp" #include "global.hpp"
#include "colors.hpp" #include "colors.hpp"
#include "master.hpp" #include "master.hpp"
@@ -22,9 +19,7 @@ struct gpu_list {
struct gpu_list* get_gpu_list() { struct gpu_list* get_gpu_list() {
int idx = 0; int idx = 0;
#ifdef BACKEND_USE_PCI
struct pci_dev *devices = get_pci_devices_from_pciutils(); struct pci_dev *devices = get_pci_devices_from_pciutils();
#endif
struct gpu_list* list = (struct gpu_list*) malloc(sizeof(struct gpu_list)); struct gpu_list* list = (struct gpu_list*) malloc(sizeof(struct gpu_list));
list->num_gpus = 0; list->num_gpus = 0;
list->gpus = (struct gpu_info**) malloc(sizeof(struct info*) * MAX_GPUS); list->gpus = (struct gpu_info**) malloc(sizeof(struct info*) * MAX_GPUS);
@@ -45,7 +40,7 @@ struct gpu_list* get_gpu_list() {
bool valid = true; bool valid = true;
while(valid) { while(valid) {
list->gpus[idx] = get_gpu_info_hsa(idx); list->gpus[idx] = get_gpu_info_hsa(devices, idx);
if(list->gpus[idx] != NULL) idx++; if(list->gpus[idx] != NULL) idx++;
else valid = false; else valid = false;
} }

View File

@@ -11,7 +11,6 @@
#include "../intel/uarch.hpp" #include "../intel/uarch.hpp"
#include "../intel/intel.hpp" #include "../intel/intel.hpp"
#include "../hsa/hsa.hpp" #include "../hsa/hsa.hpp"
#include "../hsa/uarch.hpp"
#include "../cuda/cuda.hpp" #include "../cuda/cuda.hpp"
#include "../cuda/uarch.hpp" #include "../cuda/uarch.hpp"
@@ -32,60 +31,64 @@
#define MAX_ATTRIBUTES 100 #define MAX_ATTRIBUTES 100
#define MAX_TERM_SIZE 1024 #define MAX_TERM_SIZE 1024
typedef struct {
int id;
const char *name;
const char *shortname;
} AttributeField;
// AttributeField IDs
// Used by
enum { enum {
ATTRIBUTE_NAME, // ALL ATTRIBUTE_NAME,
ATTRIBUTE_CHIP, // ALL ATTRIBUTE_CHIP,
ATTRIBUTE_UARCH, // ALL ATTRIBUTE_UARCH,
ATTRIBUTE_TECHNOLOGY, // ALL ATTRIBUTE_TECHNOLOGY,
ATTRIBUTE_FREQUENCY, // ALL ATTRIBUTE_GT,
ATTRIBUTE_PEAK, // ALL ATTRIBUTE_FREQUENCY,
ATTRIBUTE_COMPUTE_UNITS, // HSA ATTRIBUTE_STREAMINGMP,
ATTRIBUTE_MATRIX_CORES, // HSA ATTRIBUTE_CORESPERMP,
ATTRIBUTE_XCDS, // HSA ATTRIBUTE_CUDA_CORES,
ATTRIBUTE_LDS_SIZE, // HSA ATTRIBUTE_TENSOR_CORES,
ATTRIBUTE_STREAMINGMP, // CUDA ATTRIBUTE_EUS,
ATTRIBUTE_CORESPERMP, // CUDA ATTRIBUTE_L2,
ATTRIBUTE_CUDA_CORES, // CUDA ATTRIBUTE_MEMORY,
ATTRIBUTE_TENSOR_CORES, // CUDA ATTRIBUTE_MEMORY_FREQ,
ATTRIBUTE_L2, // CUDA ATTRIBUTE_BUS_WIDTH,
ATTRIBUTE_MEMORY, // CUDA,HSA ATTRIBUTE_PEAK,
ATTRIBUTE_MEMORY_FREQ, // CUDA ATTRIBUTE_PEAK_TENSOR,
ATTRIBUTE_BUS_WIDTH, // CUDA,HSA
ATTRIBUTE_PEAK_TENSOR, // CUDA
ATTRIBUTE_EUS, // Intel
ATTRIBUTE_GT, // Intel
}; };
static const AttributeField ATTRIBUTE_INFO[] = { static const char* ATTRIBUTE_FIELDS [] = {
{ ATTRIBUTE_NAME, "Name:", "Name:" }, "Name:",
{ ATTRIBUTE_CHIP, "GPU processor:", "Processor:" }, "GPU processor:",
{ ATTRIBUTE_UARCH, "Microarchitecture:", "uArch:" }, "Microarchitecture:",
{ ATTRIBUTE_TECHNOLOGY, "Technology:", "Technology:" }, "Technology:",
{ ATTRIBUTE_FREQUENCY, "Max Frequency:", "Max Freq.:" }, "Graphics Tier:",
{ ATTRIBUTE_PEAK, "Peak Performance:", "Peak Perf.:" }, "Max Frequency:",
{ ATTRIBUTE_COMPUTE_UNITS, "Compute Units (CUs):", "CUs" }, "SMs:",
{ ATTRIBUTE_MATRIX_CORES, "Matrix Cores:", "Matrix Cores:" }, "Cores/SM:",
{ ATTRIBUTE_XCDS, "XCDs:", "XCDs" }, "CUDA Cores:",
{ ATTRIBUTE_LDS_SIZE, "LDS size:", "LDS:" }, "Tensor Cores:",
{ ATTRIBUTE_STREAMINGMP, "SMs:", "SMs:" }, "Execution Units:",
{ ATTRIBUTE_CORESPERMP, "Cores/SM:", "Cores/SM:" }, "L2 Size:",
{ ATTRIBUTE_CUDA_CORES, "CUDA Cores:", "CUDA Cores:" }, "Memory:",
{ ATTRIBUTE_TENSOR_CORES, "Tensor Cores:", "Tensor Cores:" }, "Memory frequency:",
{ ATTRIBUTE_L2, "L2 Size:", "L2 Size:" }, "Bus width:",
{ ATTRIBUTE_MEMORY, "Memory:", "Memory:" }, "Peak Performance:",
{ ATTRIBUTE_MEMORY_FREQ, "Memory frequency:", "Memory freq.:" }, "Peak Performance (MMA):",
{ ATTRIBUTE_BUS_WIDTH, "Bus width:", "Bus width:" }, };
{ ATTRIBUTE_PEAK_TENSOR, "Peak Performance (MMA):", "Peak Perf.(MMA):" },
{ ATTRIBUTE_EUS, "Execution Units:", "EUs:" }, static const char* ATTRIBUTE_FIELDS_SHORT [] = {
{ ATTRIBUTE_GT, "Graphics Tier:", "GT:" }, "Name:",
"Processor:",
"uArch:",
"Technology:",
"GT:",
"Max Freq.:",
"SMs:",
"Cores/SM:",
"CUDA Cores:",
"Tensor Cores:",
"EUs:",
"L2 Size:",
"Memory:",
"Memory freq.:",
"Bus width:",
"Peak Perf.:",
"Peak Perf.(MMA):",
}; };
struct terminal { struct terminal {
@@ -203,6 +206,8 @@ bool ascii_fits_screen(int termw, struct ascii_logo logo, int lf) {
void replace_bgbyfg_color(struct ascii_logo* logo) { void replace_bgbyfg_color(struct ascii_logo* logo) {
// Replace background by foreground color // Replace background by foreground color
for(int i=0; i < 2; i++) { for(int i=0; i < 2; i++) {
if(logo->color_ascii[i] == NULL) break;
if(strcmp(logo->color_ascii[i], C_BG_BLACK) == 0) strcpy(logo->color_ascii[i], C_FG_BLACK); if(strcmp(logo->color_ascii[i], C_BG_BLACK) == 0) strcpy(logo->color_ascii[i], C_FG_BLACK);
else if(strcmp(logo->color_ascii[i], C_BG_RED) == 0) strcpy(logo->color_ascii[i], C_FG_RED); else if(strcmp(logo->color_ascii[i], C_BG_RED) == 0) strcpy(logo->color_ascii[i], C_FG_RED);
else if(strcmp(logo->color_ascii[i], C_BG_GREEN) == 0) strcpy(logo->color_ascii[i], C_FG_GREEN); else if(strcmp(logo->color_ascii[i], C_BG_GREEN) == 0) strcpy(logo->color_ascii[i], C_FG_GREEN);
@@ -270,14 +275,13 @@ void choose_ascii_art(struct ascii* art, struct color** cs, struct terminal* ter
} }
} }
uint32_t longest_attribute_length(struct ascii* art, bool use_short) { uint32_t longest_attribute_length(struct ascii* art, const char** attribute_fields) {
uint32_t max = 0; uint32_t max = 0;
uint64_t len = 0; uint64_t len = 0;
for(uint32_t i=0; i < art->n_attributes_set; i++) { for(uint32_t i=0; i < art->n_attributes_set; i++) {
if(art->attributes[i]->value != NULL) { if(art->attributes[i]->value != NULL) {
const char* str = use_short ? ATTRIBUTE_INFO[art->attributes[i]->type].shortname : ATTRIBUTE_INFO[art->attributes[i]->type].name; len = strlen(attribute_fields[art->attributes[i]->type]);
len = strlen(str);
if(len > max) max = len; if(len > max) max = len;
} }
} }
@@ -301,7 +305,7 @@ uint32_t longest_field_length(struct ascii* art, int la) {
return max; return max;
} }
void print_ascii_generic(struct ascii* art, uint32_t la, int32_t text_space, bool use_short) { void print_ascii_generic(struct ascii* art, uint32_t la, int32_t text_space, const char** attribute_fields) {
struct ascii_logo* logo = art->art; struct ascii_logo* logo = art->art;
int attr_to_print = 0; int attr_to_print = 0;
int attr_type; int attr_type;
@@ -345,13 +349,11 @@ void print_ascii_generic(struct ascii* art, uint32_t la, int32_t text_space, boo
attr_value = art->attributes[attr_to_print]->value; attr_value = art->attributes[attr_to_print]->value;
attr_to_print++; attr_to_print++;
const char* attr_str = use_short ? ATTRIBUTE_INFO[attr_type].shortname : ATTRIBUTE_INFO[attr_type].name; space_right = 1 + (la - strlen(attribute_fields[attr_type]));
space_right = 1 + (la - strlen(attr_str));
current_space = max(0, text_space); current_space = max(0, text_space);
printf("%s%.*s%s", logo->color_text[0], current_space, attr_str, art->reset); printf("%s%.*s%s", logo->color_text[0], current_space, attribute_fields[attr_type], art->reset);
current_space = max(0, current_space - (int) strlen(attr_str)); current_space = max(0, current_space - (int) strlen(attribute_fields[attr_type]));
printf("%*s", min(current_space, space_right), ""); printf("%*s", min(current_space, space_right), "");
current_space = max(0, current_space - min(current_space, space_right)); current_space = max(0, current_space - min(current_space, space_right));
printf("%s%.*s%s", logo->color_text[1], current_space, attr_value, art->reset); printf("%s%.*s%s", logo->color_text[1], current_space, attr_value, art->reset);
@@ -385,19 +387,19 @@ bool print_gpufetch_intel(struct gpu_info* gpu, STYLE s, struct color** cs, stru
setAttribute(art, ATTRIBUTE_EUS, eus); setAttribute(art, ATTRIBUTE_EUS, eus);
setAttribute(art, ATTRIBUTE_PEAK, pp); setAttribute(art, ATTRIBUTE_PEAK, pp);
bool use_short = false; const char** attribute_fields = ATTRIBUTE_FIELDS;
uint32_t longest_attribute = longest_attribute_length(art, use_short); uint32_t longest_attribute = longest_attribute_length(art, attribute_fields);
uint32_t longest_field = longest_field_length(art, longest_attribute); uint32_t longest_field = longest_field_length(art, longest_attribute);
choose_ascii_art(art, cs, term, longest_field); choose_ascii_art(art, cs, term, longest_field);
if(!ascii_fits_screen(term->w, *art->art, longest_field)) { if(!ascii_fits_screen(term->w, *art->art, longest_field)) {
// Despite of choosing the smallest logo, the output does not fit // Despite of choosing the smallest logo, the output does not fit
// Choose the shorter field names and recalculate the longest attr // Choose the shorter field names and recalculate the longest attr
use_short = true; attribute_fields = ATTRIBUTE_FIELDS_SHORT;
longest_attribute = longest_attribute_length(art, use_short); longest_attribute = longest_attribute_length(art, attribute_fields);
} }
print_ascii_generic(art, longest_attribute, term->w - art->art->width, use_short); print_ascii_generic(art, longest_attribute, term->w - art->art->width, attribute_fields);
return true; return true;
} }
@@ -454,19 +456,19 @@ bool print_gpufetch_cuda(struct gpu_info* gpu, STYLE s, struct color** cs, struc
setAttribute(art, ATTRIBUTE_PEAK_TENSOR, pp_tensor); setAttribute(art, ATTRIBUTE_PEAK_TENSOR, pp_tensor);
} }
bool use_short = false; const char** attribute_fields = ATTRIBUTE_FIELDS;
uint32_t longest_attribute = longest_attribute_length(art, use_short); uint32_t longest_attribute = longest_attribute_length(art, attribute_fields);
uint32_t longest_field = longest_field_length(art, longest_attribute); uint32_t longest_field = longest_field_length(art, longest_attribute);
choose_ascii_art(art, cs, term, longest_field); choose_ascii_art(art, cs, term, longest_field);
if(!ascii_fits_screen(term->w, *art->art, longest_field)) { if(!ascii_fits_screen(term->w, *art->art, longest_field)) {
// Despite of choosing the smallest logo, the output does not fit // Despite of choosing the smallest logo, the output does not fit
// Choose the shorter field names and recalculate the longest attr // Choose the shorter field names and recalculate the longest attr
use_short = true; attribute_fields = ATTRIBUTE_FIELDS_SHORT;
longest_attribute = longest_attribute_length(art, use_short); longest_attribute = longest_attribute_length(art, attribute_fields);
} }
print_ascii_generic(art, longest_attribute, term->w - art->art->width, use_short); print_ascii_generic(art, longest_attribute, term->w - art->art->width, attribute_fields);
free(manufacturing_process); free(manufacturing_process);
free(max_frequency); free(max_frequency);
@@ -488,46 +490,26 @@ bool print_gpufetch_amd(struct gpu_info* gpu, STYLE s, struct color** cs, struct
return false; return false;
char* gpu_name = get_str_gpu_name(gpu); char* gpu_name = get_str_gpu_name(gpu);
char* gpu_chip = get_str_chip(gpu->arch); char* sms = get_str_cu(gpu);
char* uarch = get_str_uarch_hsa(gpu->arch);
char* manufacturing_process = get_str_process(gpu->arch);
char* cus = get_str_cu(gpu);
char* matrix_cores = get_str_matrix_cores(gpu);
char* xcds = get_str_xcds(gpu);
char* max_frequency = get_str_freq(gpu); char* max_frequency = get_str_freq(gpu);
char* bus_width = get_str_bus_width(gpu);
char* mem_size = get_str_memory_size(gpu);
char* lds_size = get_str_lds_size(gpu);
setAttribute(art, ATTRIBUTE_NAME, gpu_name); setAttribute(art, ATTRIBUTE_NAME, gpu_name);
if (gpu_chip != NULL) {
setAttribute(art, ATTRIBUTE_CHIP, gpu_chip);
}
setAttribute(art, ATTRIBUTE_UARCH, uarch);
setAttribute(art, ATTRIBUTE_TECHNOLOGY, manufacturing_process);
setAttribute(art, ATTRIBUTE_FREQUENCY, max_frequency); setAttribute(art, ATTRIBUTE_FREQUENCY, max_frequency);
setAttribute(art, ATTRIBUTE_COMPUTE_UNITS, cus); setAttribute(art, ATTRIBUTE_STREAMINGMP, sms);
setAttribute(art, ATTRIBUTE_MATRIX_CORES, matrix_cores);
if (xcds != NULL) {
setAttribute(art, ATTRIBUTE_XCDS, xcds);
}
setAttribute(art, ATTRIBUTE_LDS_SIZE, lds_size);
setAttribute(art, ATTRIBUTE_MEMORY, mem_size);
setAttribute(art, ATTRIBUTE_BUS_WIDTH, bus_width);
bool use_short = false; const char** attribute_fields = ATTRIBUTE_FIELDS;
uint32_t longest_attribute = longest_attribute_length(art, use_short); uint32_t longest_attribute = longest_attribute_length(art, attribute_fields);
uint32_t longest_field = longest_field_length(art, longest_attribute); uint32_t longest_field = longest_field_length(art, longest_attribute);
choose_ascii_art(art, cs, term, longest_field); choose_ascii_art(art, cs, term, longest_field);
if(!ascii_fits_screen(term->w, *art->art, longest_field)) { if(!ascii_fits_screen(term->w, *art->art, longest_field)) {
// Despite of choosing the smallest logo, the output does not fit // Despite of choosing the smallest logo, the output does not fit
// Choose the shorter field names and recalculate the longest attr // Choose the shorter field names and recalculate the longest attr
use_short = true; attribute_fields = ATTRIBUTE_FIELDS_SHORT;
longest_attribute = longest_attribute_length(art, use_short); longest_attribute = longest_attribute_length(art, attribute_fields);
} }
print_ascii_generic(art, longest_attribute, term->w - art->art->width, use_short); print_ascii_generic(art, longest_attribute, term->w - art->art->width, attribute_fields);
free(art->attributes); free(art->attributes);
free(art); free(art);

View File

@@ -16,9 +16,6 @@ struct uarch {
int32_t cc_minor; int32_t cc_minor;
int32_t compute_capability; int32_t compute_capability;
// HSA specific
int32_t llvm_target;
// Intel specific // Intel specific
int32_t gt; int32_t gt;
int32_t eu; int32_t eu;

View File

@@ -1,6 +1,3 @@
// patched cuda.cpp for cuda13 by cloudy
#include <cuda_runtime.h> #include <cuda_runtime.h>
#include <cstring> #include <cstring>
#include <cstdlib> #include <cstdlib>
@@ -8,8 +5,8 @@
#include "cuda.hpp" #include "cuda.hpp"
#include "uarch.hpp" #include "uarch.hpp"
#include "pci.hpp"
#include "gpufetch_helper_cuda.hpp" #include "gpufetch_helper_cuda.hpp"
#include "../common/pci.hpp"
#include "../common/global.hpp" #include "../common/global.hpp"
#include "../common/uarch.hpp" #include "../common/uarch.hpp"
@@ -17,22 +14,29 @@ bool print_gpu_cuda(struct gpu_info* gpu) {
char* cc = get_str_cc(gpu->arch); char* cc = get_str_cc(gpu->arch);
printf("%s (Compute Capability %s)\n", gpu->name, cc); printf("%s (Compute Capability %s)\n", gpu->name, cc);
free(cc); free(cc);
return true; return true;
} }
struct cache* get_cache_info(cudaDeviceProp prop) { struct cache* get_cache_info(cudaDeviceProp prop) {
struct cache* cach = (struct cache*) emalloc(sizeof(struct cache)); struct cache* cach = (struct cache*) emalloc(sizeof(struct cache));
cach->L2 = (struct cach*) emalloc(sizeof(struct cach)); cach->L2 = (struct cach*) emalloc(sizeof(struct cach));
cach->L2->size = prop.l2CacheSize; cach->L2->size = prop.l2CacheSize;
cach->L2->num_caches = 1; cach->L2->num_caches = 1;
cach->L2->exists = true; cach->L2->exists = true;
return cach; return cach;
} }
int get_tensor_cores(struct uarch* arch, int sm, int major) { int get_tensor_cores(struct uarch* arch, int sm, int major) {
if(major == 7) { if(major == 7) {
if (is_chip_TU116(arch)) // TU116 does not have tensor cores!
// https://www.anandtech.com/show/13973/nvidia-gtx-1660-ti-review-feat-evga-xc-gaming/2
if(arch->chip == CHIP_TU116 || arch->chip == CHIP_TU116BM ||
arch->chip == CHIP_TU116GL || arch->chip == CHIP_TU116M) {
return 0; return 0;
}
return sm * 8; return sm * 8;
} }
else if(major == 8) return sm * 4; else if(major == 8) return sm * 4;
@@ -41,57 +45,57 @@ int get_tensor_cores(struct uarch* arch, int sm, int major) {
struct topology_c* get_topology_info(struct uarch* arch, cudaDeviceProp prop) { struct topology_c* get_topology_info(struct uarch* arch, cudaDeviceProp prop) {
struct topology_c* topo = (struct topology_c*) emalloc(sizeof(struct topology_c)); struct topology_c* topo = (struct topology_c*) emalloc(sizeof(struct topology_c));
topo->streaming_mp = prop.multiProcessorCount; topo->streaming_mp = prop.multiProcessorCount;
topo->cores_per_mp = _ConvertSMVer2Cores(prop.major, prop.minor); topo->cores_per_mp = _ConvertSMVer2Cores(prop.major, prop.minor);
topo->cuda_cores = topo->streaming_mp * topo->cores_per_mp; topo->cuda_cores = topo->streaming_mp * topo->cores_per_mp;
topo->tensor_cores = get_tensor_cores(arch, topo->streaming_mp, prop.major); topo->tensor_cores = get_tensor_cores(arch, topo->streaming_mp, prop.major);
return topo; return topo;
} }
int32_t guess_clock_multipilier(struct gpu_info* gpu, struct memory* mem) { int32_t guess_clock_multipilier(struct gpu_info* gpu, struct memory* mem) {
// Guess clock multiplier
int32_t clk_mul = 1; int32_t clk_mul = 1;
int32_t clk8 = abs((mem->freq/8) - gpu->freq); int32_t clk8 = abs((mem->freq/8) - gpu->freq);
int32_t clk4 = abs((mem->freq/4) - gpu->freq); int32_t clk4 = abs((mem->freq/4) - gpu->freq);
int32_t clk2 = abs((mem->freq/2) - gpu->freq); int32_t clk2 = abs((mem->freq/2) - gpu->freq);
int32_t clk1 = abs((mem->freq/1) - gpu->freq); int32_t clk1 = abs((mem->freq/1) - gpu->freq);
int32_t min = mem->freq; int32_t min = mem->freq;
if(clkm_possible_for_uarch(8, gpu->arch) && min > clk8) { clk_mul = 8; min = clk8; } if(clkm_possible_for_uarch(8, gpu->arch) && min > clk8) { clk_mul = 8; min = clk8; }
if(clkm_possible_for_uarch(4, gpu->arch) && min > clk4) { clk_mul = 4; min = clk4; } if(clkm_possible_for_uarch(4, gpu->arch) && min > clk4) { clk_mul = 4; min = clk4; }
if(clkm_possible_for_uarch(2, gpu->arch) && min > clk2) { clk_mul = 2; min = clk2; } if(clkm_possible_for_uarch(2, gpu->arch) && min > clk2) { clk_mul = 2; min = clk2; }
if(clkm_possible_for_uarch(1, gpu->arch) && min > clk1) { clk_mul = 1; min = clk1; } if(clkm_possible_for_uarch(1, gpu->arch) && min > clk1) { clk_mul = 1; min = clk1; }
return clk_mul; return clk_mul;
} }
struct memory* get_memory_info(struct gpu_info* gpu, cudaDeviceProp prop) { struct memory* get_memory_info(struct gpu_info* gpu, cudaDeviceProp prop) {
struct memory* mem = (struct memory*) emalloc(sizeof(struct memory)); struct memory* mem = (struct memory*) emalloc(sizeof(struct memory));
int val = 0;
mem->size_bytes = (unsigned long long) prop.totalGlobalMem; mem->size_bytes = (unsigned long long) prop.totalGlobalMem;
mem->freq = prop.memoryClockRate * 0.001f;
if (cudaDeviceGetAttribute(&val, cudaDevAttrMemoryClockRate, gpu->idx) == cudaSuccess) {
if (val > 1000000)
mem->freq = (float)val / 1000000.0f;
else
mem->freq = (float)val * 0.001f;
} else {
mem->freq = 0.0f;
}
mem->bus_width = prop.memoryBusWidth; mem->bus_width = prop.memoryBusWidth;
mem->clk_mul = guess_clock_multipilier(gpu, mem); mem->clk_mul = guess_clock_multipilier(gpu, mem);
mem->type = guess_memtype_from_cmul_and_uarch(mem->clk_mul, gpu->arch); mem->type = guess_memtype_from_cmul_and_uarch(mem->clk_mul, gpu->arch);
if (mem->clk_mul > 0) // Fix frequency returned from CUDA to show real frequency
mem->freq = mem->freq / mem->clk_mul; mem->freq = mem->freq / mem->clk_mul;
return mem; return mem;
} }
// Compute peak performance when using CUDA cores
int64_t get_peak_performance_cuda(struct gpu_info* gpu) { int64_t get_peak_performance_cuda(struct gpu_info* gpu) {
return gpu->freq * 1000000 * gpu->topo_c->cuda_cores * 2; return gpu->freq * 1000000 * gpu->topo_c->cuda_cores * 2;
} }
// Compute peak performance when using tensor cores
int64_t get_peak_performance_tcu(cudaDeviceProp prop, struct gpu_info* gpu) { int64_t get_peak_performance_tcu(cudaDeviceProp prop, struct gpu_info* gpu) {
// Volta / Turing tensor cores performs 4x4x4 FP16 matrix multiplication
// Ampere tensor cores performs 8x4x8 FP16 matrix multiplicacion
if(prop.major == 7) return gpu->freq * 1000000 * 4 * 4 * 4 * 2 * gpu->topo_c->tensor_cores; if(prop.major == 7) return gpu->freq * 1000000 * 4 * 4 * 4 * 2 * gpu->topo_c->tensor_cores;
else if(prop.major == 8) return gpu->freq * 1000000 * 8 * 4 * 8 * 2 * gpu->topo_c->tensor_cores; else if(prop.major == 8) return gpu->freq * 1000000 * 8 * 4 * 8 * 2 * gpu->topo_c->tensor_cores;
else return 0; else return 0;
@@ -113,7 +117,8 @@ struct gpu_info* get_gpu_info_cuda(struct pci_dev *devices, int gpu_idx) {
} }
int num_gpus = -1; int num_gpus = -1;
cudaError_t err = cudaGetDeviceCount(&num_gpus); cudaError_t err = cudaSuccess;
err = cudaGetDeviceCount(&num_gpus);
if(gpu_idx == 0) { if(gpu_idx == 0) {
printf("\r%*c\r", (int) strlen(CUDA_DRIVER_START_WARNING), ' '); printf("\r%*c\r", (int) strlen(CUDA_DRIVER_START_WARNING), ' ');
@@ -131,6 +136,7 @@ struct gpu_info* get_gpu_info_cuda(struct pci_dev *devices, int gpu_idx) {
} }
if(gpu->idx+1 > num_gpus) { if(gpu->idx+1 > num_gpus) {
// Master is trying to query an invalid GPU
return NULL; return NULL;
} }
@@ -140,25 +146,15 @@ struct gpu_info* get_gpu_info_cuda(struct pci_dev *devices, int gpu_idx) {
return NULL; return NULL;
} }
int core_clk = 0; gpu->freq = deviceProp.clockRate * 1e-3f;
if (cudaDeviceGetAttribute(&core_clk, cudaDevAttrClockRate, gpu->idx) == cudaSuccess) {
if (core_clk > 1000000)
gpu->freq = core_clk / 1000000.0f;
else
gpu->freq = core_clk * 0.001f;
} else {
gpu->freq = 0.0f;
}
gpu->vendor = GPU_VENDOR_NVIDIA; gpu->vendor = GPU_VENDOR_NVIDIA;
gpu->name = (char *) emalloc(strlen(deviceProp.name) + 1); gpu->name = (char *) emalloc(sizeof(char) * (strlen(deviceProp.name) + 1));
strcpy(gpu->name, deviceProp.name); strcpy(gpu->name, deviceProp.name);
if((gpu->pci = get_pci_from_pciutils(devices, PCI_VENDOR_ID_NVIDIA, gpu_idx)) == NULL) { if((gpu->pci = get_pci_from_pciutils(devices, PCI_VENDOR_ID_NVIDIA, gpu_idx)) == NULL) {
printErr("Unable to find a valid device for vendor id 0x%.4X using pciutils", PCI_VENDOR_ID_NVIDIA); printErr("Unable to find a valid device for vendor id 0x%.4X using pciutils", PCI_VENDOR_ID_NVIDIA);
return NULL; return NULL;
} }
gpu->arch = get_uarch_from_cuda(gpu); gpu->arch = get_uarch_from_cuda(gpu);
gpu->cach = get_cache_info(deviceProp); gpu->cach = get_cache_info(deviceProp);
gpu->mem = get_memory_info(gpu, deviceProp); gpu->mem = get_memory_info(gpu, deviceProp);
@@ -169,7 +165,19 @@ struct gpu_info* get_gpu_info_cuda(struct pci_dev *devices, int gpu_idx) {
return gpu; return gpu;
} }
char* get_str_sm(struct gpu_info* gpu) { return get_str_generic(gpu->topo_c->streaming_mp); } char* get_str_sm(struct gpu_info* gpu) {
char* get_str_cores_sm(struct gpu_info* gpu) { return get_str_generic(gpu->topo_c->cores_per_mp); } return get_str_generic(gpu->topo_c->streaming_mp);
char* get_str_cuda_cores(struct gpu_info* gpu) { return get_str_generic(gpu->topo_c->cuda_cores); } }
char* get_str_tensor_cores(struct gpu_info* gpu) { return get_str_generic(gpu->topo_c->tensor_cores); }
char* get_str_cores_sm(struct gpu_info* gpu) {
return get_str_generic(gpu->topo_c->cores_per_mp);
}
char* get_str_cuda_cores(struct gpu_info* gpu) {
return get_str_generic(gpu->topo_c->cuda_cores);
}
char* get_str_tensor_cores(struct gpu_info* gpu) {
return get_str_generic(gpu->topo_c->tensor_cores);
}

View File

@@ -8,7 +8,6 @@
#include "../common/uarch.hpp" #include "../common/uarch.hpp"
#include "../common/global.hpp" #include "../common/global.hpp"
#include "../common/gpu.hpp" #include "../common/gpu.hpp"
#include "pci.hpp"
#include "chips.hpp" #include "chips.hpp"
// Any clock multiplier // Any clock multiplier
@@ -362,8 +361,3 @@ void free_uarch_struct(struct uarch* arch) {
free(arch->chip_str); free(arch->chip_str);
free(arch); free(arch);
} }
bool is_chip_TU116(struct uarch* arch) {
return arch->chip == CHIP_TU116 || arch->chip == CHIP_TU116BM ||
arch->chip == CHIP_TU116GL || arch->chip == CHIP_TU116M;
}

View File

@@ -13,6 +13,5 @@ char* get_str_cc(struct uarch* arch);
char* get_str_chip(struct uarch* arch); char* get_str_chip(struct uarch* arch);
char* get_str_process(struct uarch* arch); char* get_str_process(struct uarch* arch);
void free_uarch_struct(struct uarch* arch); void free_uarch_struct(struct uarch* arch);
bool is_chip_TU116(struct uarch* arch);
#endif #endif

View File

@@ -1,37 +0,0 @@
#ifndef __HSA_GPUCHIPS__
#define __HSA_GPUCHIPS__
typedef uint32_t GPUCHIP;
enum {
CHIP_UNKNOWN_HSA,
// VEGA (TODO)
// ...
// RDNA
CHIP_NAVI_10,
CHIP_NAVI_12,
CHIP_NAVI_14,
// RDNA2
// There are way more (eg Oberon)
// Maybe we'll add them in the future.
CHIP_NAVI_21,
CHIP_NAVI_22,
CHIP_NAVI_23,
CHIP_NAVI_24,
// RDNA3
// There are way more as well.
// Supporting Navi only for now.
CHIP_NAVI_31,
CHIP_NAVI_32,
CHIP_NAVI_33,
// RDNA4
CHIP_NAVI_44,
CHIP_NAVI_48,
// CDNA
CHIP_ARCTURUS, // MI100 series
CHIP_ALDEBARAN, // MI200 series
CHIP_AQUA_VANJARAM, // MI300 series
CHIP_CDNA_NEXT // MI350 series
};
#endif

View File

@@ -12,7 +12,7 @@
#include <hsa/hsa_ext_amd.h> #include <hsa/hsa_ext_amd.h>
#include "hsa.hpp" #include "hsa.hpp"
#include "uarch.hpp" #include "../common/pci.hpp"
#include "../common/global.hpp" #include "../common/global.hpp"
#include "../common/uarch.hpp" #include "../common/uarch.hpp"
@@ -22,16 +22,7 @@ struct agent_info {
char vendor_name[64]; char vendor_name[64];
char device_mkt_name[64]; char device_mkt_name[64];
uint32_t max_clock_freq; uint32_t max_clock_freq;
// Memory
uint32_t bus_width;
uint32_t lds_size;
uint64_t global_size;
// Topology
uint32_t compute_unit; uint32_t compute_unit;
uint32_t num_shader_engines;
uint32_t simds_per_cu;
uint32_t num_xcc; // Acccelerator Complex Dies (XCDs)
uint32_t matrix_cores; // Cores with WMMA/MFMA capabilities
}; };
#define RET_IF_HSA_ERR(err) { \ #define RET_IF_HSA_ERR(err) { \
@@ -43,57 +34,13 @@ struct agent_info {
snprintf(&(err_val[0]), sizeof(err_val), "%#x", (uint32_t)err); \ snprintf(&(err_val[0]), sizeof(err_val), "%#x", (uint32_t)err); \
err_str = &(err_val[0]); \ err_str = &(err_val[0]); \
} \ } \
printErr("HSA failure at: %s:%d\n", __FILE__, __LINE__); \ printErr("HSA failure at: %s:%d\n", \
__FILE__, __LINE__); \
printErr("Call returned %s\n", err_str); \ printErr("Call returned %s\n", err_str); \
return (err); \ return (err); \
} \ } \
} }
hsa_status_t memory_pool_callback(hsa_amd_memory_pool_t pool, void* data) {
struct agent_info* info = reinterpret_cast<struct agent_info *>(data);
hsa_amd_segment_t segment;
hsa_status_t err = hsa_amd_memory_pool_get_info(pool, HSA_AMD_MEMORY_POOL_INFO_SEGMENT, &segment);
RET_IF_HSA_ERR(err);
if (segment == HSA_AMD_SEGMENT_GROUP) {
// LDS memory
// We want to make sure that this memory pool is not repeated.
if (info->lds_size != 0) {
printErr("Found HSA_AMD_SEGMENT_GROUP twice!");
return HSA_STATUS_ERROR;
}
uint32_t size = 0;
err = hsa_amd_memory_pool_get_info(pool, HSA_AMD_MEMORY_POOL_INFO_SIZE, &size);
RET_IF_HSA_ERR(err);
info->lds_size = size;
}
else if (segment == HSA_AMD_SEGMENT_GLOBAL) {
// Global memory
uint32_t global_flags = 0;
err = hsa_amd_memory_pool_get_info(pool, HSA_AMD_MEMORY_POOL_INFO_GLOBAL_FLAGS, &global_flags);
RET_IF_HSA_ERR(err);
if (global_flags & HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_EXTENDED_SCOPE_FINE_GRAINED) {
if (info->global_size != 0) {
printErr("Found HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_EXTENDED_SCOPE_FINE_GRAINED twice!");
return HSA_STATUS_ERROR;
}
uint64_t size = 0;
err = hsa_amd_memory_pool_get_info(pool, HSA_AMD_MEMORY_POOL_INFO_SIZE, &size);
RET_IF_HSA_ERR(err);
info->global_size = size;
}
}
return HSA_STATUS_SUCCESS;
}
hsa_status_t agent_callback(hsa_agent_t agent, void *data) { hsa_status_t agent_callback(hsa_agent_t agent, void *data) {
struct agent_info* info = reinterpret_cast<struct agent_info *>(data); struct agent_info* info = reinterpret_cast<struct agent_info *>(data);
@@ -105,6 +52,7 @@ hsa_status_t agent_callback(hsa_agent_t agent, void *data) {
err = hsa_agent_get_info(agent, HSA_AGENT_INFO_NAME, info->gpu_name); err = hsa_agent_get_info(agent, HSA_AGENT_INFO_NAME, info->gpu_name);
RET_IF_HSA_ERR(err); 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); err = hsa_agent_get_info(agent, HSA_AGENT_INFO_VENDOR_NAME, info->vendor_name);
RET_IF_HSA_ERR(err); RET_IF_HSA_ERR(err);
@@ -116,26 +64,6 @@ hsa_status_t agent_callback(hsa_agent_t agent, void *data) {
err = hsa_agent_get_info(agent, (hsa_agent_info_t) HSA_AMD_AGENT_INFO_COMPUTE_UNIT_COUNT, &info->compute_unit); 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); RET_IF_HSA_ERR(err);
// According to the documentation, this is deprecated. But what should I be using then?
err = hsa_agent_get_info(agent, (hsa_agent_info_t) HSA_AMD_AGENT_INFO_MEMORY_WIDTH, &info->bus_width);
RET_IF_HSA_ERR(err);
err = hsa_agent_get_info(agent, (hsa_agent_info_t) HSA_AMD_AGENT_INFO_NUM_SHADER_ENGINES, &info->num_shader_engines);
RET_IF_HSA_ERR(err);
err = hsa_agent_get_info(agent, (hsa_agent_info_t) HSA_AMD_AGENT_INFO_NUM_SIMDS_PER_CU, &info->simds_per_cu);
RET_IF_HSA_ERR(err);
err = hsa_agent_get_info(agent, (hsa_agent_info_t) HSA_AMD_AGENT_INFO_NUM_XCC, &info->num_xcc);
RET_IF_HSA_ERR(err);
// We will check against zero to see if it was set beforehand.
info->global_size = 0;
info->lds_size = 0;
// This will fill global_size and lds_size.
err = hsa_amd_agent_iterate_memory_pools(agent, memory_pool_callback, data);
RET_IF_HSA_ERR(err);
} }
return HSA_STATUS_SUCCESS; return HSA_STATUS_SUCCESS;
@@ -145,27 +73,11 @@ struct topology_h* get_topology_info(struct agent_info info) {
struct topology_h* topo = (struct topology_h*) emalloc(sizeof(struct topology_h)); struct topology_h* topo = (struct topology_h*) emalloc(sizeof(struct topology_h));
topo->compute_units = info.compute_unit; topo->compute_units = info.compute_unit;
topo->num_shader_engines = info.num_shader_engines; // not printed at the moment
topo->simds_per_cu = info.simds_per_cu; // not printed at the moment
topo->num_xcc = info.num_xcc;
// Old GPUs (GCN I guess) might not have matrix cores.
// Not sure what would happen here?
topo->matrix_cores = topo->compute_units * topo->simds_per_cu;
return topo; return topo;
} }
struct memory* get_memory_info(struct gpu_info* gpu, struct agent_info info) { struct gpu_info* get_gpu_info_hsa(struct pci_dev *devices, int gpu_idx) {
struct memory* mem = (struct memory*) emalloc(sizeof(struct memory));
mem->bus_width = info.bus_width;
mem->lds_size = info.lds_size;
mem->size_bytes = info.global_size;
return mem;
}
struct gpu_info* get_gpu_info_hsa(int gpu_idx) {
struct gpu_info* gpu = (struct gpu_info*) emalloc(sizeof(struct gpu_info)); struct gpu_info* gpu = (struct gpu_info*) emalloc(sizeof(struct gpu_info));
gpu->pci = NULL; gpu->pci = NULL;
gpu->idx = gpu_idx; gpu->idx = gpu_idx;
@@ -180,8 +92,11 @@ struct gpu_info* get_gpu_info_hsa(int gpu_idx) {
return NULL; return NULL;
} }
hsa_status_t err = hsa_init(); hsa_status_t status;
if (err != HSA_STATUS_SUCCESS) {
// Initialize the HSA runtime
status = hsa_init();
if (status != HSA_STATUS_SUCCESS) {
printErr("Failed to initialize HSA runtime"); printErr("Failed to initialize HSA runtime");
return NULL; return NULL;
} }
@@ -190,53 +105,26 @@ struct gpu_info* get_gpu_info_hsa(int gpu_idx) {
info.deviceId = gpu_idx; info.deviceId = gpu_idx;
// Iterate over all agents in the system // Iterate over all agents in the system
err = hsa_iterate_agents(agent_callback, &info); status = hsa_iterate_agents(agent_callback, &info);
if (err != HSA_STATUS_SUCCESS) { if (status != HSA_STATUS_SUCCESS) {
printErr("Failed to iterate HSA agents"); printErr("Failed to iterate HSA agents");
hsa_shut_down(); hsa_shut_down();
return NULL; return NULL;
} }
if (strcmp(info.vendor_name, "AMD") != 0) {
printErr("HSA vendor name is: '%s'. Only AMD is supported!", info.vendor_name);
return NULL;
}
gpu->vendor = GPU_VENDOR_AMD;
gpu->freq = info.max_clock_freq; gpu->freq = info.max_clock_freq;
gpu->topo_h = get_topology_info(info); gpu->vendor = GPU_VENDOR_AMD;
gpu->name = (char *) emalloc(sizeof(char) * (strlen(info.device_mkt_name) + 1)); gpu->name = (char *) emalloc(sizeof(char) * (strlen(info.device_mkt_name) + 1));
strcpy(gpu->name, info.device_mkt_name); strcpy(gpu->name, info.device_mkt_name);
gpu->arch = get_uarch_from_hsa(gpu, info.gpu_name); gpu->topo_h = get_topology_info(info);
gpu->mem = get_memory_info(gpu, info);
if (gpu->arch == NULL) { // TODO: Use gpu_name for uarch detection
return NULL;
}
// Shut down the HSA runtime // Shut down the HSA runtime
err = hsa_shut_down(); hsa_shut_down();
if (err != HSA_STATUS_SUCCESS) {
printErr("Failed to shutdown HSA runtime");
return NULL;
}
return gpu; return gpu;
} }
char* get_str_cu(struct gpu_info* gpu) { char* get_str_cu(struct gpu_info* gpu) {
return get_str_generic(gpu->topo_h->compute_units); return get_str_generic(gpu->topo_h->compute_units);
} }
char* get_str_xcds(struct gpu_info* gpu) {
// If there is a single XCD, then we dont want to
// print it.
if (gpu->topo_h->num_xcc == 1) {
return NULL;
}
return get_str_generic(gpu->topo_h->num_xcc);
}
char* get_str_matrix_cores(struct gpu_info* gpu) {
// TODO: Show XX (WMMA/MFMA)
return get_str_generic(gpu->topo_h->matrix_cores);
}

View File

@@ -3,9 +3,7 @@
#include "../common/gpu.hpp" #include "../common/gpu.hpp"
struct gpu_info* get_gpu_info_hsa(int gpu_idx); struct gpu_info* get_gpu_info_hsa(struct pci_dev *devices, int gpu_idx);
char* get_str_cu(struct gpu_info* gpu); char* get_str_cu(struct gpu_info* gpu);
char* get_str_xcds(struct gpu_info* gpu);
char* get_str_matrix_cores(struct gpu_info* gpu);
#endif #endif

View File

@@ -1,321 +0,0 @@
#include <cstdlib>
#include <cstdint>
#include <cstring>
#include "../common/uarch.hpp"
#include "../common/global.hpp"
#include "../common/gpu.hpp"
#include "chips.hpp"
// MICROARCH values
enum {
UARCH_UNKNOWN,
// GCN (Graphics Core Next)
// Empty for now
// ...
// RDNA (Radeon DNA)
UARCH_RDNA,
UARCH_RDNA2,
UARCH_RDNA3,
UARCH_RDNA4,
// CDNA (Compute DNA)
UARCH_CDNA,
UARCH_CDNA2,
UARCH_CDNA3,
UARCH_CDNA4
};
static const char *uarch_str[] = {
/*[ARCH_UNKNOWN] = */ STRING_UNKNOWN,
/*[UARCH_RDNA] = */ "RDNA",
/*[UARCH_RDNA2] = */ "RDNA2",
/*[UARCH_RDNA3] = */ "RDNA3",
/*[UARCH_RDNA4] = */ "RDNA4",
/*[UARCH_CDNA] = */ "CDNA",
/*[UARCH_CDNA2] = */ "CDNA2",
/*[UARCH_CDNA3] = */ "CDNA3",
/*[UARCH_CDNA4] = */ "CDNA4",
};
// Sources:
// - https://rocm.docs.amd.com/en/latest/reference/gpu-arch-specs.html
// - https://www.techpowerup.com
//
// This is sometimes refered to as LLVM target, but also shader ISA.
//
// LLVM target *usually* maps to a specific architecture. However there
// are case where this is not true:
// MI8 is GCN3.0 with LLVM target gfx803
// MI6 is GCN4.0 with LLVM target gfx803
// or
// Strix Point can be gfx1150 or gfx1151
//
// NOTE: GCN chips are stored for completeness, but they are
// not actively supported.
enum {
TARGET_UNKNOWN_HSA,
/// GCN (Graphics Core Next)
/// ------------------------
// GCN 1.0
TARGET_GFX600,
TARGET_GFX601,
TARGET_GFX602,
// GCN 2.0
TARGET_GFX700,
TARGET_GFX701,
TARGET_GFX702,
TARGET_GFX703,
TARGET_GFX704,
TARGET_GFX705,
// GCN 3.0 / 4.0
TARGET_GFX801,
TARGET_GFX802,
TARGET_GFX803,
TARGET_GFX805,
TARGET_GFX810,
// GCN 5.0
TARGET_GFX900,
TARGET_GFX902,
TARGET_GFX904,
// GCN 5.1
TARGET_GFX906,
// ???
TARGET_GFX909,
TARGET_GFX90C,
/// RDNA (Radeon DNA)
/// -----------------
// RDNA1
TARGET_GFX1010,
TARGET_GFX1011,
TARGET_GFX1012,
// RDNA2
TARGET_GFX1013, // Oberon
TARGET_GFX1030,
TARGET_GFX1031,
TARGET_GFX1032,
TARGET_GFX1033,
TARGET_GFX1034,
TARGET_GFX1035, // ??
TARGET_GFX1036, // ??
// RDNA3
TARGET_GFX1100,
TARGET_GFX1101,
TARGET_GFX1102,
TARGET_GFX1103, // ???
// RDNA3.5
TARGET_GFX1150, // Strix Point
TARGET_GFX1151, // Strix Halo / Strix Point
TARGET_GFX1152, // Krackan Point
TARGET_GFX1153, // ???
// RDNA4
TARGET_GFX1200,
TARGET_GFX1201,
TARGET_GFX1250, // ???
TARGET_GFX1251, // ???
/// CDNA (Compute DNA)
/// ------------------
// CDNA
TARGET_GFX908,
// CDNA2
TARGET_GFX90A,
// CDNA3
TARGET_GFX942,
// CDNA4
TARGET_GFX950
};
#define CHECK_UARCH_START if (false) {}
#define CHECK_UARCH(arch, chip_, str, uarch, process) \
else if (arch->chip == chip_) fill_uarch(arch, str, uarch, process);
#define CHECK_UARCH_END else { if(arch->chip != CHIP_UNKNOWN_HSA) printBug("map_chip_to_uarch_hsa: Unknown chip id: %d", arch->chip); fill_uarch(arch, STRING_UNKNOWN, UARCH_UNKNOWN, UNK); }
void fill_uarch(struct uarch* arch, char const *str, MICROARCH u, uint32_t process) {
arch->chip_str = (char *) emalloc(sizeof(char) * (strlen(str)+1));
strcpy(arch->chip_str, str);
arch->uarch = u;
arch->process = process;
}
// On chiplet based chips (such as Navi31, Navi32, etc),
// we have 2 different processes: The MCD process and the
// rest of the chip process. They might be different and here
// we just take one - let's take MCD process for now.
//
// TODO: Should we differentiate?
void map_chip_to_uarch_hsa(struct uarch* arch) {
CHECK_UARCH_START
// RDNA
CHECK_UARCH(arch, CHIP_NAVI_10, "Navi 10", UARCH_RDNA, 7)
CHECK_UARCH(arch, CHIP_NAVI_12, "Navi 12", UARCH_RDNA, 7)
CHECK_UARCH(arch, CHIP_NAVI_14, "Navi 14", UARCH_RDNA, 7)
CHECK_UARCH(arch, CHIP_NAVI_21, "Navi 21", UARCH_RDNA2, 7)
CHECK_UARCH(arch, CHIP_NAVI_22, "Navi 22", UARCH_RDNA2, 7)
CHECK_UARCH(arch, CHIP_NAVI_23, "Navi 23", UARCH_RDNA2, 7)
CHECK_UARCH(arch, CHIP_NAVI_24, "Navi 24", UARCH_RDNA2, 6)
CHECK_UARCH(arch, CHIP_NAVI_31, "Navi 31", UARCH_RDNA3, 6)
CHECK_UARCH(arch, CHIP_NAVI_32, "Navi 32", UARCH_RDNA3, 6)
CHECK_UARCH(arch, CHIP_NAVI_33, "Navi 33", UARCH_RDNA3, 6)
CHECK_UARCH(arch, CHIP_NAVI_44, "Navi 44", UARCH_RDNA4, 4)
CHECK_UARCH(arch, CHIP_NAVI_48, "Navi 48", UARCH_RDNA4, 4)
// CDNA
// NOTE: We will not show chip name for CDNA, thus use empty str
CHECK_UARCH(arch, CHIP_ARCTURUS, "", UARCH_CDNA, 7)
CHECK_UARCH(arch, CHIP_ALDEBARAN, "", UARCH_CDNA2, 6)
CHECK_UARCH(arch, CHIP_AQUA_VANJARAM, "", UARCH_CDNA3, 6)
CHECK_UARCH(arch, CHIP_CDNA_NEXT, "", UARCH_CDNA4, 6) // big difference between MCD and rest of the chip process
CHECK_UARCH_END
}
#define CHECK_TGT_START if (false) {}
#define CHECK_TGT(target, llvm_target, chip) \
else if (target == llvm_target) return chip;
#define CHECK_TGT_END else { printBug("LLVM target '%d' has no matching chip", target); return CHIP_UNKNOWN_HSA; }
// We have at least 2 choices to infer the chip:
//
// - LLVM target (e.g., gfx1101 is Navi 32)
// - PCI ID (e.g., 0x7470 is Navi 32)
//
// For now we will use the first approach, which seems to have
// some issues like mentioned in the enum.
// However PCI detection is also not perfect, since it is
// quite hard to find PCI ids from old hardware.
GPUCHIP get_chip_from_target_hsa(int32_t target) {
CHECK_TGT_START
/// RDNA
/// -------------------------------------------
CHECK_TGT(target, TARGET_GFX1010, CHIP_NAVI_10)
CHECK_TGT(target, TARGET_GFX1011, CHIP_NAVI_12)
CHECK_TGT(target, TARGET_GFX1012, CHIP_NAVI_14)
// CHECK_TGT(target, TARGET_GFX1013, TODO)
/// RDNA2
/// -------------------------------------------
CHECK_TGT(target, TARGET_GFX1030, CHIP_NAVI_21)
CHECK_TGT(target, TARGET_GFX1031, CHIP_NAVI_22)
CHECK_TGT(target, TARGET_GFX1032, CHIP_NAVI_23)
CHECK_TGT(target, TARGET_GFX1033, CHIP_NAVI_21)
CHECK_TGT(target, TARGET_GFX1034, CHIP_NAVI_24)
// CHECK_TGT(target, TARGET_GFX1035, TODO)
// CHECK_TGT(target, TARGET_GFX1036, TODO)
/// RDNA3
/// -------------------------------------------
CHECK_TGT(target, TARGET_GFX1100, CHIP_NAVI_31)
CHECK_TGT(target, TARGET_GFX1101, CHIP_NAVI_32)
CHECK_TGT(target, TARGET_GFX1102, CHIP_NAVI_33)
// CHECK_TGT(target, TARGET_GFX1103, TODO)
/// RDNA3.5
/// -------------------------------------------
// CHECK_TGT(target, TARGET_GFX1150, TODO)
// CHECK_TGT(target, TARGET_GFX1151, TODO)
// CHECK_TGT(target, TARGET_GFX1152, TODO)
// CHECK_TGT(target, TARGET_GFX1153, TODO)
/// RDNA4
/// -------------------------------------------
CHECK_TGT(target, TARGET_GFX1200, CHIP_NAVI_44)
CHECK_TGT(target, TARGET_GFX1201, CHIP_NAVI_48)
// CHECK_TGT(target, TARGET_GFX1250, TODO)
// CHECK_TGT(target, TARGET_GFX1251, TODO)
/// CDNA
/// -------------------------------------------
CHECK_TGT(target, TARGET_GFX908, CHIP_ARCTURUS)
/// CDNA2
/// -------------------------------------------
CHECK_TGT(target, TARGET_GFX90A, CHIP_ALDEBARAN)
/// CDNA3
/// -------------------------------------------
CHECK_TGT(target, TARGET_GFX942, CHIP_AQUA_VANJARAM)
/// CDNA4
/// -------------------------------------------
CHECK_TGT(target, TARGET_GFX950, CHIP_CDNA_NEXT)
CHECK_TGT_END
}
#define CHECK_TGT_STR_START if (false) {}
#define CHECK_TGT_STR(target, llvm_target, chip) \
else if (strcmp(target, llvm_target) == 0) return chip;
#define CHECK_TGT_STR_END else { return TARGET_UNKNOWN_HSA; }
// Maps the LLVM target string to the enum value
int32_t get_llvm_target_from_str(char* target) {
// TODO: Autogenerate this
// TODO: Add all, not only the ones we support in get_chip_from_target_hsa
CHECK_TGT_STR_START
CHECK_TGT_STR(target, "gfx1010", TARGET_GFX1010)
CHECK_TGT_STR(target, "gfx1011", TARGET_GFX1011)
CHECK_TGT_STR(target, "gfx1012", TARGET_GFX1012)
CHECK_TGT_STR(target, "gfx1013", TARGET_GFX1013)
CHECK_TGT_STR(target, "gfx1030", TARGET_GFX1030)
CHECK_TGT_STR(target, "gfx1031", TARGET_GFX1031)
CHECK_TGT_STR(target, "gfx1032", TARGET_GFX1032)
CHECK_TGT_STR(target, "gfx1033", TARGET_GFX1033)
CHECK_TGT_STR(target, "gfx1034", TARGET_GFX1034)
CHECK_TGT_STR(target, "gfx1035", TARGET_GFX1035)
CHECK_TGT_STR(target, "gfx1036", TARGET_GFX1036)
CHECK_TGT_STR(target, "gfx1100", TARGET_GFX1100)
CHECK_TGT_STR(target, "gfx1101", TARGET_GFX1101)
CHECK_TGT_STR(target, "gfx1102", TARGET_GFX1102)
CHECK_TGT_STR(target, "gfx1103", TARGET_GFX1103)
CHECK_TGT_STR(target, "gfx1200", TARGET_GFX1200)
CHECK_TGT_STR(target, "gfx1201", TARGET_GFX1201)
CHECK_TGT_STR(target, "gfx1250", TARGET_GFX1250)
CHECK_TGT_STR(target, "gfx1251", TARGET_GFX1251)
CHECK_TGT_STR(target, "gfx908", TARGET_GFX908)
CHECK_TGT_STR(target, "gfx90a", TARGET_GFX90A)
CHECK_TGT_STR(target, "gfx942", TARGET_GFX942)
CHECK_TGT_STR(target, "gfx950", TARGET_GFX950)
CHECK_TGT_STR_END
}
struct uarch* get_uarch_from_hsa(struct gpu_info* gpu, char* gpu_name) {
struct uarch* arch = (struct uarch*) emalloc(sizeof(struct uarch));
arch->llvm_target = get_llvm_target_from_str(gpu_name);
if (arch->llvm_target == TARGET_UNKNOWN_HSA) {
printErr("Unknown LLVM target: '%s'", gpu_name);
return NULL;
}
arch->chip_str = NULL;
arch->chip = get_chip_from_target_hsa(arch->llvm_target);
map_chip_to_uarch_hsa(arch);
return arch;
}
bool is_uarch_valid(struct uarch* arch) {
if (arch == NULL) {
printBug("Invalid uarch: arch is NULL");
return false;
}
if (arch->uarch >= UARCH_UNKNOWN && arch->uarch <= UARCH_CDNA4) {
return true;
}
else {
printBug("Invalid uarch: %d", arch->uarch);
return false;
}
}
bool is_cdna(struct uarch* arch) {
return arch->uarch == UARCH_CDNA ||
arch->uarch == UARCH_CDNA2 ||
arch->uarch == UARCH_CDNA3 ||
arch->uarch == UARCH_CDNA4;
}
char* get_str_chip(struct uarch* arch) {
// We dont want to show CDNA chip names as they add
// no value, since each architecture maps one to one
// to a chip.
if (is_cdna(arch)) return NULL;
return arch->chip_str;
}
const char* get_str_uarch_hsa(struct uarch* arch) {
if (!is_uarch_valid(arch)) {
return NULL;
}
return uarch_str[arch->uarch];
}

View File

@@ -1,13 +0,0 @@
#ifndef __HSA_UARCH__
#define __HSA_UARCH__
#include "../common/gpu.hpp"
struct uarch;
struct uarch* get_uarch_from_hsa(struct gpu_info* gpu, char* gpu_name);
char* get_str_uarch_hsa(struct uarch* arch);
char* get_str_process(struct uarch* arch); // TODO: Shouldnt we define this in the cpp?
char* get_str_chip(struct uarch* arch);
#endif