mirror of
https://github.com/Dr-Noob/cpufetch.git
synced 2026-03-25 07:50:40 +01:00
[v1.00] Merge latest commits from master branch
This commit is contained in:
269
src/arm/midr.c
269
src/arm/midr.c
@@ -4,8 +4,19 @@
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <sys/auxv.h>
|
||||
#include <asm/hwcap.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/auxv.h>
|
||||
#include <asm/hwcap.h>
|
||||
#elif defined __APPLE__ || __MACH__
|
||||
#include "sysctl.h"
|
||||
// From Linux kernel: arch/arm64/include/asm/cputype.h
|
||||
#define MIDR_APPLE_M1_ICESTORM 0x610F0220
|
||||
#define MIDR_APPLE_M1_FIRESTORM 0x610F0230
|
||||
#ifndef CPUFAMILY_ARM_FIRESTORM_ICESTORM
|
||||
#define CPUFAMILY_ARM_FIRESTORM_ICESTORM 0x1B588BB3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "../common/global.h"
|
||||
#include "udev.h"
|
||||
@@ -13,29 +24,12 @@
|
||||
#include "uarch.h"
|
||||
#include "soc.h"
|
||||
|
||||
#define STRING_UNKNOWN "Unknown"
|
||||
|
||||
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;
|
||||
bool cores_are_equal(int c1pos, int c2pos, uint32_t* midr_array, int32_t* freq_array) {
|
||||
return midr_array[c1pos] == midr_array[c2pos] && freq_array[c1pos] == freq_array[c2pos];
|
||||
}
|
||||
|
||||
struct cache* get_cache_info(struct cpuInfo* cpu) {
|
||||
struct cache* cach = malloc(sizeof(struct cache));
|
||||
struct cache* get_cache_info(struct cpuInfo* cpu) {
|
||||
struct cache* cach = emalloc(sizeof(struct cache));
|
||||
init_cache_struct(cach);
|
||||
|
||||
cach->max_cache_level = 2;
|
||||
@@ -49,45 +43,60 @@ struct cache* get_cache_info(struct cpuInfo* cpu) {
|
||||
}
|
||||
|
||||
struct frequency* get_frequency_info(uint32_t core) {
|
||||
struct frequency* freq = malloc(sizeof(struct frequency));
|
||||
struct frequency* freq = emalloc(sizeof(struct frequency));
|
||||
|
||||
freq->base = UNKNOWN_FREQ;
|
||||
freq->max = get_max_freq_from_file(core, false);
|
||||
freq->max = get_max_freq_from_file(core);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
struct topology* get_topology_info(struct cpuInfo* cpu, struct cache* cach, uint32_t* midr_array, int socket_idx, int ncores) {
|
||||
struct topology* topo = malloc(sizeof(struct topology));
|
||||
struct topology* get_topology_info(struct cpuInfo* cpu, struct cache* cach, uint32_t* midr_array, int32_t* freq_array, int socket_idx, int ncores) {
|
||||
struct topology* topo = emalloc(sizeof(struct topology));
|
||||
init_topology_struct(topo, cach);
|
||||
|
||||
topo->cach = cach;
|
||||
topo->total_cores = 0;
|
||||
|
||||
int sockets_seen = 0;
|
||||
int first_core_idx = 0;
|
||||
int currrent_core_idx = 0;
|
||||
int cores_in_socket = 0;
|
||||
|
||||
|
||||
while(socket_idx + 1 > sockets_seen) {
|
||||
if(midr_array[first_core_idx] == midr_array[currrent_core_idx] && currrent_core_idx < ncores) {
|
||||
if(currrent_core_idx < ncores && cores_are_equal(first_core_idx, currrent_core_idx, midr_array, freq_array)) {
|
||||
currrent_core_idx++;
|
||||
cores_in_socket++;
|
||||
}
|
||||
else {
|
||||
topo->total_cores = cores_in_socket;
|
||||
topo->total_cores = cores_in_socket;
|
||||
cores_in_socket = 0;
|
||||
first_core_idx = currrent_core_idx;
|
||||
sockets_seen++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return topo;
|
||||
}
|
||||
|
||||
bool cores_are_equal(int c1pos, int c2pos, uint32_t* midr_array, int32_t* freq_array) {
|
||||
return midr_array[c1pos] == midr_array[c2pos] && freq_array[c1pos] == freq_array[c2pos];
|
||||
int64_t get_peak_performance(struct cpuInfo* cpu) {
|
||||
struct cpuInfo* ptr = cpu;
|
||||
|
||||
//First check we have consistent data
|
||||
for(int i=0; i < cpu->num_cpus; ptr = ptr->next_cpu, i++) {
|
||||
if(get_freq(ptr->freq) == UNKNOWN_FREQ) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t flops = 0;
|
||||
|
||||
ptr = 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->feat->NEON) flops = flops * 4;
|
||||
|
||||
return flops;
|
||||
}
|
||||
|
||||
|
||||
uint32_t fill_ids_from_midr(uint32_t* midr_array, int32_t* freq_array, uint32_t* ids_array, int len) {
|
||||
uint32_t latest_id = 0;
|
||||
bool found;
|
||||
@@ -128,17 +137,18 @@ void init_cpu_info(struct cpuInfo* cpu) {
|
||||
// ARM32 https://elixir.bootlin.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h
|
||||
// ARM64 https://elixir.bootlin.com/linux/latest/source/arch/arm64/include/uapi/asm/hwcap.h
|
||||
struct features* get_features_info() {
|
||||
struct features* feat = malloc(sizeof(struct features));
|
||||
struct features* feat = emalloc(sizeof(struct features));
|
||||
bool *ptr = &(feat->AES);
|
||||
for(uint32_t i = 0; i < sizeof(struct features)/sizeof(bool); i++, ptr++) {
|
||||
*ptr = false;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
errno = 0;
|
||||
long hwcaps = getauxval(AT_HWCAP);
|
||||
|
||||
|
||||
if(errno == ENOENT) {
|
||||
printWarn("Unable to retrieve AT_HWCAP using getauxval");
|
||||
printWarn("Unable to retrieve AT_HWCAP using getauxval");
|
||||
}
|
||||
#ifdef __aarch64__
|
||||
else {
|
||||
@@ -152,7 +162,7 @@ struct features* get_features_info() {
|
||||
else {
|
||||
feat->NEON = hwcaps & HWCAP_NEON;
|
||||
}
|
||||
|
||||
|
||||
hwcaps = getauxval(AT_HWCAP2);
|
||||
if(errno == ENOENT) {
|
||||
printWarn("Unable to retrieve AT_HWCAP2 using getauxval");
|
||||
@@ -163,114 +173,157 @@ struct features* get_features_info() {
|
||||
feat->SHA1 = hwcaps & HWCAP2_SHA1;
|
||||
feat->SHA2 = hwcaps & HWCAP2_SHA2;
|
||||
}
|
||||
#endif
|
||||
#endif // ifdef __aarch64__
|
||||
#elif defined __APPLE__ || __MACH__
|
||||
// Must be M1
|
||||
feat->AES = true;
|
||||
feat->CRC32 = true;
|
||||
feat->SHA1 = true;
|
||||
feat->SHA2 = true;
|
||||
feat->NEON = true;
|
||||
#endif // ifdef __linux__
|
||||
|
||||
return feat;
|
||||
}
|
||||
|
||||
struct cpuInfo* get_cpu_info() {
|
||||
struct cpuInfo* cpu = malloc(sizeof(struct cpuInfo));
|
||||
#ifdef __linux__
|
||||
struct cpuInfo* get_cpu_info_linux(struct cpuInfo* cpu) {
|
||||
init_cpu_info(cpu);
|
||||
|
||||
int ncores = get_ncores_from_cpuinfo();
|
||||
bool success = false;
|
||||
int32_t* freq_array = malloc(sizeof(uint32_t) * ncores);
|
||||
uint32_t* midr_array = malloc(sizeof(uint32_t) * ncores);
|
||||
uint32_t* ids_array = malloc(sizeof(uint32_t) * ncores);
|
||||
int32_t* freq_array = emalloc(sizeof(uint32_t) * ncores);
|
||||
uint32_t* midr_array = emalloc(sizeof(uint32_t) * ncores);
|
||||
uint32_t* ids_array = emalloc(sizeof(uint32_t) * ncores);
|
||||
|
||||
for(int i=0; i < ncores; i++) {
|
||||
midr_array[i] = get_midr_from_cpuinfo(i, &success);
|
||||
|
||||
|
||||
if(!success) {
|
||||
printWarn("Unable to fetch MIDR for core %d. This is probably because the core is offline", i);
|
||||
midr_array[i] = midr_array[0];
|
||||
}
|
||||
|
||||
freq_array[i] = get_max_freq_from_file(i, false);
|
||||
|
||||
freq_array[i] = get_max_freq_from_file(i);
|
||||
if(freq_array[i] == UNKNOWN_FREQ) {
|
||||
printWarn("Unable to fetch max frequency for core %d. This is probably because the core is offline", i);
|
||||
freq_array[i] = freq_array[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32_t sockets = fill_ids_from_midr(midr_array, freq_array, ids_array, ncores);
|
||||
|
||||
|
||||
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 = emalloc(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->midr = midr_array[midr_idx];
|
||||
ptr->arch = get_uarch_from_midr(ptr->midr, ptr);
|
||||
|
||||
|
||||
ptr->feat = get_features_info();
|
||||
ptr->freq = get_frequency_info(midr_idx);
|
||||
ptr->cach = get_cache_info(ptr);
|
||||
ptr->topo = get_topology_info(ptr, ptr->cach, midr_array, i, ncores);
|
||||
ptr->topo = get_topology_info(ptr, ptr->cach, midr_array, freq_array, i, ncores);
|
||||
}
|
||||
|
||||
|
||||
cpu->num_cpus = sockets;
|
||||
cpu->hv = malloc(sizeof(struct hypervisor));
|
||||
cpu->hv = emalloc(sizeof(struct hypervisor));
|
||||
cpu->hv->present = false;
|
||||
cpu->soc = get_soc();
|
||||
cpu->soc = get_soc();
|
||||
cpu->peak_performance = get_peak_performance(cpu);
|
||||
|
||||
return cpu;
|
||||
}
|
||||
|
||||
#elif defined __APPLE__ || __MACH__
|
||||
void fill_cpu_info_firestorm_icestorm(struct cpuInfo* cpu) {
|
||||
// 1. Fill ICESTORM
|
||||
struct cpuInfo* ice = cpu;
|
||||
|
||||
ice->midr = MIDR_APPLE_M1_ICESTORM;
|
||||
ice->arch = get_uarch_from_midr(ice->midr, ice);
|
||||
ice->cach = get_cache_info(ice);
|
||||
ice->feat = get_features_info();
|
||||
ice->topo = malloc(sizeof(struct topology));
|
||||
ice->topo->cach = ice->cach;
|
||||
ice->topo->total_cores = 4;
|
||||
ice->freq = malloc(sizeof(struct frequency));
|
||||
ice->freq->base = UNKNOWN_FREQ;
|
||||
ice->freq->max = 2064;
|
||||
ice->hv = malloc(sizeof(struct hypervisor));
|
||||
ice->hv->present = false;
|
||||
ice->next_cpu = malloc(sizeof(struct cpuInfo));
|
||||
|
||||
// 2. Fill FIRESTORM
|
||||
struct cpuInfo* fire = ice->next_cpu;
|
||||
fire->midr = MIDR_APPLE_M1_FIRESTORM;
|
||||
fire->arch = get_uarch_from_midr(fire->midr, fire);
|
||||
fire->cach = get_cache_info(fire);
|
||||
fire->feat = get_features_info();
|
||||
fire->topo = malloc(sizeof(struct topology));
|
||||
fire->topo->cach = fire->cach;
|
||||
fire->topo->total_cores = 4;
|
||||
fire->freq = malloc(sizeof(struct frequency));
|
||||
fire->freq->base = UNKNOWN_FREQ;
|
||||
fire->freq->max = 3200;
|
||||
fire->hv = malloc(sizeof(struct hypervisor));
|
||||
fire->hv->present = false;
|
||||
fire->next_cpu = NULL;
|
||||
}
|
||||
|
||||
struct cpuInfo* get_cpu_info_mach(struct cpuInfo* cpu) {
|
||||
uint32_t cpu_family = get_sys_info_by_name("hw.cpufamily");
|
||||
|
||||
// Manually fill the cpuInfo assuming that the CPU
|
||||
// is a ARM_FIRESTORM_ICESTORM (Apple M1)
|
||||
if(cpu_family == CPUFAMILY_ARM_FIRESTORM_ICESTORM) {
|
||||
cpu->num_cpus = 2;
|
||||
cpu->soc = get_soc();
|
||||
fill_cpu_info_firestorm_icestorm(cpu);
|
||||
cpu->peak_performance = get_peak_performance(cpu);
|
||||
}
|
||||
else {
|
||||
printBug("Found invalid cpu_family: 0x%.8X", cpu_family);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return cpu;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct cpuInfo* get_cpu_info() {
|
||||
struct cpuInfo* cpu = malloc(sizeof(struct cpuInfo));
|
||||
init_cpu_info(cpu);
|
||||
|
||||
#ifdef __linux__
|
||||
return get_cpu_info_linux(cpu);
|
||||
#elif defined __APPLE__ || __MACH__
|
||||
return get_cpu_info_mach(cpu);
|
||||
#endif
|
||||
}
|
||||
|
||||
char* get_str_topology(struct cpuInfo* cpu, struct topology* topo, bool dual_socket) {
|
||||
uint32_t size = 3+7+1;
|
||||
char* string = malloc(sizeof(char)*size);
|
||||
char* string = emalloc(sizeof(char)*size);
|
||||
snprintf(string, size, "%d cores", topo->total_cores);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
char* get_str_peak_performance(struct cpuInfo* cpu) {
|
||||
//7 for GFLOP/s and 6 for digits,eg 412.14
|
||||
uint32_t size = 7+6+1+1;
|
||||
assert(strlen(STRING_UNKNOWN)+1 <= size);
|
||||
char* string = malloc(sizeof(char)*size);
|
||||
struct cpuInfo* ptr = cpu;
|
||||
|
||||
//First check we have consistent data
|
||||
for(int i=0; i < cpu->num_cpus; ptr = ptr->next_cpu, i++) {
|
||||
if(get_freq(ptr->freq) == UNKNOWN_FREQ) {
|
||||
snprintf(string, strlen(STRING_UNKNOWN)+1, STRING_UNKNOWN);
|
||||
return string;
|
||||
}
|
||||
}
|
||||
|
||||
double flops = 0.0;
|
||||
|
||||
ptr = 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->feat->NEON) flops = flops * 4;
|
||||
|
||||
if(flops >= (double)1000000000000.0)
|
||||
snprintf(string,size,"%.2f TFLOP/s",flops/1000000000000);
|
||||
else if(flops >= 1000000000.0)
|
||||
snprintf(string,size,"%.2f GFLOP/s",flops/1000000000);
|
||||
else
|
||||
snprintf(string,size,"%.2f MFLOP/s",flops/1000000);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
char* get_str_features(struct cpuInfo* cpu) {
|
||||
struct features* feat = cpu->feat;
|
||||
char* string = malloc(sizeof(char) * 25);
|
||||
struct features* feat = cpu->feat;
|
||||
uint32_t max_len = strlen("NEON,SHA1,SHA2,AES,CRC32,") + 1;
|
||||
uint32_t len = 0;
|
||||
|
||||
char* string = ecalloc(max_len, sizeof(char));
|
||||
|
||||
if(feat->NEON) {
|
||||
strcat(string, "NEON,");
|
||||
len += 5;
|
||||
@@ -291,38 +344,38 @@ char* get_str_features(struct cpuInfo* cpu) {
|
||||
strcat(string, "CRC32,");
|
||||
len += 6;
|
||||
}
|
||||
|
||||
|
||||
if(len > 0) {
|
||||
string[len-1] = '\0';
|
||||
return string;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void print_debug(struct cpuInfo* cpu) {
|
||||
int ncores = get_ncores_from_cpuinfo();
|
||||
bool success = false;
|
||||
|
||||
|
||||
for(int i=0; i < ncores; i++) {
|
||||
printf("[Core %d] ", i);
|
||||
long freq = get_max_freq_from_file(i, false);
|
||||
long freq = get_max_freq_from_file(i);
|
||||
uint32_t midr = get_midr_from_cpuinfo(i, &success);
|
||||
if(!success) {
|
||||
printWarn("Unable to fetch MIDR for core %d. This is probably because the core is offline", i);
|
||||
printf("0x%.8X ", get_midr_from_cpuinfo(0, &success));
|
||||
}
|
||||
else {
|
||||
printf("0x%.8X ", midr);
|
||||
printf("0x%.8X ", midr);
|
||||
}
|
||||
if(freq == UNKNOWN_FREQ) {
|
||||
printWarn("Unable to fetch max frequency for core %d. This is probably because the core is offline", i);
|
||||
printf("%ld MHz\n", get_max_freq_from_file(0, false));
|
||||
printf("%ld MHz\n", get_max_freq_from_file(0));
|
||||
}
|
||||
else {
|
||||
printf("%ld MHz\n", freq);
|
||||
printf("%ld MHz\n", freq);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void free_topo_struct(struct topology* topo) {
|
||||
|
||||
@@ -7,7 +7,6 @@ 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);
|
||||
|
||||
367
src/arm/soc.c
367
src/arm/soc.c
@@ -9,7 +9,7 @@
|
||||
#include "../common/global.h"
|
||||
|
||||
#define min(a,b) (((a)<(b))?(a):(b))
|
||||
#define STRING_UNKNOWN "Unknown"
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
|
||||
static char* soc_trademark_string[] = {
|
||||
[SOC_VENDOR_SNAPDRAGON] = "Snapdragon ",
|
||||
@@ -17,6 +17,14 @@ static char* soc_trademark_string[] = {
|
||||
[SOC_VENDOR_EXYNOS] = "Exynos ",
|
||||
[SOC_VENDOR_KIRIN] = "Kirin ",
|
||||
[SOC_VENDOR_BROADCOM] = "Broadcom BCM",
|
||||
[SOC_VENDOR_APPLE] = "Apple "
|
||||
};
|
||||
|
||||
static char* soc_rpi_string[] = {
|
||||
"BCM2835",
|
||||
"BCM2836",
|
||||
"BCM2837",
|
||||
"BCM2711"
|
||||
};
|
||||
|
||||
void fill_soc(struct system_on_chip* soc, char* soc_name, SOC soc_model, int32_t process) {
|
||||
@@ -24,34 +32,34 @@ void fill_soc(struct system_on_chip* soc, char* soc_name, SOC soc_model, int32_t
|
||||
soc->soc_vendor = get_soc_vendor_from_soc(soc_model);
|
||||
soc->process = process;
|
||||
int len = strlen(soc_name) + strlen(soc_trademark_string[soc->soc_vendor]) + 1;
|
||||
soc->soc_name = malloc(sizeof(char) * len);
|
||||
soc->soc_name = emalloc(sizeof(char) * len);
|
||||
memset(soc->soc_name, 0, sizeof(char) * len);
|
||||
sprintf(soc->soc_name, "%s%s", soc_trademark_string[soc->soc_vendor], soc_name);
|
||||
sprintf(soc->soc_name, "%s%s", soc_trademark_string[soc->soc_vendor], soc_name);
|
||||
}
|
||||
|
||||
bool match_soc(struct system_on_chip* soc, char* raw_name, char* expected_name, char* soc_name, SOC soc_model, int32_t process) {
|
||||
if(strlen(raw_name) > strlen(expected_name))
|
||||
return false;
|
||||
|
||||
|
||||
int len = strlen(raw_name);
|
||||
if(strncmp(raw_name, expected_name, len) != 0) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
fill_soc(soc, soc_name, soc_model, process);
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
char* toupperstr(char* str) {
|
||||
int len = strlen(str) + 1;
|
||||
char* ret = malloc(sizeof(char) * len);
|
||||
char* ret = emalloc(sizeof(char) * len);
|
||||
memset(ret, 0, sizeof(char) * len);
|
||||
|
||||
|
||||
for(int i=0; i < len; i++) {
|
||||
ret[i] = toupper((unsigned char) str[i]);
|
||||
ret[i] = toupper((unsigned char) str[i]);
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -59,6 +67,12 @@ char* toupperstr(char* str) {
|
||||
#define SOC_EQ(raw_name, expected_name, soc_name, soc_model, soc, process) \
|
||||
else if (match_soc(soc, raw_name, expected_name, soc_name, soc_model, process)) return true;
|
||||
#define SOC_END else { return false; }
|
||||
// Exynos special define
|
||||
#define SOC_EXY_EQ(raw_name, tmpsoc, soc_name, soc_model, soc, process) \
|
||||
sprintf(tmpsoc, "exynos%s", soc_name); \
|
||||
if (match_soc(soc, raw_name, tmpsoc, soc_name, soc_model, process)) return true; \
|
||||
sprintf(tmpsoc, "universal%s", soc_name); \
|
||||
if (match_soc(soc, raw_name, tmpsoc, soc_name, soc_model, process)) return true;
|
||||
|
||||
// https://en.wikipedia.org/wiki/Raspberry_Pi
|
||||
// http://phonedb.net/index.php?m=processor&id=562&c=broadcom_bcm21663
|
||||
@@ -68,22 +82,22 @@ bool match_broadcom(char* soc_name, struct system_on_chip* soc) {
|
||||
|
||||
if((tmp = strstr(soc_name, "BCM")) == NULL)
|
||||
return false;
|
||||
|
||||
|
||||
SOC_START
|
||||
SOC_EQ(tmp, "BCM2835", "2835", SOC_BCM_2835, soc, 65)
|
||||
SOC_EQ(tmp, "BCM2836", "2836", SOC_BCM_2836, soc, 40)
|
||||
SOC_EQ(tmp, "BCM2837", "2837", SOC_BCM_2837, soc, 40)
|
||||
SOC_EQ(tmp, "BCM2837B0", "2837B0", SOC_BCM_2837B0, soc, 40)
|
||||
SOC_EQ(tmp, "BCM2711", "2711", SOC_BCM_2711, soc, 28)
|
||||
SOC_EQ(tmp, "BCM21553", "21553", SOC_BCM_21553, soc, 65)
|
||||
SOC_EQ(tmp, "BCM21553-Thunderbird", "21553 Thunderbird", SOC_BCM_21553T, soc, 65)
|
||||
SOC_EQ(tmp, "BCM21663", "21663", SOC_BCM_21663, soc, 40)
|
||||
SOC_EQ(tmp, "BCM21664", "21664", SOC_BCM_21664, soc, 40)
|
||||
SOC_EQ(tmp, "BCM28155", "28155", SOC_BCM_28155, soc, 40)
|
||||
SOC_EQ(tmp, "BCM23550", "23550", SOC_BCM_23550, soc, 40)
|
||||
SOC_EQ(tmp, "BCM28145", "28145", SOC_BCM_28145, soc, 40)
|
||||
SOC_EQ(tmp, "BCM2157", "2157", SOC_BCM_2157, soc, 65)
|
||||
SOC_EQ(tmp, "BCM21654", "21654", SOC_BCM_21654, soc, 40)
|
||||
SOC_EQ(tmp, "BCM2835", "2835", SOC_BCM_2835, soc, 65)
|
||||
SOC_EQ(tmp, "BCM2836", "2836", SOC_BCM_2836, soc, 40)
|
||||
SOC_EQ(tmp, "BCM2837", "2837", SOC_BCM_2837, soc, 40)
|
||||
SOC_EQ(tmp, "BCM2837B0", "2837B0", SOC_BCM_2837B0, soc, 40)
|
||||
SOC_EQ(tmp, "BCM2711", "2711", SOC_BCM_2711, soc, 28)
|
||||
SOC_EQ(tmp, "BCM21553", "21553", SOC_BCM_21553, soc, 65)
|
||||
SOC_EQ(tmp, "BCM21553-Thunderbird", "21553 Thunderbird", SOC_BCM_21553T, soc, 65)
|
||||
SOC_EQ(tmp, "BCM21663", "21663", SOC_BCM_21663, soc, 40)
|
||||
SOC_EQ(tmp, "BCM21664", "21664", SOC_BCM_21664, soc, 40)
|
||||
SOC_EQ(tmp, "BCM28155", "28155", SOC_BCM_28155, soc, 40)
|
||||
SOC_EQ(tmp, "BCM23550", "23550", SOC_BCM_23550, soc, 40)
|
||||
SOC_EQ(tmp, "BCM28145", "28145", SOC_BCM_28145, soc, 40)
|
||||
SOC_EQ(tmp, "BCM2157", "2157", SOC_BCM_2157, soc, 65)
|
||||
SOC_EQ(tmp, "BCM21654", "21654", SOC_BCM_21654, soc, 40)
|
||||
SOC_END
|
||||
}
|
||||
|
||||
@@ -94,7 +108,7 @@ bool match_hisilicon(char* soc_name, struct system_on_chip* soc) {
|
||||
|
||||
if((tmp = strstr(soc_name, "Hi")) == NULL)
|
||||
return false;
|
||||
|
||||
|
||||
SOC_START
|
||||
SOC_EQ(tmp, "Hi3620GFC", "K3V2", SOC_HISILICON_3620, soc, 40)
|
||||
//SOC_EQ(tmp, "?", "K3V2E", SOC_KIRIN, soc, ?)
|
||||
@@ -130,63 +144,75 @@ bool match_hisilicon(char* soc_name, struct system_on_chip* soc) {
|
||||
bool match_exynos(char* soc_name, struct system_on_chip* soc) {
|
||||
char* tmp;
|
||||
|
||||
if((tmp = strstr(soc_name, "universal")) == NULL)
|
||||
return false;
|
||||
|
||||
if((tmp = strstr(soc_name, "universal")) != NULL);
|
||||
else if((tmp = strstr(soc_name, "exynos")) != NULL);
|
||||
else return false;
|
||||
|
||||
// Because exynos are recently using "exynosXXXX" instead
|
||||
// of "universalXXXX" as codenames, SOC_EXY_EQ will check for
|
||||
// both cases, since it seems that there are some SoCs that
|
||||
// can appear with both codenames
|
||||
|
||||
// Used by SOC_EXY_EQ
|
||||
char tmpsoc[14];
|
||||
|
||||
SOC_START
|
||||
// universalXXXX //
|
||||
SOC_EQ(tmp, "universal3475", "3475", SOC_EXYNOS_3475, soc, 28)
|
||||
SOC_EQ(tmp, "universal4210", "4210", SOC_EXYNOS_4210, soc, 45)
|
||||
SOC_EQ(tmp, "universal4212", "4212", SOC_EXYNOS_4212, soc, 32)
|
||||
SOC_EQ(tmp, "universal4412", "4412", SOC_EXYNOS_4412, soc, 32)
|
||||
SOC_EQ(tmp, "universal5250", "5250", SOC_EXYNOS_5250, soc, 32)
|
||||
SOC_EQ(tmp, "universal5410", "5410", SOC_EXYNOS_5410, soc, 28)
|
||||
SOC_EQ(tmp, "universal5420", "5420", SOC_EXYNOS_5420, soc, 28)
|
||||
SOC_EQ(tmp, "universal5422", "5422", SOC_EXYNOS_5422, soc, 28)
|
||||
SOC_EQ(tmp, "universal5430", "5430", SOC_EXYNOS_5430, soc, 20)
|
||||
SOC_EQ(tmp, "universal5433", "5433", SOC_EXYNOS_5433, soc, 20)
|
||||
SOC_EQ(tmp, "universal5260", "5260", SOC_EXYNOS_5260, soc, 28)
|
||||
SOC_EQ(tmp, "universal7270", "7270", SOC_EXYNOS_7270, soc, 14)
|
||||
SOC_EQ(tmp, "universal7420", "7420", SOC_EXYNOS_7420, soc, 14)
|
||||
SOC_EQ(tmp, "universal7570", "7570", SOC_EXYNOS_7570, soc, 14)
|
||||
SOC_EQ(tmp, "universal7870", "7870", SOC_EXYNOS_7870, soc, 14)
|
||||
SOC_EQ(tmp, "universal7872", "7872", SOC_EXYNOS_7872, soc, 14)
|
||||
SOC_EQ(tmp, "universal7880", "7880", SOC_EXYNOS_7880, soc, 14)
|
||||
SOC_EQ(tmp, "universal7884", "7884", SOC_EXYNOS_7884, soc, 14)
|
||||
SOC_EQ(tmp, "universal7885", "7885", SOC_EXYNOS_7885, soc, 14)
|
||||
SOC_EQ(tmp, "universal7904", "7904", SOC_EXYNOS_7904, soc, 14)
|
||||
SOC_EQ(tmp, "universal8890", "8890", SOC_EXYNOS_8890, soc, 14)
|
||||
SOC_EQ(tmp, "universal8895", "8895", SOC_EXYNOS_8895, soc, 10)
|
||||
SOC_EQ(tmp, "universal9110", "9110", SOC_EXYNOS_9110, soc, 14)
|
||||
SOC_EQ(tmp, "universal9609", "9609", SOC_EXYNOS_9609, soc, 10)
|
||||
SOC_EQ(tmp, "universal9610", "9610", SOC_EXYNOS_9610, soc, 10)
|
||||
SOC_EQ(tmp, "universal9611", "9611", SOC_EXYNOS_9611, soc, 10)
|
||||
SOC_EQ(tmp, "universal9810", "9810", SOC_EXYNOS_9810, soc, 10)
|
||||
SOC_EQ(tmp, "universal9820", "9820", SOC_EXYNOS_9820, soc, 8)
|
||||
SOC_EQ(tmp, "universal9825", "9825", SOC_EXYNOS_9825, soc, 7)
|
||||
// New exynos. Dont know if they will work //
|
||||
SOC_EQ(tmp, "universal1080", "1080", SOC_EXYNOS_1080, soc, 5)
|
||||
SOC_EQ(tmp, "universal990", "990", SOC_EXYNOS_990, soc, 7)
|
||||
SOC_EQ(tmp, "universal980", "980", SOC_EXYNOS_980, soc, 8)
|
||||
SOC_EQ(tmp, "universal880", "880", SOC_EXYNOS_880, soc, 8)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "3475", SOC_EXYNOS_3475, soc, 28)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "4210", SOC_EXYNOS_4210, soc, 45)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "4212", SOC_EXYNOS_4212, soc, 32)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "4412", SOC_EXYNOS_4412, soc, 32)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "5250", SOC_EXYNOS_5250, soc, 32)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "5410", SOC_EXYNOS_5410, soc, 28)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "5420", SOC_EXYNOS_5420, soc, 28)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "5422", SOC_EXYNOS_5422, soc, 28)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "5430", SOC_EXYNOS_5430, soc, 20)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "5433", SOC_EXYNOS_5433, soc, 20)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "5260", SOC_EXYNOS_5260, soc, 28)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "7270", SOC_EXYNOS_7270, soc, 14)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "7420", SOC_EXYNOS_7420, soc, 14)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "7570", SOC_EXYNOS_7570, soc, 14)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "7570", SOC_EXYNOS_7570, soc, 14)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "7870", SOC_EXYNOS_7870, soc, 14)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "7870", SOC_EXYNOS_7870, soc, 14)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "7872", SOC_EXYNOS_7872, soc, 14)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "7880", SOC_EXYNOS_7880, soc, 14)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "7884", SOC_EXYNOS_7884, soc, 14)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "7885", SOC_EXYNOS_7885, soc, 14)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "7904", SOC_EXYNOS_7904, soc, 14)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "8890", SOC_EXYNOS_8890, soc, 14)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "8895", SOC_EXYNOS_8895, soc, 10)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "9110", SOC_EXYNOS_9110, soc, 14)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "9609", SOC_EXYNOS_9609, soc, 10)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "9610", SOC_EXYNOS_9610, soc, 10)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "9611", SOC_EXYNOS_9611, soc, 10)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "9810", SOC_EXYNOS_9810, soc, 10)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "9820", SOC_EXYNOS_9820, soc, 8)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "9825", SOC_EXYNOS_9825, soc, 7)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "1080", SOC_EXYNOS_1080, soc, 5)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "990", SOC_EXYNOS_990, soc, 7)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "980", SOC_EXYNOS_980, soc, 8)
|
||||
SOC_EXY_EQ(tmp, tmpsoc, "880", SOC_EXYNOS_880, soc, 8)
|
||||
SOC_END
|
||||
}
|
||||
|
||||
bool match_mediatek(char* soc_name, struct system_on_chip* soc) {
|
||||
char* tmp;
|
||||
char* soc_name_upper = toupperstr(soc_name);
|
||||
|
||||
if((tmp = strstr(soc_name, "MT")) == NULL)
|
||||
if((tmp = strstr(soc_name_upper, "MT")) == NULL)
|
||||
return false;
|
||||
|
||||
|
||||
SOC_START
|
||||
// Dimensity //
|
||||
SOC_EQ(tmp, "MT6889", "Dimensity 1000", SOC_MTK_MT6889, soc, 7)
|
||||
SOC_EQ(tmp, "MT6885Z", "Dimensity 1000L", SOC_MTK_MT6885Z, soc, 7)
|
||||
//SOC_EQ(tmp, "?", "Dimensity 700", SOC_MTK_, soc, 7)
|
||||
SOC_EQ(tmp, "MT6853", "Dimensity 720", SOC_MTK_MT6853, soc, 7)
|
||||
SOC_EQ(tmp, "MT6893", "Dimensity 1200", SOC_MTK_MT6893, soc, 6)
|
||||
SOC_EQ(tmp, "MT6891", "Dimensity 1100", SOC_MTK_MT6891, soc, 6)
|
||||
SOC_EQ(tmp, "MT6889", "Dimensity 1000", SOC_MTK_MT6889, soc, 7)
|
||||
SOC_EQ(tmp, "MT6885Z", "Dimensity 1000L", SOC_MTK_MT6885Z, soc, 7)
|
||||
//SOC_EQ(tmp, "?", "Dimensity 700", SOC_MTK_, soc, 7)
|
||||
SOC_EQ(tmp, "MT6853", "Dimensity 720", SOC_MTK_MT6853, soc, 7)
|
||||
SOC_EQ(tmp, "MT6873", "Dimensity 800", SOC_MTK_MT6873, soc, 7)
|
||||
SOC_EQ(tmp, "MT6875", "Dimensity 820", SOC_MTK_MT6875, soc, 7)
|
||||
// Helio //
|
||||
// Helio //
|
||||
SOC_EQ(tmp, "MT6761D", "Helio A20", SOC_MTK_MT6761D, soc, 12)
|
||||
SOC_EQ(tmp, "MT6761", "Helio A22", SOC_MTK_MT6761, soc, 12)
|
||||
SOC_EQ(tmp, "MT6762D", "Helio A25", SOC_MTK_MT6762D, soc, 12)
|
||||
@@ -287,7 +313,7 @@ bool match_mediatek(char* soc_name, struct system_on_chip* soc) {
|
||||
*
|
||||
* If Qualcomm official website reports the SoC name without the initial two or three SKU name,
|
||||
* we assume APQ if second number is 0, or MSM if second number is different than 0
|
||||
*
|
||||
*
|
||||
* All SoC names here have been retrieved from official Qualcomm resources. However, Linux kernel
|
||||
* and Android may report the SoC with slightly different. Therefore, this function needs some
|
||||
* rework (e.g, debug with http://specdevice.com/unmoderated.php?lang=en)
|
||||
@@ -299,11 +325,11 @@ bool match_qualcomm(char* soc_name, struct system_on_chip* soc) {
|
||||
if((tmp = strstr(soc_name_upper, "MSM")) != NULL);
|
||||
else if((tmp = strstr(soc_name_upper, "SDM")) != NULL);
|
||||
else if((tmp = strstr(soc_name_upper, "APQ")) != NULL);
|
||||
else if((tmp = strstr(soc_name_upper, "SM")) != NULL);
|
||||
else if((tmp = strstr(soc_name_upper, "QM")) != NULL);
|
||||
else if((tmp = strstr(soc_name_upper, "SM")) != NULL);
|
||||
else if((tmp = strstr(soc_name_upper, "QM")) != NULL);
|
||||
else if((tmp = strstr(soc_name_upper, "QSD")) != NULL);
|
||||
else return false;
|
||||
|
||||
|
||||
SOC_START
|
||||
// Snapdragon S1 //
|
||||
SOC_EQ(tmp, "QSD8650", "S1", SOC_SNAPD_QSD8650, soc, 65)
|
||||
@@ -317,37 +343,37 @@ bool match_qualcomm(char* soc_name, struct system_on_chip* soc) {
|
||||
SOC_EQ(tmp, "MSM7625A", "S1", SOC_SNAPD_MSM7625A, soc, 45)
|
||||
SOC_EQ(tmp, "MSM7225A", "S1", SOC_SNAPD_MSM7225A, soc, 45)
|
||||
// Snapdragon S2 //
|
||||
SOC_EQ(tmp, "MSM8655", "S2", SOC_SNAPD_MSM8655, soc, 45)
|
||||
SOC_EQ(tmp, "MSM8255", "S2", SOC_SNAPD_MSM8255, soc, 45)
|
||||
SOC_EQ(tmp, "MSM8655", "S2", SOC_SNAPD_MSM8655, soc, 45)
|
||||
SOC_EQ(tmp, "MSM8255", "S2", SOC_SNAPD_MSM8255, soc, 45)
|
||||
SOC_EQ(tmp, "APQ8055", "S2", SOC_SNAPD_APQ8055, soc, 45)
|
||||
SOC_EQ(tmp, "MSM7630", "S2", SOC_SNAPD_MSM7630, soc, 45)
|
||||
SOC_EQ(tmp, "MSM7230", "S2", SOC_SNAPD_MSM7230, soc, 45)
|
||||
SOC_EQ(tmp, "MSM7230", "S2", SOC_SNAPD_MSM7230, soc, 45)
|
||||
// Snapdragon S3 //
|
||||
SOC_EQ(tmp, "MSM8660", "S3", SOC_SNAPD_MSM8660, soc, 45)
|
||||
SOC_EQ(tmp, "MSM8260", "S3", SOC_SNAPD_MSM8260, soc, 45)
|
||||
SOC_EQ(tmp, "APQ8060", "S3", SOC_SNAPD_APQ8060, soc, 45)
|
||||
SOC_EQ(tmp, "MSM8660", "S3", SOC_SNAPD_MSM8660, soc, 45)
|
||||
SOC_EQ(tmp, "MSM8260", "S3", SOC_SNAPD_MSM8260, soc, 45)
|
||||
SOC_EQ(tmp, "APQ8060", "S3", SOC_SNAPD_APQ8060, soc, 45)
|
||||
// Snapdragon S4 //
|
||||
SOC_EQ(tmp, "MSM8225", "S4 Play", SOC_SNAPD_MSM8225, soc, 45)
|
||||
SOC_EQ(tmp, "MSM8625", "S4 Play", SOC_SNAPD_MSM8625, soc, 45)
|
||||
SOC_EQ(tmp, "APQ8060A", "S4 Plus", SOC_SNAPD_APQ8060A, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8960", "S4 Plus", SOC_SNAPD_MSM8960, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8260A", "S4 Plus", SOC_SNAPD_MSM8260A, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8627", "S4 Plus", SOC_SNAPD_MSM8627, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8227", "S4 Plus", SOC_SNAPD_MSM8227, soc, 28)
|
||||
SOC_EQ(tmp, "APQ8064", "S4 Pro", SOC_SNAPD_APQ8064, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8960T", "S4 Pro", SOC_SNAPD_MSM8960T, soc, 28)
|
||||
SOC_EQ(tmp, "APQ8060A", "S4 Plus", SOC_SNAPD_APQ8060A, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8960", "S4 Plus", SOC_SNAPD_MSM8960, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8260A", "S4 Plus", SOC_SNAPD_MSM8260A, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8627", "S4 Plus", SOC_SNAPD_MSM8627, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8227", "S4 Plus", SOC_SNAPD_MSM8227, soc, 28)
|
||||
SOC_EQ(tmp, "APQ8064", "S4 Pro", SOC_SNAPD_APQ8064, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8960T", "S4 Pro", SOC_SNAPD_MSM8960T, soc, 28)
|
||||
// Snapdragon 2XX //
|
||||
SOC_EQ(tmp, "MSM8110", "200", SOC_SNAPD_MSM8110, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8210", "200", SOC_SNAPD_MSM8210, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8610", "200", SOC_SNAPD_MSM8610, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8112", "200", SOC_SNAPD_MSM8112, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8212", "200", SOC_SNAPD_MSM8212, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8612", "200", SOC_SNAPD_MSM8612, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8225Q", "200", SOC_SNAPD_MSM8225Q, soc, 45)
|
||||
SOC_EQ(tmp, "MSM8625Q", "200", SOC_SNAPD_MSM8625Q, soc, 45)
|
||||
SOC_EQ(tmp, "MSM8208", "208", SOC_SNAPD_MSM8208, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8905", "205", SOC_SNAPD_MSM8905, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8909", "210 / 212", SOC_SNAPD_MSM8909, soc, 28) // In the future, we can differenciate them using frequency
|
||||
SOC_EQ(tmp, "MSM8110", "200", SOC_SNAPD_MSM8110, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8210", "200", SOC_SNAPD_MSM8210, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8610", "200", SOC_SNAPD_MSM8610, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8112", "200", SOC_SNAPD_MSM8112, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8212", "200", SOC_SNAPD_MSM8212, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8612", "200", SOC_SNAPD_MSM8612, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8225Q", "200", SOC_SNAPD_MSM8225Q, soc, 45)
|
||||
SOC_EQ(tmp, "MSM8625Q", "200", SOC_SNAPD_MSM8625Q, soc, 45)
|
||||
SOC_EQ(tmp, "MSM8208", "208", SOC_SNAPD_MSM8208, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8905", "205", SOC_SNAPD_MSM8905, soc, 28)
|
||||
SOC_EQ(tmp, "MSM8909", "210 / 212", SOC_SNAPD_MSM8909, soc, 28) // In the future, we can differentiate them using frequency
|
||||
SOC_EQ(tmp, "QM215", "215", SOC_SNAPD_QM215, soc, 28)
|
||||
// Snapdragon 4XX //
|
||||
SOC_EQ(tmp, "APQ8028", "400", SOC_SNAPD_APQ8028, soc, 28)
|
||||
@@ -424,6 +450,7 @@ bool match_qualcomm(char* soc_name, struct system_on_chip* soc) {
|
||||
SOC_EQ(tmp, "SM8250", "865", SOC_SNAPD_SM8250, soc, 7)
|
||||
SOC_EQ(tmp, "SM8250-AB", "865+", SOC_SNAPD_SM8250_AB, soc, 7)
|
||||
SOC_EQ(tmp, "SM8350", "888", SOC_SNAPD_SM8350, soc, 5)
|
||||
SOC_EQ(tmp, "SM8350-AC", "888+", SOC_SNAPD_SM8350, soc, 5)
|
||||
SOC_END
|
||||
}
|
||||
|
||||
@@ -450,21 +477,20 @@ struct system_on_chip* parse_soc_from_string(struct system_on_chip* soc) {
|
||||
|
||||
if(match_special(raw_name, soc))
|
||||
return soc;
|
||||
|
||||
|
||||
if (match_qualcomm(raw_name, soc))
|
||||
return soc;
|
||||
|
||||
|
||||
if(match_mediatek(raw_name, soc))
|
||||
return soc;
|
||||
|
||||
|
||||
if(match_exynos(raw_name, soc))
|
||||
return soc;
|
||||
|
||||
|
||||
if(match_hisilicon(raw_name, soc))
|
||||
return soc;
|
||||
|
||||
|
||||
match_broadcom(raw_name, soc);
|
||||
|
||||
return soc;
|
||||
}
|
||||
|
||||
@@ -475,53 +501,122 @@ static inline int android_property_get(const char* key, char* value) {
|
||||
return __system_property_get(key, value);
|
||||
}
|
||||
|
||||
void try_parse_soc_from_string(struct system_on_chip* soc, int soc_len, char* soc_str) {
|
||||
soc->raw_name = emalloc(sizeof(char) * (soc_len + 1));
|
||||
strncpy(soc->raw_name, soc_str, soc_len + 1);
|
||||
soc->raw_name[soc_len] = '\0';
|
||||
soc->soc_vendor = SOC_VENDOR_UNKNOWN;
|
||||
parse_soc_from_string(soc);
|
||||
}
|
||||
|
||||
struct system_on_chip* guess_soc_from_android(struct system_on_chip* soc) {
|
||||
char tmp[100];
|
||||
int property_len = 0;
|
||||
|
||||
|
||||
property_len = android_property_get("ro.mediatek.platform", (char *) &tmp);
|
||||
if(property_len > 0) {
|
||||
soc->raw_name = malloc(sizeof(char) * (property_len + 1));
|
||||
strncpy(soc->raw_name, tmp, property_len + 1);
|
||||
soc->raw_name[property_len] = '\0';
|
||||
soc->soc_vendor = SOC_VENDOR_UNKNOWN;
|
||||
return parse_soc_from_string(soc);
|
||||
try_parse_soc_from_string(soc, property_len, tmp);
|
||||
if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) printWarn("SoC detection failed using Android property ro.mediatek.platform: %s", tmp);
|
||||
else return soc;
|
||||
}
|
||||
|
||||
|
||||
property_len = android_property_get("ro.product.board", (char *) &tmp);
|
||||
if(property_len > 0) {
|
||||
soc->raw_name = malloc(sizeof(char) * (property_len + 1));
|
||||
strncpy(soc->raw_name, tmp, property_len + 1);
|
||||
soc->raw_name[property_len] = '\0';
|
||||
soc->soc_vendor = SOC_VENDOR_UNKNOWN;
|
||||
return parse_soc_from_string(soc);
|
||||
}
|
||||
|
||||
if(property_len > 0) {
|
||||
try_parse_soc_from_string(soc, property_len, tmp);
|
||||
if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) printWarn("SoC detection failed using Android property ro.product.board: %s", tmp);
|
||||
else return soc;
|
||||
}
|
||||
|
||||
property_len = android_property_get("ro.board.platform", (char *) &tmp);
|
||||
if(property_len > 0) {
|
||||
try_parse_soc_from_string(soc, property_len, tmp);
|
||||
if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) printWarn("SoC detection failed using Android property ro.board.platform: %s", tmp);
|
||||
else return soc;
|
||||
}
|
||||
|
||||
return soc;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct system_on_chip* guess_soc_from_cpuinfo(struct system_on_chip* soc) {
|
||||
char* tmp = get_hardware_from_cpuinfo(&strlen);
|
||||
|
||||
char* tmp = get_hardware_from_cpuinfo();
|
||||
|
||||
if(tmp != NULL) {
|
||||
soc->raw_name = tmp;
|
||||
return parse_soc_from_string(soc);
|
||||
}
|
||||
|
||||
|
||||
return soc;
|
||||
}
|
||||
|
||||
int hex2int(char c) {
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
if (c >= 'A' && c <= 'F')
|
||||
return c - 'A' + 10;
|
||||
if (c >= 'a' && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md
|
||||
struct system_on_chip* guess_soc_raspbery_pi(struct system_on_chip* soc) {
|
||||
char* revision = get_revision_from_cpuinfo();
|
||||
|
||||
if(revision == NULL) {
|
||||
printWarn("[RPi] Couldn't find revision field in cpuinfo");
|
||||
return soc;
|
||||
}
|
||||
|
||||
if(strlen(revision) != 6) {
|
||||
printWarn("[RPi] Found invalid RPi revision code: '%s'", revision);
|
||||
return soc;
|
||||
}
|
||||
|
||||
int arr_size = ARRAY_SIZE(soc_rpi_string);
|
||||
int pppp = hex2int(revision[2]);
|
||||
if(pppp == -1) {
|
||||
printErr("[RPi] Found invalid RPi PPPP code: %s", revision[2]);
|
||||
return soc;
|
||||
}
|
||||
|
||||
if(pppp > arr_size) {
|
||||
printErr("[RPi] Found invalid RPi PPPP code: %d while max is %d", pppp, arr_size);
|
||||
return soc;
|
||||
}
|
||||
|
||||
char* soc_raw_name = soc_rpi_string[pppp];
|
||||
/*int soc_len = strlen(soc_raw_name);
|
||||
soc->raw_name = emalloc(sizeof(char) * (soc_len + 1));
|
||||
strncpy(soc->raw_name, soc_raw_name, soc_len + 1);*/
|
||||
|
||||
match_broadcom(soc_raw_name, soc);
|
||||
return soc;
|
||||
}
|
||||
|
||||
struct system_on_chip* get_soc() {
|
||||
struct system_on_chip* soc = malloc(sizeof(struct system_on_chip));
|
||||
struct system_on_chip* soc = emalloc(sizeof(struct system_on_chip));
|
||||
soc->raw_name = NULL;
|
||||
soc->soc_vendor = SOC_VENDOR_UNKNOWN;
|
||||
soc->process = UNKNOWN;
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
bool isRPi = is_raspberry_pi();
|
||||
if(isRPi) {
|
||||
soc = guess_soc_raspbery_pi(soc);
|
||||
if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) {
|
||||
printWarn("SoC detection failed using revision code");
|
||||
}
|
||||
else {
|
||||
return soc;
|
||||
}
|
||||
}
|
||||
|
||||
soc = guess_soc_from_cpuinfo(soc);
|
||||
if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) {
|
||||
if(soc->raw_name != NULL)
|
||||
printWarn("SoC detection failed using /proc/cpuinfo: Found '%s' string", soc->raw_name);
|
||||
printWarn("SoC detection failed using /proc/cpuinfo: Found '%s' string", soc->raw_name);
|
||||
else
|
||||
printWarn("SoC detection failed using /proc/cpuinfo: No string found");
|
||||
#ifdef __ANDROID__
|
||||
@@ -529,16 +624,19 @@ struct system_on_chip* get_soc() {
|
||||
if(soc->raw_name == NULL)
|
||||
printWarn("SoC detection failed using Android: No string found");
|
||||
else if(soc->soc_vendor == SOC_VENDOR_UNKNOWN)
|
||||
printWarn("SoC detection failed using Android: Found '%s' string", soc->raw_name);
|
||||
#endif
|
||||
printWarn("SoC detection failed using Android: Found '%s' string", soc->raw_name);
|
||||
#endif // ifdef __ANDROID__
|
||||
}
|
||||
#elif defined __APPLE__ || __MACH__
|
||||
fill_soc(soc, "M1", SOC_APPLE_M1, 5);
|
||||
#endif // ifdef __linux__
|
||||
|
||||
if(soc->raw_name == NULL) {
|
||||
soc->raw_name = malloc(sizeof(char) * (strlen(STRING_UNKNOWN)+1));
|
||||
soc->raw_name = emalloc(sizeof(char) * (strlen(STRING_UNKNOWN)+1));
|
||||
snprintf(soc->raw_name, strlen(STRING_UNKNOWN)+1, STRING_UNKNOWN);
|
||||
}
|
||||
|
||||
return soc;
|
||||
|
||||
return soc;
|
||||
}
|
||||
|
||||
char* get_soc_name(struct system_on_chip* soc) {
|
||||
@@ -553,16 +651,15 @@ VENDOR get_soc_vendor(struct system_on_chip* soc) {
|
||||
|
||||
char* get_str_process(struct system_on_chip* soc) {
|
||||
char* str;
|
||||
|
||||
|
||||
if(soc->process == UNKNOWN) {
|
||||
str = malloc(sizeof(char) * (strlen(STRING_UNKNOWN)+1));
|
||||
str = emalloc(sizeof(char) * (strlen(STRING_UNKNOWN)+1));
|
||||
snprintf(str, strlen(STRING_UNKNOWN)+1, STRING_UNKNOWN);
|
||||
}
|
||||
else {
|
||||
str = malloc(sizeof(char) * 5);
|
||||
str = emalloc(sizeof(char) * 5);
|
||||
memset(str, 0, sizeof(char) * 5);
|
||||
snprintf(str, 5, "%dnm", soc->process);
|
||||
snprintf(str, 5, "%dnm", soc->process);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@ enum {
|
||||
SOC_VENDOR_MEDIATEK,
|
||||
SOC_VENDOR_EXYNOS,
|
||||
SOC_VENDOR_KIRIN,
|
||||
SOC_VENDOR_BROADCOM
|
||||
SOC_VENDOR_BROADCOM,
|
||||
SOC_VENDOR_APPLE
|
||||
};
|
||||
|
||||
struct system_on_chip {
|
||||
|
||||
@@ -63,6 +63,8 @@ enum {
|
||||
SOC_EXYNOS_980,
|
||||
SOC_EXYNOS_880,
|
||||
// Mediatek //
|
||||
SOC_MTK_MT6893,
|
||||
SOC_MTK_MT6891,
|
||||
SOC_MTK_MT6889,
|
||||
SOC_MTK_MT6885Z,
|
||||
SOC_MTK_MT6853,
|
||||
@@ -250,14 +252,17 @@ enum {
|
||||
SOC_SNAPD_SM8250,
|
||||
SOC_SNAPD_SM8250_AB,
|
||||
SOC_SNAPD_SM8350,
|
||||
// APPLE
|
||||
SOC_APPLE_M1
|
||||
};
|
||||
|
||||
inline static VENDOR get_soc_vendor_from_soc(SOC soc) {
|
||||
if(soc >= SOC_BCM_2835 && soc <= SOC_BCM_21654) return SOC_VENDOR_BROADCOM;
|
||||
else if(soc >= SOC_HISILICON_3620 && soc <= SOC_HISILICON_3690) return SOC_VENDOR_KIRIN;
|
||||
else if(soc >= SOC_EXYNOS_3475 && soc <= SOC_EXYNOS_880) return SOC_VENDOR_EXYNOS;
|
||||
else if(soc >= SOC_MTK_MT6889 && soc <= SOC_MTK_MT8783) return SOC_VENDOR_MEDIATEK;
|
||||
else if(soc >= SOC_MTK_MT6893 && soc <= SOC_MTK_MT8783) return SOC_VENDOR_MEDIATEK;
|
||||
else if(soc >= SOC_SNAPD_QSD8650 && soc <= SOC_SNAPD_SM8350) return SOC_VENDOR_SNAPDRAGON;
|
||||
else if(soc >= SOC_APPLE_M1 && soc <= SOC_APPLE_M1) return SOC_VENDOR_APPLE;
|
||||
return SOC_VENDOR_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
25
src/arm/sysctl.c
Normal file
25
src/arm/sysctl.c
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../common/global.h"
|
||||
#include "../common/cpu.h"
|
||||
|
||||
uint32_t get_sys_info_by_name(char* name) {
|
||||
size_t size = 0;
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (sysctlbyname(name, NULL, &size, NULL, 0) != 0) {
|
||||
printWarn("sysctlbyname(%s) failed: %s", name, strerror(errno));
|
||||
}
|
||||
else if (size == sizeof(uint32_t)) {
|
||||
sysctlbyname(name, &ret, &size, NULL, 0);
|
||||
}
|
||||
else {
|
||||
printWarn("sysctl does not support non-integer lookup for '%s'", name);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
6
src/arm/sysctl.h
Normal file
6
src/arm/sysctl.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef __SYSCTL__
|
||||
#define __SYSCTL__
|
||||
|
||||
uint32_t get_sys_info_by_name(char* name);
|
||||
|
||||
#endif
|
||||
103
src/arm/uarch.c
103
src/arm/uarch.c
@@ -7,8 +7,6 @@
|
||||
#include "uarch.h"
|
||||
#include "../common/global.h"
|
||||
|
||||
#define STRING_UNKNOWN "Unknown"
|
||||
|
||||
// Data not available
|
||||
#define NA -1
|
||||
|
||||
@@ -34,6 +32,7 @@ enum {
|
||||
ISA_ARMv8_1_A,
|
||||
ISA_ARMv8_2_A,
|
||||
ISA_ARMv8_3_A,
|
||||
ISA_ARMv8_4_A,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -45,26 +44,27 @@ enum {
|
||||
UARCH_ARM1156,
|
||||
UARCH_ARM1176,
|
||||
UARCH_ARM11MPCORE,
|
||||
UARCH_CORTEX_A5,
|
||||
UARCH_CORTEX_A7,
|
||||
UARCH_CORTEX_A8,
|
||||
UARCH_CORTEX_A9,
|
||||
UARCH_CORTEX_A12,
|
||||
UARCH_CORTEX_A15,
|
||||
UARCH_CORTEX_A17,
|
||||
UARCH_CORTEX_A32,
|
||||
UARCH_CORTEX_A35,
|
||||
UARCH_CORTEX_A53,
|
||||
UARCH_CORTEX_A5,
|
||||
UARCH_CORTEX_A7,
|
||||
UARCH_CORTEX_A8,
|
||||
UARCH_CORTEX_A9,
|
||||
UARCH_CORTEX_A12,
|
||||
UARCH_CORTEX_A15,
|
||||
UARCH_CORTEX_A17,
|
||||
UARCH_CORTEX_A32,
|
||||
UARCH_CORTEX_A35,
|
||||
UARCH_CORTEX_A53,
|
||||
UARCH_CORTEX_A55r0, // ARM Cortex-A55 revision 0 (restricted dual-issue capabilities compared to revision 1+).
|
||||
UARCH_CORTEX_A55,
|
||||
UARCH_CORTEX_A57,
|
||||
UARCH_CORTEX_A65,
|
||||
UARCH_CORTEX_A72,
|
||||
UARCH_CORTEX_A73,
|
||||
UARCH_CORTEX_A75,
|
||||
UARCH_CORTEX_A55,
|
||||
UARCH_CORTEX_A57,
|
||||
UARCH_CORTEX_A65,
|
||||
UARCH_CORTEX_A72,
|
||||
UARCH_CORTEX_A73,
|
||||
UARCH_CORTEX_A75,
|
||||
UARCH_CORTEX_A76,
|
||||
UARCH_CORTEX_A77,
|
||||
UARCH_CORTEX_A78,
|
||||
UARCH_CORTEX_A78,
|
||||
UARCH_CORTEX_X1,
|
||||
UARCH_NEOVERSE_N1,
|
||||
UARCH_NEOVERSE_E1,
|
||||
UARCH_SCORPION,
|
||||
@@ -93,6 +93,8 @@ enum {
|
||||
UARCH_TEMPEST, // Apple A12 processor (big cores).
|
||||
UARCH_LIGHTNING, // Apple A13 processor (big cores).
|
||||
UARCH_THUNDER, // Apple A13 processor (little cores).
|
||||
UARCH_ICESTORM, // Apple M1 processor (little cores).
|
||||
UARCH_FIRESTORM, // Apple M1 processor (big cores).
|
||||
// CAVIUM
|
||||
UARCH_THUNDERX, // Cavium ThunderX
|
||||
UARCH_THUNDERX2, // Cavium ThunderX2 (originally Broadcom Vulkan).
|
||||
@@ -118,17 +120,18 @@ static const ISA isas_uarch[] = {
|
||||
[UARCH_CORTEX_A17] = ISA_ARMv7_A,
|
||||
[UARCH_CORTEX_A32] = ISA_ARMv8_A_AArch32,
|
||||
[UARCH_CORTEX_A35] = ISA_ARMv8_A,
|
||||
[UARCH_CORTEX_A53] = ISA_ARMv8_A,
|
||||
[UARCH_CORTEX_A53] = ISA_ARMv8_A,
|
||||
[UARCH_CORTEX_A55r0] = ISA_ARMv8_2_A,
|
||||
[UARCH_CORTEX_A55] = ISA_ARMv8_2_A,
|
||||
[UARCH_CORTEX_A57] = ISA_ARMv8_A,
|
||||
[UARCH_CORTEX_A65] = ISA_ARMv8_2_A,
|
||||
[UARCH_CORTEX_A65] = ISA_ARMv8_2_A,
|
||||
[UARCH_CORTEX_A72] = ISA_ARMv8_A,
|
||||
[UARCH_CORTEX_A73] = ISA_ARMv8_A,
|
||||
[UARCH_CORTEX_A75] = ISA_ARMv8_2_A,
|
||||
[UARCH_CORTEX_A76] = ISA_ARMv8_2_A,
|
||||
[UARCH_CORTEX_A76] = ISA_ARMv8_2_A,
|
||||
[UARCH_CORTEX_A77] = ISA_ARMv8_2_A,
|
||||
[UARCH_CORTEX_A78] = ISA_ARMv8_2_A,
|
||||
[UARCH_CORTEX_X1] = ISA_ARMv8_2_A,
|
||||
[UARCH_NEOVERSE_N1] = ISA_ARMv8_2_A,
|
||||
[UARCH_NEOVERSE_E1] = ISA_ARMv8_2_A,
|
||||
[UARCH_BRAHMA_B15] = ISA_ARMv7_A, // Same as Cortex-A15
|
||||
@@ -150,6 +153,8 @@ static const ISA isas_uarch[] = {
|
||||
[UARCH_EXYNOS_M3] = ISA_ARMv8_A,
|
||||
[UARCH_EXYNOS_M4] = ISA_ARMv8_2_A,
|
||||
[UARCH_EXYNOS_M5] = ISA_ARMv8_2_A,
|
||||
[UARCH_ICESTORM] = ISA_ARMv8_4_A,
|
||||
[UARCH_FIRESTORM] = ISA_ARMv8_4_A,
|
||||
[UARCH_PJ4] = ISA_ARMv7_A,
|
||||
};
|
||||
|
||||
@@ -164,24 +169,25 @@ static char* isas_string[] = {
|
||||
[ISA_ARMv8_1_A] = "ARMv8.1",
|
||||
[ISA_ARMv8_2_A] = "ARMv8.2",
|
||||
[ISA_ARMv8_3_A] = "ARMv8.3",
|
||||
[ISA_ARMv8_4_A] = "ARMv8.4"
|
||||
};
|
||||
|
||||
#define UARCH_START if (false) {}
|
||||
#define CHECK_UARCH(arch, cpu, im_, p_, v_, r_, str, uarch, vendor) \
|
||||
else if (im_ == im && p_ == p && (v_ == NA || v_ == v) && (r_ == NA || r_ == r)) fill_uarch(arch, cpu, str, uarch, vendor);
|
||||
#define UARCH_END else { printBug("Unknown microarchitecture detected: IM=0x%.8X P=0x%.8X V=0x%.8X R=0x%.8X", im, p, v, r); fill_uarch(arch, cpu, "Unknown", UARCH_UNKNOWN, CPU_VENDOR_UNKNOWN); }
|
||||
|
||||
|
||||
void fill_uarch(struct uarch* arch, struct cpuInfo* cpu, char* str, MICROARCH u, VENDOR vendor) {
|
||||
arch->uarch = u;
|
||||
arch->uarch = u;
|
||||
arch->isa = isas_uarch[arch->uarch];
|
||||
cpu->cpu_vendor = vendor;
|
||||
|
||||
arch->uarch_str = malloc(sizeof(char) * (strlen(str)+1));
|
||||
|
||||
arch->uarch_str = emalloc(sizeof(char) * (strlen(str)+1));
|
||||
strcpy(arch->uarch_str, str);
|
||||
|
||||
arch->isa_str = malloc(sizeof(char) * (strlen(isas_string[arch->isa])+1));
|
||||
strcpy(arch->isa_str, isas_string[arch->isa]);
|
||||
}
|
||||
|
||||
arch->isa_str = emalloc(sizeof(char) * (strlen(isas_string[arch->isa])+1));
|
||||
strcpy(arch->isa_str, isas_string[arch->isa]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Codes are based on pytorch/cpuinfo, more precisely:
|
||||
@@ -191,7 +197,7 @@ void fill_uarch(struct uarch* arch, struct cpuInfo* cpu, char* str, MICROARCH u,
|
||||
* - https://elixir.bootlin.com/linux/latest/source/arch/arm/include/asm/cputype.h
|
||||
*/
|
||||
struct uarch* get_uarch_from_midr(uint32_t midr, struct cpuInfo* cpu) {
|
||||
struct uarch* arch = malloc(sizeof(struct uarch));
|
||||
struct uarch* arch = emalloc(sizeof(struct uarch));
|
||||
uint32_t im = midr_get_implementer(midr);
|
||||
uint32_t p = midr_get_part(midr);
|
||||
uint32_t v = midr_get_variant(midr);
|
||||
@@ -221,7 +227,7 @@ struct uarch* get_uarch_from_midr(uint32_t midr, struct cpuInfo* cpu) {
|
||||
CHECK_UARCH(arch, cpu, 'A', 0xD03, NA, NA, "Cortex-A53", UARCH_CORTEX_A53, CPU_VENDOR_ARM)
|
||||
CHECK_UARCH(arch, cpu, 'A', 0xD04, NA, NA, "Cortex-A35", UARCH_CORTEX_A35, CPU_VENDOR_ARM)
|
||||
CHECK_UARCH(arch, cpu, 'A', 0xD05, NA, 0, "Cortex-A55", UARCH_CORTEX_A55r0, CPU_VENDOR_ARM)
|
||||
CHECK_UARCH(arch, cpu, 'A', 0xD05, NA, NA, "Cortex-A55", UARCH_CORTEX_A55, CPU_VENDOR_ARM)
|
||||
CHECK_UARCH(arch, cpu, 'A', 0xD05, NA, NA, "Cortex-A55", UARCH_CORTEX_A55, CPU_VENDOR_ARM)
|
||||
CHECK_UARCH(arch, cpu, 'A', 0xD06, NA, NA, "Cortex-A65", UARCH_CORTEX_A65, CPU_VENDOR_ARM)
|
||||
CHECK_UARCH(arch, cpu, 'A', 0xD07, NA, NA, "Cortex-A57", UARCH_CORTEX_A57, CPU_VENDOR_ARM)
|
||||
CHECK_UARCH(arch, cpu, 'A', 0xD08, NA, NA, "Cortex-A72", UARCH_CORTEX_A72, CPU_VENDOR_ARM)
|
||||
@@ -232,27 +238,28 @@ struct uarch* get_uarch_from_midr(uint32_t midr, struct cpuInfo* cpu) {
|
||||
CHECK_UARCH(arch, cpu, 'A', 0xD0D, NA, NA, "Cortex-A77", UARCH_CORTEX_A77, CPU_VENDOR_ARM)
|
||||
CHECK_UARCH(arch, cpu, 'A', 0xD0E, NA, NA, "Cortex-A76", UARCH_CORTEX_A76, CPU_VENDOR_ARM)
|
||||
CHECK_UARCH(arch, cpu, 'A', 0xD41, NA, NA, "Cortex-A78", UARCH_CORTEX_A78, CPU_VENDOR_ARM)
|
||||
CHECK_UARCH(arch, cpu, 'A', 0xD44, NA, NA, "Cortex-X1", UARCH_CORTEX_X1, CPU_VENDOR_ARM)
|
||||
CHECK_UARCH(arch, cpu, 'A', 0xD4A, NA, NA, "Neoverse E1", UARCH_NEOVERSE_E1, CPU_VENDOR_ARM)
|
||||
|
||||
|
||||
CHECK_UARCH(arch, cpu, 'B', 0x00F, NA, NA, "Brahma B15", UARCH_BRAHMA_B15, CPU_VENDOR_BROADCOM)
|
||||
CHECK_UARCH(arch, cpu, 'B', 0x100, NA, NA, "Brahma B53", UARCH_BRAHMA_B53, CPU_VENDOR_BROADCOM)
|
||||
CHECK_UARCH(arch, cpu, 'B', 0x516, NA, NA, "ThunderX2", UARCH_THUNDERX2, CPU_VENDOR_CAVIUM)
|
||||
|
||||
|
||||
CHECK_UARCH(arch, cpu, 'C', 0x0A0, NA, NA, "ThunderX", UARCH_THUNDERX, CPU_VENDOR_CAVIUM)
|
||||
CHECK_UARCH(arch, cpu, 'C', 0x0A1, NA, NA, "ThunderX 88XX", UARCH_THUNDERX, CPU_VENDOR_CAVIUM)
|
||||
CHECK_UARCH(arch, cpu, 'C', 0x0A2, NA, NA, "ThunderX 81XX", UARCH_THUNDERX, CPU_VENDOR_CAVIUM)
|
||||
CHECK_UARCH(arch, cpu, 'C', 0x0A3, NA, NA, "ThunderX 81XX", UARCH_THUNDERX, CPU_VENDOR_CAVIUM)
|
||||
CHECK_UARCH(arch, cpu, 'C', 0x0AF, NA, NA, "ThunderX2 99XX", UARCH_THUNDERX2, CPU_VENDOR_CAVIUM)
|
||||
|
||||
|
||||
CHECK_UARCH(arch, cpu, 'H', 0xD01, NA, NA, "TaiShan v110", UARCH_TAISHAN_V110, CPU_VENDOR_HUAWUEI) // Kunpeng 920 series
|
||||
CHECK_UARCH(arch, cpu, 'H', 0xD40, NA, NA, "Cortex-A76", UARCH_CORTEX_A76, CPU_VENDOR_ARM) // Kirin 980 Big/Medium cores -> Cortex-A76
|
||||
|
||||
|
||||
CHECK_UARCH(arch, cpu, 'N', 0x000, NA, NA, "Denver", UARCH_DENVER, CPU_VENDOR_NVIDIA)
|
||||
CHECK_UARCH(arch, cpu, 'N', 0x003, NA, NA, "Denver2", UARCH_DENVER2, CPU_VENDOR_NVIDIA)
|
||||
CHECK_UARCH(arch, cpu, 'N', 0x004, NA, NA, "Carmel", UARCH_CARMEL, CPU_VENDOR_NVIDIA)
|
||||
|
||||
|
||||
CHECK_UARCH(arch, cpu, 'P', 0x000, NA, NA, "Xgene", UARCH_XGENE, CPU_VENDOR_APM)
|
||||
|
||||
|
||||
CHECK_UARCH(arch, cpu, 'Q', 0x00F, NA, NA, "Scorpion", UARCH_SCORPION, CPU_VENDOR_QUALCOMM)
|
||||
CHECK_UARCH(arch, cpu, 'Q', 0x02D, NA, NA, "Scorpion", UARCH_KRAIT, CPU_VENDOR_QUALCOMM)
|
||||
CHECK_UARCH(arch, cpu, 'Q', 0x04D, 1, 0, "Krait 200", UARCH_KRAIT, CPU_VENDOR_QUALCOMM)
|
||||
@@ -273,29 +280,31 @@ struct uarch* get_uarch_from_midr(uint32_t midr, struct cpuInfo* cpu) {
|
||||
CHECK_UARCH(arch, cpu, 'Q', 0x803, NA, NA, "Kryo 385 Silver", UARCH_CORTEX_A55r0, CPU_VENDOR_ARM) // Low-power Kryo 385 "Silver" -> Cortex-A55r0
|
||||
CHECK_UARCH(arch, cpu, 'Q', 0x804, NA, NA, "Kryo 485 Gold", UARCH_CORTEX_A76, CPU_VENDOR_ARM) // High-performance Kryo 485 "Gold" / "Gold Prime" -> Cortex-A76
|
||||
CHECK_UARCH(arch, cpu, 'Q', 0x805, NA, NA, "Kryo 485 Silver", UARCH_CORTEX_A55, CPU_VENDOR_ARM) // Low-performance Kryo 485 "Silver" -> Cortex-A55
|
||||
CHECK_UARCH(arch, cpu, 'Q', 0xC00, NA, NA, "Falkor", UARCH_FALKOR, CPU_VENDOR_QUALCOMM)
|
||||
CHECK_UARCH(arch, cpu, 'Q', 0xC01, NA, NA, "Saphira", UARCH_SAPHIRA, CPU_VENDOR_QUALCOMM)
|
||||
|
||||
CHECK_UARCH(arch, cpu, 'Q', 0xC00, NA, NA, "Falkor", UARCH_FALKOR, CPU_VENDOR_QUALCOMM)
|
||||
CHECK_UARCH(arch, cpu, 'Q', 0xC01, NA, NA, "Saphira", UARCH_SAPHIRA, CPU_VENDOR_QUALCOMM)
|
||||
|
||||
CHECK_UARCH(arch, cpu, 'S', 0x001, 1, NA, "Exynos M1", UARCH_EXYNOS_M1, CPU_VENDOR_SAMSUNG) // Exynos 8890
|
||||
CHECK_UARCH(arch, cpu, 'S', 0x001, 4, NA, "Exynos M2", UARCH_EXYNOS_M2, CPU_VENDOR_SAMSUNG) // Exynos 8895
|
||||
CHECK_UARCH(arch, cpu, 'S', 0x002, 1, NA, "Exynos M3", UARCH_EXYNOS_M3, CPU_VENDOR_SAMSUNG) // Exynos 9810
|
||||
CHECK_UARCH(arch, cpu, 'S', 0x003, 1, NA, "Exynos M4", UARCH_EXYNOS_M4, CPU_VENDOR_SAMSUNG) // Exynos 9820
|
||||
CHECK_UARCH(arch, cpu, 'S', 0x004, 1, NA, "Exynos M5", UARCH_EXYNOS_M5, CPU_VENDOR_SAMSUNG) // Exynos 9820 (this one looks wrong at uarch.c ...)
|
||||
|
||||
|
||||
CHECK_UARCH(arch, cpu, 'a', 0x022, NA, NA, "Icestorm", UARCH_ICESTORM, CPU_VENDOR_APPLE)
|
||||
CHECK_UARCH(arch, cpu, 'a', 0x023, NA, NA, "Firestorm", UARCH_FIRESTORM, CPU_VENDOR_APPLE)
|
||||
|
||||
CHECK_UARCH(arch, cpu, 'V', 0x581, NA, NA, "PJ4", UARCH_PJ4, CPU_VENDOR_MARVELL)
|
||||
CHECK_UARCH(arch, cpu, 'V', 0x584, NA, NA, "PJ4B-MP", UARCH_PJ4, CPU_VENDOR_MARVELL)
|
||||
|
||||
|
||||
UARCH_END
|
||||
|
||||
|
||||
return arch;
|
||||
}
|
||||
|
||||
char* get_str_uarch(struct cpuInfo* cpu) {
|
||||
return cpu->arch->uarch_str;
|
||||
return cpu->arch->uarch_str;
|
||||
}
|
||||
|
||||
void free_uarch_struct(struct uarch* arch) {
|
||||
void free_uarch_struct(struct uarch* arch) {
|
||||
free(arch->uarch_str);
|
||||
free(arch);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "../common/global.h"
|
||||
#include "udev.h"
|
||||
#include "midr.h"
|
||||
|
||||
#define _PATH_DEVICETREE_MODEL "/sys/firmware/devicetree/base/model"
|
||||
#define _PATH_CPUS_PRESENT _PATH_SYS_SYSTEM _PATH_SYS_CPU "/present"
|
||||
#define _PATH_CPUINFO "/proc/cpuinfo"
|
||||
//#define _PATH_CPUINFO "cpuinfo_debug"
|
||||
@@ -11,6 +13,7 @@
|
||||
#define CPUINFO_CPU_PART_STR "CPU part\t: "
|
||||
#define CPUINFO_CPU_REVISION_STR "CPU revision\t: "
|
||||
#define CPUINFO_HARDWARE_STR "Hardware\t: "
|
||||
#define CPUINFO_REVISION_STR "Revision\t: "
|
||||
|
||||
#define CPUINFO_CPU_STRING "processor"
|
||||
|
||||
@@ -24,7 +27,7 @@ int get_ncores_from_cpuinfo() {
|
||||
int filelen;
|
||||
char* buf;
|
||||
if((buf = read_file(_PATH_CPUS_PRESENT, &filelen)) == NULL) {
|
||||
perror("open");
|
||||
printWarn("read_file: %s: %s\n", _PATH_CPUS_PRESENT, strerror(errno));
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -47,7 +50,7 @@ int get_ncores_from_cpuinfo() {
|
||||
errno = 0;
|
||||
ncores = strtol(ncores_str, &end, 10) + 1;
|
||||
if(errno != 0) {
|
||||
perror("strtol");
|
||||
printWarn("strtol: %s:\n", strerror(errno));
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -65,7 +68,7 @@ long parse_cpuinfo_field(char* buf, char* field_str, int field_base) {
|
||||
errno = 0;
|
||||
long ret = strtol(tmp, &end, field_base);
|
||||
if(errno != 0) {
|
||||
perror("strtol");
|
||||
printWarn("strtol: %s:\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -78,9 +81,9 @@ uint32_t get_midr_from_cpuinfo(uint32_t core, bool* success) {
|
||||
char* buf;
|
||||
*success = true;
|
||||
if((buf = read_file(_PATH_CPUINFO, &filelen)) == NULL) {
|
||||
perror("open");
|
||||
*success = false;
|
||||
return 0;
|
||||
printWarn("read_file: %s: %s\n", _PATH_CPUINFO, strerror(errno));
|
||||
*success = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* tmp = strstr(buf, CPUINFO_CPU_STRING);
|
||||
@@ -90,9 +93,9 @@ uint32_t get_midr_from_cpuinfo(uint32_t core, bool* success) {
|
||||
current_core++;
|
||||
tmp = strstr(tmp, CPUINFO_CPU_STRING);
|
||||
}
|
||||
|
||||
|
||||
if(tmp == NULL) {
|
||||
*success = false;
|
||||
*success = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -105,36 +108,36 @@ uint32_t get_midr_from_cpuinfo(uint32_t core, bool* success) {
|
||||
long ret;
|
||||
|
||||
if ((ret = parse_cpuinfo_field(tmp, CPUINFO_CPU_IMPLEMENTER_STR, 16)) < 0) {
|
||||
printf("Failed parsing cpu_implementer\n");
|
||||
*success = false;
|
||||
printBug("get_midr_from_cpuinfo: Failed parsing cpu_implementer\n");
|
||||
*success = false;
|
||||
return 0;
|
||||
}
|
||||
cpu_implementer = (uint32_t) ret;
|
||||
|
||||
if ((ret = parse_cpuinfo_field(tmp, CPUINFO_CPU_ARCHITECTURE_STR, 10)) < 0) {
|
||||
printf("Failed parsing cpu_architecture\n");
|
||||
*success = false;
|
||||
printBug("get_midr_from_cpuinfo: Failed parsing cpu_architecture\n");
|
||||
*success = false;
|
||||
return 0;
|
||||
}
|
||||
cpu_architecture = (uint32_t) 0xF; // Why?
|
||||
|
||||
if ((ret = parse_cpuinfo_field(tmp, CPUINFO_CPU_VARIANT_STR, 16)) < 0) {
|
||||
printf("Failed parsing cpu_variant\n");
|
||||
*success = false;
|
||||
printBug("get_midr_from_cpuinfo: Failed parsing cpu_variant\n");
|
||||
*success = false;
|
||||
return 0;
|
||||
}
|
||||
cpu_variant = (uint32_t) ret;
|
||||
|
||||
if ((ret = parse_cpuinfo_field(tmp, CPUINFO_CPU_PART_STR, 16)) < 0) {
|
||||
printf("Failed parsing cpu_part\n");
|
||||
*success = false;
|
||||
printBug("get_midr_from_cpuinfo: Failed parsing cpu_part\n");
|
||||
*success = false;
|
||||
return 0;
|
||||
}
|
||||
cpu_part = (uint32_t) ret;
|
||||
|
||||
if ((ret = parse_cpuinfo_field(tmp, CPUINFO_CPU_REVISION_STR, 10)) < 0) {
|
||||
printf("Failed parsing cpu_revision\n");
|
||||
*success = false;
|
||||
printBug("get_midr_from_cpuinfo: Failed parsing cpu_revision\n");
|
||||
*success = false;
|
||||
return 0;
|
||||
}
|
||||
cpu_revision = (uint32_t) ret;
|
||||
@@ -148,24 +151,45 @@ uint32_t get_midr_from_cpuinfo(uint32_t core, bool* success) {
|
||||
return midr;
|
||||
}
|
||||
|
||||
char* get_hardware_from_cpuinfo() {
|
||||
char* get_field_from_cpuinfo(char* CPUINFO_FIELD) {
|
||||
int filelen;
|
||||
char* buf;
|
||||
if((buf = read_file(_PATH_CPUINFO, &filelen)) == NULL) {
|
||||
perror("open");
|
||||
return NULL;
|
||||
printWarn("read_file: %s: %s:\n", _PATH_CPUINFO, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* tmp1 = strstr(buf, CPUINFO_HARDWARE_STR);
|
||||
|
||||
char* tmp1 = strstr(buf, CPUINFO_FIELD);
|
||||
if(tmp1 == NULL) return NULL;
|
||||
tmp1 = tmp1 + strlen(CPUINFO_HARDWARE_STR);
|
||||
tmp1 = tmp1 + strlen(CPUINFO_FIELD);
|
||||
char* tmp2 = strstr(tmp1, "\n");
|
||||
|
||||
|
||||
int strlen = (1 + (tmp2-tmp1));
|
||||
char* hardware = malloc(sizeof(char) * strlen);
|
||||
char* hardware = emalloc(sizeof(char) * strlen);
|
||||
memset(hardware, 0, sizeof(char) * strlen);
|
||||
strncpy(hardware, tmp1, tmp2-tmp1);
|
||||
|
||||
|
||||
return hardware;
|
||||
}
|
||||
|
||||
char* get_hardware_from_cpuinfo() {
|
||||
return get_field_from_cpuinfo(CPUINFO_HARDWARE_STR);
|
||||
}
|
||||
|
||||
char* get_revision_from_cpuinfo() {
|
||||
return get_field_from_cpuinfo(CPUINFO_REVISION_STR);
|
||||
}
|
||||
|
||||
bool is_raspberry_pi() {
|
||||
int filelen;
|
||||
char* buf;
|
||||
if((buf = read_file(_PATH_DEVICETREE_MODEL, &filelen)) == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char* tmp;
|
||||
if((tmp = strstr(buf, "Raspberry Pi")) == NULL) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
int get_ncores_from_cpuinfo();
|
||||
uint32_t get_midr_from_cpuinfo(uint32_t core, bool* success);
|
||||
char* get_hardware_from_cpuinfo();
|
||||
char* get_revision_from_cpuinfo();
|
||||
bool is_raspberry_pi();
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -5,9 +5,13 @@
|
||||
#include "args.h"
|
||||
#include "global.h"
|
||||
|
||||
#define COLOR_STR_INTEL "intel"
|
||||
#define COLOR_STR_AMD "amd"
|
||||
#define COLOR_STR_ARM "arm"
|
||||
#define NUM_COLORS 5
|
||||
|
||||
#define COLOR_STR_INTEL "intel"
|
||||
#define COLOR_STR_INTEL_NEW "intel-new"
|
||||
#define COLOR_STR_AMD "amd"
|
||||
#define COLOR_STR_IBM "ibm"
|
||||
#define COLOR_STR_ARM "arm"
|
||||
|
||||
static const char *SYTLES_STR_LIST[] = {
|
||||
[STYLE_EMPTY] = NULL,
|
||||
@@ -21,30 +25,48 @@ struct args_struct {
|
||||
bool debug_flag;
|
||||
bool help_flag;
|
||||
bool raw_flag;
|
||||
bool accurate_pp;
|
||||
bool full_cpu_name_flag;
|
||||
bool logo_long;
|
||||
bool logo_short;
|
||||
bool logo_intel_new;
|
||||
bool logo_intel_old;
|
||||
bool verbose_flag;
|
||||
bool version_flag;
|
||||
STYLE style;
|
||||
struct colors* colors;
|
||||
struct color** colors;
|
||||
};
|
||||
|
||||
const char args_chr[] = {
|
||||
/* [ARG_CHAR_STYLE] = */ 's',
|
||||
/* [ARG_CHAR_COLOR] = */ 'c',
|
||||
/* [ARG_CHAR_HELP] = */ 'h',
|
||||
/* [ARG_CHAR_RAW] = */ 'r',
|
||||
/* [ARG_CHAR_DEBUG] = */ 'd',
|
||||
/* [ARG_CHAR_VERBOSE] = */ 'v',
|
||||
/* [ARG_CHAR_VERSION] = */ 'V',
|
||||
/* [ARG_STYLE] = */ 's',
|
||||
/* [ARG_COLOR] = */ 'c',
|
||||
/* [ARG_HELP] = */ 'h',
|
||||
/* [ARG_RAW] = */ 'r',
|
||||
/* [ARG_FULLCPUNAME] = */ 'F',
|
||||
/* [ARG_LOGO_LONG] = */ 1,
|
||||
/* [ARG_LOGO_SHORT] = */ 2,
|
||||
/* [ARG_LOGO_INTEL_NEW] = */ 3,
|
||||
/* [ARG_LOGO_INTEL_OLD] = */ 4,
|
||||
/* [ARG_ACCURATE_PP] = */ 5,
|
||||
/* [ARG_DEBUG] = */ 'd',
|
||||
/* [ARG_VERBOSE] = */ 'v',
|
||||
/* [ARG_VERSION] = */ 'V',
|
||||
};
|
||||
|
||||
const char *args_str[] = {
|
||||
/* [ARG_CHAR_STYLE] = */ "style",
|
||||
/* [ARG_CHAR_COLOR] = */ "color",
|
||||
/* [ARG_CHAR_HELP] = */ "help",
|
||||
/* [ARG_CHAR_RAW] = */ "raw",
|
||||
/* [ARG_CHAR_DEBUG] = */ "debug",
|
||||
/* [ARG_CHAR_VERBOSE] = */ "verbose",
|
||||
/* [ARG_CHAR_VERSION] = */ "version",
|
||||
/* [ARG_STYLE] = */ "style",
|
||||
/* [ARG_COLOR] = */ "color",
|
||||
/* [ARG_HELP] = */ "help",
|
||||
/* [ARG_RAW] = */ "raw",
|
||||
/* [ARG_FULLCPUNAME] = */ "full-cpu-name",
|
||||
/* [ARG_LOGO_LONG] = */ "logo-long",
|
||||
/* [ARG_LOGO_SHORT] = */ "logo-short",
|
||||
/* [ARG_LOGO_INTEL_NEW] = */ "logo-intel-new",
|
||||
/* [ARG_LOGO_INTEL_OLD] = */ "logo-intel-old",
|
||||
/* [ARG_ACCURATE_PP] = */ "accurate-pp",
|
||||
/* [ARG_DEBUG] = */ "debug",
|
||||
/* [ARG_VERBOSE] = */ "verbose",
|
||||
/* [ARG_VERSION] = */ "version",
|
||||
};
|
||||
|
||||
static struct args_struct args;
|
||||
@@ -53,7 +75,7 @@ STYLE get_style() {
|
||||
return args.style;
|
||||
}
|
||||
|
||||
struct colors* get_colors() {
|
||||
struct color** get_colors() {
|
||||
return args.colors;
|
||||
}
|
||||
|
||||
@@ -70,7 +92,31 @@ bool show_debug() {
|
||||
}
|
||||
|
||||
bool show_raw() {
|
||||
return args.raw_flag;
|
||||
return args.raw_flag;
|
||||
}
|
||||
|
||||
bool accurate_pp() {
|
||||
return args.accurate_pp;
|
||||
}
|
||||
|
||||
bool show_full_cpu_name() {
|
||||
return args.full_cpu_name_flag;
|
||||
}
|
||||
|
||||
bool show_logo_long() {
|
||||
return args.logo_long;
|
||||
}
|
||||
|
||||
bool show_logo_short() {
|
||||
return args.logo_short;
|
||||
}
|
||||
|
||||
bool show_logo_intel_new() {
|
||||
return args.logo_intel_new;
|
||||
}
|
||||
|
||||
bool show_logo_intel_old() {
|
||||
return args.logo_intel_old;
|
||||
}
|
||||
|
||||
bool verbose_enabled() {
|
||||
@@ -82,121 +128,109 @@ int max_arg_str_length() {
|
||||
int len = sizeof(args_str) / sizeof(args_str[0]);
|
||||
for(int i=0; i < len; i++) {
|
||||
max_len = max(max_len, (int) strlen(args_str[i]));
|
||||
}
|
||||
}
|
||||
return max_len;
|
||||
}
|
||||
|
||||
STYLE parse_style(char* style) {
|
||||
uint8_t i = 0;
|
||||
uint8_t styles_count = sizeof(SYTLES_STR_LIST) / sizeof(SYTLES_STR_LIST[0]);
|
||||
|
||||
|
||||
while(i != styles_count && (SYTLES_STR_LIST[i] == NULL || strcmp(SYTLES_STR_LIST[i], style) != 0))
|
||||
i++;
|
||||
|
||||
if(i == styles_count)
|
||||
return STYLE_INVALID;
|
||||
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void free_colors_struct(struct colors* cs) {
|
||||
free(cs->c1);
|
||||
free(cs->c2);
|
||||
free(cs->c3);
|
||||
free(cs->c4);
|
||||
void free_colors_struct(struct color** cs) {
|
||||
for(int i=0; i < NUM_COLORS; i++) {
|
||||
free(cs[i]);
|
||||
}
|
||||
free(cs);
|
||||
}
|
||||
|
||||
bool parse_color(char* optarg_str, struct colors** cs) {
|
||||
*cs = malloc(sizeof(struct colors));
|
||||
(*cs)->c1 = malloc(sizeof(struct color));
|
||||
(*cs)->c2 = malloc(sizeof(struct color));
|
||||
(*cs)->c3 = malloc(sizeof(struct color));
|
||||
(*cs)->c4 = malloc(sizeof(struct color));
|
||||
struct color** c1 = &((*cs)->c1);
|
||||
struct color** c2 = &((*cs)->c2);
|
||||
struct color** c3 = &((*cs)->c3);
|
||||
struct color** c4 = &((*cs)->c4);
|
||||
bool parse_color(char* optarg_str, struct color*** cs) {
|
||||
for(int i=0; i < NUM_COLORS; i++) {
|
||||
(*cs)[i] = emalloc(sizeof(struct color));
|
||||
}
|
||||
|
||||
struct color** c = *cs;
|
||||
int32_t ret;
|
||||
char* str_to_parse = NULL;
|
||||
bool free_ptr;
|
||||
|
||||
if(strcmp(optarg_str, COLOR_STR_INTEL) == 0) {
|
||||
str_to_parse = malloc(sizeof(char) * 46);
|
||||
strcpy(str_to_parse, COLOR_DEFAULT_INTEL);
|
||||
free_ptr = true;
|
||||
}
|
||||
else if(strcmp(optarg_str, COLOR_STR_AMD) == 0) {
|
||||
str_to_parse = malloc(sizeof(char) * 44);
|
||||
strcpy(str_to_parse, COLOR_DEFAULT_AMD);
|
||||
free_ptr = true;
|
||||
}
|
||||
else if(strcmp(optarg_str, COLOR_STR_ARM) == 0) {
|
||||
str_to_parse = malloc(sizeof(char) * 46);
|
||||
strcpy(str_to_parse, COLOR_DEFAULT_ARM);
|
||||
free_ptr = true;
|
||||
}
|
||||
else {
|
||||
char* color_to_copy = NULL;
|
||||
bool free_ptr = true;
|
||||
|
||||
if(strcmp(optarg_str, COLOR_STR_INTEL) == 0) color_to_copy = COLOR_DEFAULT_INTEL;
|
||||
else if(strcmp(optarg_str, COLOR_STR_INTEL_NEW) == 0) color_to_copy = COLOR_DEFAULT_INTEL_NEW;
|
||||
else if(strcmp(optarg_str, COLOR_STR_AMD) == 0) color_to_copy = COLOR_DEFAULT_AMD;
|
||||
else if(strcmp(optarg_str, COLOR_STR_IBM) == 0) color_to_copy = COLOR_DEFAULT_IBM;
|
||||
else if(strcmp(optarg_str, COLOR_STR_ARM) == 0) color_to_copy = COLOR_DEFAULT_ARM;
|
||||
else {
|
||||
str_to_parse = optarg_str;
|
||||
free_ptr = false;
|
||||
}
|
||||
|
||||
ret = sscanf(str_to_parse, "%d,%d,%d:%d,%d,%d:%d,%d,%d:%d,%d,%d",
|
||||
&(*c1)->R, &(*c1)->G, &(*c1)->B,
|
||||
&(*c2)->R, &(*c2)->G, &(*c2)->B,
|
||||
&(*c3)->R, &(*c3)->G, &(*c3)->B,
|
||||
&(*c4)->R, &(*c4)->G, &(*c4)->B);
|
||||
|
||||
if(ret != 12) {
|
||||
printErr("Expected to read 12 values for color but read %d", ret);
|
||||
return false;
|
||||
|
||||
if(str_to_parse == NULL) {
|
||||
str_to_parse = emalloc(sizeof(char) * (strlen(color_to_copy) + 1));
|
||||
strcpy(str_to_parse, color_to_copy);
|
||||
}
|
||||
|
||||
//TODO: Refactor c1->R c2->R ... to c[i]->R
|
||||
if((*c1)->R < 0 || (*c1)->R > 255) {
|
||||
printErr("Red in color 1 is invalid. Must be in range (0, 255)");
|
||||
|
||||
ret = sscanf(str_to_parse, "%d,%d,%d:%d,%d,%d:%d,%d,%d:%d,%d,%d:%d,%d,%d",
|
||||
&c[0]->R, &c[0]->G, &c[0]->B,
|
||||
&c[1]->R, &c[1]->G, &c[1]->B,
|
||||
&c[2]->R, &c[2]->G, &c[2]->B,
|
||||
&c[3]->R, &c[3]->G, &c[3]->B,
|
||||
&c[4]->R, &c[4]->G, &c[4]->B);
|
||||
|
||||
int expected_colors = 3 * NUM_COLORS;
|
||||
if(ret != expected_colors) {
|
||||
printErr("Expected to read %d values for color but read %d", expected_colors, ret);
|
||||
return false;
|
||||
}
|
||||
if((*c1)->G < 0 || (*c1)->G > 255) {
|
||||
printErr("Green in color 1 is invalid. Must be in range (0, 255)");
|
||||
return false;
|
||||
|
||||
for(int i=0; i < NUM_COLORS; i++) {
|
||||
if(c[i]->R < 0 || c[i]->R > 255) {
|
||||
printErr("Red in color %d is invalid: %d; must be in range (0, 255)", i+1, c[i]->R);
|
||||
return false;
|
||||
}
|
||||
if(c[i]->G < 0 || c[i]->G > 255) {
|
||||
printErr("Green in color %d is invalid: %d; must be in range (0, 255)", i+1, c[i]->G);
|
||||
return false;
|
||||
}
|
||||
if(c[i]->B < 0 || c[i]->B > 255) {
|
||||
printErr("Blue in color %d is invalid: %d; must be in range (0, 255)", i+1, c[i]->B);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if((*c1)->B < 0 || (*c1)->B > 255) {
|
||||
printErr("Blue in color 1 is invalid. Must be in range (0, 255)");
|
||||
return false;
|
||||
}
|
||||
if((*c2)->R < 0 || (*c2)->R > 255) {
|
||||
printErr("Red in color 2 is invalid. Must be in range (0, 255)");
|
||||
return false;
|
||||
}
|
||||
if((*c2)->G < 0 || (*c2)->G > 255) {
|
||||
printErr("Green in color 2 is invalid. Must be in range (0, 255)");
|
||||
return false;
|
||||
}
|
||||
if((*c2)->B < 0 || (*c2)->B > 255) {
|
||||
printErr("Blue in color 2 is invalid. Must be in range (0, 255)");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if(free_ptr) free (str_to_parse);
|
||||
|
||||
return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char* build_short_options() {
|
||||
const char *c = args_chr;
|
||||
int len = sizeof(args_chr) / sizeof(args_chr[0]);
|
||||
char* str = (char *) malloc(sizeof(char) * (len*2 + 1));
|
||||
char* str = (char *) emalloc(sizeof(char) * (len*2 + 1));
|
||||
memset(str, 0, sizeof(char) * (len*2 + 1));
|
||||
|
||||
#ifdef ARCH_X86
|
||||
sprintf(str, "%c:%c:%c%c%c%c%c",
|
||||
c[ARG_STYLE], c[ARG_COLOR], c[ARG_HELP], c[ARG_RAW],
|
||||
c[ARG_DEBUG], c[ARG_VERBOSE], c[ARG_VERSION]);
|
||||
#else
|
||||
sprintf(str, "%c:%c:%c%c%c%c",
|
||||
sprintf(str, "%c:%c:%c%c%c%c%c%c%c%c%c%c%c",
|
||||
c[ARG_STYLE], c[ARG_COLOR], c[ARG_HELP],
|
||||
c[ARG_DEBUG], c[ARG_VERBOSE], c[ARG_VERSION]);
|
||||
c[ARG_RAW], c[ARG_FULLCPUNAME],
|
||||
c[ARG_LOGO_SHORT], c[ARG_LOGO_LONG],
|
||||
c[ARG_LOGO_INTEL_NEW], c[ARG_LOGO_INTEL_OLD],
|
||||
c[ARG_ACCURATE_PP], c[ARG_DEBUG], c[ARG_VERBOSE],
|
||||
c[ARG_VERSION]);
|
||||
#else
|
||||
sprintf(str, "%c:%c:%c%c%c%c%c%c",
|
||||
c[ARG_STYLE], c[ARG_COLOR], c[ARG_HELP],
|
||||
c[ARG_LOGO_SHORT], c[ARG_LOGO_LONG],
|
||||
c[ARG_DEBUG], c[ARG_VERBOSE],
|
||||
c[ARG_VERSION]);
|
||||
#endif
|
||||
|
||||
return str;
|
||||
@@ -204,27 +238,42 @@ char* build_short_options() {
|
||||
|
||||
bool parse_args(int argc, char* argv[]) {
|
||||
int opt;
|
||||
int option_index = 0;
|
||||
int option_index = 0;
|
||||
opterr = 0;
|
||||
|
||||
bool color_flag = false;
|
||||
args.debug_flag = false;
|
||||
args.accurate_pp = false;
|
||||
args.full_cpu_name_flag = false;
|
||||
args.raw_flag = false;
|
||||
args.verbose_flag = false;
|
||||
args.logo_long = false;
|
||||
args.logo_short = false;
|
||||
args.logo_intel_new = false;
|
||||
args.logo_intel_old = false;
|
||||
args.help_flag = false;
|
||||
args.style = STYLE_EMPTY;
|
||||
args.colors = NULL;
|
||||
|
||||
// Temporary enable verbose level to allow printing warnings inside parse_args
|
||||
set_log_level(true);
|
||||
|
||||
const struct option long_options[] = {
|
||||
{args_str[ARG_STYLE], required_argument, 0, args_chr[ARG_STYLE] },
|
||||
{args_str[ARG_COLOR], required_argument, 0, args_chr[ARG_COLOR] },
|
||||
{args_str[ARG_HELP], no_argument, 0, args_chr[ARG_HELP] },
|
||||
{args_str[ARG_STYLE], required_argument, 0, args_chr[ARG_STYLE] },
|
||||
{args_str[ARG_COLOR], required_argument, 0, args_chr[ARG_COLOR] },
|
||||
{args_str[ARG_HELP], no_argument, 0, args_chr[ARG_HELP] },
|
||||
#ifdef ARCH_X86
|
||||
{args_str[ARG_RAW], no_argument, 0, args_chr[ARG_RAW] },
|
||||
{args_str[ARG_LOGO_INTEL_NEW], no_argument, 0, args_chr[ARG_LOGO_INTEL_NEW] },
|
||||
{args_str[ARG_LOGO_INTEL_OLD], no_argument, 0, args_chr[ARG_LOGO_INTEL_OLD] },
|
||||
{args_str[ARG_ACCURATE_PP], no_argument, 0, args_chr[ARG_ACCURATE_PP] },
|
||||
{args_str[ARG_FULLCPUNAME], no_argument, 0, args_chr[ARG_FULLCPUNAME] },
|
||||
{args_str[ARG_RAW], no_argument, 0, args_chr[ARG_RAW] },
|
||||
#endif
|
||||
{args_str[ARG_DEBUG], no_argument, 0, args_chr[ARG_DEBUG] },
|
||||
{args_str[ARG_VERBOSE], no_argument, 0, args_chr[ARG_VERBOSE] },
|
||||
{args_str[ARG_VERSION], no_argument, 0, args_chr[ARG_VERSION] },
|
||||
{args_str[ARG_LOGO_SHORT], no_argument, 0, args_chr[ARG_LOGO_SHORT] },
|
||||
{args_str[ARG_LOGO_LONG], no_argument, 0, args_chr[ARG_LOGO_LONG] },
|
||||
{args_str[ARG_DEBUG], no_argument, 0, args_chr[ARG_DEBUG] },
|
||||
{args_str[ARG_VERBOSE], no_argument, 0, args_chr[ARG_VERBOSE] },
|
||||
{args_str[ARG_VERSION], no_argument, 0, args_chr[ARG_VERSION] },
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -237,9 +286,9 @@ bool parse_args(int argc, char* argv[]) {
|
||||
printErr("Color option specified more than once");
|
||||
return false;
|
||||
}
|
||||
color_flag = true;
|
||||
color_flag = true;
|
||||
args.colors = emalloc(sizeof(struct color *) * NUM_COLORS);
|
||||
if(!parse_color(optarg, &args.colors)) {
|
||||
printErr("Color parsing failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -253,11 +302,28 @@ bool parse_args(int argc, char* argv[]) {
|
||||
printErr("Invalid style '%s'",optarg);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if(opt == args_chr[ARG_HELP]) {
|
||||
args.help_flag = true;
|
||||
}
|
||||
else if(opt == args_chr[ARG_ACCURATE_PP]) {
|
||||
args.accurate_pp = true;
|
||||
}
|
||||
else if(opt == args_chr[ARG_FULLCPUNAME]) {
|
||||
args.full_cpu_name_flag = true;
|
||||
}
|
||||
else if(opt == args_chr[ARG_LOGO_SHORT]) {
|
||||
args.logo_short = true;
|
||||
}
|
||||
else if(opt == args_chr[ARG_LOGO_LONG]) {
|
||||
args.logo_long = true;
|
||||
}
|
||||
else if(opt == args_chr[ARG_LOGO_INTEL_NEW]) {
|
||||
args.logo_intel_new = true;
|
||||
}
|
||||
else if(opt == args_chr[ARG_LOGO_INTEL_OLD]) {
|
||||
args.logo_intel_old = true;
|
||||
}
|
||||
else if(opt == args_chr[ARG_RAW]) {
|
||||
args.raw_flag = true;
|
||||
}
|
||||
@@ -270,7 +336,7 @@ bool parse_args(int argc, char* argv[]) {
|
||||
else if(opt == args_chr[ARG_VERSION]) {
|
||||
args.version_flag = true;
|
||||
}
|
||||
else {
|
||||
else {
|
||||
printWarn("Invalid options");
|
||||
args.help_flag = true;
|
||||
}
|
||||
@@ -284,10 +350,27 @@ bool parse_args(int argc, char* argv[]) {
|
||||
args.help_flag = true;
|
||||
}
|
||||
|
||||
if((args.help_flag + args.version_flag + color_flag) > 1) {
|
||||
printWarn("You should specify just one option");
|
||||
if(args.logo_intel_new && args.logo_intel_old) {
|
||||
printWarn("%s and %s cannot be specified together", args_str[ARG_LOGO_INTEL_NEW], args_str[ARG_LOGO_INTEL_OLD]);
|
||||
args.logo_intel_new = false;
|
||||
args.logo_intel_old = false;
|
||||
}
|
||||
|
||||
if(args.logo_short && args.logo_long) {
|
||||
printWarn("%s and %s cannot be specified together", args_str[ARG_LOGO_SHORT], args_str[ARG_LOGO_LONG]);
|
||||
args.logo_short = false;
|
||||
args.logo_long = false;
|
||||
}
|
||||
|
||||
#if defined(ARCH_X86) && ! defined(__linux__)
|
||||
if(args.accurate_pp) {
|
||||
printWarn("%s option is valid only in Linux x86_64", args_str[ARG_ACCURATE_PP]);
|
||||
args.help_flag = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Leave log level untouched after returning
|
||||
set_log_level(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -10,17 +10,9 @@ struct color {
|
||||
int32_t B;
|
||||
};
|
||||
|
||||
struct colors {
|
||||
struct color* c1;
|
||||
struct color* c2;
|
||||
struct color* c3;
|
||||
struct color* c4;
|
||||
};
|
||||
|
||||
enum {
|
||||
STYLE_EMPTY,
|
||||
STYLE_FANCY,
|
||||
STYLE_WILD,
|
||||
STYLE_RETRO,
|
||||
STYLE_LEGACY,
|
||||
STYLE_INVALID
|
||||
@@ -31,6 +23,12 @@ enum {
|
||||
ARG_COLOR,
|
||||
ARG_HELP,
|
||||
ARG_RAW,
|
||||
ARG_FULLCPUNAME,
|
||||
ARG_LOGO_LONG,
|
||||
ARG_LOGO_SHORT,
|
||||
ARG_LOGO_INTEL_NEW,
|
||||
ARG_LOGO_INTEL_OLD,
|
||||
ARG_ACCURATE_PP,
|
||||
ARG_DEBUG,
|
||||
ARG_VERBOSE,
|
||||
ARG_VERSION
|
||||
@@ -44,12 +42,18 @@ extern const char *args_str[];
|
||||
int max_arg_str_length();
|
||||
bool parse_args(int argc, char* argv[]);
|
||||
bool show_help();
|
||||
bool accurate_pp();
|
||||
bool show_full_cpu_name();
|
||||
bool show_logo_long();
|
||||
bool show_logo_short();
|
||||
bool show_logo_intel_new();
|
||||
bool show_logo_intel_old();
|
||||
bool show_raw();
|
||||
bool show_debug();
|
||||
bool show_version();
|
||||
bool verbose_enabled();
|
||||
void free_colors_struct(struct colors* cs);
|
||||
struct colors* get_colors();
|
||||
void free_colors_struct(struct color** cs);
|
||||
struct color** get_colors();
|
||||
STYLE get_style();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,208 +1,329 @@
|
||||
#ifndef __ASCII__
|
||||
#define __ASCII__
|
||||
|
||||
#define NUMBER_OF_LINES 19
|
||||
#define LINE_SIZE 62
|
||||
#define COLOR_NONE ""
|
||||
#define C_FG_BLACK "\x1b[30;1m"
|
||||
#define C_FG_RED "\x1b[31;1m"
|
||||
#define C_FG_GREEN "\x1b[32;1m"
|
||||
#define C_FG_YELLOW "\x1b[33;1m"
|
||||
#define C_FG_BLUE "\x1b[34;1m"
|
||||
#define C_FG_MAGENTA "\x1b[35;1m"
|
||||
#define C_FG_CYAN "\x1b[36;1m"
|
||||
#define C_FG_WHITE "\x1b[37;1m"
|
||||
#define C_BG_BLACK "\x1b[40;1m"
|
||||
#define C_BG_RED "\x1b[41;1m"
|
||||
#define C_BG_GREEN "\x1b[42;1m"
|
||||
#define C_BG_YELLOW "\x1b[43;1m"
|
||||
#define C_BG_BLUE "\x1b[44;1m"
|
||||
#define C_BG_MAGENTA "\x1b[45;1m"
|
||||
#define C_BG_CYAN "\x1b[46;1m"
|
||||
#define C_BG_WHITE "\x1b[47;1m"
|
||||
#define C_FG_B_BLACK "\x1b[90;1m"
|
||||
#define C_FG_B_RED "\x1b[91;1m"
|
||||
#define C_FG_B_GREEN "\x1b[92;1m"
|
||||
#define C_FG_B_YELLOW "\x1b[93;1m"
|
||||
#define C_FG_B_BLUE "\x1b[94;1m"
|
||||
#define C_FG_B_MAGENTA "\x1b[95;1m"
|
||||
#define C_FG_B_CYAN "\x1b[96;1m"
|
||||
#define C_FG_B_WHITE "\x1b[97;1m"
|
||||
#define COLOR_RESET "\x1b[m"
|
||||
|
||||
#define AMD_ASCII \
|
||||
" \
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
@@@@ @@@ @@@ @@@@@@@@ ############ \
|
||||
@@@@@@ @@@@@ @@@@@ @@@ @@@ ########## \
|
||||
@@@ @@@ @@@@@@@@@@@@@ @@@ @@ # ##### \
|
||||
@@@ @@@ @@@ @@@ @@@ @@@ @@ ### ##### \
|
||||
@@@@@@@@@@@@ @@@ @@@ @@@ @@@ ######### ### \
|
||||
@@@ @@@ @@@ @@@ @@@@@@@@@ ######## ## \
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
"
|
||||
struct ascii_logo {
|
||||
char* art;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
bool replace_blocks;
|
||||
char color_ascii[3][100];
|
||||
char color_text[2][100];
|
||||
};
|
||||
|
||||
#define INTEL_ASCII \
|
||||
" ################ \
|
||||
####### ####### \
|
||||
#### #### \
|
||||
### #### \
|
||||
### ### \
|
||||
### ### \
|
||||
# ### ### ### \
|
||||
## ### ######### ###### ###### ### ### \
|
||||
## ### ### ### ### #### #### ### ### \
|
||||
## ### ### ### ### ### ### ### ### \
|
||||
## ### ### ### ### ########## ### #### \
|
||||
## ### ### ### ### ### ### ##### \
|
||||
## ## ### ### ##### ######### ## ### \
|
||||
### \
|
||||
### \
|
||||
#### #### \
|
||||
##### ########## \
|
||||
########## ################ \
|
||||
############################### "
|
||||
|
||||
#define SNAPDRAGON_ASCII \
|
||||
" \
|
||||
@@######## \
|
||||
@@@@@########### \
|
||||
@@ @@@@@################# \
|
||||
@@@@@@@@@@#################### \
|
||||
@@@@@@@@@@@@##################### \
|
||||
@@@@@@@@@@@@@@@#################### \
|
||||
@@@@@@@@@@@@@@@@@################### \
|
||||
@@@@@@@@@@@@@@@@@@@@################ \
|
||||
@@@@@@@@@@@@@@@@@@@@############# \
|
||||
@@@@@@@@@@@@@@@@@@############ \
|
||||
@ @@@@@@@@@@@@@@@########### \
|
||||
@@@@@ @@@@@@@@@@@@@########## \
|
||||
@@@@@@@@@ @@@@@@@@@@@@######## \
|
||||
@@@@@@@@@ @@@@@@@@@@####### \
|
||||
@@@@@@@@@@@@@@@@####### \
|
||||
@@@@########### \
|
||||
\
|
||||
"
|
||||
|
||||
#define MEDIATEK_ASCII \
|
||||
" \
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
## ## ###### ###### # ### @@@@@@ @@@@@@ @@ @@ \
|
||||
### ### # # # # #### @@ @ @@ @@ \
|
||||
######## # ### # # # ## ## @@ @ @@@ @@@@ \
|
||||
## ### ## # # # # ## ## @@ @ @@ @@ \
|
||||
## ## ## ###### ##### # ## ## @@ @@@@@@ @@ @@ \
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
"
|
||||
/*
|
||||
* ASCII logos brief documentation
|
||||
* ----------------------------------------------------
|
||||
* C1, C2, ...: ColorN, gets replaced by printer.c with
|
||||
* the color in ascii_logo->color_ascii[N]
|
||||
* CR: Color reset, gets replaced by the reset
|
||||
* color by printer.c
|
||||
*
|
||||
* Logos with replace_blocks=true are replaced by character
|
||||
* blocks (actually, spaces with background color), so
|
||||
* the color in the structure must be C_BG_XXX. When
|
||||
* replace_blocks is true, the characters '#' are replaced
|
||||
* by spaces printed with color_ascii[0], and '@' are
|
||||
* printed with color_ascii[1]. If replace_blocks=true,
|
||||
* color format specified in ASCIIs ($C1, $C2) are ignored.
|
||||
*
|
||||
* In any case, '$' is a illegal character to be used in
|
||||
* the ascii logos because it is used to parse colors
|
||||
*
|
||||
* LONG_LOGOS will be printed only if the fit in the screen,
|
||||
* otherwise SHORT_LOGOS will be used
|
||||
*/
|
||||
|
||||
#define EXYNOS_ASCII \
|
||||
" \
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
## ## ## \
|
||||
## ## \
|
||||
## \
|
||||
## ## \
|
||||
## ## ## \
|
||||
\
|
||||
SAMSUNG \
|
||||
Exynos \
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
"
|
||||
|
||||
#define KIRIN_ASCII \
|
||||
" \
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
####### \
|
||||
##### #################### \
|
||||
###################################### \
|
||||
####################################### \
|
||||
####################################### \
|
||||
############################## \
|
||||
########################## \
|
||||
######################### \
|
||||
######################## \
|
||||
######################## \
|
||||
######################### \
|
||||
######################### \
|
||||
\
|
||||
"
|
||||
|
||||
#define BROADCOM_ASCII \
|
||||
" \
|
||||
################ \
|
||||
######################### \
|
||||
############################### \
|
||||
################@@@@################ \
|
||||
################@@@@@@################ \
|
||||
#################@@@@@@################ \
|
||||
#################@@@@@@@@################# \
|
||||
#################@@@@@@@@################# \
|
||||
#################@@@@##@@@@################ \
|
||||
################@@@@##@@@@################ \
|
||||
###############@@@@####@@@@############### \
|
||||
@@@@@@@@@@####@@@@####@@@@####@@@@@@@@@@ \
|
||||
######@@@@@@@@@@######@@@@@@@@@@###### \
|
||||
################################## \
|
||||
############################## \
|
||||
######################## \
|
||||
############### \
|
||||
"
|
||||
|
||||
#define ARM_ASCII \
|
||||
" \
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
############ ########## #### ###### ######## \
|
||||
############### ######### ####################### \
|
||||
#### #### #### ##### ####### ##### \
|
||||
#### #### #### #### ##### #### \
|
||||
#### #### #### #### #### #### \
|
||||
#### ##### #### #### #### #### \
|
||||
############### #### #### #### #### \
|
||||
######## #### #### #### #### #### \
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
"
|
||||
// SHORT LOGOS //
|
||||
#define ASCII_AMD \
|
||||
"$C2 '############### \
|
||||
$C2 ,############# \
|
||||
$C2 .#### \
|
||||
$C2 #. .#### \
|
||||
$C2 :##. .#### \
|
||||
$C2 :###. .#### \
|
||||
$C2 #########. :## \
|
||||
$C2 #######. ; \
|
||||
$C1 \
|
||||
$C1 ### ### ### ####### \
|
||||
$C1 ## ## ##### ##### ## ## \
|
||||
$C1 ## ## ### #### ### ## ## \
|
||||
$C1 ######### ### ## ### ## ## \
|
||||
$C1## ## ### ### ## ## \
|
||||
$C1## ## ### ### ####### "
|
||||
|
||||
#define UNKNOWN_ASCII \
|
||||
" \
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
"
|
||||
|
||||
static const char* ASCII_ARRAY [] = {
|
||||
AMD_ASCII,
|
||||
INTEL_ASCII,
|
||||
ARM_ASCII,
|
||||
SNAPDRAGON_ASCII,
|
||||
MEDIATEK_ASCII,
|
||||
EXYNOS_ASCII,
|
||||
KIRIN_ASCII,
|
||||
BROADCOM_ASCII,
|
||||
UNKNOWN_ASCII
|
||||
};
|
||||
#define ASCII_INTEL \
|
||||
"$C1 .#################. \
|
||||
$C1 .#### ####. \
|
||||
$C1 .## ### \
|
||||
$C1 ## :## ### \
|
||||
$C1 # ## :## ## \
|
||||
$C1 ## ## ######. #### ###### :## ## \
|
||||
$C1 ## ## ##: ##: ## ## ### :## ### \
|
||||
$C1## ## ##: ##: ## :######## :## ## \
|
||||
$C1## ## ##: ##: ## ##. . :## #### \
|
||||
$C1## # ##: ##: #### #####: ## \
|
||||
$C1 ## \
|
||||
$C1 ###. ..o####. \
|
||||
$C1 ######oo... ..oo####### \
|
||||
$C1 o###############o "
|
||||
|
||||
#define ASCII_INTEL_NEW \
|
||||
"$C1 MMM oddl MMN \
|
||||
$C1 MMM dMMN MMN \
|
||||
$C1 ... .... ... dMMM.. .cc. NMN \
|
||||
$C1 MMM :MMMdWMMMMMX. dMMMMM, .XMMMMMMNo MMN \
|
||||
$C1 MMM :MMMp dMMM dMMX .NMW WMN. MMN \
|
||||
$C1 MMM :MMM WMM dMMK kMMXooooooNMMx MMN \
|
||||
$C1 MMM :MMM NMM dMMK dMMX MMN \
|
||||
$C1 MMM :MMM NMM dMMMoo OMM0....:Nx. MMN \
|
||||
$C1 MMM :WWW XWW lONMM 'xXMMMMNOc MMN "
|
||||
|
||||
#define ASCII_SNAPD \
|
||||
" $C1@@$C2######## \
|
||||
$C1@@@@@$C2########### \
|
||||
$C1@@ @@@@@$C2################# \
|
||||
$C1@@@@@@@@@@$C2#################### \
|
||||
$C1@@@@@@@@@@@@$C2##################### \
|
||||
$C1@@@@@@@@@@@@@@@$C2#################### \
|
||||
$C1@@@@@@@@@@@@@@@@@$C2################### \
|
||||
$C1@@@@@@@@@@@@@@@@@@@@$C2################ \
|
||||
$C1@@@@@@@@@@@@@@@@@@@@$C2############# \
|
||||
$C1@@@@@@@@@@@@@@@@@@$C2############ \
|
||||
$C1@ @@@@@@@@@@@@@@@$C2########### \
|
||||
$C1@@@@@ @@@@@@@@@@@@@$C2########## \
|
||||
$C1@@@@@@@@@ @@@@@@@@@@@@$C2######## \
|
||||
$C1@@@@@@@@@ @@@@@@@@@@$C2####### \
|
||||
$C1@@@@@@@@@@@@@@@@$C2####### \
|
||||
$C1@@@@$C2########### "
|
||||
|
||||
#define ASCII_MTK \
|
||||
"$C1 ## ## ###### ###### # ### $C2@@@@@@ @@@@@@ @@ @@ \
|
||||
$C1 ### ### # # # # #### $C2@@ @ @@ @@ \
|
||||
$C1 ######## # ### # # # ## ## $C2@@ @ @@@ @@@@ \
|
||||
$C1 ## ### ## # # # # ## ## $C2@@ @ @@ @@ \
|
||||
$C1## ## ## ###### ##### # ## ## $C2@@ @@@@@@ @@ @@ "
|
||||
|
||||
#define ASCII_EXYNOS \
|
||||
"$C2 \
|
||||
$C2 \
|
||||
$C2 \
|
||||
$C1##$CR $C1##$CR $C1##$CR \
|
||||
$C1##$CR $C1##$CR \
|
||||
$C1##$CR \
|
||||
$C1##$CR $C1##$CR \
|
||||
$C1##$CR $C1##$CR $C1##$CR \
|
||||
$C2 \
|
||||
$C2 SAMSUNG \
|
||||
$C2 Exynos \
|
||||
$C2 \
|
||||
$C2 "
|
||||
|
||||
#define ASCII_KIRIN \
|
||||
"$C1 ####### \
|
||||
$C1 ##### #################### \
|
||||
$C1 ###################################### \
|
||||
$C1 ####################################### \
|
||||
$C1 ####################################### \
|
||||
$C1 ############################## \
|
||||
$C1 ########################## \
|
||||
$C1 ######################### \
|
||||
$C1 ######################## \
|
||||
$C1 ######################## \
|
||||
$C1 ######################### \
|
||||
$C1######################### "
|
||||
|
||||
#define ASCII_BROADCOM \
|
||||
"$C2 \
|
||||
$C2 ################ \
|
||||
$C2 ########################## \
|
||||
$C2 ################################ \
|
||||
$C2 ################$C1@@@@$C2################ \
|
||||
$C2 ################$C1@@@@@@$C2################ \
|
||||
$C2 #################$C1@@@@@@$C2################# \
|
||||
$C2#################$C1@@@@@@@@$C2################# \
|
||||
$C2#################$C1@@@@@@@@$C2################# \
|
||||
$C2################$C1@@@@$C2##$C1@@@@$C2################ \
|
||||
$C2################$C1@@@@$C2##$C1@@@@$C2################ \
|
||||
$C2###############$C1@@@@$C2####$C1@@@@$C2############### \
|
||||
$C1 @@@@@@@@@@$C2####$C1@@@@$C2####$C1@@@@$C2####$C1@@@@@@@@@@ \
|
||||
$C2 ######$C1@@@@@@@@@@$C2######$C1@@@@@@@@@@$C2###### \
|
||||
$C2 ################################## \
|
||||
$C2 ############################## \
|
||||
$C2 ######################## \
|
||||
$C2 ############### \
|
||||
$C2 "
|
||||
|
||||
#define ASCII_ARM \
|
||||
"$C1 ##### ## # ##### ## #### ###### \
|
||||
$C1 ### #### ### #### ### ### \
|
||||
$C1### ## ### ### ## ### \
|
||||
$C1 ### #### ### ### ## ### \
|
||||
$C1 ###### ## ### ### ## ### "
|
||||
|
||||
#define ASCII_IBM \
|
||||
"$C1######## ########## ###### ###### \
|
||||
$C1######## ########### ####### ####### \
|
||||
$C1 #### ### #### ###### ###### \
|
||||
$C1 #### ### ### ####### ####### \
|
||||
$C1 #### ######## ############### \
|
||||
$C1 #### ### ### #### ##### #### \
|
||||
$C1 #### ### #### #### ### #### \
|
||||
$C1######## ########### ###### # ###### \
|
||||
$C1######## ########## ###### ###### "
|
||||
|
||||
// inspired by the neofetch mac logo
|
||||
#define ASCII_APPLE \
|
||||
"$C1 .\"c. \
|
||||
$C1 ,xNMM. \
|
||||
$C1 .lMM\" \
|
||||
$C1 MM* \
|
||||
$C1 .;loddo;:. olloddol;. \
|
||||
$C1 cKMMMMMMMMMMNWMMMMMMMMMMM0: \
|
||||
$C1 .KMMMMMMMMMMMMMMMMMMMMMMMW* \
|
||||
$C1 XMMMMMMMMMMMMMMMMMMMMMMMX. \
|
||||
$C1;MMMMMMMMMMMMMMMMMMMMMMMM: \
|
||||
$C1:MMMMMMMMMMMMMMMMMMMMMMMM: \
|
||||
$C1.MMMMMMMMMMMMMMMMMMMMMMMMX. \
|
||||
$C1 kMMMMMMMMMMMMMMMMMMMMMMMMWd. \
|
||||
$C1 'XMMMMMMMMMMMMMMMMMMMMMMMMMMk \
|
||||
$C1 'XMMMMMMMMMMMMMMMMMMMMMMMMK. \
|
||||
$C1 kMMMMMMMMMMMMMMMMMMMMMMd \
|
||||
$C1 'KMMMMMMMWXXWMMMMMMMk. \
|
||||
$C1 \"cooc\"* \"*coo'\" "
|
||||
|
||||
// --------------------- LONG LOGOS ------------------------- //
|
||||
#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 ######@ ######@ \
|
||||
$C1 ###@ ###@ \
|
||||
$C1 ##@ ###@ \
|
||||
$C1 ##@ ##@ \
|
||||
$C1 ##@ ##@ \
|
||||
$C1 @ ##@ ##@ ##@ \
|
||||
$C1 #@ ##@ ########@ #####@ #####@ ##@ ##@ \
|
||||
$C1 #@ ##@ ##@ ##@ ##@ ###@ ###@ ##@ ##@ \
|
||||
$C1 #@ ##@ ##@ ##@ ##@ ##@ ##@ ##@ ##@ \
|
||||
$C1 #@ ##@ ##@ ##@ ##@ #########@ ##@ ###@ \
|
||||
$C1 #@ ##@ ##@ ##@ ##@ ##@ ##@ ####@ \
|
||||
$C1 #@ #@ ##@ ##@ ####@ ########@ #@ ##@ \
|
||||
$C1 ##@ \
|
||||
$C1 ##@ \
|
||||
$C1 ###@ ###@ \
|
||||
$C1 ####@ #########@ \
|
||||
$C1 #########@ ###############@ \
|
||||
$C1 ##############################@ "
|
||||
|
||||
#define ASCII_INTEL_L_NEW \
|
||||
" ####################################################### \
|
||||
####################################################### \
|
||||
####%%%#################@@@#####################@@@#### \
|
||||
####%%%#################@@@#####################@@@#### \
|
||||
########################@@@#####################@@@#### \
|
||||
####@@@##@@@#@@@@@@@####@@@@@@####@@@@@@@@@#####@@@#### \
|
||||
####@@@##@@@@@@@@@@@@###@@@@@@##@@@@#####@@@@###@@@#### \
|
||||
####@@@##@@@@#####@@@@##@@@####@@@@#######@@@@##@@@#### \
|
||||
####@@@##@@@#######@@@##@@@####@@@@@@@@@@@@@@@##@@@#### \
|
||||
####@@@##@@@#######@@@##@@@####@@@@#############@@@#### \
|
||||
####@@@##@@@#######@@@##@@@@@@##@@@@#####@@@@###@@@#### \
|
||||
####@@@##@@@#######@@@###@@@@@####@@@@@@@@@#####@@@#### \
|
||||
####################################################### \
|
||||
####################################################### "
|
||||
|
||||
#define ASCII_ARM_L \
|
||||
"$C1 ############ ########## #### ####### ######## \
|
||||
$C1 ############### ######### ######################## \
|
||||
$C1 #### #### #### ##### ######## ##### \
|
||||
$C1#### #### #### #### ###### #### \
|
||||
$C1#### #### #### #### #### #### \
|
||||
$C1 #### ##### #### #### #### #### \
|
||||
$C1 ############### #### #### #### #### \
|
||||
$C1 ######## #### #### #### #### #### "
|
||||
|
||||
#define ASCII_IBM_L \
|
||||
"$C1 ############ ################ ########## ########## \
|
||||
$C1 \
|
||||
$C1 ############ ################## ############ ############ \
|
||||
$C1 \
|
||||
$C1 ###### ###### ###### #################### \
|
||||
$C1 \
|
||||
$C1 ###### ############## #################### \
|
||||
$C1 \
|
||||
$C1 ###### ###### ###### ##### ###### ##### \
|
||||
$C1 \
|
||||
$C1 ############ ################## ######### #### ######### \
|
||||
$C1 \
|
||||
$C1 ############ ################ ######### ## ######### "
|
||||
|
||||
typedef struct ascii_logo asciiL;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------+
|
||||
// | LOGO | W | H | REPLACE | COLORS LOGO (>0 && <10) | COLORS TEXT (=2) |
|
||||
// ------------------------------------------------------------------------------------------------------+
|
||||
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} };
|
||||
asciiL logo_intel_new = { ASCII_INTEL_NEW, 51, 9, false, {C_FG_CYAN}, {C_FG_CYAN, C_FG_WHITE} };
|
||||
asciiL logo_snapd = { ASCII_SNAPD, 39, 16, false, {C_FG_RED, C_FG_WHITE}, {C_FG_RED, C_FG_WHITE} };
|
||||
asciiL logo_mtk = { ASCII_MTK, 59, 5, false, {C_FG_BLUE, C_FG_YELLOW}, {C_FG_BLUE, C_FG_YELLOW} };
|
||||
asciiL logo_exynos = { ASCII_EXYNOS, 22, 13, true, {C_BG_BLUE, C_FG_WHITE}, {C_FG_BLUE, C_FG_WHITE} };
|
||||
asciiL logo_kirin = { ASCII_KIRIN, 53, 12, false, {C_FG_RED}, {C_FG_WHITE, C_FG_RED} };
|
||||
asciiL logo_broadcom = { ASCII_BROADCOM, 44, 19, false, {C_FG_WHITE, C_FG_RED}, {C_FG_WHITE, C_FG_RED} };
|
||||
asciiL logo_arm = { ASCII_ARM, 42, 5, false, {C_FG_CYAN}, {C_FG_WHITE, C_FG_CYAN} };
|
||||
asciiL logo_ibm = { ASCII_IBM, 42, 9, false, {C_FG_CYAN, C_FG_WHITE}, {C_FG_CYAN, C_FG_WHITE} };
|
||||
asciiL logo_apple = { ASCII_APPLE, 32, 17, false, {C_FG_WHITE}, {C_FG_B_BLACK, C_FG_B_WHITE} };
|
||||
// Long variants | ----------------------------------------------------------------------------------------------------|
|
||||
asciiL logo_amd_l = { ASCII_AMD_L, 62, 19, true, {C_BG_WHITE, C_BG_GREEN}, {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_intel_l_new = { ASCII_INTEL_L_NEW, 57, 14, true, {C_BG_CYAN, C_BG_WHITE, C_BG_BLUE}, {C_FG_CYAN, C_FG_WHITE} };
|
||||
asciiL logo_arm_l = { ASCII_ARM_L, 60, 8, true, {C_BG_CYAN}, {C_FG_WHITE, C_FG_CYAN} };
|
||||
asciiL logo_ibm_l = { ASCII_IBM_L, 62, 13, true, {C_BG_CYAN, C_FG_WHITE}, {C_FG_CYAN, C_FG_WHITE} };
|
||||
asciiL logo_unknown = { NULL, 0, 0, false, {COLOR_NONE}, {COLOR_NONE, COLOR_NONE} };
|
||||
|
||||
#endif
|
||||
|
||||
158
src/common/cpu.c
158
src/common/cpu.c
@@ -9,11 +9,15 @@
|
||||
|
||||
#ifdef ARCH_X86
|
||||
#include "../x86/uarch.h"
|
||||
#include "../x86/apic.h"
|
||||
#elif ARCH_PPC
|
||||
#include "../ppc/uarch.h"
|
||||
#elif ARCH_ARM
|
||||
#include "../arm/uarch.h"
|
||||
#endif
|
||||
|
||||
#define STRING_UNKNOWN "Unknown"
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
#define STRING_YES "Yes"
|
||||
#define STRING_NO "No"
|
||||
#define STRING_NONE "None"
|
||||
@@ -30,13 +34,20 @@ int64_t get_freq(struct frequency* freq) {
|
||||
return freq->max;
|
||||
}
|
||||
|
||||
#ifdef ARCH_X86
|
||||
char* get_str_cpu_name(struct cpuInfo* cpu) {
|
||||
return cpu->cpu_name;
|
||||
#if defined(ARCH_X86) || defined(ARCH_PPC)
|
||||
char* get_str_cpu_name(struct cpuInfo* cpu, bool fcpuname) {
|
||||
#ifdef ARCH_X86
|
||||
if(!fcpuname) {
|
||||
return get_str_cpu_name_abbreviated(cpu);
|
||||
}
|
||||
#elif ARCH_PPC
|
||||
UNUSED(fcpuname);
|
||||
#endif
|
||||
return cpu->cpu_name;
|
||||
}
|
||||
|
||||
char* get_str_sockets(struct topology* topo) {
|
||||
char* string = malloc(sizeof(char) * 2);
|
||||
char* string = emalloc(sizeof(char) * 2);
|
||||
int32_t sanity_ret = snprintf(string, 2, "%d", topo->sockets);
|
||||
if(sanity_ret < 0) {
|
||||
printBug("get_str_sockets: snprintf returned a negative value for input: '%d'", topo->sockets);
|
||||
@@ -51,71 +62,58 @@ uint32_t get_nsockets(struct topology* topo) {
|
||||
#endif
|
||||
|
||||
int32_t get_value_as_smallest_unit(char ** str, uint32_t value) {
|
||||
int32_t sanity_ret;
|
||||
*str = malloc(sizeof(char)* 11); //8 for digits, 2 for units
|
||||
int32_t ret;
|
||||
int max_len = 10; // Max is 8 for digits, 2 for units
|
||||
*str = emalloc(sizeof(char)* (max_len + 1));
|
||||
|
||||
if(value/1024 >= 1024)
|
||||
sanity_ret = snprintf(*str, 10,"%.4g"STRING_MEGABYTES, (double)value/(1<<20));
|
||||
ret = snprintf(*str, max_len, "%.4g"STRING_MEGABYTES, (double)value/(1<<20));
|
||||
else
|
||||
sanity_ret = snprintf(*str, 10,"%.4g"STRING_KILOBYTES, (double)value/(1<<10));
|
||||
|
||||
return sanity_ret;
|
||||
ret = snprintf(*str, max_len, "%.4g"STRING_KILOBYTES, (double)value/(1<<10));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// String functions
|
||||
// String functions
|
||||
char* get_str_cache_two(int32_t cache_size, uint32_t physical_cores) {
|
||||
// 4 for digits, 2 for units, 2 for ' (', 3 digits, 2 for units and 7 for ' Total)'
|
||||
uint32_t max_size = 4+2 + 2 + 4+2 + 7 + 1;
|
||||
int32_t sanity_ret;
|
||||
char* string = malloc(sizeof(char) * max_size);
|
||||
char* tmp1;
|
||||
char* tmp2;
|
||||
char* tmp2;
|
||||
int32_t tmp1_len = get_value_as_smallest_unit(&tmp1, cache_size);
|
||||
int32_t tmp2_len = get_value_as_smallest_unit(&tmp2, cache_size * physical_cores);
|
||||
|
||||
|
||||
// tmp1_len for first output, 2 for ' (', tmp2_len for second output and 7 for ' Total)'
|
||||
uint32_t size = tmp1_len + 2 + tmp2_len + 7 + 1;
|
||||
char* string = emalloc(sizeof(char) * size);
|
||||
|
||||
if(tmp1_len < 0) {
|
||||
printBug("get_value_as_smallest_unit: snprintf returned a negative value for input: %d\n", cache_size);
|
||||
return NULL;
|
||||
printBug("get_value_as_smallest_unit: snprintf failed for input: %d\n", cache_size);
|
||||
return NULL;
|
||||
}
|
||||
if(tmp2_len < 0) {
|
||||
printBug("get_value_as_smallest_unit: snprintf returned a negative value for input: %d\n", cache_size * physical_cores);
|
||||
return NULL;
|
||||
printBug("get_value_as_smallest_unit: snprintf failed for input: %d\n", cache_size * physical_cores);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t size = tmp1_len + 2 + tmp2_len + 7 + 1;
|
||||
sanity_ret = snprintf(string, size, "%s (%s Total)", tmp1, tmp2);
|
||||
|
||||
if(sanity_ret < 0) {
|
||||
printBug("get_str_cache_two: snprintf returned a negative value for input: '%s' and '%s'\n", tmp1, tmp2);
|
||||
return NULL;
|
||||
|
||||
if(snprintf(string, size, "%s (%s Total)", tmp1, tmp2) < 0) {
|
||||
printBug("get_str_cache_two: snprintf failed for input: '%s' and '%s'\n", tmp1, tmp2);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
free(tmp1);
|
||||
free(tmp2);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
char* get_str_cache_one(int32_t cache_size) {
|
||||
// 4 for digits, 2 for units, 2 for ' (', 3 digits, 2 for units and 7 for ' Total)'
|
||||
uint32_t max_size = 4+2 + 1;
|
||||
int32_t sanity_ret;
|
||||
char* string = malloc(sizeof(char) * max_size);
|
||||
char* tmp;
|
||||
int32_t tmp_len = get_value_as_smallest_unit(&tmp, cache_size);
|
||||
|
||||
if(tmp_len < 0) {
|
||||
printBug("get_value_as_smallest_unit: snprintf returned a negative value for input: %d", cache_size);
|
||||
return NULL;
|
||||
char* string;
|
||||
int32_t str_len = get_value_as_smallest_unit(&string, cache_size);
|
||||
|
||||
if(str_len < 0) {
|
||||
printBug("get_value_as_smallest_unit: snprintf failed for input: %d", cache_size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t size = tmp_len + 1;
|
||||
sanity_ret = snprintf(string, size, "%s", tmp);
|
||||
|
||||
if(sanity_ret < 0) {
|
||||
printBug("get_str_cache_one: snprintf returned a negative value for input: '%s'", tmp);
|
||||
return NULL;
|
||||
}
|
||||
free(tmp);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
@@ -141,7 +139,7 @@ char* get_str_l2(struct cache* cach) {
|
||||
|
||||
char* get_str_l3(struct cache* cach) {
|
||||
if(!cach->L3->exists)
|
||||
return NULL;
|
||||
return NULL;
|
||||
return get_str_cache(cach->L3->size, cach->L3->num_caches);
|
||||
}
|
||||
|
||||
@@ -149,7 +147,7 @@ char* get_str_freq(struct frequency* freq) {
|
||||
//Max 3 digits and 3 for '(M/G)Hz' plus 1 for '\0'
|
||||
uint32_t size = (5+1+3+1);
|
||||
assert(strlen(STRING_UNKNOWN)+1 <= size);
|
||||
char* string = malloc(sizeof(char)*size);
|
||||
char* string = emalloc(sizeof(char)*size);
|
||||
memset(string, 0, sizeof(char)*size);
|
||||
|
||||
if(freq->max == UNKNOWN_FREQ || freq->max < 0)
|
||||
@@ -162,6 +160,64 @@ char* get_str_freq(struct frequency* freq) {
|
||||
return string;
|
||||
}
|
||||
|
||||
char* get_str_peak_performance(int64_t flops) {
|
||||
char* str;
|
||||
|
||||
if(flops == -1) {
|
||||
str = emalloc(sizeof(char) * (strlen(STRING_UNKNOWN) + 1));
|
||||
strncpy(str, STRING_UNKNOWN, strlen(STRING_UNKNOWN) + 1);
|
||||
return str;
|
||||
}
|
||||
|
||||
// 7 for digits (e.g, XXXX.XX), 7 for XFLOP/s
|
||||
double flopsd = (double) flops;
|
||||
uint32_t max_size = 7+1+7+1;
|
||||
str = ecalloc(max_size, sizeof(char));
|
||||
|
||||
if(flopsd >= (double)1000000000000.0)
|
||||
snprintf(str, max_size, "%.2f TFLOP/s", flopsd/1000000000000);
|
||||
else if(flopsd >= 1000000000.0)
|
||||
snprintf(str, max_size, "%.2f GFLOP/s", flopsd/1000000000);
|
||||
else
|
||||
snprintf(str, max_size, "%.2f MFLOP/s", flopsd/1000000);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
void init_topology_struct(struct topology* topo, struct cache* cach) {
|
||||
topo->total_cores = 0;
|
||||
topo->cach = cach;
|
||||
#if defined(ARCH_X86) || defined(ARCH_PPC)
|
||||
topo->physical_cores = 0;
|
||||
topo->logical_cores = 0;
|
||||
topo->smt_supported = 0;
|
||||
topo->sockets = 0;
|
||||
#ifdef ARCH_X86
|
||||
topo->smt_available = 0;
|
||||
topo->apic = emalloc(sizeof(struct apic));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void init_cache_struct(struct cache* cach) {
|
||||
cach->L1i = emalloc(sizeof(struct cach));
|
||||
cach->L1d = emalloc(sizeof(struct cach));
|
||||
cach->L2 = emalloc(sizeof(struct cach));
|
||||
cach->L3 = emalloc(sizeof(struct cach));
|
||||
|
||||
cach->cach_arr = emalloc(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;
|
||||
}
|
||||
|
||||
void free_cache_struct(struct cache* cach) {
|
||||
for(int i=0; i < 4; i++) free(cach->cach_arr[i]);
|
||||
free(cach->cach_arr);
|
||||
|
||||
@@ -10,6 +10,7 @@ enum {
|
||||
CPU_VENDOR_AMD,
|
||||
// ARCH_ARM
|
||||
CPU_VENDOR_ARM,
|
||||
CPU_VENDOR_APPLE,
|
||||
CPU_VENDOR_BROADCOM,
|
||||
CPU_VENDOR_CAVIUM,
|
||||
CPU_VENDOR_NVIDIA,
|
||||
@@ -69,14 +70,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 {
|
||||
@@ -94,7 +97,9 @@ struct features {
|
||||
bool SSE4_2;
|
||||
bool FMA3;
|
||||
bool FMA4;
|
||||
bool SHA;
|
||||
bool SHA;
|
||||
#elif ARCH_PPC
|
||||
bool altivec;
|
||||
#elif ARCH_ARM
|
||||
bool NEON;
|
||||
bool SHA1;
|
||||
@@ -111,16 +116,22 @@ struct cpuInfo {
|
||||
struct cache* cach;
|
||||
struct topology* topo;
|
||||
struct features* feat;
|
||||
|
||||
#ifdef ARCH_X86
|
||||
int64_t peak_performance;
|
||||
|
||||
#if defined(ARCH_X86) || defined(ARCH_PPC)
|
||||
// CPU name from model
|
||||
char* cpu_name;
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_X86
|
||||
// Max cpuids levels
|
||||
uint32_t maxLevels;
|
||||
// Max cpuids extended levels
|
||||
uint32_t maxExtendedLevels;
|
||||
// Topology Extensions (AMD only)
|
||||
bool topology_extensions;
|
||||
#elif ARCH_PPC
|
||||
uint32_t pvr;
|
||||
#elif ARCH_ARM
|
||||
// Main ID register
|
||||
uint32_t midr;
|
||||
@@ -136,8 +147,8 @@ struct cpuInfo {
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef ARCH_X86
|
||||
char* get_str_cpu_name(struct cpuInfo* cpu);
|
||||
#if defined(ARCH_X86) || defined(ARCH_PPC)
|
||||
char* get_str_cpu_name(struct cpuInfo* cpu, bool fcpuname);
|
||||
char* get_str_sockets(struct topology* topo);
|
||||
uint32_t get_nsockets(struct topology* topo);
|
||||
#endif
|
||||
@@ -152,6 +163,10 @@ char* get_str_l1d(struct cache* cach);
|
||||
char* get_str_l2(struct cache* cach);
|
||||
char* get_str_l3(struct cache* cach);
|
||||
char* get_str_freq(struct frequency* freq);
|
||||
char* get_str_peak_performance(int64_t flops);
|
||||
|
||||
void init_topology_struct(struct topology* topo, struct cache* cach);
|
||||
void init_cache_struct(struct cache* cach);
|
||||
|
||||
void free_cache_struct(struct cache* cach);
|
||||
void free_freq_struct(struct frequency* freq);
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -53,10 +57,10 @@ void printBug(const char *fmt, ...) {
|
||||
vsnprintf(buffer,buffer_size, fmt, args);
|
||||
va_end(args);
|
||||
fprintf(stderr,RED "[ERROR]: "RESET "%s\n",buffer);
|
||||
#ifdef ARCH_X86
|
||||
fprintf(stderr,"Please, create a new issue with this error message and the output of 'cpufetch --debug' in https://github.com/Dr-Noob/cpufetch/issues\n");
|
||||
#if defined(ARCH_X86) || defined(ARCH_PPC)
|
||||
fprintf(stderr, "Please, create a new issue with this error message, the output of 'cpufetch' and 'cpufetch --debug' on https://github.com/Dr-Noob/cpufetch/issues\n");
|
||||
#elif ARCH_ARM
|
||||
fprintf(stderr,"Please, create a new issue with this error message, your smartphone/computer model and the output of 'cpufetch --debug' in https://github.com/Dr-Noob/cpufetch/issues\n");
|
||||
fprintf(stderr, "Please, create a new issue with this error message, your smartphone/computer model, the output of 'cpufetch' and 'cpufetch --debug' on https://github.com/Dr-Noob/cpufetch/issues\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -68,3 +72,42 @@ void set_log_level(bool verbose) {
|
||||
int max(int a, int b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
int min(int a, int b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
char *strremove(char *str, const char *sub) {
|
||||
char *p, *q, *r;
|
||||
if (*sub && (q = r = strstr(str, sub)) != NULL) {
|
||||
size_t len = strlen(sub);
|
||||
while ((r = strstr(p = r + len, sub)) != NULL) {
|
||||
memmove(q, p, r - p);
|
||||
q += r - p;
|
||||
}
|
||||
memmove(q, p, strlen(p) + 1);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
void* emalloc(size_t size) {
|
||||
void* ptr = malloc(size);
|
||||
|
||||
if(ptr == NULL) {
|
||||
printErr("malloc failed: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* ecalloc(size_t nmemb, size_t size) {
|
||||
void* ptr = calloc(nmemb, size);
|
||||
|
||||
if(ptr == NULL) {
|
||||
printErr("calloc failed: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -2,11 +2,18 @@
|
||||
#define __GLOBAL__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define STRING_UNKNOWN "Unknown"
|
||||
|
||||
void set_log_level(bool verbose);
|
||||
void printWarn(const char *fmt, ...);
|
||||
void printErr(const char *fmt, ...);
|
||||
void printBug(const char *fmt, ...);
|
||||
int min(int a, int b);
|
||||
int max(int a, int b);
|
||||
char *strremove(char *str, const char *sub);
|
||||
void* emalloc(size_t size);
|
||||
void* ecalloc(size_t nmemb, size_t size);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,67 +9,105 @@
|
||||
#ifdef ARCH_X86
|
||||
static const char* ARCH_STR = "x86_64 build";
|
||||
#include "../x86/cpuid.h"
|
||||
#elif ARCH_PPC
|
||||
static const char* ARCH_STR = "PowerPC build";
|
||||
#include "../ppc/ppc.h"
|
||||
#elif ARCH_ARM
|
||||
static const char* ARCH_STR = "ARM build";
|
||||
#include "../arm/midr.h"
|
||||
#endif
|
||||
|
||||
static const char* VERSION = "0.97";
|
||||
#ifdef __linux__
|
||||
#ifdef __ANDROID__
|
||||
static const char* OS_STR = "Android";
|
||||
#else
|
||||
static const char* OS_STR = "Linux";
|
||||
#endif
|
||||
#elif __FreeBSD__
|
||||
static const char* OS_STR = "FreeBSD";
|
||||
#elif _WIN32
|
||||
static const char* OS_STR = "Windows";
|
||||
#elif defined __APPLE__ || __MACH__
|
||||
static const char* OS_STR = "macOS";
|
||||
#else
|
||||
static const char* OS_STR = "Unknown OS";
|
||||
#endif
|
||||
|
||||
static const char* VERSION = "1.00";
|
||||
|
||||
void print_help(char *argv[]) {
|
||||
const char **t = args_str;
|
||||
const char *c = args_chr;
|
||||
const char *c = args_chr;
|
||||
int max_len = max_arg_str_length();
|
||||
|
||||
printf("Usage: %s [OPTION]...\n", argv[0]);
|
||||
printf("Simple yet fancy CPU architecture fetching tool\n\n");
|
||||
|
||||
printf("Options: \n");
|
||||
printf("OPTIONS: \n");
|
||||
printf(" -%c, --%s %*s Set the color scheme (by default, cpufetch uses the system color scheme)\n", c[ARG_COLOR], t[ARG_COLOR], (int) (max_len-strlen(t[ARG_COLOR])), "");
|
||||
printf(" -%c, --%s %*s Set the style of CPU art\n", c[ARG_STYLE], t[ARG_STYLE], (int) (max_len-strlen(t[ARG_STYLE])), "");
|
||||
printf(" -%c, --%s %*s Set the style of CPU logo\n", c[ARG_STYLE], t[ARG_STYLE], (int) (max_len-strlen(t[ARG_STYLE])), "");
|
||||
#ifdef ARCH_X86
|
||||
printf(" -%c, --%s %*s Prints CPU model and cpuid levels (debug purposes)\n", c[ARG_DEBUG], t[ARG_DEBUG], (int) (max_len-strlen(t[ARG_DEBUG])), "");
|
||||
printf(" -%c, --%s %*s Print CPU model and cpuid levels (debug purposes)\n", c[ARG_DEBUG], t[ARG_DEBUG], (int) (max_len-strlen(t[ARG_DEBUG])), "");
|
||||
#elif ARCH_PPC
|
||||
printf(" -%c, --%s %*s Print PVR register (debug purposes)\n", c[ARG_DEBUG], t[ARG_DEBUG], (int) (max_len-strlen(t[ARG_DEBUG])), "");
|
||||
#elif ARCH_ARM
|
||||
printf(" -%c, --%s %*s Prints main ID register values for all cores (debug purposes)\n", c[ARG_DEBUG], t[ARG_DEBUG], (int) (max_len-strlen(t[ARG_DEBUG])), "");
|
||||
printf(" -%c, --%s %*s Print main ID register values (debug purposes)\n", c[ARG_DEBUG], t[ARG_DEBUG], (int) (max_len-strlen(t[ARG_DEBUG])), "");
|
||||
#endif
|
||||
printf(" -%c, --%s %*s Prints extra information (if available) about how cpufetch tried fetching information\n", c[ARG_VERBOSE], t[ARG_VERBOSE], (int) (max_len-strlen(t[ARG_VERBOSE])), "");
|
||||
printf(" --%s %*s Show the short version of the logo\n", t[ARG_LOGO_SHORT], (int) (max_len-strlen(t[ARG_LOGO_SHORT])), "");
|
||||
printf(" --%s %*s Show the long version of the logo\n", t[ARG_LOGO_LONG], (int) (max_len-strlen(t[ARG_LOGO_LONG])), "");
|
||||
printf(" -%c, --%s %*s Print extra information (if available) about how cpufetch tried fetching information\n", c[ARG_VERBOSE], t[ARG_VERBOSE], (int) (max_len-strlen(t[ARG_VERBOSE])), "");
|
||||
#ifdef ARCH_X86
|
||||
printf(" -%c, --%s %*s Prints raw cpuid data\n", c[ARG_RAW], t[ARG_RAW], (int) (max_len-strlen(t[ARG_RAW])), "");
|
||||
#ifdef __linux__
|
||||
printf(" --%s %*s Compute the peak performance accurately (measure the CPU frequency instead of using the maximum)\n", t[ARG_ACCURATE_PP], (int) (max_len-strlen(t[ARG_ACCURATE_PP])), "");
|
||||
#endif
|
||||
printf(" -%c, --%s %*s Prints this help and exit\n", c[ARG_HELP], t[ARG_HELP], (int) (max_len-strlen(t[ARG_HELP])), "");
|
||||
printf(" -%c, --%s %*s Prints cpufetch version and exit\n", c[ARG_VERSION], t[ARG_VERSION], (int) (max_len-strlen(t[ARG_VERSION])), "");
|
||||
|
||||
printf(" --%s %*s Show the old Intel logo\n", t[ARG_LOGO_INTEL_OLD], (int) (max_len-strlen(t[ARG_LOGO_INTEL_OLD])), "");
|
||||
printf(" --%s %*s Show the new Intel logo\n", t[ARG_LOGO_INTEL_NEW], (int) (max_len-strlen(t[ARG_LOGO_INTEL_NEW])), "");
|
||||
printf(" -%c, --%s %*s Show the full CPU name (do not abbreviate it)\n", c[ARG_FULLCPUNAME], t[ARG_FULLCPUNAME], (int) (max_len-strlen(t[ARG_FULLCPUNAME])), "");
|
||||
printf(" -%c, --%s %*s Print raw cpuid data (debug purposes)\n", c[ARG_RAW], t[ARG_RAW], (int) (max_len-strlen(t[ARG_RAW])), "");
|
||||
#endif
|
||||
printf(" -%c, --%s %*s Print this help and exit\n", c[ARG_HELP], t[ARG_HELP], (int) (max_len-strlen(t[ARG_HELP])), "");
|
||||
printf(" -%c, --%s %*s Print cpufetch version and exit\n", c[ARG_VERSION], t[ARG_VERSION], (int) (max_len-strlen(t[ARG_VERSION])), "");
|
||||
|
||||
printf("\nCOLORS: \n");
|
||||
printf(" * \"intel\": Use Intel default color scheme \n");
|
||||
printf(" * \"amd\": Use AMD default color scheme \n");
|
||||
printf(" * \"ibm\", Use IBM default color scheme \n");
|
||||
printf(" * \"arm\": Use ARM default color scheme \n");
|
||||
printf(" * custom: If color argument do not match \"intel\", \"amd\" or \"arm\", a custom scheme can be specified.\n");
|
||||
printf(" 4 colors must be given in RGB with the format: R,G,B:R,G,B:...\n");
|
||||
printf(" The first 2 colors are the CPU art color and the next 2 colors are the text colors\n");
|
||||
|
||||
printf(" * custom: If the argument of --color does not match any of the previous strings, a custom scheme can be specified.\n");
|
||||
printf(" 5 colors must be given in RGB with the format: R,G,B:R,G,B:...\n");
|
||||
printf(" The first 3 colors are the CPU art color and the next 2 colors are the text colors\n");
|
||||
|
||||
printf("\nSTYLES: \n");
|
||||
printf(" * \"fancy\": Default style\n");
|
||||
printf(" * \"retro\": Old cpufetch style\n");
|
||||
printf(" * \"legacy\": Fallback style for terminals that do not support colors\n");
|
||||
|
||||
|
||||
printf("\nLOGOS: \n");
|
||||
printf(" cpufetch will try to adapt the logo size and the text to the terminal width. When the output (logo and text) is wider than\n");
|
||||
printf(" the terminal width, cpufetch will print a smaller version of the logo (if it exists). This behavior can be overridden by\n");
|
||||
printf(" --logo-short and --logo-long, which always sets the logo size as specified by the user, even if it is too big. After the\n");
|
||||
printf(" logo selection (either automatically or set by the user), cpufetch will check again if the output fits in the terminal.\n");
|
||||
printf(" If not, it will use a shorter name for the fields (the left part of the text). If, after all of this, the output still does\n");
|
||||
printf(" not fit, cpufetch will cut the text and will only print the text until there is no space left in each line\n");
|
||||
|
||||
printf("\nEXAMPLES: \n");
|
||||
printf(" Run cpufetch with Intel color scheme:\n");
|
||||
printf(" ./cpufetch --color intel\n");
|
||||
printf(" Run cpufetch with a custom color scheme:\n");
|
||||
printf(" ./cpufetch --color 239,90,45:210,200,200:100,200,45:0,200,200\n");
|
||||
|
||||
printf(" Run cpufetch with Intel color scheme:\n");
|
||||
printf(" ./cpufetch --color intel\n");
|
||||
printf(" Run cpufetch with a custom color scheme:\n");
|
||||
printf(" ./cpufetch --color 239,90,45:210,200,200:0,0,0:100,200,45:0,200,200\n");
|
||||
|
||||
printf("\nBUGS: \n");
|
||||
printf(" Report bugs to https://github.com/Dr-Noob/cpufetch/issues\n");
|
||||
|
||||
|
||||
printf("\nNOTE: \n");
|
||||
printf(" Peak performance information is NOT accurate. cpufetch computes peak performance using the max\n");
|
||||
printf(" frequency. However, to properly compute peak performance, you need to know the frequency of the\n");
|
||||
printf(" CPU running AVX code, which is not be fetched by cpufetch since it depends on each specific CPU.\n");
|
||||
printf(" For peak performance measurement see: https://github.com/Dr-Noob/peakperf\n");
|
||||
printf(" frequency of the CPU. However, to compute the peak performance, you need to know the frequency of the\n");
|
||||
printf(" CPU running AVX code. This value is not be fetched by cpufetch since it depends on each specific CPU.\n");
|
||||
printf(" To correctly measure peak performance, see: https://github.com/Dr-Noob/peakperf\n");
|
||||
}
|
||||
|
||||
void print_version() {
|
||||
printf("cpufetch v%s (%s)\n",VERSION, ARCH_STR);
|
||||
printf("cpufetch v%s (%s %s)\n",VERSION, OS_STR, ARCH_STR);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
@@ -97,7 +135,8 @@ int main(int argc, char* argv[]) {
|
||||
print_debug(cpu);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
// TODO: This should be moved to the end of args.c
|
||||
if(show_raw()) {
|
||||
#ifdef ARCH_X86
|
||||
print_version();
|
||||
@@ -108,8 +147,8 @@ int main(int argc, char* argv[]) {
|
||||
return EXIT_FAILURE;
|
||||
#endif
|
||||
}
|
||||
|
||||
if(print_cpufetch(cpu, get_style(), get_colors()))
|
||||
|
||||
if(print_cpufetch(cpu, get_style(), get_colors(), show_full_cpu_name()))
|
||||
return EXIT_SUCCESS;
|
||||
else
|
||||
return EXIT_FAILURE;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,18 +7,25 @@ typedef int STYLE;
|
||||
|
||||
#ifdef ARCH_X86
|
||||
#include "../x86/cpuid.h"
|
||||
#else
|
||||
#elif ARCH_PPC
|
||||
#include "../ppc/ppc.h"
|
||||
#elif ARCH_ARM
|
||||
#include "../arm/midr.h"
|
||||
#endif
|
||||
|
||||
#define COLOR_DEFAULT_INTEL "15,125,194:230,230,230:40,150,220:230,230,230"
|
||||
#define COLOR_DEFAULT_AMD "250,250,250:0,154,102:250,250,250:0,154,102"
|
||||
#define COLOR_DEFAULT_ARM "0,145,189:0,145,189:240,240,240:0,145,189"
|
||||
// +-----------------------------------+-----------------------+
|
||||
// | Color logo | Color text |
|
||||
// | Color 1 | Color 2 | Color 3 | Color 1 | Color 2 |
|
||||
#define COLOR_DEFAULT_INTEL "015,125,194:230,230,230:000,000,000:040,150,220:230,230,230"
|
||||
#define COLOR_DEFAULT_INTEL_NEW "030,204,251:250,250,250:000,104,181:230,230,230:030,204,251"
|
||||
#define COLOR_DEFAULT_AMD "250,250,250:000,154,102:000,000,000:250,250,250:000,154,102"
|
||||
#define COLOR_DEFAULT_IBM "092,119,172:092,119,172:000,000,000:240,240,240:092,119,172"
|
||||
#define COLOR_DEFAULT_ARM "000,145,189:000,145,189:000,000,000:240,240,240:000,145,189"
|
||||
|
||||
#ifdef ARCH_X86
|
||||
void print_levels(struct cpuInfo* cpu);
|
||||
#endif
|
||||
|
||||
bool print_cpufetch(struct cpuInfo* cpu, STYLE s, struct colors* cs);
|
||||
bool print_cpufetch(struct cpuInfo* cpu, STYLE s, struct color** cs, bool fcpuname);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
char* read_file(char* path, int* len) {
|
||||
int fd = open(path, O_RDONLY);
|
||||
|
||||
|
||||
if(fd == -1) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -13,30 +13,26 @@ char* read_file(char* path, int* len) {
|
||||
int bytes_read = 0;
|
||||
int offset = 0;
|
||||
int block = 128;
|
||||
char* buf = malloc(sizeof(char)*DEFAULT_FILE_SIZE);
|
||||
char* buf = emalloc(sizeof(char)*DEFAULT_FILE_SIZE);
|
||||
memset(buf, 0, sizeof(char)*DEFAULT_FILE_SIZE);
|
||||
|
||||
while ( (bytes_read = read(fd, buf+offset, block)) > 0 ) {
|
||||
offset += bytes_read;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (close(fd) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
*len = offset;
|
||||
return buf;
|
||||
}
|
||||
|
||||
long get_freq_from_file(char* path, bool hv_present) {
|
||||
long get_freq_from_file(char* path) {
|
||||
int filelen;
|
||||
char* buf;
|
||||
if((buf = read_file(path, &filelen)) == NULL) {
|
||||
if(hv_present)
|
||||
printWarn("Could not open '%s' (HV is present)", path);
|
||||
else
|
||||
printWarn("Could not open '%s'", path);
|
||||
|
||||
printWarn("Could not open '%s'", path);
|
||||
return UNKNOWN_FREQ;
|
||||
}
|
||||
|
||||
@@ -44,12 +40,11 @@ long get_freq_from_file(char* path, bool hv_present) {
|
||||
errno = 0;
|
||||
long ret = strtol(buf, &end, 10);
|
||||
if(errno != 0) {
|
||||
perror("strtol");
|
||||
printBug("Failed parsing '%s' file. Read data was: '%s'", path, buf);
|
||||
printBug("strtol: %s", strerror(errno));
|
||||
free(buf);
|
||||
return UNKNOWN_FREQ;
|
||||
}
|
||||
|
||||
|
||||
// We will be getting the frequency in KHz
|
||||
// We consider it is an error if frequency is
|
||||
// greater than 10 GHz or less than 100 MHz
|
||||
@@ -57,20 +52,145 @@ long get_freq_from_file(char* path, bool hv_present) {
|
||||
printBug("Invalid data was read from file '%s': %ld\n", path, ret);
|
||||
return UNKNOWN_FREQ;
|
||||
}
|
||||
|
||||
|
||||
free(buf);
|
||||
|
||||
|
||||
return ret/1000;
|
||||
}
|
||||
|
||||
long get_max_freq_from_file(uint32_t core, bool hv_present) {
|
||||
char path[_PATH_FREQUENCY_MAX_LEN];
|
||||
sprintf(path, "%s%s/cpu%d%s%s", _PATH_SYS_SYSTEM, _PATH_SYS_CPU, core, _PATH_FREQUENCY, _PATH_FREQUENCY_MAX);
|
||||
return get_freq_from_file(path, hv_present);
|
||||
long get_cache_size_from_file(char* path) {
|
||||
int filelen;
|
||||
char* buf;
|
||||
if((buf = read_file(path, &filelen)) == NULL) {
|
||||
printWarn("Could not open '%s'", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf[filelen] = '\0'; // remove the K at the end
|
||||
|
||||
char* end;
|
||||
errno = 0;
|
||||
long ret = strtol(buf, &end, 10);
|
||||
if(errno != 0) {
|
||||
printBug("strtol: %s", strerror(errno));
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
return ret * 1024;
|
||||
}
|
||||
|
||||
long get_min_freq_from_file(uint32_t core, bool hv_present) {
|
||||
long get_max_freq_from_file(uint32_t core) {
|
||||
char path[_PATH_FREQUENCY_MAX_LEN];
|
||||
sprintf(path, "%s%s/cpu%d%s%s", _PATH_SYS_SYSTEM, _PATH_SYS_CPU, core, _PATH_FREQUENCY, _PATH_FREQUENCY_MAX);
|
||||
return get_freq_from_file(path);
|
||||
}
|
||||
|
||||
long get_min_freq_from_file(uint32_t core) {
|
||||
char path[_PATH_FREQUENCY_MAX_LEN];
|
||||
sprintf(path, "%s%s/cpu%d%s%s", _PATH_SYS_SYSTEM, _PATH_SYS_CPU, core, _PATH_FREQUENCY, _PATH_FREQUENCY_MIN);
|
||||
return get_freq_from_file(path, hv_present);
|
||||
return get_freq_from_file(path);
|
||||
}
|
||||
|
||||
long get_l1i_cache_size(uint32_t core) {
|
||||
char path[_PATH_CACHE_MAX_LEN];
|
||||
sprintf(path, "%s%s/cpu%d%s%s", _PATH_SYS_SYSTEM, _PATH_SYS_CPU, core, _PATH_CACHE_L1I, _PATH_CACHE_SIZE);
|
||||
return get_cache_size_from_file(path);
|
||||
}
|
||||
|
||||
long get_l1d_cache_size(uint32_t core) {
|
||||
char path[_PATH_CACHE_MAX_LEN];
|
||||
sprintf(path, "%s%s/cpu%d%s%s", _PATH_SYS_SYSTEM, _PATH_SYS_CPU, core, _PATH_CACHE_L1D, _PATH_CACHE_SIZE);
|
||||
return get_cache_size_from_file(path);
|
||||
}
|
||||
|
||||
long get_l2_cache_size(uint32_t core) {
|
||||
char path[_PATH_CACHE_MAX_LEN];
|
||||
sprintf(path, "%s%s/cpu%d%s%s", _PATH_SYS_SYSTEM, _PATH_SYS_CPU, core, _PATH_CACHE_L2, _PATH_CACHE_SIZE);
|
||||
return get_cache_size_from_file(path);
|
||||
}
|
||||
|
||||
long get_l3_cache_size(uint32_t core) {
|
||||
char path[_PATH_CACHE_MAX_LEN];
|
||||
sprintf(path, "%s%s/cpu%d%s%s", _PATH_SYS_SYSTEM, _PATH_SYS_CPU, core, _PATH_CACHE_L3, _PATH_CACHE_SIZE);
|
||||
return get_cache_size_from_file(path);
|
||||
}
|
||||
|
||||
int get_num_caches_from_files(char** paths, int num_paths) {
|
||||
int SHARED_MAP_MAX_LEN = 8 + 1;
|
||||
int filelen;
|
||||
char* buf;
|
||||
uint32_t* shared_maps = emalloc(sizeof(uint32_t *) * num_paths);
|
||||
|
||||
// 1. Read cpu_shared_map from every core
|
||||
for(int i=0; i < num_paths; i++) {
|
||||
if((buf = read_file(paths[i], &filelen)) == NULL) {
|
||||
printWarn("Could not open '%s'", paths[i]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(filelen > SHARED_MAP_MAX_LEN) {
|
||||
printBug("Shared map length is %d while the max is be %d", filelen, SHARED_MAP_MAX_LEN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char* end;
|
||||
errno = 0;
|
||||
long ret = strtol(buf, &end, 16);
|
||||
if(errno != 0) {
|
||||
printBug("strtol: %s", strerror(errno));
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
shared_maps[i] = (uint32_t) ret;
|
||||
}
|
||||
|
||||
// 2. Count number of different masks; this is the number of caches
|
||||
int num_caches = 0;
|
||||
bool found = false;
|
||||
uint32_t* unique_shared_maps = emalloc(sizeof(uint32_t *) * num_paths);
|
||||
for(int i=0; i < num_paths; i++) unique_shared_maps[i] = 0;
|
||||
|
||||
for(int i=0; i < num_paths; i++) {
|
||||
for(int j=0; j < num_paths && !found; j++) {
|
||||
if(shared_maps[i] == unique_shared_maps[j]) found = true;
|
||||
}
|
||||
if(!found) {
|
||||
unique_shared_maps[num_caches] = shared_maps[i];
|
||||
num_caches++;
|
||||
}
|
||||
found = false;
|
||||
}
|
||||
|
||||
return num_caches;
|
||||
}
|
||||
|
||||
int get_num_caches_by_level(struct cpuInfo* cpu, uint32_t level) {
|
||||
char** paths = emalloc(sizeof(char *) * cpu->topo->total_cores);
|
||||
char* cache_path = NULL;
|
||||
|
||||
if(level == 0) cache_path = _PATH_CACHE_L1I;
|
||||
else if(level == 1) cache_path = _PATH_CACHE_L1D;
|
||||
else if(level == 2) cache_path = _PATH_CACHE_L2;
|
||||
else if(level == 3) cache_path = _PATH_CACHE_L3;
|
||||
else {
|
||||
printBug("Found invalid cache level to inspect: %d\n", level);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(int i=0; i < cpu->topo->total_cores; i++) {
|
||||
paths[i] = emalloc(sizeof(char) * _PATH_CACHE_MAX_LEN);
|
||||
sprintf(paths[i], "%s%s/cpu%d%s%s", _PATH_SYS_SYSTEM, _PATH_SYS_CPU, i, cache_path, _PATH_CACHE_SHARED_MAP);
|
||||
}
|
||||
|
||||
int ret = get_num_caches_from_files(paths, cpu->topo->total_cores);
|
||||
|
||||
for(int i=0; i < cpu->topo->total_cores; i++)
|
||||
free(paths[i]);
|
||||
free(paths);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -17,12 +17,24 @@
|
||||
#define _PATH_FREQUENCY "/cpufreq"
|
||||
#define _PATH_FREQUENCY_MAX "/cpuinfo_max_freq"
|
||||
#define _PATH_FREQUENCY_MIN "/cpuinfo_min_freq"
|
||||
#define _PATH_CACHE_L1D "/cache/index0"
|
||||
#define _PATH_CACHE_L1I "/cache/index1"
|
||||
#define _PATH_CACHE_L2 "/cache/index2"
|
||||
#define _PATH_CACHE_L3 "/cache/index3"
|
||||
#define _PATH_CACHE_SIZE "/size"
|
||||
#define _PATH_CACHE_SHARED_MAP "/shared_cpu_map"
|
||||
|
||||
#define _PATH_FREQUENCY_MAX_LEN 100
|
||||
#define _PATH_CACHE_MAX_LEN 200
|
||||
#define DEFAULT_FILE_SIZE 4096
|
||||
|
||||
char* read_file(char* path, int* len);
|
||||
long get_max_freq_from_file(uint32_t core, bool hv_present);
|
||||
long get_min_freq_from_file(uint32_t core, bool hv_present);
|
||||
long get_max_freq_from_file(uint32_t core);
|
||||
long get_min_freq_from_file(uint32_t core);
|
||||
long get_l1i_cache_size(uint32_t core);
|
||||
long get_l1d_cache_size(uint32_t core);
|
||||
long get_l2_cache_size(uint32_t core);
|
||||
long get_l3_cache_size(uint32_t core);
|
||||
int get_num_caches_by_level(struct cpuInfo* cpu, uint32_t level);
|
||||
|
||||
#endif
|
||||
|
||||
223
src/ppc/ppc.c
Normal file
223
src/ppc/ppc.c
Normal file
@@ -0,0 +1,223 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "ppc.h"
|
||||
#include "uarch.h"
|
||||
#include "udev.h"
|
||||
#include "../common/udev.h"
|
||||
#include "../common/global.h"
|
||||
|
||||
struct cache* get_cache_info(struct cpuInfo* cpu) {
|
||||
struct cache* cach = emalloc(sizeof(struct cache));
|
||||
init_cache_struct(cach);
|
||||
|
||||
cach->L1i->size = get_l1i_cache_size(0);
|
||||
cach->L1d->size = get_l1d_cache_size(0);
|
||||
cach->L2->size = get_l2_cache_size(0);
|
||||
cach->L3->size = get_l3_cache_size(0);
|
||||
|
||||
if(cach->L1i->size > 0) {
|
||||
cach->L1i->exists = true;
|
||||
cach->L1i->num_caches = get_num_caches_by_level(cpu, 0);
|
||||
cach->max_cache_level = 1;
|
||||
}
|
||||
if(cach->L1d->size > 0) {
|
||||
cach->L1d->exists = true;
|
||||
cach->L1d->num_caches = get_num_caches_by_level(cpu, 1);
|
||||
cach->max_cache_level = 2;
|
||||
}
|
||||
if(cach->L2->size > 0) {
|
||||
cach->L2->exists = true;
|
||||
cach->L2->num_caches = get_num_caches_by_level(cpu, 2);
|
||||
cach->max_cache_level = 3;
|
||||
}
|
||||
if(cach->L3->size > 0) {
|
||||
cach->L3->exists = true;
|
||||
cach->L3->num_caches = get_num_caches_by_level(cpu, 3);
|
||||
cach->max_cache_level = 4;
|
||||
}
|
||||
|
||||
return cach;
|
||||
}
|
||||
|
||||
struct topology* get_topology_info(struct cache* cach) {
|
||||
struct topology* topo = emalloc(sizeof(struct topology));
|
||||
init_topology_struct(topo, cach);
|
||||
|
||||
// 1. Total cores detection
|
||||
if((topo->total_cores = sysconf(_SC_NPROCESSORS_ONLN)) == -1) {
|
||||
printWarn("sysconf(_SC_NPROCESSORS_ONLN): %s", strerror(errno));
|
||||
topo->total_cores = 1; // fallback
|
||||
}
|
||||
|
||||
// To find physical cores, we use topo->total_cores and core_ids
|
||||
// To find number of sockets, we use package_ids
|
||||
int* core_ids = emalloc(sizeof(int) * topo->total_cores);
|
||||
int* package_ids = emalloc(sizeof(int) * topo->total_cores);
|
||||
|
||||
if(!fill_core_ids_from_sys(core_ids, topo->total_cores)) {
|
||||
printWarn("fill_core_ids_from_sys failed, output may be incomplete/invalid");
|
||||
for(int i=0; i < topo->total_cores; i++) core_ids[i] = 0;
|
||||
}
|
||||
if(!fill_package_ids_from_sys(package_ids, topo->total_cores)) {
|
||||
printWarn("fill_package_ids_from_sys failed, output may be incomplete/invalid");
|
||||
for(int i=0; i < topo->total_cores; i++) package_ids[i] = 0;
|
||||
}
|
||||
|
||||
// 2. Socket detection
|
||||
int *package_ids_count = emalloc(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 = emalloc(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;
|
||||
}
|
||||
|
||||
static inline uint32_t mfpvr() {
|
||||
uint32_t pvr;
|
||||
|
||||
asm ("mfpvr %0"
|
||||
: "=r"(pvr));
|
||||
return pvr;
|
||||
}
|
||||
|
||||
struct uarch* get_cpu_uarch(struct cpuInfo* cpu) {
|
||||
return get_uarch_from_pvr(cpu->pvr);
|
||||
}
|
||||
|
||||
struct frequency* get_frequency_info() {
|
||||
struct frequency* freq = emalloc(sizeof(struct frequency));
|
||||
|
||||
freq->max = get_max_freq_from_file(0);
|
||||
freq->base = get_min_freq_from_file(0);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
int64_t get_peak_performance(struct cpuInfo* cpu, struct topology* topo, int64_t freq) {
|
||||
/*
|
||||
* Not sure about this
|
||||
* PP(SP) = N_CORES * FREQUENCY * 4(If altivec)
|
||||
*/
|
||||
|
||||
//First check we have consistent data
|
||||
if(freq == UNKNOWN_FREQ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct features* feat = cpu->feat;
|
||||
int64_t flops = topo->physical_cores * topo->sockets * (freq * 1000000);
|
||||
if(feat->altivec) flops = flops * 4;
|
||||
|
||||
// POWER9 has the concept called "slices". Each SMT4 core has two super-slices,
|
||||
// and each super-slice is capable of doing two FLOPS per cycle. In the case of
|
||||
// SMT8, it has 4 super-slices, thus four FLOPS per cycle.
|
||||
if(is_power9(cpu->arch)) {
|
||||
int threads_per_core = topo->logical_cores / topo->physical_cores;
|
||||
flops = flops * (threads_per_core / 2);
|
||||
}
|
||||
|
||||
return flops;
|
||||
}
|
||||
|
||||
struct cpuInfo* get_cpu_info() {
|
||||
struct cpuInfo* cpu = emalloc(sizeof(struct cpuInfo));
|
||||
struct features* feat = emalloc(sizeof(struct features));
|
||||
cpu->feat = feat;
|
||||
|
||||
bool *ptr = &(feat->AES);
|
||||
for(uint32_t i = 0; i < sizeof(struct features)/sizeof(bool); i++, ptr++) {
|
||||
*ptr = false;
|
||||
}
|
||||
|
||||
int len;
|
||||
char* path = emalloc(sizeof(char) * (strlen(_PATH_DT) + strlen(_PATH_DT_PART) + 1));
|
||||
sprintf(path, "%s%s", _PATH_DT, _PATH_DT_PART);
|
||||
|
||||
cpu->cpu_name = read_file(path, &len);
|
||||
cpu->pvr = mfpvr();
|
||||
cpu->arch = get_cpu_uarch(cpu);
|
||||
cpu->freq = get_frequency_info();
|
||||
cpu->topo = get_topology_info(cpu->cach);
|
||||
cpu->cach = get_cache_info(cpu);
|
||||
feat->altivec = has_altivec(cpu->arch);
|
||||
cpu->peak_performance = get_peak_performance(cpu, cpu->topo, get_freq(cpu->freq));
|
||||
|
||||
if(cpu->cach == NULL || cpu->topo == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return cpu;
|
||||
}
|
||||
|
||||
char* get_str_altivec(struct cpuInfo* cpu) {
|
||||
char* string = ecalloc(4, sizeof(char));
|
||||
|
||||
if(cpu->feat->altivec) strcpy(string, "Yes");
|
||||
else strcpy(string, "No");
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
char* get_str_topology(struct topology* topo, bool dual_socket) {
|
||||
char* string;
|
||||
if(topo->smt_supported > 1) {
|
||||
uint32_t size = 3+3+17+1;
|
||||
string = emalloc(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 = emalloc(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("PVR: 0x%.8X\n", cpu->pvr);
|
||||
}
|
||||
11
src/ppc/ppc.h
Normal file
11
src/ppc/ppc.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef __POWERPC__
|
||||
#define __POWERPC__
|
||||
|
||||
#include "../common/cpu.h"
|
||||
|
||||
struct cpuInfo* get_cpu_info();
|
||||
char* get_str_altivec(struct cpuInfo* cpu);
|
||||
char* get_str_topology(struct topology* topo, bool dual_socket);
|
||||
void print_debug(struct cpuInfo* cpu);
|
||||
|
||||
#endif
|
||||
28
src/ppc/pvr_kern_to_cpufetch.sh
Executable file
28
src/ppc/pvr_kern_to_cpufetch.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script takes as input cputable.c from linux kernel
|
||||
# and generates a valid output for cpufetch in src/ppc/uarch.c
|
||||
|
||||
CPUTABLE_PATH="linux-5.13.7/arch/powerpc/kernel/cputable.c"
|
||||
|
||||
raw_values=$(grep '\.pvr_value' "$CPUTABLE_PATH" | grep -oP "= .*," | cut -d' ' -f2 | tr -d ',')
|
||||
raw_masks=$(grep '\.pvr_mask' "$CPUTABLE_PATH" | grep -oE "0x........")
|
||||
|
||||
raw_v_len=$(echo "$raw_values" | wc -l)
|
||||
raw_m_len=$(echo "$raw_masks" | wc -l)
|
||||
|
||||
if [ $raw_v_len -ne $raw_m_len ]
|
||||
then
|
||||
echo "Lengths do not match!"
|
||||
echo "values length: $raw_v_len"
|
||||
echo "masks length: $raw_m_len"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IFS=$'\n' read -r -d ' ' -a values <<< "$raw_values"
|
||||
IFS=$'\n' read -r -d ' ' -a masks <<< "$raw_masks"
|
||||
|
||||
for i in "${!values[@]}"
|
||||
do
|
||||
echo ' CHECK_UARCH(arch, pvr, '"${masks[i]}"', '"${values[i]}"', "POWERX", UARCH_POWERX, -1)'
|
||||
done
|
||||
286
src/ppc/uarch.c
Normal file
286
src/ppc/uarch.c
Normal file
@@ -0,0 +1,286 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/auxv.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "uarch.h"
|
||||
#include "../common/global.h"
|
||||
|
||||
typedef uint32_t MICROARCH;
|
||||
|
||||
// Data not available
|
||||
#define NA -1
|
||||
|
||||
// Unknown manufacturing process
|
||||
#define UNK -1
|
||||
|
||||
enum {
|
||||
UARCH_UNKNOWN,
|
||||
UARCH_PPC604,
|
||||
UARCH_PPCG3,
|
||||
UARCH_PPCG4,
|
||||
UARCH_PPC405,
|
||||
UARCH_PPC603,
|
||||
UARCH_PPC440,
|
||||
UARCH_PPC470,
|
||||
UARCH_PPC970,
|
||||
UARCH_PPC970FX,
|
||||
UARCH_PPC970MP,
|
||||
UARCH_CELLBE,
|
||||
UARCH_POWER5,
|
||||
UARCH_POWER5PLUS,
|
||||
UARCH_POWER6,
|
||||
UARCH_POWER7,
|
||||
UARCH_POWER7PLUS,
|
||||
UARCH_POWER8,
|
||||
UARCH_POWER9,
|
||||
UARCH_POWER9_DD20,
|
||||
UARCH_POWER9_DD21,
|
||||
UARCH_POWER9_DD22,
|
||||
UARCH_POWER9_DD23,
|
||||
UARCH_POWER10,
|
||||
};
|
||||
|
||||
struct uarch {
|
||||
MICROARCH uarch;
|
||||
char* uarch_str;
|
||||
int32_t process; // measured in nanometers
|
||||
};
|
||||
|
||||
#define UARCH_START if (false) {}
|
||||
#define CHECK_UARCH(arch, cpu_pvr, pvr_mask, pvr_value, uarch) \
|
||||
else if ((cpu_pvr & pvr_mask) == pvr_value) fill_uarch(arch, uarch);
|
||||
#define UARCH_END else { printBug("Unknown microarchitecture detected: 0x%.8X", pvr); fill_uarch(arch, UARCH_UNKNOWN); }
|
||||
|
||||
#define FILL_START if (false) {}
|
||||
#define FILL_UARCH(u, uarch, uarch_str, uarch_process) \
|
||||
else if(u == uarch) { fill = true; str = uarch_str; process = uarch_process; }
|
||||
#define FILL_END else { printBug("Found invalid microarchitecture: %d", u); }
|
||||
|
||||
void fill_uarch(struct uarch* arch, MICROARCH u) {
|
||||
arch->uarch = u;
|
||||
char* str = NULL;
|
||||
int32_t process = UNK;
|
||||
bool fill = false;
|
||||
|
||||
FILL_START
|
||||
FILL_UARCH(arch->uarch, UARCH_UNKNOWN, STRING_UNKNOWN, UNK)
|
||||
FILL_UARCH(arch->uarch, UARCH_PPC604, "PowerPC 604", 500)
|
||||
FILL_UARCH(arch->uarch, UARCH_PPCG3, "PowerPC G3", UNK) // varies
|
||||
FILL_UARCH(arch->uarch, UARCH_PPCG4, "PowerPC G4", UNK) // varies
|
||||
FILL_UARCH(arch->uarch, UARCH_PPC405, "PowerPC 405", UNK)
|
||||
FILL_UARCH(arch->uarch, UARCH_PPC603, "PowerPC 603", UNK) // varies
|
||||
FILL_UARCH(arch->uarch, UARCH_PPC440, "PowerPC 440", UNK)
|
||||
FILL_UARCH(arch->uarch, UARCH_PPC470, "PowerPC 470", 45) // strange...
|
||||
FILL_UARCH(arch->uarch, UARCH_PPC970, "PowerPC 970", 130)
|
||||
FILL_UARCH(arch->uarch, UARCH_PPC970FX, "PowerPC 970FX", 90)
|
||||
FILL_UARCH(arch->uarch, UARCH_PPC970MP, "PowerPC 970MP", 90)
|
||||
FILL_UARCH(arch->uarch, UARCH_CELLBE, "Cell BE", UNK) // varies depending on manufacturer
|
||||
FILL_UARCH(arch->uarch, UARCH_POWER5, "POWER5", 130)
|
||||
FILL_UARCH(arch->uarch, UARCH_POWER5PLUS, "POWER5+", 90)
|
||||
FILL_UARCH(arch->uarch, UARCH_POWER6, "POWER6", 65)
|
||||
FILL_UARCH(arch->uarch, UARCH_POWER7, "POWER7", 45)
|
||||
FILL_UARCH(arch->uarch, UARCH_POWER7PLUS, "POWER7+", 32)
|
||||
FILL_UARCH(arch->uarch, UARCH_POWER8, "POWER8", 22)
|
||||
FILL_UARCH(arch->uarch, UARCH_POWER9, "POWER9", 14)
|
||||
FILL_UARCH(arch->uarch, UARCH_POWER9_DD20, "POWER9 (DD2.0)", 14)
|
||||
FILL_UARCH(arch->uarch, UARCH_POWER9_DD21, "POWER9 (DD2.1)", 14)
|
||||
FILL_UARCH(arch->uarch, UARCH_POWER9_DD22, "POWER9 (DD2.2)", 14)
|
||||
FILL_UARCH(arch->uarch, UARCH_POWER9_DD23, "POWER9 (DD2.3)", 14)
|
||||
FILL_UARCH(arch->uarch, UARCH_POWER10, "POWER10", 7)
|
||||
FILL_END
|
||||
|
||||
if(fill) {
|
||||
arch->uarch_str = emalloc(sizeof(char) * (strlen(str)+1));
|
||||
strcpy(arch->uarch_str, str);
|
||||
arch->process= process;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* PVR masks/values from arch/powerpc/kernel/cputable.c (Linux kernel)
|
||||
* This list may be incorrect, incomplete or overly simplified,
|
||||
* specially in the case of 32 bit entries
|
||||
*/
|
||||
struct uarch* get_uarch_from_pvr(uint32_t pvr) {
|
||||
struct uarch* arch = emalloc(sizeof(struct uarch));
|
||||
|
||||
UARCH_START
|
||||
// 64 bit
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x00390000, UARCH_PPC970)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x003c0000, UARCH_PPC970FX)
|
||||
CHECK_UARCH(arch, pvr, 0xffffffff, 0x00440100, UARCH_PPC970MP)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x00440000, UARCH_PPC970MP)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x003a0000, UARCH_POWER5)
|
||||
CHECK_UARCH(arch, pvr, 0xffffff00, 0x003b0300, UARCH_POWER5PLUS)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x003b0000, UARCH_POWER5)
|
||||
CHECK_UARCH(arch, pvr, 0xffffffff, 0x0f000001, UARCH_POWER5)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x003e0000, UARCH_POWER6)
|
||||
CHECK_UARCH(arch, pvr, 0xffffffff, 0x0f000002, UARCH_POWER6)
|
||||
CHECK_UARCH(arch, pvr, 0xffffffff, 0x0f000003, UARCH_POWER7)
|
||||
CHECK_UARCH(arch, pvr, 0xffffffff, 0x0f000004, UARCH_POWER8)
|
||||
CHECK_UARCH(arch, pvr, 0xffffffff, 0x0f000005, UARCH_POWER9)
|
||||
CHECK_UARCH(arch, pvr, 0xffffffff, 0x0f000006, UARCH_POWER10)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x003f0000, UARCH_POWER7)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x004A0000, UARCH_POWER7PLUS)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x004b0000, UARCH_POWER8)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x004c0000, UARCH_POWER8)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x004d0000, UARCH_POWER8)
|
||||
CHECK_UARCH(arch, pvr, 0xffffefff, 0x004e0200, UARCH_POWER9_DD20)
|
||||
CHECK_UARCH(arch, pvr, 0xffffefff, 0x004e0201, UARCH_POWER9_DD21)
|
||||
CHECK_UARCH(arch, pvr, 0xffffefff, 0x004e0202, UARCH_POWER9_DD22)
|
||||
CHECK_UARCH(arch, pvr, 0xffffefff, 0x004e0203, UARCH_POWER9_DD23)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x00800000, UARCH_POWER10)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x00700000, UARCH_CELLBE)
|
||||
// 32 bit
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x00040000, UARCH_PPC604)
|
||||
CHECK_UARCH(arch, pvr, 0xfffff000, 0x00090000, UARCH_PPC604)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x00090000, UARCH_PPC604)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x000a0000, UARCH_PPC604)
|
||||
CHECK_UARCH(arch, pvr, 0xffffffff, 0x00084202, UARCH_PPCG3)
|
||||
CHECK_UARCH(arch, pvr, 0xfffffff0, 0x00080100, UARCH_PPCG3)
|
||||
CHECK_UARCH(arch, pvr, 0xfffffff0, 0x00082200, UARCH_PPCG3)
|
||||
CHECK_UARCH(arch, pvr, 0xfffffff0, 0x00082210, UARCH_PPCG3)
|
||||
CHECK_UARCH(arch, pvr, 0xffffffff, 0x00083214, UARCH_PPCG3)
|
||||
CHECK_UARCH(arch, pvr, 0xfffff0e0, 0x00087000, UARCH_PPCG3)
|
||||
CHECK_UARCH(arch, pvr, 0xfffff000, 0x00083000, UARCH_PPCG3)
|
||||
CHECK_UARCH(arch, pvr, 0xffffff00, 0x70000100, UARCH_PPCG3)
|
||||
CHECK_UARCH(arch, pvr, 0xffffffff, 0x70000200, UARCH_PPCG3)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x70000000, UARCH_PPCG3)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x70020000, UARCH_PPCG3)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x00080000, UARCH_PPCG3)
|
||||
CHECK_UARCH(arch, pvr, 0xffffffff, 0x000c1101, UARCH_PPCG4)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x000c0000, UARCH_PPCG4)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x800c0000, UARCH_PPCG4)
|
||||
CHECK_UARCH(arch, pvr, 0xffffffff, 0x80000200, UARCH_PPCG4)
|
||||
CHECK_UARCH(arch, pvr, 0xffffffff, 0x80000201, UARCH_PPCG4)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x80000000, UARCH_PPCG4)
|
||||
CHECK_UARCH(arch, pvr, 0xffffff00, 0x80010100, UARCH_PPCG4)
|
||||
CHECK_UARCH(arch, pvr, 0xffffffff, 0x80010200, UARCH_PPCG4)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x80010000, UARCH_PPCG4)
|
||||
CHECK_UARCH(arch, pvr, 0xffffffff, 0x80020100, UARCH_PPCG4)
|
||||
CHECK_UARCH(arch, pvr, 0xffffffff, 0x80020101, UARCH_PPCG4)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x80020000, UARCH_PPCG4)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x80030000, UARCH_PPCG4)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x80040000, UARCH_PPCG4)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x00030000, UARCH_PPC603)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x00060000, UARCH_PPC603)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x00070000, UARCH_PPC603)
|
||||
CHECK_UARCH(arch, pvr, 0x7fff0000, 0x00810000, UARCH_PPC603)
|
||||
CHECK_UARCH(arch, pvr, 0x7fff0000, 0x00820000, UARCH_PPC603)
|
||||
CHECK_UARCH(arch, pvr, 0x7fff0000, 0x00830000, UARCH_PPC603)
|
||||
CHECK_UARCH(arch, pvr, 0x7fff0000, 0x00840000, UARCH_PPC603)
|
||||
CHECK_UARCH(arch, pvr, 0x7fff0000, 0x00850000, UARCH_PPC603)
|
||||
CHECK_UARCH(arch, pvr, 0x7fff0000, 0x00860000, UARCH_PPC603)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x41810000, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x41610000, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x40B10000, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x41410000, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x50910000, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x51510000, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x41F10000, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x51210000, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff000f, 0x12910007, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff000f, 0x1291000d, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff000f, 0x1291000f, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff000f, 0x12910003, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff000f, 0x12910005, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff000f, 0x12910001, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff000f, 0x12910009, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff000f, 0x1291000b, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff000f, 0x12910000, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff000f, 0x12910002, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x41510000, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x7ff11432, UARCH_PPC405)
|
||||
CHECK_UARCH(arch, pvr, 0xf0000fff, 0x40000850, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xf0000fff, 0x40000858, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xf0000fff, 0x400008d3, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xf0000ff7, 0x400008d4, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xf0000fff, 0x400008db, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xf0000ffb, 0x200008D0, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xf0000ffb, 0x200008D8, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xf0000fff, 0x40000440, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xf0000fff, 0x40000481, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xf0000fff, 0x50000850, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xf0000fff, 0x50000851, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xf0000fff, 0x50000892, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xf0000fff, 0x50000894, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xfff00fff, 0x53200891, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xfff00fff, 0x53400890, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xfff00fff, 0x53400891, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0006, 0x13020002, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0007, 0x13020004, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0006, 0x13020000, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0007, 0x13020005, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xffffff00, 0x13541800, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xfffffff0, 0x12C41C80, UARCH_PPC440)
|
||||
CHECK_UARCH(arch, pvr, 0xffffffff, 0x11a52080, UARCH_PPC470)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x7ff50000, UARCH_PPC470)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x00050000, UARCH_PPC470)
|
||||
CHECK_UARCH(arch, pvr, 0xffff0000, 0x11a50000, UARCH_PPC470)
|
||||
UARCH_END
|
||||
|
||||
return arch;
|
||||
}
|
||||
|
||||
bool has_altivec(struct uarch* arch) {
|
||||
switch(arch->uarch) {
|
||||
case UARCH_PPC970FX:
|
||||
case UARCH_PPC970MP:
|
||||
case UARCH_CELLBE:
|
||||
case UARCH_POWER6:
|
||||
case UARCH_POWER7:
|
||||
case UARCH_POWER7PLUS:
|
||||
case UARCH_POWER8:
|
||||
case UARCH_POWER9:
|
||||
case UARCH_POWER9_DD20:
|
||||
case UARCH_POWER9_DD21:
|
||||
case UARCH_POWER9_DD22:
|
||||
case UARCH_POWER9_DD23:
|
||||
case UARCH_POWER10:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_power9(struct uarch* arch) {
|
||||
return arch->uarch == UARCH_POWER9 ||
|
||||
arch->uarch == UARCH_POWER9_DD20 ||
|
||||
arch->uarch == UARCH_POWER9_DD21 ||
|
||||
arch->uarch == UARCH_POWER9_DD22 ||
|
||||
arch->uarch == UARCH_POWER9_DD23;
|
||||
}
|
||||
|
||||
char* get_str_uarch(struct cpuInfo* cpu) {
|
||||
return cpu->arch->uarch_str;
|
||||
}
|
||||
|
||||
char* get_str_process(struct cpuInfo* cpu) {
|
||||
char* str = emalloc(sizeof(char) * (strlen(STRING_UNKNOWN)+1));
|
||||
int32_t process = cpu->arch->process;
|
||||
|
||||
if(process == UNK) {
|
||||
snprintf(str, strlen(STRING_UNKNOWN)+1, STRING_UNKNOWN);
|
||||
}
|
||||
else if(process > 100) {
|
||||
sprintf(str, "%.2fum", (double)process/100);
|
||||
}
|
||||
else if(process > 0){
|
||||
sprintf(str, "%dnm", process);
|
||||
}
|
||||
else {
|
||||
snprintf(str, strlen(STRING_UNKNOWN)+1, STRING_UNKNOWN);
|
||||
printBug("Found invalid process: '%d'", process);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
void free_uarch_struct(struct uarch* arch) {
|
||||
free(arch->uarch_str);
|
||||
free(arch);
|
||||
}
|
||||
16
src/ppc/uarch.h
Normal file
16
src/ppc/uarch.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef __UARCH__
|
||||
#define __UARCH__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ppc.h"
|
||||
|
||||
struct uarch;
|
||||
|
||||
struct uarch* get_uarch_from_pvr(uint32_t pvr);
|
||||
bool has_altivec(struct uarch* arch);
|
||||
bool is_power9(struct uarch* arch);
|
||||
char* get_str_uarch(struct cpuInfo* cpu);
|
||||
char* get_str_process(struct cpuInfo* cpu);
|
||||
void free_uarch_struct(struct uarch* arch);
|
||||
|
||||
#endif
|
||||
40
src/ppc/udev.c
Normal file
40
src/ppc/udev.c
Normal file
@@ -0,0 +1,40 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include "../common/global.h"
|
||||
#include "udev.h"
|
||||
|
||||
#define _PATH_TOPO_CORE_ID "topology/core_id"
|
||||
#define _PATH_TOPO_PACKAGE_ID "topology/physical_package_id"
|
||||
|
||||
bool fill_array_from_sys(int *core_ids, int total_cores, char* SYS_PATH) {
|
||||
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, SYS_PATH);
|
||||
if((buf = read_file(path, &filelen)) == NULL) {
|
||||
printWarn("fill_array_from_sys: %s: %s", path, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
core_ids[i] = strtol(buf, &end, 10);
|
||||
if(errno != 0) {
|
||||
printWarn("fill_array_from_sys: %s:", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fill_core_ids_from_sys(int *core_ids, int total_cores) {
|
||||
return fill_array_from_sys(core_ids, total_cores, _PATH_TOPO_CORE_ID);
|
||||
}
|
||||
|
||||
bool fill_package_ids_from_sys(int* package_ids, int total_cores) {
|
||||
return fill_array_from_sys(package_ids, total_cores, _PATH_TOPO_PACKAGE_ID);
|
||||
}
|
||||
11
src/ppc/udev.h
Normal file
11
src/ppc/udev.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef __UDEV_PPC__
|
||||
#define __UDEV_PPC__
|
||||
|
||||
#include "../common/udev.h"
|
||||
#define _PATH_DT "/proc/device-tree/vpd/root-node-vpd@a000/enclosure@1e00/backplane@800/processor@1000"
|
||||
#define _PATH_DT_PART "/part-number"
|
||||
|
||||
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
|
||||
203
src/x86/apic.c
203
src/x86/apic.c
@@ -4,6 +4,9 @@
|
||||
#elif defined __linux__
|
||||
#define _GNU_SOURCE
|
||||
#include <sched.h>
|
||||
#elif defined __FreeBSD__
|
||||
#include <sys/param.h>
|
||||
#include <sys/cpuset.h>
|
||||
#elif defined __APPLE__
|
||||
#define UNUSED(x) (void)(x)
|
||||
#endif
|
||||
@@ -13,6 +16,7 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "apic.h"
|
||||
#include "cpuid_asm.h"
|
||||
@@ -24,7 +28,7 @@
|
||||
*/
|
||||
unsigned char bit_scan_reverse(uint32_t* index, uint64_t mask) {
|
||||
for(uint64_t i = (8 * sizeof(uint64_t)); i > 0; i--) {
|
||||
if((mask & (1LL << (i-1))) != 0) {
|
||||
if((mask & (1ULL << (i-1))) != 0) {
|
||||
*index = (uint64_t) (i-1);
|
||||
break;
|
||||
}
|
||||
@@ -57,7 +61,7 @@ uint32_t get_apic_id(bool x2apic_id) {
|
||||
uint32_t ebx = 0;
|
||||
uint32_t ecx = 0;
|
||||
uint32_t edx = 0;
|
||||
|
||||
|
||||
if(x2apic_id) {
|
||||
eax = 0x0000000B;
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
@@ -76,16 +80,25 @@ bool bind_to_cpu(int cpu_id) {
|
||||
HANDLE process = GetCurrentProcess();
|
||||
DWORD_PTR processAffinityMask = 1 << cpu_id;
|
||||
return SetProcessAffinityMask(process, processAffinityMask);
|
||||
#else
|
||||
#elif defined __linux__
|
||||
cpu_set_t currentCPU;
|
||||
CPU_ZERO(¤tCPU);
|
||||
CPU_SET(cpu_id, ¤tCPU);
|
||||
if (sched_setaffinity (0, sizeof(currentCPU), ¤tCPU) == -1) {
|
||||
perror("sched_setaffinity");
|
||||
printWarn("sched_setaffinity: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
#elif defined __FreeBSD__
|
||||
cpuset_t currentCPU;
|
||||
CPU_ZERO(¤tCPU);
|
||||
CPU_SET(cpu_id, ¤tCPU);
|
||||
if(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(cpuset_t), ¤tCPU) == -1) {
|
||||
printWarn("cpuset_setaffinity: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -97,51 +110,51 @@ bool fill_topo_masks_apic(struct topology* topo) {
|
||||
uint32_t core_plus_smt_id_max_cnt;
|
||||
uint32_t core_id_max_cnt;
|
||||
uint32_t smt_id_per_core_max_cnt;
|
||||
|
||||
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
|
||||
|
||||
core_plus_smt_id_max_cnt = (ebx >> 16) & 0xFF;
|
||||
|
||||
|
||||
eax = 0x00000004;
|
||||
ecx = 0;
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
|
||||
|
||||
core_id_max_cnt = (eax >> 26) + 1;
|
||||
smt_id_per_core_max_cnt = core_plus_smt_id_max_cnt / core_id_max_cnt;
|
||||
|
||||
topo->apic->smt_mask = create_mask(smt_id_per_core_max_cnt, &(topo->apic->smt_mask_width));
|
||||
smt_id_per_core_max_cnt = core_plus_smt_id_max_cnt / core_id_max_cnt;
|
||||
|
||||
topo->apic->smt_mask = create_mask(smt_id_per_core_max_cnt, &(topo->apic->smt_mask_width));
|
||||
topo->apic->core_mask = create_mask(core_id_max_cnt,&(topo->apic->pkg_mask_shift));
|
||||
topo->apic->pkg_mask_shift += topo->apic->smt_mask_width;
|
||||
topo->apic->core_mask <<= topo->apic->smt_mask_width;
|
||||
topo->apic->pkg_mask = (-1) ^ (topo->apic->core_mask | topo->apic->smt_mask);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fill_topo_masks_x2apic(struct topology* topo) {
|
||||
int32_t level_type;
|
||||
int32_t level_shift;
|
||||
|
||||
|
||||
int32_t coreplus_smt_mask = 0;
|
||||
bool level2 = false;
|
||||
bool level1 = false;
|
||||
|
||||
|
||||
uint32_t eax = 0;
|
||||
uint32_t ebx = 0;
|
||||
uint32_t ecx = 0;
|
||||
uint32_t edx = 0;
|
||||
uint32_t i = 0;
|
||||
|
||||
|
||||
while(true) {
|
||||
eax = 0x0000000B;
|
||||
ecx = i;
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
if(ebx == 0) break;
|
||||
|
||||
|
||||
level_type = (ecx >> 8) & 0xFF;
|
||||
level_shift = eax & 0xFFF;
|
||||
|
||||
switch(level_type) {
|
||||
level_shift = eax & 0xFFF;
|
||||
|
||||
switch(level_type) {
|
||||
case 1: // SMT
|
||||
topo->apic->smt_mask = ~(0xFFFFFFFF << level_shift);
|
||||
topo->apic->smt_mask_width = level_shift;
|
||||
@@ -158,10 +171,10 @@ bool fill_topo_masks_x2apic(struct topology* topo) {
|
||||
printErr("Found invalid level when querying topology: %d", level_type);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
i++; // sublevel to query
|
||||
}
|
||||
|
||||
|
||||
if (level1 && level2) {
|
||||
topo->apic->core_mask = coreplus_smt_mask ^ topo->apic->smt_mask;
|
||||
}
|
||||
@@ -182,13 +195,13 @@ bool fill_topo_masks_x2apic(struct topology* topo) {
|
||||
// as the number of cores, but in the case of Xeon Phi KNL it is not
|
||||
uint32_t max_apic_id_size(uint32_t** cache_id_apic, struct topology* topo) {
|
||||
uint32_t max = 0;
|
||||
|
||||
|
||||
for(int i=0; i < topo->cach->max_cache_level; i++) {
|
||||
for(int j=0; j < topo->total_cores; j++) {
|
||||
for(int j=0; j < topo->total_cores; j++) {
|
||||
if(cache_id_apic[j][i] > max) max = cache_id_apic[j][i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
max++;
|
||||
if(max > (uint32_t) topo->total_cores) return max;
|
||||
return topo->total_cores;
|
||||
@@ -196,15 +209,15 @@ uint32_t max_apic_id_size(uint32_t** cache_id_apic, struct topology* topo) {
|
||||
|
||||
bool build_topo_from_apic(uint32_t* apic_pkg, uint32_t* apic_smt, uint32_t** cache_id_apic, struct topology* topo) {
|
||||
uint32_t size = max_apic_id_size(cache_id_apic, topo);
|
||||
uint32_t* sockets = malloc(sizeof(uint32_t) * size);
|
||||
uint32_t* smt = malloc(sizeof(uint32_t) * size);
|
||||
uint32_t* apic_id = malloc(sizeof(uint32_t) * size);
|
||||
uint32_t* sockets = emalloc(sizeof(uint32_t) * size);
|
||||
uint32_t* smt = emalloc(sizeof(uint32_t) * size);
|
||||
uint32_t* apic_id = emalloc(sizeof(uint32_t) * size);
|
||||
uint32_t num_caches = 0;
|
||||
|
||||
|
||||
memset(sockets, 0, sizeof(uint32_t) * size);
|
||||
memset(smt, 0, sizeof(uint32_t) * size);
|
||||
memset(apic_id, 0, sizeof(uint32_t) * size);
|
||||
|
||||
memset(apic_id, 0, sizeof(uint32_t) * size);
|
||||
|
||||
// System topology
|
||||
for(int i=0; i < topo->total_cores; i++) {
|
||||
sockets[apic_pkg[i]] = 1;
|
||||
@@ -216,45 +229,43 @@ bool build_topo_from_apic(uint32_t* apic_pkg, uint32_t* apic_smt, uint32_t** cac
|
||||
if(smt[i] != 0)
|
||||
topo->smt_available++;
|
||||
}
|
||||
|
||||
|
||||
topo->logical_cores = topo->total_cores / topo->sockets;
|
||||
topo->physical_cores = topo->logical_cores / topo->smt_available;
|
||||
|
||||
|
||||
// Cache topology
|
||||
for(int i=0; i < topo->cach->max_cache_level; i++) {
|
||||
num_caches = 0;
|
||||
memset(apic_id, 0, sizeof(uint32_t) * size);
|
||||
|
||||
for(int c=0; c < topo->total_cores; c++) {
|
||||
|
||||
for(int c=0; c < topo->total_cores; c++) {
|
||||
apic_id[cache_id_apic[c][i]]++;
|
||||
}
|
||||
for(uint32_t c=0; c < size; c++) {
|
||||
for(uint32_t c=0; c < size; c++) {
|
||||
if(apic_id[c] > 0) num_caches++;
|
||||
}
|
||||
|
||||
printf("[i=%d]: %p\n", i, (void *) topo->cach->cach_arr[i]);
|
||||
topo->cach->cach_arr[i]->num_caches = num_caches;
|
||||
}
|
||||
|
||||
|
||||
free(sockets);
|
||||
free(smt);
|
||||
free(apic_id);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void get_cache_topology_from_apic(struct topology* topo) {
|
||||
void get_cache_topology_from_apic(struct topology* topo) {
|
||||
uint32_t eax = 0x00000004;
|
||||
uint32_t ebx = 0;
|
||||
uint32_t ecx = 0;
|
||||
uint32_t edx = 0;
|
||||
|
||||
for(int i=0; i < topo->cach->max_cache_level; i++) {
|
||||
|
||||
for(int i=0; i < topo->cach->max_cache_level; i++) {
|
||||
eax = 0x00000004;
|
||||
ecx = i;
|
||||
|
||||
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
|
||||
|
||||
uint32_t SMTMaxCntPerEachCache = ((eax >> 14) & 0x7FF) + 1;
|
||||
uint32_t dummy;
|
||||
topo->apic->cache_select_mask[i] = create_mask(SMTMaxCntPerEachCache,&dummy);
|
||||
@@ -278,15 +289,15 @@ void add_apic_to_array(uint32_t apic, uint32_t* apic_ids, int n) {
|
||||
if(apic_ids[i] != (uint32_t) -1) last = i+1;
|
||||
i++;
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
|
||||
if(!found) {
|
||||
apic_ids[last] = apic;
|
||||
//printf("Added %d\n", apic);
|
||||
}
|
||||
}
|
||||
|
||||
bool fill_apic_ids(uint32_t* apic_ids, int n, bool x2apic_id) {
|
||||
#ifdef __APPLE__
|
||||
#ifdef __APPLE__
|
||||
// macOS extremely dirty approach...
|
||||
printf("cpufetch is computing APIC IDs, please wait...\n");
|
||||
bool end = false;
|
||||
@@ -295,12 +306,21 @@ bool fill_apic_ids(uint32_t* apic_ids, int n, bool x2apic_id) {
|
||||
|
||||
while(!end) {
|
||||
apic = get_apic_id(x2apic_id);
|
||||
|
||||
|
||||
add_apic_to_array(apic, apic_ids, n);
|
||||
end = apic_array_full(apic_ids, n);
|
||||
end = apic_array_full(apic_ids, n);
|
||||
usleep(1000);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifdef __linux__
|
||||
// In Linux we reset the affinity; first we get the original mask
|
||||
cpu_set_t original_mask;
|
||||
if(sched_getaffinity(0, sizeof(original_mask), &original_mask) == -1) {
|
||||
printWarn("sched_getaffinity: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
for(int i=0; i < n; i++) {
|
||||
if(!bind_to_cpu(i)) {
|
||||
printErr("Failed binding to CPU %d", i);
|
||||
@@ -308,18 +328,27 @@ bool fill_apic_ids(uint32_t* apic_ids, int n, bool x2apic_id) {
|
||||
}
|
||||
apic_ids[i] = get_apic_id(x2apic_id);
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
// With the original mask previosly retrieved, we reset the affinity
|
||||
if (sched_setaffinity (0, sizeof(original_mask), &original_mask) == -1) {
|
||||
printWarn("sched_setaffinity: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_topology_from_apic(struct cpuInfo* cpu, struct topology* topo) {
|
||||
uint32_t apic_id;
|
||||
uint32_t* apic_ids = malloc(sizeof(uint32_t) * topo->total_cores);
|
||||
uint32_t* apic_pkg = malloc(sizeof(uint32_t) * topo->total_cores);
|
||||
uint32_t* apic_core = malloc(sizeof(uint32_t) * topo->total_cores);
|
||||
uint32_t* apic_smt = malloc(sizeof(uint32_t) * topo->total_cores);
|
||||
uint32_t** cache_smt_id_apic = malloc(sizeof(uint32_t*) * topo->total_cores);
|
||||
uint32_t** cache_id_apic = malloc(sizeof(uint32_t*) * topo->total_cores);
|
||||
bool get_topology_from_apic(struct cpuInfo* cpu, struct topology* topo) {
|
||||
uint32_t apic_id;
|
||||
uint32_t* apic_ids = emalloc(sizeof(uint32_t) * topo->total_cores);
|
||||
uint32_t* apic_pkg = emalloc(sizeof(uint32_t) * topo->total_cores);
|
||||
uint32_t* apic_core = emalloc(sizeof(uint32_t) * topo->total_cores);
|
||||
uint32_t* apic_smt = emalloc(sizeof(uint32_t) * topo->total_cores);
|
||||
uint32_t** cache_smt_id_apic = emalloc(sizeof(uint32_t*) * topo->total_cores);
|
||||
uint32_t** cache_id_apic = emalloc(sizeof(uint32_t*) * topo->total_cores);
|
||||
bool x2apic_id;
|
||||
|
||||
if(cpu->maxLevels >= 0x0000000B) {
|
||||
@@ -336,48 +365,48 @@ bool get_topology_from_apic(struct cpuInfo* cpu, struct topology* topo) {
|
||||
else {
|
||||
x2apic_id = false;
|
||||
}
|
||||
|
||||
|
||||
for(int i=0; i < topo->total_cores; i++) {
|
||||
cache_smt_id_apic[i] = malloc(sizeof(uint32_t) * (topo->cach->max_cache_level));
|
||||
cache_id_apic[i] = malloc(sizeof(uint32_t) * (topo->cach->max_cache_level));
|
||||
cache_smt_id_apic[i] = emalloc(sizeof(uint32_t) * (topo->cach->max_cache_level));
|
||||
cache_id_apic[i] = emalloc(sizeof(uint32_t) * (topo->cach->max_cache_level));
|
||||
}
|
||||
topo->apic->cache_select_mask = malloc(sizeof(uint32_t) * (topo->cach->max_cache_level));
|
||||
topo->apic->cache_id_apic = malloc(sizeof(uint32_t) * (topo->cach->max_cache_level));
|
||||
|
||||
topo->apic->cache_select_mask = emalloc(sizeof(uint32_t) * (topo->cach->max_cache_level));
|
||||
topo->apic->cache_id_apic = emalloc(sizeof(uint32_t) * (topo->cach->max_cache_level));
|
||||
|
||||
if(x2apic_id) {
|
||||
if(!fill_topo_masks_x2apic(topo))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(!fill_topo_masks_apic(topo))
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
get_cache_topology_from_apic(topo);
|
||||
|
||||
|
||||
get_cache_topology_from_apic(topo);
|
||||
|
||||
if(!fill_apic_ids(apic_ids, topo->total_cores, x2apic_id))
|
||||
return false;
|
||||
|
||||
for(int i=0; i < topo->total_cores; i++) {
|
||||
|
||||
for(int i=0; i < topo->total_cores; i++) {
|
||||
apic_id = apic_ids[i];
|
||||
|
||||
|
||||
apic_pkg[i] = (apic_id & topo->apic->pkg_mask) >> topo->apic->pkg_mask_shift;
|
||||
apic_core[i] = (apic_id & topo->apic->core_mask) >> topo->apic->smt_mask_width;
|
||||
apic_smt[i] = apic_id & topo->apic->smt_mask;
|
||||
|
||||
|
||||
for(int c=0; c < topo->cach->max_cache_level; c++) {
|
||||
cache_smt_id_apic[i][c] = apic_id & topo->apic->cache_select_mask[c];
|
||||
cache_id_apic[i][c] = apic_id & (-1 ^ topo->apic->cache_select_mask[c]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* DEBUG
|
||||
for(int i=0; i < topo->cach->max_cache_level; i++) {
|
||||
printf("[CACH %1d]", i);
|
||||
for(int j=0; j < topo->total_cores; j++)
|
||||
printf("[%03d]", cache_id_apic[j][i]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
for(int i=0; i < topo->total_cores; i++)
|
||||
printf("[%2d] 0x%.8X\n", i, apic_pkg[i]);
|
||||
printf("\n");
|
||||
@@ -386,16 +415,16 @@ bool get_topology_from_apic(struct cpuInfo* cpu, struct topology* topo) {
|
||||
printf("\n");
|
||||
for(int i=0; i < topo->total_cores; i++)
|
||||
printf("[%2d] 0x%.8X\n", i, apic_smt[i]);*/
|
||||
|
||||
|
||||
|
||||
|
||||
bool ret = build_topo_from_apic(apic_pkg, apic_smt, cache_id_apic, topo);
|
||||
|
||||
|
||||
// Assumption: If we cant get smt_available, we assume it is equal to smt_supported...
|
||||
if (!x2apic_id) {
|
||||
printWarn("Can't read SMT from cpuid (needed level is 0x%.8X, max is 0x%.8X)", 0x0000000B, cpu->maxLevels);
|
||||
printWarn("Can't read SMT from cpuid (needed level is 0x%.8X, max is 0x%.8X)", 0x0000000B, cpu->maxLevels);
|
||||
topo->smt_supported = topo->smt_available;
|
||||
}
|
||||
|
||||
|
||||
free(apic_pkg);
|
||||
free(apic_core);
|
||||
free(apic_smt);
|
||||
@@ -405,17 +434,17 @@ bool get_topology_from_apic(struct cpuInfo* cpu, struct topology* topo) {
|
||||
}
|
||||
free(cache_smt_id_apic);
|
||||
free(cache_id_apic);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t is_smt_enabled_amd(struct topology* topo) {
|
||||
#ifdef __APPLE__
|
||||
UNUSED(topo);
|
||||
return 1;
|
||||
#else
|
||||
#else
|
||||
uint32_t id;
|
||||
|
||||
|
||||
for(int i = 0; i < topo->total_cores; i++) {
|
||||
if(!bind_to_cpu(i)) {
|
||||
printErr("Failed binding to CPU %d", i);
|
||||
@@ -424,7 +453,7 @@ uint32_t is_smt_enabled_amd(struct topology* topo) {
|
||||
id = get_apic_id(false) & 1; // get the last bit
|
||||
if(id == 1) return 2; // We assume there isn't any AMD CPU with more than 2th per core.
|
||||
}
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
608
src/x86/cpuid.c
608
src/x86/cpuid.c
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,7 @@ char* get_str_avx(struct cpuInfo* cpu);
|
||||
char* get_str_sse(struct cpuInfo* cpu);
|
||||
char* get_str_fma(struct cpuInfo* cpu);
|
||||
char* get_str_topology(struct cpuInfo* cpu, struct topology* topo, bool dual_socket);
|
||||
char* get_str_peak_performance(struct cpuInfo* cpu, struct topology* topo, int64_t freq);
|
||||
char* get_str_cpu_name_abbreviated(struct cpuInfo* cpu);
|
||||
|
||||
void print_debug(struct cpuInfo* cpu);
|
||||
void print_raw(struct cpuInfo* cpu);
|
||||
|
||||
158
src/x86/freq.c
Normal file
158
src/x86/freq.c
Normal file
@@ -0,0 +1,158 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
|
||||
#include "freq.h"
|
||||
#include "../common/global.h"
|
||||
|
||||
#include <immintrin.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define MEASURE_TIME_SECONDS 5
|
||||
#define MAX_NUMBER_THREADS 512
|
||||
#define FREQ_VECTOR_SIZE 1<<16
|
||||
#define LOOP_ITERS 100000000
|
||||
|
||||
struct freq_thread {
|
||||
bool end;
|
||||
bool measure;
|
||||
double freq;
|
||||
};
|
||||
|
||||
double vector_average_harmonic(double* v, int len) {
|
||||
double acc = 0.0;
|
||||
for(int i=0; i < len; i++) {
|
||||
acc += 1 / v[i];
|
||||
}
|
||||
return len / acc;
|
||||
}
|
||||
|
||||
void sleep_ms(int64_t ms) {
|
||||
struct timespec ts;
|
||||
ts.tv_sec = ms / 1000;
|
||||
ts.tv_nsec = (ms % 1000) * 1000000;
|
||||
nanosleep(&ts, &ts);
|
||||
}
|
||||
|
||||
void* measure_freq(void *freq_ptr) {
|
||||
struct freq_thread* freq = (struct freq_thread*) freq_ptr;
|
||||
|
||||
char* end = NULL;
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read;
|
||||
|
||||
int v = 0;
|
||||
double* freq_vector = malloc(sizeof(double) * FREQ_VECTOR_SIZE);
|
||||
|
||||
while(!freq->end) {
|
||||
if(!freq->measure) continue;
|
||||
|
||||
FILE* fp = fopen("/proc/cpuinfo", "r");
|
||||
if(fp == NULL) return NULL;
|
||||
while ((read = getline(&line, &len, fp)) != -1) {
|
||||
if((line = strstr(line, "cpu MHz")) != NULL) {
|
||||
line = strstr(line, "\t: ");
|
||||
if(line == NULL) return NULL;
|
||||
line += sizeof("\t: ") - 1;
|
||||
double f = strtold(line, &end);
|
||||
if(errno != 0) {
|
||||
printf("strtol: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
freq_vector[v] = f;
|
||||
v++;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
sleep_ms(500);
|
||||
}
|
||||
|
||||
freq->freq = vector_average_harmonic(freq_vector, v);
|
||||
printWarn("AVX2 measured freq=%f\n", freq->freq);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* compute_avx() {
|
||||
bool end = false;
|
||||
|
||||
struct timeval begin, now;
|
||||
|
||||
__m256 a = _mm256_set1_ps(1.5);
|
||||
__m256 b = _mm256_set1_ps(1.2);
|
||||
__m256 c = _mm256_set1_ps(0.0);
|
||||
|
||||
gettimeofday(&begin, NULL);
|
||||
while(!end) {
|
||||
for(uint64_t i=0; i < LOOP_ITERS; i++) {
|
||||
c = _mm256_fmadd_ps(a, b, c);
|
||||
}
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
double elapsed = (now.tv_sec - begin.tv_sec) + ((now.tv_usec - begin.tv_usec)/1000000.0);
|
||||
end = elapsed >= (double) MEASURE_TIME_SECONDS;
|
||||
}
|
||||
|
||||
FILE* fp = fopen("/dev/null", "w");
|
||||
if(fp == NULL) {
|
||||
printf("fopen: %s", strerror(errno));
|
||||
}
|
||||
else {
|
||||
fprintf(fp, "%f", c[0]);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int64_t measure_avx_frequency(struct cpuInfo* cpu) {
|
||||
int ret;
|
||||
struct freq_thread* freq_struct = malloc(sizeof(struct freq_thread));
|
||||
freq_struct->end = false;
|
||||
freq_struct->measure = false;
|
||||
|
||||
pthread_t freq_t;
|
||||
if(pthread_create(&freq_t, NULL, measure_freq, freq_struct)) {
|
||||
fprintf(stderr, "Error creating thread\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pthread_t* compute_th = malloc(sizeof(pthread_t) * cpu->topo->total_cores);
|
||||
for(int i=0; i < cpu->topo->total_cores; i++) {
|
||||
ret = pthread_create(&compute_th[i], NULL, compute_avx, NULL);
|
||||
|
||||
if(ret != 0) {
|
||||
fprintf(stderr, "Error creating thread\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("cpufetch is measuring AVX2 frequency...");
|
||||
fflush(stdout);
|
||||
|
||||
sleep_ms(500);
|
||||
freq_struct->measure = true;
|
||||
|
||||
for(int i=0; i < cpu->topo->total_cores; i++) {
|
||||
if(pthread_join(compute_th[i], NULL)) {
|
||||
fprintf(stderr, "Error joining thread\n");
|
||||
return -1;
|
||||
}
|
||||
freq_struct->end = true;
|
||||
}
|
||||
|
||||
if(pthread_join(freq_t, NULL)) {
|
||||
fprintf(stderr, "Error joining thread\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("\r ");
|
||||
return freq_struct->freq;
|
||||
}
|
||||
9
src/x86/freq.h
Normal file
9
src/x86/freq.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef __FREQ__
|
||||
#define __FREQ__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "../common/cpu.h"
|
||||
|
||||
int64_t measure_avx_frequency(struct cpuInfo* cpu);
|
||||
|
||||
#endif
|
||||
113
src/x86/uarch.c
113
src/x86/uarch.c
@@ -38,8 +38,6 @@
|
||||
|
||||
typedef uint32_t MICROARCH;
|
||||
|
||||
#define STRING_UNKNOWN "Unknown"
|
||||
|
||||
// Data not available
|
||||
#define NA -1
|
||||
|
||||
@@ -80,7 +78,7 @@ enum {
|
||||
UARCH_SUNNY_COVE,
|
||||
UARCH_GOLDMONT_PLUS,
|
||||
UARCH_TREMONT,
|
||||
UARCH_WILLOW_COVE,
|
||||
UARCH_LAKEMONT,
|
||||
UARCH_COFFE_LAKE,
|
||||
UARCH_ITANIUM,
|
||||
UARCH_KNIGHTS_FERRY,
|
||||
@@ -91,6 +89,7 @@ enum {
|
||||
UARCH_CEDAR_MILL,
|
||||
UARCH_ITANIUM2,
|
||||
UARCH_ICE_LAKE,
|
||||
UARCH_TIGER_LAKE,
|
||||
// AMD //
|
||||
UARCH_AM486,
|
||||
UARCH_AM5X86,
|
||||
@@ -121,10 +120,10 @@ struct uarch {
|
||||
#define UARCH_START if (false) {}
|
||||
#define CHECK_UARCH(arch, ef_, f_, em_, m_, s_, str, uarch, process) \
|
||||
else if (ef_ == ef && f_ == f && (em_ == NA || em_ == em) && (m_ == NA || m_ == m) && (s_ == NA || s_ == s)) fill_uarch(arch, str, uarch, process);
|
||||
#define UARCH_END else { printBug("Unknown microarchitecture detected: M=0x%.8X EM=0x%.8X F=0x%.8X EF=0x%.8X S=0x%.8X", m, em, f, ef, s); fill_uarch(arch, "Unknown", UARCH_UNKNOWN, 0); }
|
||||
#define UARCH_END else { printBug("Unknown microarchitecture detected: M=0x%.8X EM=0x%.8X F=0x%.8X EF=0x%.8X S=0x%.8X", m, em, f, ef, s); fill_uarch(arch, STRING_UNKNOWN, UARCH_UNKNOWN, 0); }
|
||||
|
||||
void fill_uarch(struct uarch* arch, char* str, MICROARCH u, uint32_t process) {
|
||||
arch->uarch_str = malloc(sizeof(char) * (strlen(str)+1));
|
||||
arch->uarch_str = emalloc(sizeof(char) * (strlen(str)+1));
|
||||
strcpy(arch->uarch_str, str);
|
||||
arch->uarch = u;
|
||||
arch->process= process;
|
||||
@@ -132,8 +131,8 @@ void fill_uarch(struct uarch* arch, char* str, MICROARCH u, uint32_t process) {
|
||||
|
||||
// Inspired in Todd Allen's decode_uarch_intel
|
||||
struct uarch* get_uarch_from_cpuid_intel(uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s) {
|
||||
struct uarch* arch = malloc(sizeof(struct uarch));
|
||||
|
||||
struct uarch* arch = emalloc(sizeof(struct uarch));
|
||||
|
||||
// EF: Extended Family //
|
||||
// F: Family //
|
||||
// EM: Extended Model //
|
||||
@@ -149,7 +148,9 @@ struct uarch* get_uarch_from_cpuid_intel(uint32_t ef, uint32_t f, uint32_t em, u
|
||||
CHECK_UARCH(arch, 0, 5, 0, 4, NA, "P5 MMX", UARCH_P5, UNK)
|
||||
CHECK_UARCH(arch, 0, 5, 0, 7, NA, "P5 MMX", UARCH_P5, UNK)
|
||||
CHECK_UARCH(arch, 0, 5, 0, 8, NA, "P5 MMX", UARCH_P5, 250)
|
||||
CHECK_UARCH(arch, 0, 5, 0, 9, 0, "Lakemont", UARCH_LAKEMONT, 32)
|
||||
CHECK_UARCH(arch, 0, 5, 0, 9, NA, "P5 MMX", UARCH_P5, UNK)
|
||||
CHECK_UARCH(arch, 0, 5, 0, 10, 0, "Lakemont", UARCH_LAKEMONT, 32)
|
||||
CHECK_UARCH(arch, 0, 6, 0, 0, NA, "P6 Pentium II", UARCH_P6, UNK)
|
||||
CHECK_UARCH(arch, 0, 6, 0, 1, NA, "P6 Pentium II", UARCH_P6, UNK) // process depends on core
|
||||
CHECK_UARCH(arch, 0, 6, 0, 2, NA, "P6 Pentium II", UARCH_P6, UNK)
|
||||
@@ -220,13 +221,14 @@ struct uarch* get_uarch_from_cpuid_intel(uint32_t ef, uint32_t f, uint32_t em, u
|
||||
CHECK_UARCH(arch, 0, 6, 8, 5, NA, "Knights Mill", UARCH_KNIGHTS_MILL, 14) // no spec update; only MSR_CPUID_table* so far
|
||||
CHECK_UARCH(arch, 0, 6, 8, 6, NA, "Tremont", UARCH_TREMONT, 10) // LX*
|
||||
CHECK_UARCH(arch, 0, 6, 8, 10, NA, "Tremont", UARCH_TREMONT, 10) // no spec update; only geekbench.com example
|
||||
CHECK_UARCH(arch, 0, 6, 8, 12, NA, "Willow Cove", UARCH_WILLOW_COVE, 10) // found only on en.wikichip.org
|
||||
CHECK_UARCH(arch, 0, 6, 8, 13, NA, "Willow Cove", UARCH_WILLOW_COVE, 10) // LX*
|
||||
CHECK_UARCH(arch, 0, 6, 8, 14, 9, "Amber Lake", UARCH_AMBER_LAKE, 14) // wikichip
|
||||
CHECK_UARCH(arch, 0, 6, 8, 12, NA, "Tiger Lake", UARCH_TIGER_LAKE, 10) // instlatx64
|
||||
CHECK_UARCH(arch, 0, 6, 8, 13, NA, "Tiger Lake", UARCH_TIGER_LAKE, 10) // instlatx64
|
||||
// CHECK_UARCH(arch, 0, 6, 8, 14, 9, ...) It is not possible to determine uarch only from CPUID dump (can be Kaby Lake or Amber Lake)
|
||||
CHECK_UARCH(arch, 0, 6, 8, 14, 10, "Kaby Lake", UARCH_KABY_LAKE, 14) // wikichip
|
||||
CHECK_UARCH(arch, 0, 6, 8, 14, 11, "Whiskey Lake", UARCH_WHISKEY_LAKE, 14) // wikichip
|
||||
CHECK_UARCH(arch, 0, 6, 8, 14, 12, "Comet Lake", UARCH_COMET_LAKE, 14) // wikichip
|
||||
CHECK_UARCH(arch, 0, 6, 9, 6, NA, "Tremont", UARCH_TREMONT, 10) // LX*
|
||||
CHECK_UARCH(arch, 0, 6, 9, 10, NA, "Tremont", UARCH_TREMONT, 10) // instlatx64
|
||||
CHECK_UARCH(arch, 0, 6, 9, 12, NA, "Tremont", UARCH_TREMONT, 10) // LX*
|
||||
CHECK_UARCH(arch, 0, 6, 9, 13, NA, "Sunny Cove", UARCH_SUNNY_COVE, 10) // LX*
|
||||
CHECK_UARCH(arch, 0, 6, 9, 14, 9, "Kaby Lake", UARCH_KABY_LAKE, 14)
|
||||
@@ -249,14 +251,14 @@ struct uarch* get_uarch_from_cpuid_intel(uint32_t ef, uint32_t f, uint32_t em, u
|
||||
CHECK_UARCH(arch, 1, 15, 0, 1, NA, "Itanium2", UARCH_ITANIUM2, 130)
|
||||
CHECK_UARCH(arch, 1, 15, 0, 2, NA, "Itanium2", UARCH_ITANIUM2, 130)
|
||||
UARCH_END
|
||||
|
||||
|
||||
return arch;
|
||||
}
|
||||
|
||||
// iNApired in Todd Allen's decode_uarch_amd
|
||||
struct uarch* get_uarch_from_cpuid_amd(uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s) {
|
||||
struct uarch* arch = malloc(sizeof(struct uarch));
|
||||
|
||||
struct uarch* arch = emalloc(sizeof(struct uarch));
|
||||
|
||||
// EF: Extended Family //
|
||||
// F: Family //
|
||||
// EM: Extended Model //
|
||||
@@ -264,7 +266,7 @@ struct uarch* get_uarch_from_cpuid_amd(uint32_t ef, uint32_t f, uint32_t em, uin
|
||||
// S: Stepping //
|
||||
// ----------------------------------------------------------------------------- //
|
||||
// EF F EM M S //
|
||||
UARCH_START
|
||||
UARCH_START
|
||||
CHECK_UARCH(arch, 0, 4, 0, 3, NA, "Am486", UARCH_AM486, UNK)
|
||||
CHECK_UARCH(arch, 0, 4, 0, 7, NA, "Am486", UARCH_AM486, UNK)
|
||||
CHECK_UARCH(arch, 0, 4, 0, 8, NA, "Am486", UARCH_AM486, UNK)
|
||||
@@ -272,7 +274,8 @@ struct uarch* get_uarch_from_cpuid_amd(uint32_t ef, uint32_t f, uint32_t em, uin
|
||||
CHECK_UARCH(arch, 0, 4, NA, NA, NA, "Am5x86", UARCH_AM5X86, UNK)
|
||||
CHECK_UARCH(arch, 0, 5, 0, 6, NA, "K6", UARCH_K6, 300)
|
||||
CHECK_UARCH(arch, 0, 5, 0, 7, NA, "K6", UARCH_K6, 250) // *p from sandpile.org
|
||||
CHECK_UARCH(arch, 0, 5, 0, 13, NA, "K6", UARCH_K6, 80) // *p from sandpile.org
|
||||
CHECK_UARCH(arch, 0, 5, 0, 10, NA, "K7", UARCH_K7, 130) // Geode NX
|
||||
CHECK_UARCH(arch, 0, 5, 0, 13, NA, "K6", UARCH_K6, 80) // *p from sandpile.org
|
||||
CHECK_UARCH(arch, 0, 5, NA, NA, NA, "K6", UARCH_K6, UNK)
|
||||
CHECK_UARCH(arch, 0, 6, 0, 1, NA, "K7", UARCH_K7, 250)
|
||||
CHECK_UARCH(arch, 0, 6, 0, 2, NA, "K7", UARCH_K7, 180)
|
||||
@@ -327,7 +330,7 @@ struct uarch* get_uarch_from_cpuid_amd(uint32_t ef, uint32_t f, uint32_t em, uin
|
||||
CHECK_UARCH(arch, 2, 15, NA, NA, NA, "Puma 2008", UARCH_PUMA_2008, 65)
|
||||
CHECK_UARCH(arch, 3, 15, NA, NA, NA, "K10", UARCH_K10, 32)
|
||||
CHECK_UARCH(arch, 5, 15, NA, NA, NA, "Bobcat", UARCH_BOBCAT, 40)
|
||||
CHECK_UARCH(arch, 6, 15, 0, 0, NA, "Bulldozer", UARCH_BULLDOZER, 32) // iNAtlatx64 engr sample
|
||||
CHECK_UARCH(arch, 6, 15, 0, 0, NA, "Bulldozer", UARCH_BULLDOZER, 32) // instlatx64 engr sample
|
||||
CHECK_UARCH(arch, 6, 15, 0, 1, NA, "Bulldozer", UARCH_BULLDOZER, 32)
|
||||
CHECK_UARCH(arch, 6, 15, 0, 2, NA, "Piledriver", UARCH_PILEDRIVER, 32)
|
||||
CHECK_UARCH(arch, 6, 15, 1, 0, NA, "Piledriver", UARCH_PILEDRIVER, 32)
|
||||
@@ -335,76 +338,108 @@ struct uarch* get_uarch_from_cpuid_amd(uint32_t ef, uint32_t f, uint32_t em, uin
|
||||
CHECK_UARCH(arch, 6, 15, 3, 0, NA, "Steamroller", UARCH_STEAMROLLER, 28)
|
||||
CHECK_UARCH(arch, 6, 15, 3, 8, NA, "Steamroller", UARCH_STEAMROLLER, 28)
|
||||
CHECK_UARCH(arch, 6, 15, 4, 0, NA, "Steamroller", UARCH_STEAMROLLER, 28) // Software Optimization Guide (15h) says it has the same iNAt latencies as (6,15),(3,x).
|
||||
CHECK_UARCH(arch, 6, 15, 6, 0, NA, "Excavator", UARCH_EXCAVATOR, 28) // undocumented, but iNAtlatx64 samples
|
||||
CHECK_UARCH(arch, 6, 15, 6, 0, NA, "Excavator", UARCH_EXCAVATOR, 28) // undocumented, but instlatx64 samples
|
||||
CHECK_UARCH(arch, 6, 15, 6, 5, NA, "Excavator", UARCH_EXCAVATOR, 28) // undocumented, but sample from Alexandros Couloumbis
|
||||
CHECK_UARCH(arch, 6, 15, 7, 0, NA, "Excavator", UARCH_EXCAVATOR, 28)
|
||||
CHECK_UARCH(arch, 7, 15, 0, 0, NA, "Jaguar", UARCH_JAGUAR, 28)
|
||||
CHECK_UARCH(arch, 7, 15, 2, 6, NA, "Jaguar", UARCH_JAGUAR, 28) // AMD Cato (Xbox One?)
|
||||
CHECK_UARCH(arch, 7, 15, 3, 0, NA, "Puma 2014", UARCH_PUMA_2014, 28)
|
||||
CHECK_UARCH(arch, 8, 15, 0, 0, NA, "Zen", UARCH_ZEN, 14) // iNAtlatx64 engr sample
|
||||
CHECK_UARCH(arch, 8, 15, 0, 0, NA, "Zen", UARCH_ZEN, 14) // instlatx64 engr sample
|
||||
CHECK_UARCH(arch, 8, 15, 0, 1, NA, "Zen", UARCH_ZEN, 14)
|
||||
CHECK_UARCH(arch, 8, 15, 0, 8, NA, "Zen+", UARCH_ZEN_PLUS, 12)
|
||||
CHECK_UARCH(arch, 8, 15, 1, 1, NA, "Zen", UARCH_ZEN, 14) // found only on en.wikichip.org & iNAtlatx64 examples
|
||||
CHECK_UARCH(arch, 8, 15, 1, 1, NA, "Zen", UARCH_ZEN, 14) // found only on en.wikichip.org & instlatx64 examples
|
||||
CHECK_UARCH(arch, 8, 15, 1, 8, NA, "Zen+", UARCH_ZEN_PLUS, 12) // found only on en.wikichip.org
|
||||
CHECK_UARCH(arch, 8, 15, 2, 0, NA, "Zen", UARCH_ZEN, 14) // Dali, found on instlatx64 and en.wikichip.org
|
||||
CHECK_UARCH(arch, 8, 15, 3, 1, NA, "Zen 2", UARCH_ZEN2, 7) // found only on en.wikichip.org
|
||||
CHECK_UARCH(arch, 8, 15, 4, 7, NA, "Zen 2", UARCH_ZEN2, 7) // instlatx64 example (AMD 4700S)
|
||||
CHECK_UARCH(arch, 8, 15, 5, 0, NA, "Zen", UARCH_ZEN, 14) // instlatx64 example (Subor Z+)
|
||||
CHECK_UARCH(arch, 8, 15, 6, 0, NA, "Zen 2", UARCH_ZEN2, 7) // undocumented, geekbench.com example
|
||||
CHECK_UARCH(arch, 8, 15, 7, 1, NA, "Zen 2", UARCH_ZEN2, 7) // undocumented, but samples from Steven Noonan
|
||||
CHECK_UARCH(arch, 10, 15, NA, NA, NA, "Zen 3", UARCH_ZEN3, 7) // undocumented, LX*
|
||||
CHECK_UARCH(arch, 8, 15, 6, 8, NA, "Zen 2", UARCH_ZEN2, 7) // found on instlatx64
|
||||
CHECK_UARCH(arch, 8, 15, 7, 1, NA, "Zen 2", UARCH_ZEN2, 7) // samples from Steven Noonan and instlatx64
|
||||
CHECK_UARCH(arch, 10, 15, 0, 1, NA, "Zen 3", UARCH_ZEN3, 7) // instlatx64
|
||||
CHECK_UARCH(arch, 10, 15, 2, 1, NA, "Zen 3", UARCH_ZEN3, 7) // instlatx64
|
||||
CHECK_UARCH(arch, 10, 15, 5, 0, NA, "Zen 3", UARCH_ZEN3, 7) // instlatx64
|
||||
UARCH_END
|
||||
|
||||
|
||||
return arch;
|
||||
}
|
||||
|
||||
struct uarch* get_uarch_from_cpuid(struct cpuInfo* cpu, uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s) {
|
||||
if(cpu->cpu_vendor == CPU_VENDOR_INTEL)
|
||||
struct uarch* get_uarch_from_cpuid(struct cpuInfo* cpu, uint32_t dump, uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s) {
|
||||
if(cpu->cpu_vendor == CPU_VENDOR_INTEL) {
|
||||
if(dump == 0x000806E9) {
|
||||
// It is not possible to determine uarch only from CPUID dump (can be Kaby Lake or Amber Lake)
|
||||
struct uarch* arch = emalloc(sizeof(struct uarch));
|
||||
|
||||
if(strstr(cpu->cpu_name, "Y") != NULL) {
|
||||
fill_uarch(arch, "Amber Lake", UARCH_AMBER_LAKE, 14);
|
||||
}
|
||||
else {
|
||||
fill_uarch(arch, "Kaby Lake", UARCH_KABY_LAKE, 14);
|
||||
}
|
||||
|
||||
return arch;
|
||||
}
|
||||
return get_uarch_from_cpuid_intel(ef, f, em, m, s);
|
||||
else
|
||||
}
|
||||
else
|
||||
return get_uarch_from_cpuid_amd(ef, f, em, m, s);
|
||||
}
|
||||
|
||||
bool vpus_are_AVX512(struct cpuInfo* cpu) {
|
||||
return cpu->arch->uarch != UARCH_ICE_LAKE;
|
||||
return cpu->arch->uarch != UARCH_ICE_LAKE && cpu->arch->uarch != UARCH_TIGER_LAKE;
|
||||
}
|
||||
|
||||
bool is_knights_landing(struct cpuInfo* cpu) {
|
||||
return cpu->arch->uarch == UARCH_KNIGHTS_LANDING;
|
||||
return cpu->arch->uarch == UARCH_KNIGHTS_LANDING;
|
||||
}
|
||||
|
||||
int get_number_of_vpus(struct cpuInfo* cpu) {
|
||||
int get_number_of_vpus(struct cpuInfo* cpu) {
|
||||
switch(cpu->arch->uarch) {
|
||||
// Intel
|
||||
case UARCH_HASWELL:
|
||||
case UARCH_BROADWELL:
|
||||
|
||||
|
||||
case UARCH_SKYLAKE:
|
||||
case UARCH_CASCADE_LAKE:
|
||||
case UARCH_CASCADE_LAKE:
|
||||
case UARCH_KABY_LAKE:
|
||||
case UARCH_COMET_LAKE:
|
||||
case UARCH_ROCKET_LAKE:
|
||||
case UARCH_AMBER_LAKE:
|
||||
case UARCH_WHISKEY_LAKE:
|
||||
case UARCH_COFFE_LAKE:
|
||||
case UARCH_PALM_COVE:
|
||||
|
||||
case UARCH_PALM_COVE:
|
||||
|
||||
case UARCH_KNIGHTS_LANDING:
|
||||
case UARCH_KNIGHTS_MILL:
|
||||
|
||||
case UARCH_ICE_LAKE:
|
||||
|
||||
|
||||
case UARCH_ICE_LAKE:
|
||||
case UARCH_TIGER_LAKE:
|
||||
|
||||
// AMD
|
||||
case UARCH_ZEN2:
|
||||
case UARCH_ZEN3:
|
||||
case UARCH_ZEN3:
|
||||
return 2;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool choose_new_intel_logo_uarch(struct cpuInfo* cpu) {
|
||||
switch(cpu->arch->uarch) {
|
||||
case UARCH_ROCKET_LAKE:
|
||||
case UARCH_TIGER_LAKE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
char* get_str_uarch(struct cpuInfo* cpu) {
|
||||
return cpu->arch->uarch_str;
|
||||
return cpu->arch->uarch_str;
|
||||
}
|
||||
|
||||
char* get_str_process(struct cpuInfo* cpu) {
|
||||
char* str = malloc(sizeof(char) * (strlen(STRING_UNKNOWN)+1));
|
||||
char* str = emalloc(sizeof(char) * (strlen(STRING_UNKNOWN)+1));
|
||||
int32_t process = cpu->arch->process;
|
||||
|
||||
if(process == UNK) {
|
||||
@@ -424,7 +459,7 @@ char* get_str_process(struct cpuInfo* cpu) {
|
||||
return str;
|
||||
}
|
||||
|
||||
void free_uarch_struct(struct uarch* arch) {
|
||||
void free_uarch_struct(struct uarch* arch) {
|
||||
free(arch->uarch_str);
|
||||
free(arch);
|
||||
}
|
||||
|
||||
@@ -7,10 +7,11 @@
|
||||
|
||||
struct uarch;
|
||||
|
||||
struct uarch* get_uarch_from_cpuid(struct cpuInfo* cpu, uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s);
|
||||
struct uarch* get_uarch_from_cpuid(struct cpuInfo* cpu, uint32_t dump, uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s);
|
||||
bool vpus_are_AVX512(struct cpuInfo* cpu);
|
||||
bool is_knights_landing(struct cpuInfo* cpu);
|
||||
int get_number_of_vpus(struct cpuInfo* cpu);
|
||||
bool choose_new_intel_logo_uarch(struct cpuInfo* cpu);
|
||||
char* get_str_uarch(struct cpuInfo* cpu);
|
||||
char* get_str_process(struct cpuInfo* cpu);
|
||||
void free_uarch_struct(struct uarch* arch);
|
||||
|
||||
23
src/x86/uarch_decode.sh
Executable file
23
src/x86/uarch_decode.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash -u
|
||||
|
||||
CPUID=0x00A50F00
|
||||
|
||||
efamily=$(((${CPUID}>>20)&0xFF))
|
||||
family=$(((${CPUID}>>8)&0xF))
|
||||
emodel=$(((${CPUID}>>16)&0xF))
|
||||
model=$(((${CPUID}>>4)&0xF))
|
||||
stepping=$((${CPUID}&0xF))
|
||||
|
||||
printf 'CPUID: 0x%.8X\n' $CPUID
|
||||
printf -- '- EF = 0x%X (%d)\n' $efamily $efamily
|
||||
printf -- '- F = 0x%X (%d)\n' $family $family
|
||||
printf -- '- EM = 0x%X (%d)\n' $emodel $emodel
|
||||
printf -- '- M = 0x%X (%d)\n' $model $model
|
||||
printf -- '- S = 0x%X (%d)\n' $stepping $stepping
|
||||
|
||||
#EF=$efamily
|
||||
#F=$family
|
||||
#EM=$emodel
|
||||
#M=$model
|
||||
#S=$stepping
|
||||
#grep -E "\s*CHECK_UARCH\(arch,\s*${EF},\s*${F},\s*(${EM}|NA),\s*(${M}|NA),\s*(${S}|NA)" uarch.c
|
||||
Reference in New Issue
Block a user