diff --git a/src/arm/midr.c b/src/arm/midr.c index f4edbd2..6eedf0d 100644 --- a/src/arm/midr.c +++ b/src/arm/midr.c @@ -3,6 +3,9 @@ #include #include #include +#include +#include +#include #include "../common/global.h" #include "udev.h" @@ -115,9 +118,54 @@ uint32_t fill_ids_from_midr(uint32_t* midr_array, int32_t* freq_array, uint32_t* return latest_id+1; } +void init_cpu_info(struct cpuInfo* cpu) { + cpu->NEON = false; + cpu->AES = false; + cpu->SHA1 = false; + cpu->SHA2 = false; + cpu->CRC32 = false; + cpu->next_cpu = NULL; +} + +// We assume all cpus share the same hardware +// capabilities but I'm not sure it is always +// true... +void fill_cpu_features(struct cpuInfo* cpu) { + errno = 0; + long hwcaps = getauxval(AT_HWCAP); + + if(errno == ENOENT) { + printWarn("Unable to retrieve AT_HWCAP using getauxval"); + } +#ifdef __aarch64__ + else { + cpu->AES = hwcaps & HWCAP_AES; + cpu->CRC32 = hwcaps & HWCAP_CRC32; + cpu->SHA1 = hwcaps & HWCAP_SHA1; + cpu->SHA2 = hwcaps & HWCAP_SHA2; + cpu->NEON = hwcaps & HWCAP_ASIMD; + } +#else + else { + cpu->NEON = hwcaps & HWCAP_NEON; + } + + hwcaps = getauxval(AT_HWCAP2); + if(errno == ENOENT) { + printWarn("Unable to retrieve AT_HWCAP2 using getauxval"); + } + else { + cpu->AES = hwcaps & HWCAP2_AES; + cpu->CRC32 = hwcaps & HWCAP2_CRC32; + cpu->SHA1 = hwcaps & HWCAP2_SHA1; + cpu->SHA2 = hwcaps & HWCAP2_SHA2; + } +#endif +} + struct cpuInfo* get_cpu_info() { struct cpuInfo* cpu = malloc(sizeof(struct cpuInfo)); - cpu->next_cpu = NULL; + init_cpu_info(cpu); int ncores = get_ncores_from_cpuinfo(); bool success = false; @@ -140,20 +188,21 @@ struct cpuInfo* get_cpu_info() { } } uint32_t sockets = fill_ids_from_midr(midr_array, freq_array, ids_array, ncores); - + fill_cpu_features(cpu); + struct cpuInfo* ptr = cpu; int midr_idx = 0; int tmp_midr_idx = 0; for(uint32_t i=0; i < sockets; i++) { if(i > 0) { - ptr->next_cpu = malloc(sizeof(struct cpuInfo)); + ptr->next_cpu = malloc(sizeof(struct cpuInfo)); ptr = ptr->next_cpu; + init_cpu_info(ptr); tmp_midr_idx = midr_idx; while(cores_are_equal(midr_idx, tmp_midr_idx, midr_array, freq_array)) tmp_midr_idx++; midr_idx = tmp_midr_idx; - } - ptr->next_cpu = NULL; + } ptr->midr = midr_array[midr_idx]; ptr->arch = get_uarch_from_midr(ptr->midr, ptr); @@ -200,6 +249,7 @@ char* get_str_peak_performance(struct cpuInfo* cpu) { for(int i=0; i < cpu->num_cpus; ptr = ptr->next_cpu, i++) { flops += ptr->topo->total_cores * (get_freq(ptr->freq) * 1000000); } + if(cpu->NEON) flops = flops * 4; if(flops >= (double)1000000000000.0) snprintf(string,size,"%.2f TFLOP/s",flops/1000000000000); @@ -211,6 +261,39 @@ char* get_str_peak_performance(struct cpuInfo* cpu) { return string; } +char* get_str_features(struct cpuInfo* cpu) { + char* string = malloc(sizeof(char) * 100); //TODO: Fix + uint32_t len = 0; + + if(cpu->NEON) { + strcat(string, "NEON,"); + len += 5; + } + if(cpu->SHA1) { + strcat(string, "SHA1,"); + len += 5; + } + if(cpu->SHA2) { + strcat(string, "SHA2,"); + len += 5; + } + if(cpu->AES) { + strcat(string, "AES,"); + len += 4; + } + if(cpu->CRC32) { + strcat(string, "CRC32,"); + len += 6; + } + + if(len > 0) { + string[len-1] = '\0'; + return string; + } + else + return NULL; +} + void print_debug(struct cpuInfo* cpu) { int ncores = get_ncores_from_cpuinfo(); bool success = false; diff --git a/src/arm/midr.h b/src/arm/midr.h index edbd2aa..2d468a0 100644 --- a/src/arm/midr.h +++ b/src/arm/midr.h @@ -8,6 +8,7 @@ struct cpuInfo* get_cpu_info(); uint32_t get_nsockets(struct topology* topo); char* get_str_topology(struct cpuInfo* cpu, struct topology* topo, bool dual_socket); char* get_str_peak_performance(struct cpuInfo* cpu); +char* get_str_features(struct cpuInfo* cpu); void print_debug(struct cpuInfo* cpu); void free_topo_struct(struct topology* topo); diff --git a/src/common/cpu.h b/src/common/cpu.h index 2e418b3..9bffea2 100644 --- a/src/common/cpu.h +++ b/src/common/cpu.h @@ -93,9 +93,14 @@ struct cpuInfo { bool SSE4_2; bool FMA3; bool FMA4; + bool SHA; +#elif ARCH_ARM + bool NEON; + bool SHA1; + bool SHA2; + bool CRC32; #endif bool AES; - bool SHA; VENDOR cpu_vendor; struct uarch* arch; diff --git a/src/common/main.c b/src/common/main.c index 937e88c..b8ff5f6 100644 --- a/src/common/main.c +++ b/src/common/main.c @@ -13,7 +13,7 @@ #include "../arm/midr.h" #endif -static const char* VERSION = "0.93"; +static const char* VERSION = "0.94"; void print_help(char *argv[]) { printf("Usage: %s [--version] [--help] [--debug] [--style \"fancy\"|\"retro\"|\"legacy\"] [--color \"intel\"|\"amd\"|'R,G,B:R,G,B:R,G,B:R,G,B']\n\n", argv[0]); diff --git a/src/common/printer.c b/src/common/printer.c index 7d5695c..23fef13 100644 --- a/src/common/printer.c +++ b/src/common/printer.c @@ -61,6 +61,8 @@ enum { #ifdef ARCH_X86 ATTRIBUTE_AVX, ATTRIBUTE_FMA, +#elif ARCH_ARM + ATTRIBUTE_FEATURES, #endif ATTRIBUTE_L1i, ATTRIBUTE_L1d, @@ -86,6 +88,8 @@ static const char* ATTRIBUTE_FIELDS [] = { #ifdef ARCH_X86 "AVX:", "FMA:", +#elif ARCH_ARM + "Features: ", #endif "L1i Size:", "L1d Size:", @@ -611,6 +615,7 @@ bool print_cpufetch_arm(struct cpuInfo* cpu, STYLE s, struct colors* cs) { char* manufacturing_process = get_str_process(cpu->soc); char* soc_name = get_soc_name(cpu->soc); + char* features = get_str_features(cpu); setAttribute(art,ATTRIBUTE_SOC,soc_name); setAttribute(art,ATTRIBUTE_TECHNOLOGY,manufacturing_process); @@ -626,6 +631,9 @@ bool print_cpufetch_arm(struct cpuInfo* cpu, STYLE s, struct colors* cs) { setAttribute(art,ATTRIBUTE_UARCH,uarch); setAttribute(art,ATTRIBUTE_FREQUENCY,max_frequency); setAttribute(art,ATTRIBUTE_NCORES,n_cores); + if(features != NULL) { + setAttribute(art, ATTRIBUTE_FEATURES, features); + } setAttribute(art,ATTRIBUTE_L1i,l1i); setAttribute(art,ATTRIBUTE_L1d,l1d); setAttribute(art,ATTRIBUTE_L2,l2); @@ -634,11 +642,11 @@ bool print_cpufetch_arm(struct cpuInfo* cpu, STYLE s, struct colors* cs) { } } else { - struct cpuInfo* ptr = cpu; + struct cpuInfo* ptr = cpu; for(int i = 0; i < cpu->num_cpus; ptr = ptr->next_cpu, i++) { char* uarch = get_str_uarch(ptr); char* max_frequency = get_str_freq(ptr->freq); - char* n_cores = get_str_topology(ptr, ptr->topo, false); + char* n_cores = get_str_topology(ptr, ptr->topo, false); char* l1i = get_str_l1i(ptr->cach); char* l1d = get_str_l1d(ptr->cach); char* l2 = get_str_l2(ptr->cach); @@ -650,6 +658,9 @@ bool print_cpufetch_arm(struct cpuInfo* cpu, STYLE s, struct colors* cs) { setAttribute(art, ATTRIBUTE_UARCH, uarch); setAttribute(art, ATTRIBUTE_FREQUENCY, max_frequency); setAttribute(art, ATTRIBUTE_NCORES, n_cores); + if(features != NULL) { + setAttribute(art, ATTRIBUTE_FEATURES, features); + } setAttribute(art, ATTRIBUTE_L1i, l1i); setAttribute(art, ATTRIBUTE_L1d, l1d); setAttribute(art, ATTRIBUTE_L2, l2);