Files
cpufetch/src/arm/midr.c

244 lines
6.2 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h>
#include "../common/udev.h"
#include "../common/global.h"
#include "midr.h"
#include "uarch.h"
#include "soc.h"
#define STRING_UNKNOWN "Unknown"
void init_topology_struct(struct topology* topo, struct cache* cach) {
topo->total_cores = 0;
topo->physical_cores = 0;
topo->logical_cores = 0;
topo->smt_available = 0;
topo->smt_supported = 0;
topo->sockets = 0;
topo->cach = cach;
}
void init_cache_struct(struct cache* cach) {
cach->L1i = malloc(sizeof(struct cach));
cach->L1d = malloc(sizeof(struct cach));
cach->L2 = malloc(sizeof(struct cach));
cach->L3 = malloc(sizeof(struct cach));
cach->cach_arr = malloc(sizeof(struct cach*) * 4);
cach->cach_arr[0] = cach->L1i;
cach->cach_arr[1] = cach->L1d;
cach->cach_arr[2] = cach->L2;
cach->cach_arr[3] = cach->L3;
cach->max_cache_level = 0;
cach->L1i->exists = false;
cach->L1d->exists = false;
cach->L2->exists = false;
cach->L3->exists = false;
}
struct cache* get_cache_info(struct cpuInfo* cpu) {
struct cache* cach = malloc(sizeof(struct cache));
init_cache_struct(cach);
cach->max_cache_level = 2;
for(int i=0; i < cach->max_cache_level + 1; i++) {
cach->cach_arr[i]->exists = true;
cach->cach_arr[i]->num_caches = 1;
cach->cach_arr[i]->size = 0;
}
return cach;
}
struct frequency* get_frequency_info(uint32_t core) {
struct frequency* freq = malloc(sizeof(struct frequency));
freq->base = UNKNOWN_FREQ;
freq->max = get_max_freq_from_file(core);
return freq;
}
struct topology* get_topology_info(struct cpuInfo* cpu, struct cache* cach) {
struct topology* topo = malloc(sizeof(struct topology));
init_topology_struct(topo, cach);
topo->total_cores = get_ncores_from_cpuinfo();
topo->physical_cores = topo->total_cores;
topo->logical_cores = topo->total_cores;
topo->smt_available = 1;
topo->smt_supported = 0;
topo->sockets = 1;
return topo;
}
int count_distinct(uint32_t* arr, int n) {
int res = 1;
for (int i = 1; i < n; i++) {
int j = 0;
for (j = 0; j < i; j++) {
if (arr[i] == arr[j])
break;
}
if (i == j)
res++;
}
return res;
}
uint32_t fill_ids_from_midr(uint32_t* midr_array, uint32_t* ids_array, int len) {
uint32_t latest_id = 0;
bool found;
ids_array[0] = latest_id;
for (int i = 1; i < len; i++) {
int j = 0;
found = false;
for (j = 0; j < len && !found; j++) {
if (i != j && midr_array[i] == midr_array[j]) {
if(j > i) {
latest_id++;
ids_array[i] = latest_id;
}
else {
ids_array[i] = ids_array[j];
}
found = true;
}
}
if(!found) {
latest_id++;
ids_array[i] = latest_id;
}
}
return latest_id+1;
}
struct cpuInfo* get_cpu_info() {
struct cpuInfo* cpu = malloc(sizeof(struct cpuInfo));
cpu->next_cpu = NULL;
int ncores = get_ncores_from_cpuinfo();
bool success = false;
uint32_t* midr_array = malloc(sizeof(uint32_t) * ncores);
uint32_t* ids_array = malloc(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];
}
}
uint32_t sockets = fill_ids_from_midr(midr_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 = ptr->next_cpu;
tmp_midr_idx = midr_idx;
while(midr_array[midr_idx] == midr_array[tmp_midr_idx]) tmp_midr_idx++;
midr_idx = tmp_midr_idx;
}
ptr->next_cpu = NULL;
ptr->midr = midr_array[midr_idx];
ptr->arch = get_uarch_from_midr(ptr->midr, ptr);
ptr->freq = get_frequency_info(i); // TODO: wrong!
ptr->cach = get_cache_info(ptr);
ptr->topo = get_topology_info(ptr, ptr->cach);
}
cpu->num_cpus = sockets;
cpu->hv = malloc(sizeof(struct hypervisor));
cpu->hv->present = false;
cpu->soc = get_soc();
return cpu;
}
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);
snprintf(string, size, "%d cores", topo->physical_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(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;
}
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);
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);
}
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));
}
else {
printf("%ld MHz\n", freq);
}
}
}
void free_topo_struct(struct topology* topo) {
free(topo);
}