[v1.03][RISCV] Add basic SoC detection backend

This commit is contained in:
Dr-Noob
2023-04-03 12:41:59 +02:00
parent 9a69a7f58d
commit 14819c350e
9 changed files with 229 additions and 13 deletions

View File

@@ -5,6 +5,7 @@
#include "../common/global.h"
#include "../common/udev.h"
#include "soc.h"
struct frequency* get_frequency_info(uint32_t core) {
struct frequency* freq = emalloc(sizeof(struct frequency));
@@ -15,23 +16,45 @@ struct frequency* get_frequency_info(uint32_t core) {
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* cpu = malloc(sizeof(struct cpuInfo));
//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->present = false;
//cpu->soc = get_soc();
//cpu->peak_performance = get_peak_performance(cpu);
cpu->peak_performance = 0;
cpu->soc = get_soc();
cpu->freq = get_frequency_info(0);
cpu->cpu_vendor = CPU_VENDOR_RISCV;
cpu->peak_performance = get_peak_performance(cpu);
return cpu;
}
//TODO: Might be worth refactoring with other archs
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) {

View File

@@ -5,6 +5,7 @@
struct cpuInfo* get_cpu_info(void);
char* get_str_topology(struct cpuInfo* cpu, struct topology* topo);
char* get_str_features(struct cpuInfo* cpu);
void print_debug(struct cpuInfo* cpu);
#endif

View File

@@ -1,9 +1,118 @@
#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) {
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) {
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;
}

View File

@@ -6,6 +6,11 @@
typedef int32_t SOC;
enum {
SOC_VENDOR_UNKNOWN,
SOC_VENDOR_SIFIVE
};
struct system_on_chip {
SOC soc_model;
VENDOR soc_vendor;
@@ -14,7 +19,9 @@ struct system_on_chip {
char* raw_name;
};
struct system_on_chip* get_soc(void);
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);
#endif

19
src/riscv/socs.h Normal file
View 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
View 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
View 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