diff --git a/Makefile b/Makefile index c68385c..2194934 100644 --- a/Makefile +++ b/Makefile @@ -19,8 +19,8 @@ ifneq ($(OS),Windows_NT) CFLAGS += -DARCH_X86 else ifeq ($(arch), $(filter $(arch), ppc64el ppc64le ppc32)) SRC_DIR=src/ppc/ - SOURCE += $(COMMON_SRC) $(SRC_DIR)ppc.c $(SRC_DIR)uarch.c - HEADERS += $(COMMON_HDR) $(SRC_DIR)ppc.h $(SRC_DIR)uarch.h + SOURCE += $(COMMON_SRC) $(SRC_DIR)ppc.c $(SRC_DIR)uarch.c $(SRC_DIR)udev.c + HEADERS += $(COMMON_HDR) $(SRC_DIR)ppc.h $(SRC_DIR)uarch.h $(SRC_DIR)udev.c CFLAGS += -DARCH_PPC else # Assume ARM diff --git a/src/common/cpu.c b/src/common/cpu.c index 545b039..301e928 100644 --- a/src/common/cpu.c +++ b/src/common/cpu.c @@ -34,11 +34,9 @@ int64_t get_freq(struct frequency* freq) { #if defined(ARCH_X86) || defined(ARCH_PPC) char* get_str_cpu_name(struct cpuInfo* cpu) { - return cpu->cpu_name; + return cpu->cpu_name; } -#endif -#ifdef ARCH_X86 char* get_str_sockets(struct topology* topo) { char* string = malloc(sizeof(char) * 2); int32_t sanity_ret = snprintf(string, 2, "%d", topo->sockets); diff --git a/src/common/cpu.h b/src/common/cpu.h index 33b1b84..aa8970b 100644 --- a/src/common/cpu.h +++ b/src/common/cpu.h @@ -69,14 +69,16 @@ struct cache { struct topology { int32_t total_cores; struct cache* cach; -#ifdef ARCH_X86 - uint32_t physical_cores; +#if defined(ARCH_X86) || defined(ARCH_PPC) + uint32_t physical_cores; uint32_t logical_cores; - uint32_t smt_available; // Number of SMT that is currently enabled - uint32_t smt_supported; // Number of SMT that CPU supports (equal to smt_available if SMT is enabled) uint32_t sockets; + uint32_t smt_supported; // Number of SMT that CPU supports (equal to smt_available if SMT is enabled) +#ifdef ARCH_X86 + uint32_t smt_available; // Number of SMT that is currently enabled struct apic* apic; #endif +#endif }; struct features { @@ -143,16 +145,12 @@ struct cpuInfo { #endif }; -#ifdef ARCH_X86 +#if defined(ARCH_X86) || defined(ARCH_PPC) char* get_str_cpu_name(struct cpuInfo* cpu); char* get_str_sockets(struct topology* topo); uint32_t get_nsockets(struct topology* topo); #endif -#ifdef ARCH_PPC -char* get_str_cpu_name(struct cpuInfo* cpu); -#endif - VENDOR get_cpu_vendor(struct cpuInfo* cpu); int64_t get_freq(struct frequency* freq); diff --git a/src/common/printer.c b/src/common/printer.c index 9c3100e..c971fda 100644 --- a/src/common/printer.c +++ b/src/common/printer.c @@ -568,11 +568,11 @@ bool print_cpufetch_ppc(struct cpuInfo* cpu, STYLE s, struct colors* cs) { /*char* uarch = get_str_uarch(cpu); char* manufacturing_process = get_str_process(cpu); + */ char* sockets = get_str_sockets(cpu->topo); - char* max_frequency = get_str_freq(cpu->freq); + // char* max_frequency = get_str_freq(cpu->freq); char* n_cores = get_str_topology(cpu, cpu->topo, false); char* n_cores_dual = get_str_topology(cpu, cpu->topo, true); - */ char* cpu_name = get_str_cpu_name(cpu); /* @@ -589,7 +589,7 @@ bool print_cpufetch_ppc(struct cpuInfo* cpu, STYLE s, struct colors* cs) { } setAttribute(art,ATTRIBUTE_UARCH,uarch); setAttribute(art,ATTRIBUTE_TECHNOLOGY,manufacturing_process); - setAttribute(art,ATTRIBUTE_FREQUENCY,max_frequency); + setAttribute(art,ATTRIBUTE_FREQUENCY,max_frequency);*/ uint32_t socket_num = get_nsockets(cpu->topo); if (socket_num > 1) { setAttribute(art, ATTRIBUTE_SOCKETS, sockets); @@ -599,6 +599,7 @@ bool print_cpufetch_ppc(struct cpuInfo* cpu, STYLE s, struct colors* cs) { else { setAttribute(art,ATTRIBUTE_NCORES,n_cores); } + /* setAttribute(art,ATTRIBUTE_AVX,avx); setAttribute(art,ATTRIBUTE_FMA,fma); setAttribute(art,ATTRIBUTE_L1i,l1i); diff --git a/src/ppc/ppc.c b/src/ppc/ppc.c index 64f6255..9317cc9 100644 --- a/src/ppc/ppc.c +++ b/src/ppc/ppc.c @@ -2,11 +2,109 @@ #include #include #include +#include #include "ppc.h" +#include "udev.h" #define STRING_UNKNOWN "Unknown" +void init_topology_struct(struct topology* topo, struct cache* cach) { + topo->total_cores = 0; + topo->physical_cores = 0; + topo->logical_cores = 0; + topo->smt_supported = 0; + topo->sockets = 0; + topo->cach = cach; +} + +void init_cache_struct(struct cache* cach) { + cach->L1i = malloc(sizeof(struct cach)); + cach->L1d = malloc(sizeof(struct cach)); + cach->L2 = malloc(sizeof(struct cach)); + cach->L3 = malloc(sizeof(struct cach)); + + cach->cach_arr = malloc(sizeof(struct cach*) * 4); + cach->cach_arr[0] = cach->L1i; + cach->cach_arr[1] = cach->L1d; + cach->cach_arr[2] = cach->L2; + cach->cach_arr[3] = cach->L3; + + cach->max_cache_level = 0; + cach->L1i->exists = false; + cach->L1d->exists = false; + cach->L2->exists = false; + cach->L3->exists = false; +} + +struct cache* get_cache_info(struct cpuInfo* cpu) { + struct cache* cach = malloc(sizeof(struct cache)); + init_cache_struct(cach); + + return cach; +} + +struct topology* get_topology_info(struct cpuInfo* cpu, struct cache* cach) { + struct topology* topo = malloc(sizeof(struct topology)); + init_topology_struct(topo, cach); + + // 1. Total cores detection + if((topo->total_cores = sysconf(_SC_NPROCESSORS_ONLN)) == -1) { + perror("sysconf"); + return NULL; + } + + // To find physical cores, we use topo->total_cores and core_ids + // To find number of sockets, we use package_ids + int* core_ids = malloc(sizeof(int) * topo->total_cores); + int* package_ids = malloc(sizeof(int) * topo->total_cores); + + fill_core_ids_from_sys(core_ids, topo->total_cores); + fill_package_ids_from_sys(package_ids, topo->total_cores); + + // 2. Socket detection + int *package_ids_count = malloc(sizeof(int) * topo->total_cores); + for(int i=0; i < topo->total_cores; i++) { + package_ids_count[i] = 0; + } + for(int i=0; i < topo->total_cores; i++) { + package_ids_count[package_ids[i]]++; + } + for(int i=0; i < topo->total_cores; i++) { + if(package_ids_count[i] != 0) { + topo->sockets++; + } + } + + // 3. Physical cores detection + int *core_ids_unified = malloc(sizeof(int) * topo->total_cores); + for(int i=0; i < topo->total_cores; i++) { + core_ids_unified[i] = -1; + } + bool found = false; + for(int i=0; i < topo->total_cores; i++) { + for(int j=0; j < topo->total_cores && !found; j++) { + if(core_ids_unified[j] == core_ids[i]) found = true; + } + if(!found) { + core_ids_unified[topo->physical_cores] = core_ids[i]; + topo->physical_cores++; + } + found = false; + } + + topo->physical_cores = topo->physical_cores / topo->sockets; // only count cores on one socket + topo->logical_cores = topo->total_cores / topo->sockets; // only count threads on one socket + topo->smt_supported = topo->logical_cores / topo->physical_cores; + + free(core_ids); + free(package_ids); + free(package_ids_count); + free(core_ids_unified); + + return topo; +} + struct cpuInfo* get_cpu_info() { struct cpuInfo* cpu = malloc(sizeof(struct cpuInfo)); struct features* feat = malloc(sizeof(struct features)); @@ -20,9 +118,37 @@ struct cpuInfo* get_cpu_info() { cpu->cpu_name = malloc(sizeof(char) * strlen(STRING_UNKNOWN) + 1); snprintf(cpu->cpu_name, strlen(STRING_UNKNOWN) + 1, STRING_UNKNOWN); + cpu->cach = get_cache_info(cpu); + cpu->topo = get_topology_info(cpu, cpu->cach); + + if(cpu->cach == NULL || cpu->topo == NULL) { + return NULL; + } return cpu; } +char* get_str_topology(struct cpuInfo* cpu, struct topology* topo, bool dual_socket) { + char* string; + if(topo->smt_supported > 1) { + uint32_t size = 3+3+17+1; + string = malloc(sizeof(char)*size); + if(dual_socket) + snprintf(string, size, "%d cores (%d threads)", topo->physical_cores * topo->sockets, topo->logical_cores * topo->sockets); + else + snprintf(string, size, "%d cores (%d threads)",topo->physical_cores,topo->logical_cores); + } + else { + uint32_t size = 3+7+1; + string = malloc(sizeof(char)*size); + if(dual_socket) + snprintf(string, size, "%d cores",topo->physical_cores * topo->sockets); + else + snprintf(string, size, "%d cores",topo->physical_cores); + } + return string; +} + + void print_debug(struct cpuInfo* cpu) { printf("TODO\n"); } diff --git a/src/ppc/ppc.h b/src/ppc/ppc.h index d19ca87..1276a52 100644 --- a/src/ppc/ppc.h +++ b/src/ppc/ppc.h @@ -3,6 +3,7 @@ #include "../common/cpu.h" +struct topology* get_topology_info(struct cpuInfo* cpu, struct cache* cach); struct cpuInfo* get_cpu_info(); void print_debug(struct cpuInfo* cpu); diff --git a/src/ppc/udev.c b/src/ppc/udev.c new file mode 100644 index 0000000..c989c23 --- /dev/null +++ b/src/ppc/udev.c @@ -0,0 +1,49 @@ +#include "udev.h" + +#define _PATH_TOPO_CORE_ID "topology/core_id" +#define _PATH_TOPO_PACKAGE_ID "topology/physical_package_id" + +bool fill_core_ids_from_sys(int *core_ids, int total_cores) { + int filelen; + char* buf; + char* end; + char path[128]; + + for(int i=0; i < total_cores; i++) { + sprintf(path, "%s%s/cpu%d/%s", _PATH_SYS_SYSTEM, _PATH_SYS_CPU, i, _PATH_TOPO_CORE_ID); + if((buf = read_file(path, &filelen)) == NULL) { + perror("open"); + return false; + } + + errno = 0; + core_ids[i] = strtol(buf, &end, 10); + if(errno != 0) { + perror("strtol"); + return false; + } + free(buf); + } + + return true; +} + +bool fill_package_ids_from_sys(int* package_ids, int total_cores) { + int filelen; + char* buf; + char* end; + char path[128]; + + for(int i=0; i < total_cores; i++) { + sprintf(path, "%s%s/cpu%d/%s", _PATH_SYS_SYSTEM, _PATH_SYS_CPU, i, _PATH_TOPO_PACKAGE_ID); + buf = read_file(path, &filelen); + + errno = 0; + package_ids[i] = strtol(buf, &end, 10); + if(errno != 0) { + perror("strtol"); + return -1; + } + free(buf); + } +} diff --git a/src/ppc/udev.h b/src/ppc/udev.h new file mode 100644 index 0000000..e13ad16 --- /dev/null +++ b/src/ppc/udev.h @@ -0,0 +1,9 @@ +#ifndef __UDEV_PPC__ +#define __UDEV_PPC__ + +#include "../common/udev.h" + +bool fill_core_ids_from_sys(int *core_ids, int total_cores); +bool fill_package_ids_from_sys(int* package_ids, int total_cores); + +#endif