mirror of
https://github.com/Dr-Noob/cpufetch.git
synced 2026-03-25 16:00:39 +01:00
[v1.03][RISCV] Add basic SoC detection backend
This commit is contained in:
4
Makefile
4
Makefile
@@ -43,8 +43,8 @@ ifneq ($(OS),Windows_NT)
|
|||||||
endif
|
endif
|
||||||
else ifeq ($(arch), $(filter $(arch), riscv64 riscv32))
|
else ifeq ($(arch), $(filter $(arch), riscv64 riscv32))
|
||||||
SRC_DIR=src/riscv/
|
SRC_DIR=src/riscv/
|
||||||
SOURCE += $(COMMON_SRC) $(SRC_DIR)riscv.c $(SRC_DIR)uarch.c $(SRC_DIR)soc.c
|
SOURCE += $(COMMON_SRC) $(SRC_DIR)riscv.c $(SRC_DIR)uarch.c $(SRC_DIR)soc.c $(SRC_DIR)udev.c
|
||||||
HEADERS += $(COMMON_SRC) $(SRC_DIR)riscv.h $(SRC_DIR)uarch.h $(SRC_DIR)soc.h
|
HEADERS += $(COMMON_SRC) $(SRC_DIR)riscv.h $(SRC_DIR)uarch.h $(SRC_DIR)soc.h $(SRC_DIR)udev.h $(SRC_DIR)socs.h
|
||||||
CFLAGS += -DARCH_RISCV -Wno-unused-parameter -std=c99 -fstack-protector-all
|
CFLAGS += -DARCH_RISCV -Wno-unused-parameter -std=c99 -fstack-protector-all
|
||||||
else
|
else
|
||||||
# Error lines should not be tabulated because Makefile complains about it
|
# Error lines should not be tabulated because Makefile complains about it
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
enum {
|
enum {
|
||||||
#if defined(ARCH_X86) || defined(ARCH_PPC)
|
#if defined(ARCH_X86) || defined(ARCH_PPC)
|
||||||
ATTRIBUTE_NAME,
|
ATTRIBUTE_NAME,
|
||||||
#elif ARCH_ARM
|
#elif defined(ARCH_ARM) || defined(ARCH_RISCV)
|
||||||
ATTRIBUTE_SOC,
|
ATTRIBUTE_SOC,
|
||||||
#endif
|
#endif
|
||||||
#if defined(ARCH_X86) || defined(ARCH_ARM)
|
#if defined(ARCH_X86) || defined(ARCH_ARM)
|
||||||
@@ -79,7 +79,7 @@ static const char* ATTRIBUTE_FIELDS [] = {
|
|||||||
"Name:",
|
"Name:",
|
||||||
#elif ARCH_PPC
|
#elif ARCH_PPC
|
||||||
"Part Number:",
|
"Part Number:",
|
||||||
#elif ARCH_ARM
|
#elif defined(ARCH_ARM) || defined(ARCH_RISCV)
|
||||||
"SoC:",
|
"SoC:",
|
||||||
#endif
|
#endif
|
||||||
#if defined(ARCH_X86) || defined(ARCH_ARM)
|
#if defined(ARCH_X86) || defined(ARCH_ARM)
|
||||||
@@ -926,6 +926,8 @@ bool print_cpufetch_riscv(struct cpuInfo* cpu, STYLE s, struct color** cs, struc
|
|||||||
// Step 1. Retrieve attributes
|
// Step 1. Retrieve attributes
|
||||||
char* uarch = get_str_uarch(cpu);
|
char* uarch = get_str_uarch(cpu);
|
||||||
char* manufacturing_process = get_str_process(cpu->soc);
|
char* manufacturing_process = get_str_process(cpu->soc);
|
||||||
|
char* soc_name = get_soc_name(cpu->soc);
|
||||||
|
char* features = get_str_features(cpu);
|
||||||
char* max_frequency = get_str_freq(cpu->freq);
|
char* max_frequency = get_str_freq(cpu->freq);
|
||||||
char* n_cores = get_str_topology(cpu, cpu->topo);
|
char* n_cores = get_str_topology(cpu, cpu->topo);
|
||||||
|
|
||||||
@@ -936,10 +938,11 @@ bool print_cpufetch_riscv(struct cpuInfo* cpu, STYLE s, struct color** cs, struc
|
|||||||
char* pp = get_str_peak_performance(cpu->peak_performance);
|
char* pp = get_str_peak_performance(cpu->peak_performance);
|
||||||
|
|
||||||
// Step 2. Set attributes
|
// Step 2. Set attributes
|
||||||
setAttribute(art,ATTRIBUTE_UARCH,uarch);
|
setAttribute(art,ATTRIBUTE_SOC,soc_name);
|
||||||
setAttribute(art,ATTRIBUTE_TECHNOLOGY,manufacturing_process);
|
setAttribute(art,ATTRIBUTE_TECHNOLOGY,manufacturing_process);
|
||||||
setAttribute(art,ATTRIBUTE_FREQUENCY,max_frequency);
|
setAttribute(art,ATTRIBUTE_UARCH,uarch);
|
||||||
setAttribute(art,ATTRIBUTE_NCORES, n_cores);
|
setAttribute(art,ATTRIBUTE_NCORES, n_cores);
|
||||||
|
setAttribute(art,ATTRIBUTE_FREQUENCY,max_frequency);
|
||||||
/*setAttribute(art,ATTRIBUTE_L1i,l1i);
|
/*setAttribute(art,ATTRIBUTE_L1i,l1i);
|
||||||
setAttribute(art,ATTRIBUTE_L1d,l1d);
|
setAttribute(art,ATTRIBUTE_L1d,l1d);
|
||||||
setAttribute(art,ATTRIBUTE_L2,l2);
|
setAttribute(art,ATTRIBUTE_L2,l2);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "../common/global.h"
|
#include "../common/global.h"
|
||||||
#include "../common/udev.h"
|
#include "../common/udev.h"
|
||||||
|
#include "soc.h"
|
||||||
|
|
||||||
struct frequency* get_frequency_info(uint32_t core) {
|
struct frequency* get_frequency_info(uint32_t core) {
|
||||||
struct frequency* freq = emalloc(sizeof(struct frequency));
|
struct frequency* freq = emalloc(sizeof(struct frequency));
|
||||||
@@ -15,23 +16,45 @@ struct frequency* get_frequency_info(uint32_t core) {
|
|||||||
return freq;
|
return freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t get_peak_performance(struct cpuInfo* cpu) {
|
||||||
|
//First check we have consistent data
|
||||||
|
if(get_freq(cpu->freq) == UNKNOWN_DATA) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t flops = cpu->topo->total_cores * (get_freq(cpu->freq) * 1000000);
|
||||||
|
return flops;
|
||||||
|
}
|
||||||
|
|
||||||
struct cpuInfo* get_cpu_info(void) {
|
struct cpuInfo* get_cpu_info(void) {
|
||||||
struct cpuInfo* cpu = malloc(sizeof(struct cpuInfo));
|
struct cpuInfo* cpu = malloc(sizeof(struct cpuInfo));
|
||||||
//init_cpu_info(cpu);
|
//init_cpu_info(cpu);
|
||||||
int ncores = get_ncores_from_cpuinfo();
|
struct topology* topo = emalloc(sizeof(struct topology));
|
||||||
|
topo->total_cores = get_ncores_from_cpuinfo();
|
||||||
|
topo->cach = NULL;
|
||||||
|
cpu->topo = topo;
|
||||||
|
|
||||||
cpu->hv = emalloc(sizeof(struct hypervisor));
|
cpu->hv = emalloc(sizeof(struct hypervisor));
|
||||||
cpu->hv->present = false;
|
cpu->hv->present = false;
|
||||||
//cpu->soc = get_soc();
|
cpu->soc = get_soc();
|
||||||
//cpu->peak_performance = get_peak_performance(cpu);
|
|
||||||
cpu->peak_performance = 0;
|
|
||||||
cpu->freq = get_frequency_info(0);
|
cpu->freq = get_frequency_info(0);
|
||||||
cpu->cpu_vendor = CPU_VENDOR_RISCV;
|
cpu->cpu_vendor = CPU_VENDOR_RISCV;
|
||||||
|
cpu->peak_performance = get_peak_performance(cpu);
|
||||||
|
|
||||||
return cpu;
|
return cpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: Might be worth refactoring with other archs
|
||||||
char* get_str_topology(struct cpuInfo* cpu, struct topology* topo) {
|
char* get_str_topology(struct cpuInfo* cpu, struct topology* topo) {
|
||||||
return "Many cores";
|
uint32_t size = 3+7+1;
|
||||||
|
char* string = emalloc(sizeof(char)*size);
|
||||||
|
snprintf(string, size, "%d cores", topo->total_cores);
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* get_str_features(struct cpuInfo* cpu) {
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_debug(struct cpuInfo* cpu) {
|
void print_debug(struct cpuInfo* cpu) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
struct cpuInfo* get_cpu_info(void);
|
struct cpuInfo* get_cpu_info(void);
|
||||||
char* get_str_topology(struct cpuInfo* cpu, struct topology* topo);
|
char* get_str_topology(struct cpuInfo* cpu, struct topology* topo);
|
||||||
|
char* get_str_features(struct cpuInfo* cpu);
|
||||||
void print_debug(struct cpuInfo* cpu);
|
void print_debug(struct cpuInfo* cpu);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
113
src/riscv/soc.c
113
src/riscv/soc.c
@@ -1,9 +1,118 @@
|
|||||||
#include "soc.h"
|
#include "soc.h"
|
||||||
|
#include "socs.h"
|
||||||
|
#include "udev.h"
|
||||||
|
#include "../common/global.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
char* get_str_process(struct system_on_chip* soc) {
|
char* get_str_process(struct system_on_chip* soc) {
|
||||||
return "-1 nm";
|
char* str;
|
||||||
|
|
||||||
|
if(soc->process == UNKNOWN) {
|
||||||
|
str = emalloc(sizeof(char) * (strlen(STRING_UNKNOWN)+1));
|
||||||
|
snprintf(str, strlen(STRING_UNKNOWN)+1, STRING_UNKNOWN);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
str = emalloc(sizeof(char) * 5);
|
||||||
|
memset(str, 0, sizeof(char) * 5);
|
||||||
|
snprintf(str, 5, "%dnm", soc->process);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* get_soc_name(struct system_on_chip* soc) {
|
char* get_soc_name(struct system_on_chip* soc) {
|
||||||
return "Unknown";
|
if(soc->soc_model == SOC_MODEL_UNKNOWN)
|
||||||
|
return soc->raw_name;
|
||||||
|
return soc->soc_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* soc_trademark_string[] = {
|
||||||
|
[SOC_VENDOR_SIFIVE] = "SiFive "
|
||||||
|
};
|
||||||
|
|
||||||
|
void fill_soc(struct system_on_chip* soc, char* soc_name, SOC soc_model, int32_t process) {
|
||||||
|
soc->soc_model = soc_model;
|
||||||
|
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 = 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool match_soc(struct system_on_chip* soc, char* raw_name, char* expected_name, char* soc_name, SOC soc_model, int32_t process) {
|
||||||
|
int len1 = strlen(raw_name);
|
||||||
|
int len2 = strlen(expected_name);
|
||||||
|
int len = min(len1, len2);
|
||||||
|
|
||||||
|
if(strncmp(raw_name, expected_name, len) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fill_soc(soc, soc_name, soc_model, process);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SOC_START if (false) {}
|
||||||
|
#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; }
|
||||||
|
|
||||||
|
bool match_sifive(char* soc_name, struct system_on_chip* soc) {
|
||||||
|
char* tmp = soc_name;
|
||||||
|
|
||||||
|
// Dont know if it makes sense in RISC-V
|
||||||
|
/*if((tmp = strstr(soc_name, "???")) == NULL)
|
||||||
|
return false;*/
|
||||||
|
|
||||||
|
//soc->soc_vendor = ???
|
||||||
|
|
||||||
|
SOC_START
|
||||||
|
SOC_EQ(tmp, "fu740", "Freedom U740", SOC_SIFIVE_U740, soc, 40)
|
||||||
|
SOC_END
|
||||||
|
}
|
||||||
|
|
||||||
|
struct system_on_chip* parse_soc_from_string(struct system_on_chip* soc) {
|
||||||
|
char* raw_name = soc->raw_name;
|
||||||
|
match_sifive(raw_name, soc);
|
||||||
|
return soc;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct system_on_chip* guess_soc_from_devtree(struct system_on_chip* soc) {
|
||||||
|
char* tmp = get_hardware_from_devtree();
|
||||||
|
|
||||||
|
if(tmp != NULL) {
|
||||||
|
soc->raw_name = tmp;
|
||||||
|
return parse_soc_from_string(soc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return soc;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct system_on_chip* get_soc(void) {
|
||||||
|
struct system_on_chip* soc = emalloc(sizeof(struct system_on_chip));
|
||||||
|
soc->raw_name = NULL;
|
||||||
|
soc->soc_vendor = SOC_VENDOR_UNKNOWN;
|
||||||
|
soc->soc_model = SOC_MODEL_UNKNOWN;
|
||||||
|
soc->process = UNKNOWN;
|
||||||
|
|
||||||
|
soc = guess_soc_from_devtree(soc);
|
||||||
|
if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) {
|
||||||
|
if(soc->raw_name != NULL) {
|
||||||
|
printWarn("SoC detection failed using device tree: Found '%s' string", soc->raw_name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printWarn("SoC detection failed using device tree");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(soc->soc_model == SOC_MODEL_UNKNOWN) {
|
||||||
|
// raw_name might not be NULL, but if we were unable to find
|
||||||
|
// the exact SoC, just print "Unkwnown"
|
||||||
|
soc->raw_name = emalloc(sizeof(char) * (strlen(STRING_UNKNOWN)+1));
|
||||||
|
snprintf(soc->raw_name, strlen(STRING_UNKNOWN)+1, STRING_UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return soc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,11 @@
|
|||||||
|
|
||||||
typedef int32_t SOC;
|
typedef int32_t SOC;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SOC_VENDOR_UNKNOWN,
|
||||||
|
SOC_VENDOR_SIFIVE
|
||||||
|
};
|
||||||
|
|
||||||
struct system_on_chip {
|
struct system_on_chip {
|
||||||
SOC soc_model;
|
SOC soc_model;
|
||||||
VENDOR soc_vendor;
|
VENDOR soc_vendor;
|
||||||
@@ -14,7 +19,9 @@ struct system_on_chip {
|
|||||||
char* raw_name;
|
char* raw_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct system_on_chip* get_soc(void);
|
||||||
char* get_soc_name(struct system_on_chip* soc);
|
char* get_soc_name(struct system_on_chip* soc);
|
||||||
|
//VENDOR get_soc_vendor(struct system_on_chip* soc);
|
||||||
char* get_str_process(struct system_on_chip* soc);
|
char* get_str_process(struct system_on_chip* soc);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
19
src/riscv/socs.h
Normal file
19
src/riscv/socs.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef __SOCS__
|
||||||
|
#define __SOCS__
|
||||||
|
|
||||||
|
#include "soc.h"
|
||||||
|
|
||||||
|
// List of supported SOCs
|
||||||
|
enum {
|
||||||
|
// SIFIVE
|
||||||
|
SOC_SIFIVE_U740,
|
||||||
|
// UNKNOWN
|
||||||
|
SOC_MODEL_UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
inline static VENDOR get_soc_vendor_from_soc(SOC soc) {
|
||||||
|
if(soc >= SOC_SIFIVE_U740 && soc <= SOC_SIFIVE_U740) return SOC_VENDOR_SIFIVE;
|
||||||
|
return SOC_VENDOR_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
44
src/riscv/udev.c
Normal file
44
src/riscv/udev.c
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "../common/global.h"
|
||||||
|
#include "udev.h"
|
||||||
|
|
||||||
|
#define _PATH_DEVTREE "/proc/device-tree/compatible"
|
||||||
|
#define DEVTREE_HARDWARE_FIELD 3
|
||||||
|
|
||||||
|
// TODO: Works only for DEVTREE_FIELD == DEVTREE_HARDWARE_FIELD
|
||||||
|
char* get_field_from_devtree(int DEVTREE_FIELD) {
|
||||||
|
int filelen;
|
||||||
|
char* buf;
|
||||||
|
if((buf = read_file(_PATH_DEVTREE, &filelen)) == NULL) {
|
||||||
|
printWarn("read_file: %s: %s:\n", _PATH_DEVTREE, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here we would use strstr to find the comma
|
||||||
|
// However, the device-tree file may contain NULL
|
||||||
|
// bytes in the middle of the string, which would
|
||||||
|
// cause strstr to return NULL even when there might
|
||||||
|
// be an occurence after the NULL byte
|
||||||
|
int i=0;
|
||||||
|
char* tmp1 = buf;
|
||||||
|
do {
|
||||||
|
tmp1++;
|
||||||
|
if(*tmp1 == ',') i++;
|
||||||
|
} while(filelen > (tmp1-buf) && i < DEVTREE_FIELD);
|
||||||
|
|
||||||
|
tmp1++;
|
||||||
|
if((tmp1-buf) >= filelen) return NULL;
|
||||||
|
|
||||||
|
int strlen = filelen-(tmp1-buf);
|
||||||
|
char* hardware = emalloc(sizeof(char) * strlen);
|
||||||
|
memset(hardware, 0, sizeof(char) * strlen);
|
||||||
|
strncpy(hardware, tmp1, strlen-1);
|
||||||
|
|
||||||
|
return hardware;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* get_hardware_from_devtree(void) {
|
||||||
|
return get_field_from_devtree(DEVTREE_HARDWARE_FIELD);
|
||||||
|
}
|
||||||
10
src/riscv/udev.h
Normal file
10
src/riscv/udev.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef __UDEV_RISCV__
|
||||||
|
#define __UDEV_RISCV__
|
||||||
|
|
||||||
|
#include "../common/udev.h"
|
||||||
|
|
||||||
|
#define UNKNOWN -1
|
||||||
|
|
||||||
|
char* get_hardware_from_devtree(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user