mirror of
https://github.com/Dr-Noob/cpufetch.git
synced 2026-03-25 07:50:40 +01:00
[v0.98][PPC] Basic support for topology detection
This commit is contained in:
4
Makefile
4
Makefile
@@ -19,8 +19,8 @@ ifneq ($(OS),Windows_NT)
|
|||||||
CFLAGS += -DARCH_X86
|
CFLAGS += -DARCH_X86
|
||||||
else ifeq ($(arch), $(filter $(arch), ppc64el ppc64le ppc32))
|
else ifeq ($(arch), $(filter $(arch), ppc64el ppc64le ppc32))
|
||||||
SRC_DIR=src/ppc/
|
SRC_DIR=src/ppc/
|
||||||
SOURCE += $(COMMON_SRC) $(SRC_DIR)ppc.c $(SRC_DIR)uarch.c
|
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
|
HEADERS += $(COMMON_HDR) $(SRC_DIR)ppc.h $(SRC_DIR)uarch.h $(SRC_DIR)udev.c
|
||||||
CFLAGS += -DARCH_PPC
|
CFLAGS += -DARCH_PPC
|
||||||
else
|
else
|
||||||
# Assume ARM
|
# Assume ARM
|
||||||
|
|||||||
@@ -36,9 +36,7 @@ int64_t get_freq(struct frequency* freq) {
|
|||||||
char* get_str_cpu_name(struct cpuInfo* cpu) {
|
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* get_str_sockets(struct topology* topo) {
|
||||||
char* string = malloc(sizeof(char) * 2);
|
char* string = malloc(sizeof(char) * 2);
|
||||||
int32_t sanity_ret = snprintf(string, 2, "%d", topo->sockets);
|
int32_t sanity_ret = snprintf(string, 2, "%d", topo->sockets);
|
||||||
|
|||||||
@@ -69,14 +69,16 @@ struct cache {
|
|||||||
struct topology {
|
struct topology {
|
||||||
int32_t total_cores;
|
int32_t total_cores;
|
||||||
struct cache* cach;
|
struct cache* cach;
|
||||||
#ifdef ARCH_X86
|
#if defined(ARCH_X86) || defined(ARCH_PPC)
|
||||||
uint32_t physical_cores;
|
uint32_t physical_cores;
|
||||||
uint32_t logical_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 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;
|
struct apic* apic;
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct features {
|
struct features {
|
||||||
@@ -143,16 +145,12 @@ struct cpuInfo {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef ARCH_X86
|
#if defined(ARCH_X86) || defined(ARCH_PPC)
|
||||||
char* get_str_cpu_name(struct cpuInfo* cpu);
|
char* get_str_cpu_name(struct cpuInfo* cpu);
|
||||||
char* get_str_sockets(struct topology* topo);
|
char* get_str_sockets(struct topology* topo);
|
||||||
uint32_t get_nsockets(struct topology* topo);
|
uint32_t get_nsockets(struct topology* topo);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ARCH_PPC
|
|
||||||
char* get_str_cpu_name(struct cpuInfo* cpu);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
VENDOR get_cpu_vendor(struct cpuInfo* cpu);
|
VENDOR get_cpu_vendor(struct cpuInfo* cpu);
|
||||||
int64_t get_freq(struct frequency* freq);
|
int64_t get_freq(struct frequency* freq);
|
||||||
|
|
||||||
|
|||||||
@@ -568,11 +568,11 @@ bool print_cpufetch_ppc(struct cpuInfo* cpu, STYLE s, struct colors* cs) {
|
|||||||
|
|
||||||
/*char* uarch = get_str_uarch(cpu);
|
/*char* uarch = get_str_uarch(cpu);
|
||||||
char* manufacturing_process = get_str_process(cpu);
|
char* manufacturing_process = get_str_process(cpu);
|
||||||
|
*/
|
||||||
char* sockets = get_str_sockets(cpu->topo);
|
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 = get_str_topology(cpu, cpu->topo, false);
|
||||||
char* n_cores_dual = get_str_topology(cpu, cpu->topo, true);
|
char* n_cores_dual = get_str_topology(cpu, cpu->topo, true);
|
||||||
*/
|
|
||||||
char* cpu_name = get_str_cpu_name(cpu);
|
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_UARCH,uarch);
|
||||||
setAttribute(art,ATTRIBUTE_TECHNOLOGY,manufacturing_process);
|
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);
|
uint32_t socket_num = get_nsockets(cpu->topo);
|
||||||
if (socket_num > 1) {
|
if (socket_num > 1) {
|
||||||
setAttribute(art, ATTRIBUTE_SOCKETS, sockets);
|
setAttribute(art, ATTRIBUTE_SOCKETS, sockets);
|
||||||
@@ -599,6 +599,7 @@ bool print_cpufetch_ppc(struct cpuInfo* cpu, STYLE s, struct colors* cs) {
|
|||||||
else {
|
else {
|
||||||
setAttribute(art,ATTRIBUTE_NCORES,n_cores);
|
setAttribute(art,ATTRIBUTE_NCORES,n_cores);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
setAttribute(art,ATTRIBUTE_AVX,avx);
|
setAttribute(art,ATTRIBUTE_AVX,avx);
|
||||||
setAttribute(art,ATTRIBUTE_FMA,fma);
|
setAttribute(art,ATTRIBUTE_FMA,fma);
|
||||||
setAttribute(art,ATTRIBUTE_L1i,l1i);
|
setAttribute(art,ATTRIBUTE_L1i,l1i);
|
||||||
|
|||||||
126
src/ppc/ppc.c
126
src/ppc/ppc.c
@@ -2,11 +2,109 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "ppc.h"
|
#include "ppc.h"
|
||||||
|
#include "udev.h"
|
||||||
|
|
||||||
#define STRING_UNKNOWN "Unknown"
|
#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* get_cpu_info() {
|
||||||
struct cpuInfo* cpu = malloc(sizeof(struct cpuInfo));
|
struct cpuInfo* cpu = malloc(sizeof(struct cpuInfo));
|
||||||
struct features* feat = malloc(sizeof(struct features));
|
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);
|
cpu->cpu_name = malloc(sizeof(char) * strlen(STRING_UNKNOWN) + 1);
|
||||||
snprintf(cpu->cpu_name, strlen(STRING_UNKNOWN) + 1, STRING_UNKNOWN);
|
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;
|
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) {
|
void print_debug(struct cpuInfo* cpu) {
|
||||||
printf("TODO\n");
|
printf("TODO\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "../common/cpu.h"
|
#include "../common/cpu.h"
|
||||||
|
|
||||||
|
struct topology* get_topology_info(struct cpuInfo* cpu, struct cache* cach);
|
||||||
struct cpuInfo* get_cpu_info();
|
struct cpuInfo* get_cpu_info();
|
||||||
void print_debug(struct cpuInfo* cpu);
|
void print_debug(struct cpuInfo* cpu);
|
||||||
|
|
||||||
|
|||||||
49
src/ppc/udev.c
Normal file
49
src/ppc/udev.c
Normal file
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
9
src/ppc/udev.h
Normal file
9
src/ppc/udev.h
Normal file
@@ -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
|
||||||
Reference in New Issue
Block a user