Compare commits

...

5 Commits

Author SHA1 Message Date
Dr-Noob
37ed766be0 Test 2025-11-01 10:06:56 +01:00
Dr-Noob
b1f20cfec6 [v1.07] Fix bug introduced by #251 (reported in #375)
PR #251 added:

```
if defined (__FreeBSD__) || defined (__APPLE__)
...
get_sys_info_by_name
```

that function is available in src/common/sysctl.c.
In the Makefile it builds with sysctl.c but only under FreeBSD:

```
ifeq ($(os), FreeBSD)
```

So it fails under macOS as reported by #375
2025-11-01 09:17:02 +01:00
Dr-Noob
284faf84c3 [v1.07] Bump version 2025-10-31 07:50:04 +01:00
Dr-Noob
a19c421362 [v1.06][RISCV] Add latest extensions and refactor the mask structure
There are *a lot* of new extensions in the Linux kernel now (Linux
v6.16) since the last time I checked (Linux v6.2.10), so added them all
plus ime, which is not present in the kernel apparently, but that I
spotted in a RISC-V chip.

Previously, the mask was represented with a uint64_t value, which is
fine as long as we have less than 65 possible extensions. This is not
the case anymore, so instead I replaced that with a pointer of bool,
which gets allocated depending on the max number of extensions that
we support.
2025-10-31 07:45:07 +01:00
Dr-Noob
5bddbc6b06 [v1.06] Reorganize attributes in printer
This follows the same approach of gpufetch (in
6589de971750b7f4e52c0c35c031fe6204cefdba) where, instead of having a
separate struct for long and short names, both gets merged in a single
struct (ATTRIBUTE_INFO)

This indirectly fixes a bug in RISC-V printer where, if the output
was too large and the short name was selected, it could try to print
an out-of-bound value when accessing the ATTRIBUTE_PEAK. The reason is
that the long and short structures didnt have the same length (because
one attribute name was missing in the short struct). This is now fixed
since we have combined both long and short attribute names.

commit 6e8cccde32
Author: Dr-Noob <peibolms@gmail.com>
Date:   Wed Oct 29 21:54:38 2025 +0100

    Reorganize attributes in printer
2025-10-29 22:08:44 +01:00
7 changed files with 337 additions and 118 deletions

View File

@@ -30,7 +30,7 @@ ifneq ($(OS),Windows_NT)
HEADERS += $(SRC_DIR)freq/freq.h HEADERS += $(SRC_DIR)freq/freq.h
CFLAGS += -pthread CFLAGS += -pthread
endif endif
ifeq ($(os), FreeBSD) ifeq ($(os), $(filter $(os), FreeBSD Darwin))
SOURCE += $(SRC_COMMON)sysctl.c SOURCE += $(SRC_COMMON)sysctl.c
HEADERS += $(SRC_COMMON)sysctl.h HEADERS += $(SRC_COMMON)sysctl.h
endif endif

56
msr.c Normal file
View File

@@ -0,0 +1,56 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#define MSR_PSTATE_0 0xC0010064
// Reads a 64-bit MSR value from a given CPU core
int read_msr(int cpu, uint64_t msr_addr, uint64_t *value) {
char msr_path[64];
snprintf(msr_path, sizeof(msr_path), "/dev/cpu/%d/msr", cpu);
int fd = open(msr_path, O_RDONLY);
if (fd < 0) {
perror("open");
return -1;
}
if (lseek(fd, msr_addr, SEEK_SET) == -1) {
perror("lseek");
close(fd);
return -1;
}
if (read(fd, value, sizeof(*value)) != sizeof(*value)) {
perror("read");
close(fd);
return -1;
}
close(fd);
return 0;
}
int main(int argc, char **argv) {
int cpu = 0;
if (argc > 1) cpu = atoi(argv[1]);
uint64_t val;
if (read_msr(cpu, MSR_PSTATE_0, &val) != 0) {
fprintf(stderr, "Failed to read MSR on CPU %d\n", cpu);
return 1;
}
unsigned int fid = val & 0xff; // bits [7:0]
unsigned int did = (val >> 8) & 0x3f; // bits [13:8]
double freq_mhz = (fid * 25.0) / (1 << did); // 25 MHz ref clock on Zen CPUs
printf("CPU%d: MSR[0x%lx] = 0x%016llx\n", cpu, (unsigned long)MSR_PSTATE_0, (unsigned long long)val);
printf("FID: %u, DID: %u\n", fid, did);
printf("Estimated frequency: %.2f MHz\n", freq_mhz);
return 0;
}

View File

