mirror of
https://github.com/Dr-Noob/cpufetch.git
synced 2026-03-25 16:00:39 +01:00
[v1.04][RISCV] Add support for multi-letter extensions
This commit is contained in:
@@ -124,7 +124,7 @@ struct features {
|
|||||||
|
|
||||||
struct extensions {
|
struct extensions {
|
||||||
char* str;
|
char* str;
|
||||||
uint32_t mask;
|
uint64_t mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cpuInfo {
|
struct cpuInfo {
|
||||||
|
|||||||
@@ -917,16 +917,14 @@ bool print_cpufetch_arm(struct cpuInfo* cpu, STYLE s, struct color** cs, struct
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ARCH_RISCV
|
#ifdef ARCH_RISCV
|
||||||
// https://stackoverflow.com/questions/109023/count-the-number-of-set-bits-in-a-32-bit-integer
|
// https://stackoverflow.com/a/2709523
|
||||||
int number_of_bits(uint32_t i) {
|
uint64_t number_of_bits(uint64_t i) {
|
||||||
i = i - ((i >> 1) & 0x55555555); // add pairs of bits
|
i = i - ((i >> 1) & 0x5555555555555555);
|
||||||
i = (i & 0x33333333) + ((i >> 2) & 0x33333333); // quads
|
i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333);
|
||||||
i = (i + (i >> 4)) & 0x0F0F0F0F; // groups of 8
|
return (((i + (i >> 4)) & 0xF0F0F0F0F0F0F0F) * 0x101010101010101) >> 56;
|
||||||
|
|
||||||
return (i * 0x01010101) >> 24; // horizontal sum of bytes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_ascii_riscv(struct ascii* art, uint32_t la, int32_t termw, const char** attribute_fields, uint32_t extensions_mask) {
|
void print_ascii_riscv(struct ascii* art, uint32_t la, int32_t termw, const char** attribute_fields, uint64_t extensions_mask) {
|
||||||
struct ascii_logo* logo = art->art;
|
struct ascii_logo* logo = art->art;
|
||||||
int attr_to_print = 0;
|
int attr_to_print = 0;
|
||||||
int attr_type;
|
int attr_type;
|
||||||
@@ -940,7 +938,7 @@ void print_ascii_riscv(struct ascii* art, uint32_t la, int32_t termw, const char
|
|||||||
int32_t space_up = ((int)logo->height - (int)(art->n_attributes_set + num_extensions))/2;
|
int32_t space_up = ((int)logo->height - (int)(art->n_attributes_set + num_extensions))/2;
|
||||||
int32_t space_down = (int)logo->height - (int)(art->n_attributes_set + num_extensions) - (int)space_up;
|
int32_t space_down = (int)logo->height - (int)(art->n_attributes_set + num_extensions) - (int)space_up;
|
||||||
uint32_t logo_pos = 0;
|
uint32_t logo_pos = 0;
|
||||||
int32_t iters = max(logo->height, art->n_attributes_set);
|
int32_t iters = max(logo->height, art->n_attributes_set + num_extensions);
|
||||||
|
|
||||||
struct line_buffer* lbuf = emalloc(sizeof(struct line_buffer));
|
struct line_buffer* lbuf = emalloc(sizeof(struct line_buffer));
|
||||||
lbuf->buf = emalloc(sizeof(char) * LINE_BUFFER_SIZE);
|
lbuf->buf = emalloc(sizeof(char) * LINE_BUFFER_SIZE);
|
||||||
|
|||||||
@@ -9,6 +9,13 @@
|
|||||||
#include "uarch.h"
|
#include "uarch.h"
|
||||||
#include "soc.h"
|
#include "soc.h"
|
||||||
|
|
||||||
|
#define SET_ISA_EXT_MAP(name, bit) \
|
||||||
|
if(strncmp(multi_letter_extension, name, \
|
||||||
|
multi_letter_extension_len) == 0) { \
|
||||||
|
ext->mask |= 1UL << bit; \
|
||||||
|
maskset = true; \
|
||||||
|
} \
|
||||||
|
|
||||||
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));
|
||||||
|
|
||||||
@@ -28,6 +35,49 @@ int64_t get_peak_performance(struct cpuInfo* cpu) {
|
|||||||
return flops;
|
return flops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the length of the multi-letter
|
||||||
|
// extension, or -1 if an error occurs
|
||||||
|
int parse_multi_letter_extension(struct extensions* ext, char* e) {
|
||||||
|
if(*e != '_') return -1;
|
||||||
|
char* multi_letter_extension_end = strstr(e+1, "_");
|
||||||
|
if(multi_letter_extension_end == NULL) {
|
||||||
|
// This is the last extension, find the end
|
||||||
|
// of the string
|
||||||
|
multi_letter_extension_end = e + strlen(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
int multi_letter_extension_len = multi_letter_extension_end-(e+1);
|
||||||
|
bool maskset = false;
|
||||||
|
char* multi_letter_extension = emalloc(multi_letter_extension_len);
|
||||||
|
strncpy(multi_letter_extension, e+1, multi_letter_extension_len);
|
||||||
|
// This should be up-to-date with
|
||||||
|
// https://elixir.bootlin.com/linux/latest/source/arch/riscv/kernel/cpufeature.c
|
||||||
|
// which should represent the list of extensions available in real chips
|
||||||
|
SET_ISA_EXT_MAP("sscofpmf", RISCV_ISA_EXT_SSCOFPMF)
|
||||||
|
SET_ISA_EXT_MAP("sstc", RISCV_ISA_EXT_SSTC)
|
||||||
|
SET_ISA_EXT_MAP("svinval", RISCV_ISA_EXT_SVINVAL)
|
||||||
|
SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT)
|
||||||
|
SET_ISA_EXT_MAP("zbb", RISCV_ISA_EXT_ZBB)
|
||||||
|
SET_ISA_EXT_MAP("zicbom", RISCV_ISA_EXT_ZICBOM)
|
||||||
|
SET_ISA_EXT_MAP("zihintpause", RISCV_ISA_EXT_ZIHINTPAUSE)
|
||||||
|
SET_ISA_EXT_MAP("svnapot", RISCV_ISA_EXT_SVNAPOT)
|
||||||
|
SET_ISA_EXT_MAP("zicboz", RISCV_ISA_EXT_ZICBOZ)
|
||||||
|
SET_ISA_EXT_MAP("smaia", RISCV_ISA_EXT_SMAIA)
|
||||||
|
SET_ISA_EXT_MAP("ssaia", RISCV_ISA_EXT_SSAIA)
|
||||||
|
SET_ISA_EXT_MAP("zba", RISCV_ISA_EXT_ZBA)
|
||||||
|
SET_ISA_EXT_MAP("zbs", RISCV_ISA_EXT_ZBS)
|
||||||
|
SET_ISA_EXT_MAP("zicntr", RISCV_ISA_EXT_ZICNTR)
|
||||||
|
SET_ISA_EXT_MAP("zicsr", RISCV_ISA_EXT_ZICSR)
|
||||||
|
SET_ISA_EXT_MAP("zifencei", RISCV_ISA_EXT_ZIFENCEI)
|
||||||
|
SET_ISA_EXT_MAP("zihpm", RISCV_ISA_EXT_ZIHPM)
|
||||||
|
if(!maskset) {
|
||||||
|
printBug("parse_multi_letter_extension: Unknown multi-letter extension: %s", multi_letter_extension);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return multi_letter_extension_len;
|
||||||
|
}
|
||||||
|
|
||||||
struct extensions* get_extensions_from_str(char* str) {
|
struct extensions* get_extensions_from_str(char* str) {
|
||||||
struct extensions* ext = emalloc(sizeof(struct extensions));
|
struct extensions* ext = emalloc(sizeof(struct extensions));
|
||||||
ext->mask = 0;
|
ext->mask = 0;
|
||||||
@@ -42,7 +92,7 @@ struct extensions* get_extensions_from_str(char* str) {
|
|||||||
memset(ext->str, 0, len);
|
memset(ext->str, 0, len);
|
||||||
strncpy(ext->str, str, sizeof(char) * len);
|
strncpy(ext->str, str, sizeof(char) * len);
|
||||||
|
|
||||||
// Code inspired in Linux kernel:
|
// Code inspired in Linux kernel (riscv_fill_hwcap):
|
||||||
// https://elixir.bootlin.com/linux/v6.2.10/source/arch/riscv/kernel/cpufeature.c
|
// https://elixir.bootlin.com/linux/v6.2.10/source/arch/riscv/kernel/cpufeature.c
|
||||||
char* isa = str;
|
char* isa = str;
|
||||||
if (!strncmp(isa, "rv32", 4))
|
if (!strncmp(isa, "rv32", 4))
|
||||||
@@ -55,8 +105,18 @@ struct extensions* get_extensions_from_str(char* str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(char* e = isa; *e != '\0'; e++) {
|
for(char* e = isa; *e != '\0'; e++) {
|
||||||
int n = *e - 'a';
|
if(*e == '_') {
|
||||||
ext->mask |= 1UL << n;
|
// Multi-letter extension
|
||||||
|
int multi_letter_extension_len = parse_multi_letter_extension(ext, e);
|
||||||
|
if(multi_letter_extension_len == -1) {
|
||||||
|
return ext;
|
||||||
|
}
|
||||||
|
e += multi_letter_extension_len;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int n = *e - 'a';
|
||||||
|
ext->mask |= 1UL << n;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ext;
|
return ext;
|
||||||
|
|||||||
@@ -8,6 +8,34 @@ struct extension {
|
|||||||
char* str;
|
char* str;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define RISCV_ISA_EXT_NAME_LEN_MAX 32
|
||||||
|
#define RISCV_ISA_EXT_BASE 26
|
||||||
|
|
||||||
|
// https://elixir.bootlin.com/linux/latest/source/arch/riscv/include/asm/hwcap.h
|
||||||
|
// This enum represent the logical ID for multi-letter RISC-V ISA extensions.
|
||||||
|
// The logical ID should start from RISCV_ISA_EXT_BASE
|
||||||
|
enum riscv_isa_ext_id {
|
||||||
|
RISCV_ISA_EXT_SSCOFPMF = RISCV_ISA_EXT_BASE,
|
||||||
|
RISCV_ISA_EXT_SSTC,
|
||||||
|
RISCV_ISA_EXT_SVINVAL,
|
||||||
|
RISCV_ISA_EXT_SVPBMT,
|
||||||
|
RISCV_ISA_EXT_ZBB,
|
||||||
|
RISCV_ISA_EXT_ZICBOM,
|
||||||
|
RISCV_ISA_EXT_ZIHINTPAUSE,
|
||||||
|
RISCV_ISA_EXT_SVNAPOT,
|
||||||
|
RISCV_ISA_EXT_ZICBOZ,
|
||||||
|
RISCV_ISA_EXT_SMAIA,
|
||||||
|
RISCV_ISA_EXT_SSAIA,
|
||||||
|
RISCV_ISA_EXT_ZBA,
|
||||||
|
RISCV_ISA_EXT_ZBS,
|
||||||
|
RISCV_ISA_EXT_ZICNTR,
|
||||||
|
RISCV_ISA_EXT_ZICSR,
|
||||||
|
RISCV_ISA_EXT_ZIFENCEI,
|
||||||
|
RISCV_ISA_EXT_ZIHPM,
|
||||||
|
RISCV_ISA_EXT_ID_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://five-embeddev.com/riscv-isa-manual/latest/preface.html#preface
|
||||||
// https://en.wikichip.org/wiki/risc-v/standard_extensions
|
// https://en.wikichip.org/wiki/risc-v/standard_extensions
|
||||||
// Included all except for G
|
// Included all except for G
|
||||||
static const struct extension extension_list[] = {
|
static const struct extension extension_list[] = {
|
||||||
@@ -26,7 +54,25 @@ static const struct extension extension_list[] = {
|
|||||||
{ 'v' - 'a', "(V) Vector Operations" },
|
{ 'v' - 'a', "(V) Vector Operations" },
|
||||||
{ 'n' - 'a', "(N) User-Level Interrupts" },
|
{ 'n' - 'a', "(N) User-Level Interrupts" },
|
||||||
{ 'h' - 'a', "(H) Hypervisor" },
|
{ 'h' - 'a', "(H) Hypervisor" },
|
||||||
{ 's' - 'a', "(S) Supervisor-level Instructions" }
|
{ 's' - 'a', "(S) Supervisor-level Instructions" },
|
||||||
|
// multi-letter extensions
|
||||||
|
{ RISCV_ISA_EXT_SSCOFPMF, "(Sscofpmf) Count OverFlow and Privilege Mode Filtering" },
|
||||||
|
{ RISCV_ISA_EXT_SSTC, "(Sstc) S and VS level Time Compare" },
|
||||||
|
{ RISCV_ISA_EXT_SVINVAL, "(Svinval) Fast TLB Invalidation" },
|
||||||
|
{ RISCV_ISA_EXT_SVPBMT, "(Svpbmt) Page-based Memory Types" },
|
||||||
|
{ RISCV_ISA_EXT_ZBB, "(Zbb) Basic bit-manipulation" },
|
||||||
|
{ RISCV_ISA_EXT_ZICBOM, "(Zicbom) Cache Block Management Operations" },
|
||||||
|
{ RISCV_ISA_EXT_ZIHINTPAUSE, "(Zihintpause) Pause Hint" },
|
||||||
|
{ RISCV_ISA_EXT_SVNAPOT, "(Svnapot) Naturally Aligned Power of Two Pages" },
|
||||||
|
{ RISCV_ISA_EXT_ZICBOZ, "(Zicboz) Cache Block Zero Operations" },
|
||||||
|
{ RISCV_ISA_EXT_SMAIA, "(Smaia) Advanced Interrupt Architecture" },
|
||||||
|
{ RISCV_ISA_EXT_SSAIA, "(Ssaia) Advanced Interrupt Architecture" },
|
||||||
|
{ RISCV_ISA_EXT_ZBA, "(Zba) Address Generation" },
|
||||||
|
{ RISCV_ISA_EXT_ZBS, "(Zbs) Single-bit Instructions" },
|
||||||
|
{ RISCV_ISA_EXT_ZICNTR, "(Zicntr) Base Counters and Timers" },
|
||||||
|
{ RISCV_ISA_EXT_ZICSR, "(Zicsr) Control and Status Register" },
|
||||||
|
{ RISCV_ISA_EXT_ZIFENCEI, "(Zifencei) Instruction-Fetch Fence" },
|
||||||
|
{ RISCV_ISA_EXT_ZIHPM, "(Zihpm) Hardware Performance Counters" }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cpuInfo* get_cpu_info(void);
|
struct cpuInfo* get_cpu_info(void);
|
||||||
|
|||||||
Reference in New Issue
Block a user