@@ -138,7 +138,7 @@ struct features {
struct extensions { struct extensions {
char* str; char* str;
uint64_t mask; bool* mask; // allocated at runtime with size RISCV_ISA_EXT_ID_MAX
}; };
struct cpuInfo { struct cpuInfo {

View File

@@ -62,7 +62,7 @@
#endif #endif
#ifndef GIT_FULL_VERSION #ifndef GIT_FULL_VERSION
static const char* VERSION = "1.06"; static const char* VERSION = "1.07";
#endif #endif
enum { enum {

View File

@@ -45,9 +45,17 @@
#define MAX_ATTRIBUTES 100 #define MAX_ATTRIBUTES 100
#define MAX_TERM_SIZE 1024 #define MAX_TERM_SIZE 1024
typedef struct {
int id;
const char *name;
const char *shortname;
} AttributeField;
enum { enum {
#if defined(ARCH_X86) || defined(ARCH_PPC) #if defined(ARCH_X86)
ATTRIBUTE_NAME, ATTRIBUTE_NAME,
#elif defined(ARCH_PPC)
ATTRIBUTE_PART_NUMBER,
#elif defined(ARCH_ARM) || defined(ARCH_RISCV) #elif defined(ARCH_ARM) || defined(ARCH_RISCV)
ATTRIBUTE_SOC, ATTRIBUTE_SOC,
#endif #endif
@@ -79,76 +87,40 @@ enum {
ATTRIBUTE_PEAK ATTRIBUTE_PEAK
}; };
static const char* ATTRIBUTE_FIELDS [] = { static const AttributeField ATTRIBUTE_INFO[] = {
#ifdef ARCH_X86
"Name:",
#elif ARCH_PPC
"Part Number:",
#elif defined(ARCH_ARM) || defined(ARCH_RISCV)
"SoC:",
#endif
#if defined(ARCH_X86) || defined(ARCH_ARM)
"",
#endif
"Hypervisor:",
"Microarchitecture:",
"Technology:",
"Max Frequency:",
"Sockets:",
"Cores:",
"Cores (Total):",
#ifdef ARCH_X86
"SSE:",
"AVX:",
"FMA:",
#elif ARCH_PPC
"Altivec: ",
#elif defined(ARCH_ARM)
"Features: ",
#elif defined(ARCH_RISCV)
"Extensions: ",
#endif
"L1i Size:",
"L1d Size:",
"L2 Size:",
"L3 Size:",
"Peak Performance:",
};
static const char* ATTRIBUTE_FIELDS_SHORT [] = {
#if defined(ARCH_X86) #if defined(ARCH_X86)
"Name:", { ATTRIBUTE_NAME, "Name:", "Name:" },
#elif ARCH_PPC #elif defined(ARCH_PPC)
"P/N:", { ATTRIBUTE_PART_NUMBER, "Part Number:", "P/N:" },
#elif ARCH_ARM #elif defined(ARCH_ARM) || defined(ARCH_RISCV)
"SoC:", { ATTRIBUTE_SOC, "SoC:", "SoC:" },
#endif #endif
#if defined(ARCH_X86) || defined(ARCH_ARM) #if defined(ARCH_X86) || defined(ARCH_ARM)
"", { ATTRIBUTE_CPU_NUM, "", "" },
#endif #endif
"Hypervisor:", { ATTRIBUTE_HYPERVISOR, "Hypervisor:", "Hypervisor:" },
"uArch:", { ATTRIBUTE_UARCH, "Microarchitecture:", "uArch:" },
"Technology:", { ATTRIBUTE_TECHNOLOGY, "Technology:", "Technology:" },
"Max Freq:", { ATTRIBUTE_FREQUENCY, "Max Frequency:", "Max Freq:" },
"Sockets:", { ATTRIBUTE_SOCKETS, "Sockets:", "Sockets:" },
"Cores:", { ATTRIBUTE_NCORES, "Cores:", "Cores:" },
"Cores (Total):", { ATTRIBUTE_NCORES_DUAL, "Cores (Total):", "Cores (Total):" },
#ifdef ARCH_X86 #ifdef ARCH_X86
"SSE:", { ATTRIBUTE_SSE, "SSE:", "SSE:" },
"AVX:", { ATTRIBUTE_AVX, "AVX:", "AVX:" },
"FMA:", { ATTRIBUTE_FMA, "FMA:", "FMA:" },
#elif ARCH_PPC #elif ARCH_PPC
"Altivec: ", { ATTRIBUTE_ALTIVEC, "Altivec: ", "Altivec: " },
#elif defined(ARCH_ARM) #elif ARCH_ARM
"Features: ", { ATTRIBUTE_FEATURES, "Features: ", "Features: " },
#elif defined(ARCH_RISCV) #elif ARCH_RISCV
"Extensions: ", { ATTRIBUTE_EXTENSIONS, "Extensions: ", "Extensions: " },
#endif #endif
"L1i Size:", { ATTRIBUTE_L1i, "L1i Size:", "L1i Size:" },
"L1d Size:", { ATTRIBUTE_L1d, "L1d Size:", "L1d Size:" },
"L2 Size:", { ATTRIBUTE_L2, "L2 Size:", "L2 Size:" },
"L3 Size:", { ATTRIBUTE_L3, "L3 Size:", "L3 Size:" },
"Peak Perf.:", { ATTRIBUTE_PEAK, "Peak Performance:", "Peak Perf.:" },
}; };
struct terminal { struct terminal {
@@ -454,13 +426,14 @@ void choose_ascii_art(struct ascii* art, struct color** cs, struct terminal* ter
} }
} }
uint32_t longest_attribute_length(struct ascii* art, const char** attribute_fields) { uint32_t longest_attribute_length(struct ascii* art, bool use_short) {
uint32_t max = 0; uint32_t max = 0;
uint64_t len = 0; uint64_t len = 0;
for(uint32_t i=0; i < art->n_attributes_set; i++) { for(uint32_t i=0; i < art->n_attributes_set; i++) {
if(art->attributes[i]->value != NULL) { if(art->attributes[i]->value != NULL) {
len = strlen(attribute_fields[art->attributes[i]->type]); const char* str = use_short ? ATTRIBUTE_INFO[art->attributes[i]->type].shortname : ATTRIBUTE_INFO[art->attributes[i]->type].name;
len = strlen(str);
if(len > max) max = len; if(len > max) max = len;
} }
} }
@@ -485,7 +458,7 @@ uint32_t longest_field_length(struct ascii* art, int la) {
} }
#if defined(ARCH_X86) || defined(ARCH_PPC) #if defined(ARCH_X86) || defined(ARCH_PPC)
void print_ascii_generic(struct ascii* art, uint32_t la, int32_t termw, const char** attribute_fields, bool hybrid_architecture) { void print_ascii_generic(struct ascii* art, uint32_t la, int32_t termw, bool use_short, bool hybrid_architecture) {
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;
@@ -547,14 +520,15 @@ void print_ascii_generic(struct ascii* art, uint32_t la, int32_t termw, const ch
else { else {
#endif #endif
beg_space = 0; beg_space = 0;
space_right = 2 + 1 + (la - strlen(attribute_fields[attr_type])); const char* attr_str = use_short ? ATTRIBUTE_INFO[attr_type].shortname : ATTRIBUTE_INFO[attr_type].name;
space_right = 2 + 1 + (la - strlen(attr_str));
if(hybrid_architecture && add_space) { if(hybrid_architecture && add_space) {
beg_space = 2; beg_space = 2;
space_right -= 2; space_right -= 2;
} }
printOut(lbuf, beg_space + strlen(attribute_fields[attr_type]) + space_right + strlen(attr_value), printOut(lbuf, beg_space + strlen(attr_str) + space_right + strlen(attr_value),
"%*s%s%s%s%*s%s%s%s", beg_space, "", logo->color_text[0], attribute_fields[attr_type], art->reset, space_right, "", logo->color_text[1], attr_value, art->reset); "%*s%s%s%s%*s%s%s%s", beg_space, "", logo->color_text[0], attr_str, art->reset, space_right, "", logo->color_text[1], attr_value, art->reset);
#ifdef ARCH_X86 #ifdef ARCH_X86
} }
#endif #endif
@@ -663,19 +637,19 @@ bool print_cpufetch_x86(struct cpuInfo* cpu, STYLE s, struct color** cs, struct
setAttribute(art, ATTRIBUTE_PEAK, pp); setAttribute(art, ATTRIBUTE_PEAK, pp);
// Step 3. Print output // Step 3. Print output
const char** attribute_fields = ATTRIBUTE_FIELDS; bool use_short = false;
uint32_t longest_attribute = longest_attribute_length(art, attribute_fields); uint32_t longest_attribute = longest_attribute_length(art, use_short);
uint32_t longest_field = longest_field_length(art, longest_attribute); uint32_t longest_field = longest_field_length(art, longest_attribute);
choose_ascii_art(art, cs, term, longest_field); choose_ascii_art(art, cs, term, longest_field);
if(!ascii_fits_screen(term->w, *art->art, longest_field)) { if(!ascii_fits_screen(term->w, *art->art, longest_field)) {
// Despite of choosing the smallest logo, the output does not fit // Despite of choosing the smallest logo, the output does not fit
// Choose the shorter field names and recalculate the longest attr // Choose the shorter field names and recalculate the longest attr
attribute_fields = ATTRIBUTE_FIELDS_SHORT; use_short = true;
longest_attribute = longest_attribute_length(art, attribute_fields); longest_attribute = longest_attribute_length(art, use_short);
} }
print_ascii_generic(art, longest_attribute, term->w, attribute_fields, hybrid_architecture); print_ascii_generic(art, longest_attribute, term->w, use_short, hybrid_architecture);
free(manufacturing_process); free(manufacturing_process);
free(sockets); free(sockets);
@@ -724,7 +698,7 @@ bool print_cpufetch_ppc(struct cpuInfo* cpu, STYLE s, struct color** cs, struct
// Step 2. Set attributes // Step 2. Set attributes
if(cpu_name != NULL) { if(cpu_name != NULL) {
setAttribute(art, ATTRIBUTE_NAME, cpu_name); setAttribute(art, ATTRIBUTE_PART_NUMBER, cpu_name);
} }
setAttribute(art, ATTRIBUTE_UARCH, uarch); setAttribute(art, ATTRIBUTE_UARCH, uarch);
if(cpu->hv->present) { if(cpu->hv->present) {
@@ -751,19 +725,19 @@ bool print_cpufetch_ppc(struct cpuInfo* cpu, STYLE s, struct color** cs, struct
setAttribute(art, ATTRIBUTE_PEAK, pp); setAttribute(art, ATTRIBUTE_PEAK, pp);
// Step 3. Print output // Step 3. Print output
const char** attribute_fields = ATTRIBUTE_FIELDS; bool use_short = false;
uint32_t longest_attribute = longest_attribute_length(art, attribute_fields); uint32_t longest_attribute = longest_attribute_length(art, use_short);
uint32_t longest_field = longest_field_length(art, longest_attribute); uint32_t longest_field = longest_field_length(art, longest_attribute);
choose_ascii_art(art, cs, term, longest_field); choose_ascii_art(art, cs, term, longest_field);
if(!ascii_fits_screen(term->w, *art->art, longest_field)) { if(!ascii_fits_screen(term->w, *art->art, longest_field)) {
// Despite of choosing the smallest logo, the output does not fit // Despite of choosing the smallest logo, the output does not fit
// Choose the shorter field names and recalculate the longest attr // Choose the shorter field names and recalculate the longest attr
attribute_fields = ATTRIBUTE_FIELDS_SHORT; use_short = true;
longest_attribute = longest_attribute_length(art, attribute_fields); longest_attribute = longest_attribute_length(art, use_short);
} }
print_ascii_generic(art, longest_attribute, term->w, attribute_fields, false); print_ascii_generic(art, longest_attribute, term->w, use_short, false);
return true; return true;
} }
@@ -791,7 +765,7 @@ uint32_t longest_field_length_arm(struct ascii* art, int la) {
return max; return max;
} }
void print_ascii_arm(struct ascii* art, uint32_t la, int32_t termw, const char** attribute_fields) { void print_ascii_arm(struct ascii* art, uint32_t la, int32_t termw, bool use_short) {
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;
@@ -862,14 +836,15 @@ void print_ascii_arm(struct ascii* art, uint32_t la, int32_t termw, const char**
} }
else { else {
beg_space = 0; beg_space = 0;
space_right = 2 + 1 + (la - strlen(attribute_fields[attr_type])); const char* attr_str = use_short ? ATTRIBUTE_INFO[attr_type].shortname : ATTRIBUTE_INFO[attr_type].name;
space_right = 2 + 1 + (la - strlen(attr_str));
if(add_space) { if(add_space) {
beg_space = 2; beg_space = 2;
space_right -= 2; space_right -= 2;
} }
printOut(lbuf, beg_space + strlen(attribute_fields[attr_type]) + space_right + strlen(attr_value), printOut(lbuf, beg_space + strlen(attr_str) + space_right + strlen(attr_value),
"%*s%s%s%s%*s%s%s%s", beg_space, "", logo->color_text[0], attribute_fields[attr_type], art->reset, space_right, "", logo->color_text[1], attr_value, art->reset); "%*s%s%s%s%*s%s%s%s", beg_space, "", logo->color_text[0], attr_str, art->reset, space_right, "", logo->color_text[1], attr_value, art->reset);
} }
} }
printOutLine(lbuf, art, termw); printOutLine(lbuf, art, termw);
@@ -939,8 +914,8 @@ bool print_cpufetch_arm(struct cpuInfo* cpu, STYLE s, struct color** cs, struct
setAttribute(art, ATTRIBUTE_HYPERVISOR, cpu->hv->hv_name); setAttribute(art, ATTRIBUTE_HYPERVISOR, cpu->hv->hv_name);
} }
const char** attribute_fields = ATTRIBUTE_FIELDS; bool use_short = false;
uint32_t longest_attribute = longest_attribute_length(art, attribute_fields); uint32_t longest_attribute = longest_attribute_length(art, use_short);
uint32_t longest_field = longest_field_length_arm(art, longest_attribute); uint32_t longest_field = longest_field_length_arm(art, longest_attribute);
choose_ascii_art(art, cs, term, longest_field); choose_ascii_art(art, cs, term, longest_field);
@@ -952,11 +927,11 @@ bool print_cpufetch_arm(struct cpuInfo* cpu, STYLE s, struct color** cs, struct
if(!ascii_fits_screen(term->w, *art->art, longest_field)) { if(!ascii_fits_screen(term->w, *art->art, longest_field)) {
// Despite of choosing the smallest logo, the output does not fit // Despite of choosing the smallest logo, the output does not fit
// Choose the shorter field names and recalculate the longest attr // Choose the shorter field names and recalculate the longest attr
attribute_fields = ATTRIBUTE_FIELDS_SHORT; use_short = true;
longest_attribute = longest_attribute_length(art, attribute_fields); longest_attribute = longest_attribute_length(art, use_short);
} }
print_ascii_arm(art, longest_attribute, term->w, attribute_fields); print_ascii_arm(art, longest_attribute, term->w, use_short);
free(manufacturing_process); free(manufacturing_process);
free(pp); free(pp);
@@ -974,14 +949,7 @@ bool print_cpufetch_arm(struct cpuInfo* cpu, STYLE s, struct color** cs, struct
#endif #endif
#ifdef ARCH_RISCV #ifdef ARCH_RISCV
// https://stackoverflow.com/a/2709523 void print_ascii_riscv(struct ascii* art, uint32_t la, int32_t termw, bool use_short, bool* extensions_mask) {
uint64_t number_of_bits(uint64_t i) {
i = i - ((i >> 1) & 0x5555555555555555);
i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333);
return (((i + (i >> 4)) & 0xF0F0F0F0F0F0F0F) * 0x101010101010101) >> 56;
}
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;
@@ -991,7 +959,7 @@ void print_ascii_riscv(struct ascii* art, uint32_t la, int32_t termw, const char
int32_t ext_list_size = sizeof(extension_list)/sizeof(extension_list[0]); int32_t ext_list_size = sizeof(extension_list)/sizeof(extension_list[0]);
int32_t ext_num = 0; int32_t ext_num = 0;
int32_t ext_to_print = 0; int32_t ext_to_print = 0;
int32_t num_extensions = number_of_bits(extensions_mask); int32_t num_extensions = get_num_extensions(extensions_mask);
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;
@@ -1037,7 +1005,9 @@ void print_ascii_riscv(struct ascii* art, uint32_t la, int32_t termw, const char
// Print extension // Print extension
if(attr_to_print > 0 && art->attributes[attr_to_print-1]->type == ATTRIBUTE_EXTENSIONS && ext_num != num_extensions) { if(attr_to_print > 0 && art->attributes[attr_to_print-1]->type == ATTRIBUTE_EXTENSIONS && ext_num != num_extensions) {
// Search for the extension to print // Search for the extension to print
while(ext_to_print < ext_list_size && !((extensions_mask >> extension_list[ext_to_print].id) & 1U)) ext_to_print++; while (ext_to_print < ext_list_size && !((extensions_mask[extension_list[ext_to_print].id])))
ext_to_print++;
if(ext_to_print == ext_list_size) { if(ext_to_print == ext_list_size) {
printBug("print_ascii_riscv: Unable to find the extension to print"); printBug("print_ascii_riscv: Unable to find the extension to print");
} }
@@ -1049,10 +1019,11 @@ void print_ascii_riscv(struct ascii* art, uint32_t la, int32_t termw, const char
else { else {
attr_to_print++; attr_to_print++;
beg_space = 0; beg_space = 0;
space_right = 2 + 1 + (la - strlen(attribute_fields[attr_type])); const char* attr_str = use_short ? ATTRIBUTE_INFO[attr_type].shortname : ATTRIBUTE_INFO[attr_type].name;
space_right = 2 + 1 + (la - strlen(attr_str));
printOut(lbuf, beg_space + strlen(attribute_fields[attr_type]) + space_right + strlen(attr_value), printOut(lbuf, beg_space + strlen(attr_str) + space_right + strlen(attr_value),
"%*s%s%s%s%*s%s%s%s", beg_space, "", logo->color_text[0], attribute_fields[attr_type], art->reset, space_right, "", logo->color_text[1], attr_value, art->reset); "%*s%s%s%s%*s%s%s%s", beg_space, "", logo->color_text[0], attr_str, art->reset, space_right, "", logo->color_text[1], attr_value, art->reset);
} }
} }
printOutLine(lbuf, art, termw); printOutLine(lbuf, art, termw);
@@ -1090,19 +1061,19 @@ bool print_cpufetch_riscv(struct cpuInfo* cpu, STYLE s, struct color** cs, struc
setAttribute(art, ATTRIBUTE_PEAK, pp); setAttribute(art, ATTRIBUTE_PEAK, pp);
// Step 3. Print output // Step 3. Print output
const char** attribute_fields = ATTRIBUTE_FIELDS; bool use_short = false;
uint32_t longest_attribute = longest_attribute_length(art, attribute_fields); uint32_t longest_attribute = longest_attribute_length(art, use_short);
uint32_t longest_field = longest_field_length(art, longest_attribute); uint32_t longest_field = longest_field_length(art, longest_attribute);
choose_ascii_art(art, cs, term, longest_field); choose_ascii_art(art, cs, term, longest_field);
if(!ascii_fits_screen(term->w, *art->art, longest_field)) { if(!ascii_fits_screen(term->w, *art->art, longest_field)) {
// Despite of choosing the smallest logo, the output does not fit // Despite of choosing the smallest logo, the output does not fit
// Choose the shorter field names and recalculate the longest attr // Choose the shorter field names and recalculate the longest attr
attribute_fields = ATTRIBUTE_FIELDS_SHORT; use_short = true;
longest_attribute = longest_attribute_length(art, attribute_fields); longest_attribute = longest_attribute_length(art, use_short);
} }
print_ascii_riscv(art, longest_attribute, term->w, attribute_fields, cpu->ext->mask); print_ascii_riscv(art, longest_attribute, term->w, use_short, cpu->ext->mask);
return true; return true;
} }

View File

@@ -12,7 +12,7 @@
#define SET_ISA_EXT_MAP(name, bit) \ #define SET_ISA_EXT_MAP(name, bit) \
if(strncmp(multi_letter_extension, name, \ if(strncmp(multi_letter_extension, name, \
multi_letter_extension_len) == 0) { \ multi_letter_extension_len) == 0) { \
ext->mask |= 1UL << bit; \ ext->mask[bit] = true; \
maskset = true; \ maskset = true; \
} \ } \
@@ -62,7 +62,6 @@ int parse_multi_letter_extension(struct extensions* ext, char* e) {
SET_ISA_EXT_MAP("zicbom", RISCV_ISA_EXT_ZICBOM) SET_ISA_EXT_MAP("zicbom", RISCV_ISA_EXT_ZICBOM)
SET_ISA_EXT_MAP("zihintpause", RISCV_ISA_EXT_ZIHINTPAUSE) SET_ISA_EXT_MAP("zihintpause", RISCV_ISA_EXT_ZIHINTPAUSE)
SET_ISA_EXT_MAP("svnapot", RISCV_ISA_EXT_SVNAPOT) SET_ISA_EXT_MAP("svnapot", RISCV_ISA_EXT_SVNAPOT)
SET_ISA_EXT_MAP("zicbop", RISCV_ISA_EXT_ZICBOP)
SET_ISA_EXT_MAP("zicboz", RISCV_ISA_EXT_ZICBOZ) SET_ISA_EXT_MAP("zicboz", RISCV_ISA_EXT_ZICBOZ)
SET_ISA_EXT_MAP("smaia", RISCV_ISA_EXT_SMAIA) SET_ISA_EXT_MAP("smaia", RISCV_ISA_EXT_SMAIA)
SET_ISA_EXT_MAP("ssaia", RISCV_ISA_EXT_SSAIA) SET_ISA_EXT_MAP("ssaia", RISCV_ISA_EXT_SSAIA)
@@ -72,6 +71,65 @@ int parse_multi_letter_extension(struct extensions* ext, char* e) {
SET_ISA_EXT_MAP("zicsr", RISCV_ISA_EXT_ZICSR) SET_ISA_EXT_MAP("zicsr", RISCV_ISA_EXT_ZICSR)
SET_ISA_EXT_MAP("zifencei", RISCV_ISA_EXT_ZIFENCEI) SET_ISA_EXT_MAP("zifencei", RISCV_ISA_EXT_ZIFENCEI)
SET_ISA_EXT_MAP("zihpm", RISCV_ISA_EXT_ZIHPM) SET_ISA_EXT_MAP("zihpm", RISCV_ISA_EXT_ZIHPM)
SET_ISA_EXT_MAP("smstateen", RISCV_ISA_EXT_SMSTATEEN)
SET_ISA_EXT_MAP("zicond", RISCV_ISA_EXT_ZICOND)
SET_ISA_EXT_MAP("zbc", RISCV_ISA_EXT_ZBC)
SET_ISA_EXT_MAP("zbkb", RISCV_ISA_EXT_ZBKB)
SET_ISA_EXT_MAP("zbkc", RISCV_ISA_EXT_ZBKC)
SET_ISA_EXT_MAP("zbkx", RISCV_ISA_EXT_ZBKX)
SET_ISA_EXT_MAP("zknd", RISCV_ISA_EXT_ZKND)
SET_ISA_EXT_MAP("zkne", RISCV_ISA_EXT_ZKNE)
SET_ISA_EXT_MAP("zknh", RISCV_ISA_EXT_ZKNH)
SET_ISA_EXT_MAP("zkr", RISCV_ISA_EXT_ZKR)
SET_ISA_EXT_MAP("zksed", RISCV_ISA_EXT_ZKSED)
SET_ISA_EXT_MAP("zksh", RISCV_ISA_EXT_ZKSH)
SET_ISA_EXT_MAP("zkt", RISCV_ISA_EXT_ZKT)
SET_ISA_EXT_MAP("zvbb", RISCV_ISA_EXT_ZVBB)
SET_ISA_EXT_MAP("zvbc", RISCV_ISA_EXT_ZVBC)
SET_ISA_EXT_MAP("zvkb", RISCV_ISA_EXT_ZVKB)
SET_ISA_EXT_MAP("zvkg", RISCV_ISA_EXT_ZVKG)
SET_ISA_EXT_MAP("zvkned", RISCV_ISA_EXT_ZVKNED)
SET_ISA_EXT_MAP("zvknha", RISCV_ISA_EXT_ZVKNHA)
SET_ISA_EXT_MAP("zvknhb", RISCV_ISA_EXT_ZVKNHB)
SET_ISA_EXT_MAP("zvksed", RISCV_ISA_EXT_ZVKSED)
SET_ISA_EXT_MAP("zvksh", RISCV_ISA_EXT_ZVKSH)
SET_ISA_EXT_MAP("zvkt", RISCV_ISA_EXT_ZVKT)
SET_ISA_EXT_MAP("zfh", RISCV_ISA_EXT_ZFH)
SET_ISA_EXT_MAP("zfhmin", RISCV_ISA_EXT_ZFHMIN)
SET_ISA_EXT_MAP("zihintntl", RISCV_ISA_EXT_ZIHINTNTL)
SET_ISA_EXT_MAP("zvfh", RISCV_ISA_EXT_ZVFH)
SET_ISA_EXT_MAP("zvfhmin", RISCV_ISA_EXT_ZVFHMIN)
SET_ISA_EXT_MAP("zfa", RISCV_ISA_EXT_ZFA)
SET_ISA_EXT_MAP("ztso", RISCV_ISA_EXT_ZTSO)
SET_ISA_EXT_MAP("zacas", RISCV_ISA_EXT_ZACAS)
SET_ISA_EXT_MAP("zve32x", RISCV_ISA_EXT_ZVE32X)
SET_ISA_EXT_MAP("zve32f", RISCV_ISA_EXT_ZVE32F)
SET_ISA_EXT_MAP("zve64x", RISCV_ISA_EXT_ZVE64X)
SET_ISA_EXT_MAP("zve64f", RISCV_ISA_EXT_ZVE64F)
SET_ISA_EXT_MAP("zve64d", RISCV_ISA_EXT_ZVE64D)
SET_ISA_EXT_MAP("zimop", RISCV_ISA_EXT_ZIMOP)
SET_ISA_EXT_MAP("zca", RISCV_ISA_EXT_ZCA)
SET_ISA_EXT_MAP("zcb", RISCV_ISA_EXT_ZCB)
SET_ISA_EXT_MAP("zcd", RISCV_ISA_EXT_ZCD)
SET_ISA_EXT_MAP("zcf", RISCV_ISA_EXT_ZCF)
SET_ISA_EXT_MAP("zcmop", RISCV_ISA_EXT_ZCMOP)
SET_ISA_EXT_MAP("zawrs", RISCV_ISA_EXT_ZAWRS)
SET_ISA_EXT_MAP("svvptc", RISCV_ISA_EXT_SVVPTC)
SET_ISA_EXT_MAP("smmpm", RISCV_ISA_EXT_SMMPM)
SET_ISA_EXT_MAP("smnpm", RISCV_ISA_EXT_SMNPM)
SET_ISA_EXT_MAP("ssnpm", RISCV_ISA_EXT_SSNPM)
SET_ISA_EXT_MAP("zabha", RISCV_ISA_EXT_ZABHA)
SET_ISA_EXT_MAP("ziccrse", RISCV_ISA_EXT_ZICCRSE)
SET_ISA_EXT_MAP("svade", RISCV_ISA_EXT_SVADE)
SET_ISA_EXT_MAP("svadu", RISCV_ISA_EXT_SVADU)
SET_ISA_EXT_MAP("zfbfmin", RISCV_ISA_EXT_ZFBFMIN)
SET_ISA_EXT_MAP("zvfbfmin", RISCV_ISA_EXT_ZVFBFMIN)
SET_ISA_EXT_MAP("zvfbfwma", RISCV_ISA_EXT_ZVFBFWMA)
SET_ISA_EXT_MAP("zaamo", RISCV_ISA_EXT_ZAAMO)
SET_ISA_EXT_MAP("zalrsc", RISCV_ISA_EXT_ZALRSC)
SET_ISA_EXT_MAP("zicbop", RISCV_ISA_EXT_ZICBOP)
SET_ISA_EXT_MAP("ime", RISCV_ISA_EXT_IME)
if(!maskset) { if(!maskset) {
printBug("parse_multi_letter_extension: Unknown multi-letter extension: %s", multi_letter_extension); printBug("parse_multi_letter_extension: Unknown multi-letter extension: %s", multi_letter_extension);
return -1; return -1;
@@ -94,7 +152,7 @@ bool valid_extension(char ext) {
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 = ecalloc(RISCV_ISA_EXT_ID_MAX, sizeof(bool));
ext->str = NULL; ext->str = NULL;
if(str == NULL) { if(str == NULL) {
@@ -107,6 +165,8 @@ struct extensions* get_extensions_from_str(char* str) {
// Code inspired in Linux kernel (riscv_fill_hwcap): // 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
// Now it seems to be here in riscv_parse_isa_string:
// https://elixir.bootlin.com/linux/v6.16/source/arch/riscv/kernel/cpufeature.c
char* isa = str; char* isa = str;
if (!strncmp(isa, "rv32", 4)) if (!strncmp(isa, "rv32", 4))
isa += 4; isa += 4;
@@ -138,7 +198,7 @@ struct extensions* get_extensions_from_str(char* str) {
// adding it to the mask // adding it to the mask
if(valid_extension(*e)) { if(valid_extension(*e)) {
int n = *e - 'a'; int n = *e - 'a';
ext->mask |= 1UL << n; ext->mask[n] = true;
} }
else { else {
printBug("get_extensions_from_str: Invalid extension: '%c'", *e); printBug("get_extensions_from_str: Invalid extension: '%c'", *e);
@@ -149,6 +209,18 @@ struct extensions* get_extensions_from_str(char* str) {
return ext; return ext;
} }
uint32_t get_num_extensions(bool* mask) {
uint32_t num = 0;
for (int i=0; i < RISCV_ISA_EXT_ID_MAX; i++) {
if (mask[i]) num++;
}
return num;
}
bool is_mask_empty(bool* mask) {
return get_num_extensions(mask) == 0;
}
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);
@@ -161,7 +233,7 @@ struct cpuInfo* get_cpu_info(void) {
cpu->hv = emalloc(sizeof(struct hypervisor)); cpu->hv = emalloc(sizeof(struct hypervisor));
cpu->hv->present = false; cpu->hv->present = false;
cpu->ext = get_extensions_from_str(ext_str); cpu->ext = get_extensions_from_str(ext_str);
if(cpu->ext->str != NULL && cpu->ext->mask == 0) return NULL; if(cpu->ext->str != NULL && is_mask_empty(cpu->ext->mask)) return NULL;
cpu->arch = get_uarch(cpu); cpu->arch = get_uarch(cpu);
cpu->soc = get_soc(cpu); cpu->soc = get_soc(cpu);
cpu->freq = get_frequency_info(0); cpu->freq = get_frequency_info(0);

View File

@@ -23,7 +23,6 @@ enum riscv_isa_ext_id {
RISCV_ISA_EXT_ZICBOM, RISCV_ISA_EXT_ZICBOM,
RISCV_ISA_EXT_ZIHINTPAUSE, RISCV_ISA_EXT_ZIHINTPAUSE,
RISCV_ISA_EXT_SVNAPOT, RISCV_ISA_EXT_SVNAPOT,
RISCV_ISA_EXT_ZICBOP,
RISCV_ISA_EXT_ZICBOZ, RISCV_ISA_EXT_ZICBOZ,
RISCV_ISA_EXT_SMAIA, RISCV_ISA_EXT_SMAIA,
RISCV_ISA_EXT_SSAIA, RISCV_ISA_EXT_SSAIA,
@@ -33,12 +32,74 @@ enum riscv_isa_ext_id {
RISCV_ISA_EXT_ZICSR, RISCV_ISA_EXT_ZICSR,
RISCV_ISA_EXT_ZIFENCEI, RISCV_ISA_EXT_ZIFENCEI,
RISCV_ISA_EXT_ZIHPM, RISCV_ISA_EXT_ZIHPM,
RISCV_ISA_EXT_SMSTATEEN,
RISCV_ISA_EXT_ZICOND,
RISCV_ISA_EXT_ZBC,
RISCV_ISA_EXT_ZBKB,
RISCV_ISA_EXT_ZBKC,
RISCV_ISA_EXT_ZBKX,
RISCV_ISA_EXT_ZKND,
RISCV_ISA_EXT_ZKNE,
RISCV_ISA_EXT_ZKNH,
RISCV_ISA_EXT_ZKR,
RISCV_ISA_EXT_ZKSED,
RISCV_ISA_EXT_ZKSH,
RISCV_ISA_EXT_ZKT,
RISCV_ISA_EXT_ZVBB,
RISCV_ISA_EXT_ZVBC,
RISCV_ISA_EXT_ZVKB,
RISCV_ISA_EXT_ZVKG,
RISCV_ISA_EXT_ZVKNED,
RISCV_ISA_EXT_ZVKNHA,
RISCV_ISA_EXT_ZVKNHB,
RISCV_ISA_EXT_ZVKSED,
RISCV_ISA_EXT_ZVKSH,
RISCV_ISA_EXT_ZVKT,
RISCV_ISA_EXT_ZFH,
RISCV_ISA_EXT_ZFHMIN,
RISCV_ISA_EXT_ZIHINTNTL,
RISCV_ISA_EXT_ZVFH,
RISCV_ISA_EXT_ZVFHMIN,
RISCV_ISA_EXT_ZFA,
RISCV_ISA_EXT_ZTSO,
RISCV_ISA_EXT_ZACAS,
RISCV_ISA_EXT_ZVE32X,
RISCV_ISA_EXT_ZVE32F,
RISCV_ISA_EXT_ZVE64X,
RISCV_ISA_EXT_ZVE64F,
RISCV_ISA_EXT_ZVE64D,
RISCV_ISA_EXT_ZIMOP,
RISCV_ISA_EXT_ZCA,
RISCV_ISA_EXT_ZCB,
RISCV_ISA_EXT_ZCD,
RISCV_ISA_EXT_ZCF,
RISCV_ISA_EXT_ZCMOP,
RISCV_ISA_EXT_ZAWRS,
RISCV_ISA_EXT_SVVPTC,
RISCV_ISA_EXT_SMMPM,
RISCV_ISA_EXT_SMNPM,
RISCV_ISA_EXT_SSNPM,
RISCV_ISA_EXT_ZABHA,
RISCV_ISA_EXT_ZICCRSE,
RISCV_ISA_EXT_SVADE,
RISCV_ISA_EXT_SVADU,
RISCV_ISA_EXT_ZFBFMIN,
RISCV_ISA_EXT_ZVFBFMIN,
RISCV_ISA_EXT_ZVFBFWMA,
RISCV_ISA_EXT_ZAAMO,
RISCV_ISA_EXT_ZALRSC,
RISCV_ISA_EXT_ZICBOP,
RISCV_ISA_EXT_IME, // This is not in the kernel! but it was seen on a Muse Pi Pro board
RISCV_ISA_EXT_ID_MAX RISCV_ISA_EXT_ID_MAX
}; };
// https://five-embeddev.com/riscv-isa-manual/latest/preface.html#preface // 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
// (Zicbop) https://github.com/riscv/riscv-CMOs/blob/master/cmobase/Zicbop.adoc // (Zicbop) https://github.com/riscv/riscv-CMOs/blob/master/cmobase/Zicbop.adoc
// https://raw.githubusercontent.com/riscv/riscv-CMOs/master/specifications/cmobase-v1.0.1.pdf
// https://www.kernel.org/doc/Documentation/devicetree/bindings/riscv/extensions.yaml
// https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Options.html
// (Ime) https://github.com/riscv/integrated-matrix-extension (not confirmed, just a guess...)
// Included all except for G // Included all except for G
static const struct extension extension_list[] = { static const struct extension extension_list[] = {
{ 'i' - 'a', "(I) Integer Instruction Set" }, { 'i' - 'a', "(I) Integer Instruction Set" },
@@ -74,12 +135,71 @@ static const struct extension extension_list[] = {
{ RISCV_ISA_EXT_ZICNTR, "(Zicntr) Base Counters and Timers" }, { RISCV_ISA_EXT_ZICNTR, "(Zicntr) Base Counters and Timers" },
{ RISCV_ISA_EXT_ZICSR, "(Zicsr) Control and Status Register" }, { RISCV_ISA_EXT_ZICSR, "(Zicsr) Control and Status Register" },
{ RISCV_ISA_EXT_ZIFENCEI, "(Zifencei) Instruction-Fetch Fence" }, { RISCV_ISA_EXT_ZIFENCEI, "(Zifencei) Instruction-Fetch Fence" },
{ RISCV_ISA_EXT_ZIHPM, "(Zihpm) Hardware Performance Counters" } { RISCV_ISA_EXT_ZIHPM, "(Zihpm) Hardware Performance Counters" },
{ RISCV_ISA_EXT_SMSTATEEN, "(Smstateen) Supervisor/Hypervisor State Enable" },
{ RISCV_ISA_EXT_ZICOND, "(Zicond) Integer Conditional Operations" },
{ RISCV_ISA_EXT_ZBC, "(Zbc) Carry-Less Multiplication" },
{ RISCV_ISA_EXT_ZBKB, "(Zbkb) Bit-Manipulation for Cryptography (Byte ops)" },
{ RISCV_ISA_EXT_ZBKC, "(Zbkc) Bit-Manipulation for Cryptography (Carry-less ops)" },
{ RISCV_ISA_EXT_ZBKX, "(Zbkx) Bit-Manipulation for Cryptography (Crossbar ops)" },
{ RISCV_ISA_EXT_ZKND, "(Zknd) NIST AES Decryption Instructions" },
{ RISCV_ISA_EXT_ZKNE, "(Zkne) NIST AES Encryption Instructions" },
{ RISCV_ISA_EXT_ZKNH, "(Zknh) NIST Hash (SHA-2/SHA-3) Instructions" },
{ RISCV_ISA_EXT_ZKR, "(Zkr) Entropy Source Reading (Random)" },
{ RISCV_ISA_EXT_ZKSED, "(Zksed) SM4 Block Cipher Decryption" },
{ RISCV_ISA_EXT_ZKSH, "(Zksh) SM3 Hash Instructions" },
{ RISCV_ISA_EXT_ZKT, "(Zkt) Data-Independent Execution Latency" },
{ RISCV_ISA_EXT_ZVBB, "(Zvbb) Vector Basic Bit-Manipulation" },
{ RISCV_ISA_EXT_ZVBC, "(Zvbc) Vector Carry-Less Multiplication" },
{ RISCV_ISA_EXT_ZVKB, "(Zvkb) Vector Cryptography (Byte ops)" },
{ RISCV_ISA_EXT_ZVKG, "(Zvkg) Vector GCM/GMAC Instructions" },
{ RISCV_ISA_EXT_ZVKNED, "(Zvkned) Vector AES Decryption" },
{ RISCV_ISA_EXT_ZVKNHA, "(Zvknha) Vector SHA-2 Hash (A variant)" },
{ RISCV_ISA_EXT_ZVKNHB, "(Zvknhb) Vector SHA-2 Hash (B variant)" },
{ RISCV_ISA_EXT_ZVKSED, "(Zvksed) Vector SM4 Block Cipher Decryption" },
{ RISCV_ISA_EXT_ZVKSH, "(Zvksh) Vector SM3 Hash Instructions" },
{ RISCV_ISA_EXT_ZVKT, "(Zvkt) Vector Data-Independent Execution Latency" },
{ RISCV_ISA_EXT_ZFH, "(Zfh) Half-Precision Floating Point" },
{ RISCV_ISA_EXT_ZFHMIN, "(Zfhmin) Minimal Half-Precision Floating Point" },
{ RISCV_ISA_EXT_ZIHINTNTL, "(Zihintntl) Non-Temporal Load/Store Hints" },
{ RISCV_ISA_EXT_ZVFH, "(Zvfh) Vector Half-Precision Floating Point" },
{ RISCV_ISA_EXT_ZVFHMIN, "(Zvfhmin) Minimal Vector Half-Precision Floating Point" },
{ RISCV_ISA_EXT_ZFA, "(Zfa) Additional Floating-Point Instructions" },
{ RISCV_ISA_EXT_ZTSO, "(Ztso) Total Store Ordering Memory Model" },
{ RISCV_ISA_EXT_ZACAS, "(Zacas) Atomic Compare-and-Swap" },
{ RISCV_ISA_EXT_ZVE32X, "(Zve32x) Embedded Vector Integer (32-bit elements)" },
{ RISCV_ISA_EXT_ZVE32F, "(Zve32f) Embedded Vector Floating Point (f32)" },
{ RISCV_ISA_EXT_ZVE64X, "(Zve64x) Embedded Vector Integer (64-bit elements)" },
{ RISCV_ISA_EXT_ZVE64F, "(Zve64f) Embedded Vector Floating Point (f64)" },
{ RISCV_ISA_EXT_ZVE64D, "(Zve64d) Embedded Vector Double-Precision FP (f64)" },
{ RISCV_ISA_EXT_ZIMOP, "(Zimop) Integer Multiply-Only Instructions" },
{ RISCV_ISA_EXT_ZCA, "(Zca) Compressed Integer Instructions" },
{ RISCV_ISA_EXT_ZCB, "(Zcb) Compressed Bit-Manipulation Instructions" },
{ RISCV_ISA_EXT_ZCD, "(Zcd) Compressed Double-Precision FP Instructions" },
{ RISCV_ISA_EXT_ZCF, "(Zcf) Compressed Single-Precision FP Instructions" },
{ RISCV_ISA_EXT_ZCMOP, "(Zcmop) Compressed Multiply-Only Instructions" },
{ RISCV_ISA_EXT_ZAWRS, "(Zawrs) Wait-on-Reservation-Set Instruction" },
{ RISCV_ISA_EXT_SVVPTC, "(Svvptc) Supervisor Virtual Page Table Cache Control" },
{ RISCV_ISA_EXT_SMMPM, "(Smmpm) Supervisor Memory Protection Modification" },
{ RISCV_ISA_EXT_SMNPM, "(Smnpm) Supervisor Non-Privileged Memory Access Control" },
{ RISCV_ISA_EXT_SSNPM, "(Ssnpm) Supervisor Secure Non-Privileged Memory" },
{ RISCV_ISA_EXT_ZABHA, "(Zabha) Atomic Byte/Halfword Operations" },
{ RISCV_ISA_EXT_ZICCRSE, "(Ziccrse) Cache Control Range Start/End Operations" },
{ RISCV_ISA_EXT_SVADE, "(Svade) Supervisor Virtual Address Deferred Exception" },
{ RISCV_ISA_EXT_SVADU, "(Svadu) Supervisor Virtual Address Dirty Update" },
{ RISCV_ISA_EXT_ZFBFMIN, "(Zfbfmin) Minimal BFloat16 Floating Point" },
{ RISCV_ISA_EXT_ZVFBFMIN, "(Zvfbfmin) Vector Minimal BFloat16 Floating Point" },
{ RISCV_ISA_EXT_ZVFBFWMA, "(Zvfbfwma) Vector BFloat16 Widening Multiply-Accumulate" },
{ RISCV_ISA_EXT_ZAAMO, "(Zaamo) Atomic Memory Operation (AMO) Instructions" },
{ RISCV_ISA_EXT_ZALRSC, "(Zalrsc) Atomic Load-Reserved/Store-Conditional" },
{ RISCV_ISA_EXT_ZICBOP, "(Zicbop) Cache Block Prefetch/Zero Operations" },
{ RISCV_ISA_EXT_IME, "(Ime) Integrated Matrix Extension" },
}; };
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_extensions(struct cpuInfo* cpu); char* get_str_extensions(struct cpuInfo* cpu);
uint32_t get_num_extensions(bool* mask);
void print_debug(struct cpuInfo* cpu); void print_debug(struct cpuInfo* cpu);
#endif #endif