[v0.87][PRINTER] ASCII art attributes are no longer fixed in a given position, and are not fixed in length (max length is now 100). Added different algorithms for printing ASCII art for X86 and ARM, which allows ARM to show each CPU inside a SoC

This commit is contained in:
Dr-Noob
2020-11-21 19:02:04 +01:00
parent 50931ee94d
commit 0b9f0e860c
4 changed files with 250 additions and 123 deletions

View File

@@ -97,6 +97,7 @@ struct cpuInfo {
// are different, the others will be stored in
// the next_cpu field
struct cpuInfo* next_cpu;
uint8_t num_cpus;
#endif
};

View File

@@ -13,7 +13,7 @@
#include "../arm/midr.h"
#endif
static const char* VERSION = "0.86";
static const char* VERSION = "0.87";
void print_help(char *argv[]) {
printf("Usage: %s [--version] [--help] [--debug] [--style \"fancy\"|\"retro\"|\"legacy\"] [--color \"intel\"|\"amd\"|'R,G,B:R,G,B:R,G,B:R,G,B']\n\n", argv[0]);

View File

@@ -21,6 +21,8 @@
#include <Windows.h>
#endif
#define MAX_ATTRIBUTES 100
#define COL_NONE ""
#define COL_INTEL_FANCY_1 "\x1b[46;1m"
#define COL_INTEL_FANCY_2 "\x1b[47;1m"
@@ -55,6 +57,7 @@ enum {
ATTRIBUTE_NAME,
#elif ARCH_ARM
ATTRIBUTE_SOC,
ATTRIBUTE_CPU_NUM,
#endif
ATTRIBUTE_HYPERVISOR,
ATTRIBUTE_UARCH,
@@ -79,6 +82,7 @@ static const char* ATTRIBUTE_FIELDS [] = {
"Name:",
#elif ARCH_ARM
"SoC:",
"",
#endif
"Hypervisor:",
"Microarchitecture:",
@@ -98,28 +102,9 @@ static const char* ATTRIBUTE_FIELDS [] = {
"Peak Performance:",
};
static const int ATTRIBUTE_LIST[] = {
#ifdef ARCH_X86
ATTRIBUTE_NAME,
#elif ARCH_ARM
ATTRIBUTE_SOC,
#endif
ATTRIBUTE_HYPERVISOR,
ATTRIBUTE_UARCH,
ATTRIBUTE_TECHNOLOGY,
ATTRIBUTE_FREQUENCY,
ATTRIBUTE_SOCKETS,
ATTRIBUTE_NCORES,
ATTRIBUTE_NCORES_DUAL,
#ifdef ARCH_X86
ATTRIBUTE_AVX,
ATTRIBUTE_FMA,
#endif
ATTRIBUTE_L1i,
ATTRIBUTE_L1d,
ATTRIBUTE_L2,
ATTRIBUTE_L3,
ATTRIBUTE_PEAK
struct attribute {
int type;
char* value;
};
struct ascii {
@@ -130,16 +115,20 @@ struct ascii {
char color2_text[100];
char ascii_chars[2];
char reset[100];
char** attributes;
uint32_t max_attributes;
struct attribute** attributes;
uint32_t n_attributes_set;
VENDOR vendor;
STYLE style;
};
void setAttribute(struct ascii* art, int type, char* value) {
art->attributes[type] = value;
art->attributes[art->n_attributes_set]->value = value;
art->attributes[art->n_attributes_set]->type = type;
art->n_attributes_set++;
if(art->n_attributes_set > MAX_ATTRIBUTES) {
printBug("Set %d attributes, while max value is %d!", art->n_attributes_set, MAX_ATTRIBUTES);
}
}
char* rgb_to_ansi(struct color* c, bool background, bool bold) {
@@ -158,27 +147,16 @@ char* rgb_to_ansi(struct color* c, bool background, bool bold) {
}
struct ascii* set_ascii(VENDOR cpuVendor, STYLE style, struct colors* cs) {
// Sanity checks //
uint32_t max_attributes = sizeof(ATTRIBUTE_LIST) / sizeof(ATTRIBUTE_LIST[0]);
for(uint32_t i=0; i < max_attributes; i++) {
if(ATTRIBUTE_FIELDS[i] == NULL) {
printBug("Attribute field at position %d is empty", i);
return NULL;
}
if(i > 0 && ATTRIBUTE_LIST[i] == 0) {
printBug("Attribute list at position %d is empty", i);
return NULL;
}
}
char *COL_FANCY_1, *COL_FANCY_2, *COL_FANCY_3, *COL_FANCY_4, *COL_RETRO_1, *COL_RETRO_2, *COL_RETRO_3, *COL_RETRO_4;
struct ascii* art = malloc(sizeof(struct ascii));
art->n_attributes_set = 0;
art->vendor = cpuVendor;
art->max_attributes = max_attributes;
art->attributes = malloc(sizeof(char *) * art->max_attributes);
for(uint32_t i=0; i < art->max_attributes; i++)
art->attributes[i] = NULL;
art->attributes = malloc(sizeof(struct attribute *) * MAX_ATTRIBUTES);
for(uint32_t i=0; i < MAX_ATTRIBUTES; i++) {
art->attributes[i] = malloc(sizeof(struct attribute));
art->attributes[i]->type = 0;
art->attributes[i]->value = NULL;
}
strcpy(art->reset,RESET);
if(art->vendor == CPU_VENDOR_INTEL) {
@@ -319,18 +297,29 @@ struct ascii* set_ascii(VENDOR cpuVendor, STYLE style, struct colors* cs) {
return art;
}
uint32_t get_next_attribute(struct ascii* art, uint32_t last_attr) {
last_attr++;
while(art->attributes[last_attr] == NULL) last_attr++;
return last_attr;
uint32_t longest_attribute_length(struct ascii* art) {
uint32_t max = 0;
uint64_t len = 0;
for(uint32_t i=0; i < art->n_attributes_set; i++) {
if(art->attributes[i]->value != NULL) {
len = strlen(ATTRIBUTE_FIELDS[art->attributes[i]->type]);
if(len > max) max = len;
}
}
return max;
}
void print_ascii_intel(struct ascii* art, uint32_t la) {
bool flag = false;
int attr_to_print = -1;
#ifdef ARCH_X86
void print_ascii_intel(struct ascii* art, uint32_t la) {
int attr_to_print = 0;
int attr_type;
char* attr_value;
uint32_t space_right;
uint32_t space_up = (NUMBER_OF_LINES - art->n_attributes_set)/2;
uint32_t space_down = NUMBER_OF_LINES - art->n_attributes_set - space_up;
bool flag = false;
printf("\n");
for(uint32_t n=0;n<NUMBER_OF_LINES;n++) {
@@ -356,9 +345,12 @@ void print_ascii_intel(struct ascii* art, uint32_t la) {
}
if(n > space_up-1 && n < NUMBER_OF_LINES-space_down) {
attr_to_print = get_next_attribute(art, attr_to_print);
space_right = 1 + (la - strlen(ATTRIBUTE_FIELDS[attr_to_print]));
printf("%s%s%s%*s%s%s%s\n",art->color1_text, ATTRIBUTE_FIELDS[attr_to_print], art->reset, space_right, "", art->color2_text, art->attributes[attr_to_print], art->reset);
attr_type = art->attributes[attr_to_print]->type;
attr_value = art->attributes[attr_to_print]->value;
attr_to_print++;
space_right = 1 + (la - strlen(ATTRIBUTE_FIELDS[attr_type]));
printf("%s%s%s%*s%s%s%s\n", art->color1_text, ATTRIBUTE_FIELDS[attr_type], art->reset, space_right, "", art->color2_text, attr_value, art->reset);
}
else printf("\n");
}
@@ -366,7 +358,9 @@ void print_ascii_intel(struct ascii* art, uint32_t la) {
}
void print_ascii_amd(struct ascii* art, uint32_t la) {
int attr_to_print = -1;
int attr_to_print = 0;
int attr_type;
char* attr_value;
uint32_t space_right;
uint32_t space_up = (NUMBER_OF_LINES - art->n_attributes_set)/2;
uint32_t space_down = NUMBER_OF_LINES - art->n_attributes_set - space_up;
@@ -383,9 +377,12 @@ void print_ascii_amd(struct ascii* art, uint32_t la) {
}
if(n > space_up-1 && n < NUMBER_OF_LINES-space_down) {
attr_to_print = get_next_attribute(art, attr_to_print);
space_right = 1 + (la - strlen(ATTRIBUTE_FIELDS[attr_to_print]));
printf("%s%s%s%*s%s%s%s\n",art->color1_text, ATTRIBUTE_FIELDS[attr_to_print], art->reset, space_right, "", art->color2_text, art->attributes[attr_to_print], art->reset);
attr_type = art->attributes[attr_to_print]->type;
attr_value = art->attributes[attr_to_print]->value;
attr_to_print++;
space_right = 1 + (la - strlen(ATTRIBUTE_FIELDS[attr_type]));
printf("%s%s%s%*s%s%s%s\n", art->color1_text, ATTRIBUTE_FIELDS[attr_type], art->reset, space_right, "", art->color2_text, attr_value, art->reset);
}
else printf("\n");
}
@@ -393,110 +390,67 @@ void print_ascii_amd(struct ascii* art, uint32_t la) {
}
void print_ascii_arm(struct ascii* art, uint32_t la) {
int attr_to_print = -1;
uint32_t space_right;
uint32_t space_up = (NUMBER_OF_LINES - art->n_attributes_set)/2;
uint32_t space_down = NUMBER_OF_LINES - art->n_attributes_set - space_up;
printf("\n");
for(uint32_t n=0;n<NUMBER_OF_LINES;n++) {
for(int i=0;i<LINE_SIZE;i++) {
if(art->art[n][i] == '#')
printf("%s%c%s", art->color1_ascii, art->ascii_chars[0], art->reset);
else
printf("%c",art->art[n][i]);
}
if(n > space_up-1 && n < NUMBER_OF_LINES-space_down) {
attr_to_print = get_next_attribute(art, attr_to_print);
space_right = 1 + (la - strlen(ATTRIBUTE_FIELDS[attr_to_print]));
printf("%s%s%s%*s%s%s%s\n",art->color1_text, ATTRIBUTE_FIELDS[attr_to_print], art->reset, space_right, "", art->color2_text, art->attributes[attr_to_print], art->reset);
}
else printf("\n");
}
printf("\n");
}
uint32_t longest_attribute_length(struct ascii* art) {
uint32_t max = 0;
uint64_t len = 0;
for(uint32_t i=0; i < art->max_attributes; i++) {
if(art->attributes[i] != NULL) {
len = strlen(ATTRIBUTE_FIELDS[i]);
if(len > max) max = len;
}
}
return max;
}
void print_ascii(struct ascii* art) {
uint32_t longest_attribute = longest_attribute_length(art);
if(art->vendor == CPU_VENDOR_INTEL)
print_ascii_intel(art, longest_attribute);
else if(art->vendor == CPU_VENDOR_AMD)
print_ascii_amd(art, longest_attribute);
else if(art->vendor == CPU_VENDOR_ARM)
print_ascii_arm(art, longest_attribute);
else {
printBug("Invalid CPU vendor: %d\n", art->vendor);
}
}
bool print_cpufetch(struct cpuInfo* cpu, struct cache* cach, struct frequency* freq, struct topology* topo, STYLE s, struct colors* cs) {
struct ascii* art = set_ascii(get_cpu_vendor(cpu), s, cs);
if(art == NULL)
return false;
bool print_cpufetch_x86(struct ascii* art, struct cpuInfo* cpu, struct cache* cach, struct frequency* freq, struct topology* topo, struct colors* cs) {
char* uarch = get_str_uarch(cpu);
char* manufacturing_process = get_str_process(cpu);
char* sockets = get_str_sockets(topo);
char* max_frequency = get_str_freq(freq);
char* n_cores = get_str_topology(cpu, topo, false);
char* n_cores_dual = get_str_topology(cpu, topo, true);
#ifdef ARCH_X86
char* cpu_name = get_str_cpu_name(cpu);
char* avx = get_str_avx(cpu);
char* fma = get_str_fma(cpu);
setAttribute(art,ATTRIBUTE_NAME,cpu_name);
setAttribute(art,ATTRIBUTE_AVX,avx);
setAttribute(art,ATTRIBUTE_FMA,fma);
#elif ARCH_ARM
char* soc_name = get_soc_name(cpu);
setAttribute(art, ATTRIBUTE_SOC, soc_name);
#endif
char* l1i = get_str_l1i(topo->cach);
char* l1d = get_str_l1d(topo->cach);
char* l2 = get_str_l2(topo->cach);
char* l3 = get_str_l3(topo->cach);
char* pp = get_str_peak_performance(cpu,topo,get_freq(freq));
setAttribute(art,ATTRIBUTE_NAME,cpu_name);
if(cpu->hv->present) {
setAttribute(art, ATTRIBUTE_HYPERVISOR, cpu->hv->hv_name);
}
setAttribute(art,ATTRIBUTE_UARCH,uarch);
setAttribute(art,ATTRIBUTE_TECHNOLOGY,manufacturing_process);
setAttribute(art,ATTRIBUTE_FREQUENCY,max_frequency);
setAttribute(art,ATTRIBUTE_NCORES,n_cores);
setAttribute(art,ATTRIBUTE_L1i,l1i);
setAttribute(art,ATTRIBUTE_L1d,l1d);
setAttribute(art,ATTRIBUTE_L2,l2);
setAttribute(art,ATTRIBUTE_PEAK,pp);
uint32_t socket_num = get_nsockets(topo);
if (socket_num > 1) {
setAttribute(art, ATTRIBUTE_SOCKETS, sockets);
setAttribute(art, ATTRIBUTE_NCORES,n_cores);
setAttribute(art, ATTRIBUTE_NCORES_DUAL, n_cores_dual);
}
else {
setAttribute(art,ATTRIBUTE_NCORES,n_cores);
}
setAttribute(art,ATTRIBUTE_AVX,avx);
setAttribute(art,ATTRIBUTE_FMA,fma);
setAttribute(art,ATTRIBUTE_L1i,l1i);
setAttribute(art,ATTRIBUTE_L1d,l1d);
setAttribute(art,ATTRIBUTE_L2,l2);
if(l3 != NULL) {
setAttribute(art,ATTRIBUTE_L3,l3);
}
setAttribute(art,ATTRIBUTE_PEAK,pp);
if(art->n_attributes_set > NUMBER_OF_LINES) {
printBug("The number of attributes set is bigger than the max that can be displayed");
return false;
}
if(cpu->hv->present)
setAttribute(art, ATTRIBUTE_HYPERVISOR, cpu->hv->hv_name);
print_ascii(art);
@@ -505,10 +459,8 @@ bool print_cpufetch(struct cpuInfo* cpu, struct cache* cach, struct frequency* f
free(sockets);
free(n_cores);
free(n_cores_dual);
#ifdef ARCH_X86
free(avx);
free(fma);
#endif
free(l1i);
free(l1d);
free(l2);
@@ -526,3 +478,176 @@ bool print_cpufetch(struct cpuInfo* cpu, struct cache* cach, struct frequency* f
return true;
}
#endif
#ifdef ARCH_ARM
void print_ascii_arm(struct ascii* art, uint32_t la) {
int attr_to_print = 0;
int attr_type;
char* attr_value;
uint32_t space_right;
uint32_t space_up = (NUMBER_OF_LINES - art->n_attributes_set)/2;
uint32_t space_down = NUMBER_OF_LINES - art->n_attributes_set - space_up;
bool add_space = false;
printf("\n");
for(uint32_t n=0;n<NUMBER_OF_LINES;n++) {
for(int i=0;i<LINE_SIZE;i++) {
if(art->art[n][i] == '#')
printf("%s%c%s", art->color1_ascii, art->ascii_chars[0], art->reset);
else
printf("%c",art->art[n][i]);
}
if(n > space_up-1 && n < NUMBER_OF_LINES-space_down) {
attr_type = art->attributes[attr_to_print]->type;
attr_value = art->attributes[attr_to_print]->value;
attr_to_print++;
if(attr_type == ATTRIBUTE_PEAK) {
add_space = false;
}
if(attr_type == ATTRIBUTE_CPU_NUM) {
printf("%s%s%s\n", art->color1_text, attr_value, art->reset);
add_space = true;
}
else {
if(add_space) {
space_right = 1 + (la - strlen(ATTRIBUTE_FIELDS[attr_type]));
printf(" %s%s%s%*s%s%s%s\n", art->color1_text, ATTRIBUTE_FIELDS[attr_type], art->reset, space_right, "", art->color2_text, attr_value, art->reset);
}
else {
space_right = 2 + 1 + (la - strlen(ATTRIBUTE_FIELDS[attr_type]));
printf("%s%s%s%*s%s%s%s\n", art->color1_text, ATTRIBUTE_FIELDS[attr_type], art->reset, space_right, "", art->color2_text, attr_value, art->reset);
}
}
}
else printf("\n");
}
printf("\n");
}
void print_ascii(struct ascii* art) {
uint32_t longest_attribute = longest_attribute_length(art);
if(art->vendor == CPU_VENDOR_ARM)
print_ascii_arm(art, longest_attribute);
else {
printBug("Invalid CPU vendor: %d\n", art->vendor);
}
}
bool print_cpufetch_arm(struct ascii* art, struct cpuInfo* cpu, struct cache* cach, struct frequency* freq, struct topology* topo, struct colors* cs) {
char* manufacturing_process = get_str_process(cpu);
char* soc_name = get_soc_name(cpu);
setAttribute(art,ATTRIBUTE_SOC,soc_name);
setAttribute(art,ATTRIBUTE_TECHNOLOGY,manufacturing_process);
if(cpu->num_cpus == 1) {
char* uarch = get_str_uarch(cpu);
char* max_frequency = get_str_freq(freq);
char* n_cores = get_str_topology(cpu, topo, false);
char* l1i = get_str_l1i(topo->cach);
char* l1d = get_str_l1d(topo->cach);
char* l2 = get_str_l2(topo->cach);
char* l3 = get_str_l3(topo->cach);
setAttribute(art,ATTRIBUTE_UARCH,uarch);
setAttribute(art,ATTRIBUTE_FREQUENCY,max_frequency);
setAttribute(art,ATTRIBUTE_NCORES,n_cores);
setAttribute(art,ATTRIBUTE_L1i,l1i);
setAttribute(art,ATTRIBUTE_L1d,l1d);
setAttribute(art,ATTRIBUTE_L2,l2);
if(l3 != NULL) {
setAttribute(art,ATTRIBUTE_L3,l3);
free(l3);
}
free(max_frequency);
free(l1i);
free(l1d);
free(l2);
}
else {
struct cpuInfo* ptr;
int i = 1;
for(ptr = cpu; ptr != NULL; ptr = ptr->next_cpu, i++) {
char* uarch = get_str_uarch(ptr);
char* max_frequency = get_str_freq(freq);
char* n_cores = get_str_topology(cpu, topo, false);
char* l1i = get_str_l1i(topo->cach);
char* l1d = get_str_l1d(topo->cach);
char* l2 = get_str_l2(topo->cach);
char* l3 = get_str_l3(topo->cach);
/*
switch(i) {
case 1:
setAttribute(art, ATTRIBUTE_CPU_NUM_1, NULL);
break;
case 2:
setAttribute(art, ATTRIBUTE_CPU_NUM_2, NULL);
break;
case 3:
setAttribute(art, ATTRIBUTE_CPU_NUM_3, NULL);
break;
default:
printBug("SoC has more than 3 CPUs, which is not supported!");
return false;
}*/
char* cpu_num = malloc(sizeof(char) * 6);
sprintf(cpu_num, "CPU %d:", i);
setAttribute(art, ATTRIBUTE_CPU_NUM, cpu_num);
setAttribute(art, ATTRIBUTE_UARCH, uarch);
setAttribute(art, ATTRIBUTE_FREQUENCY, max_frequency);
setAttribute(art, ATTRIBUTE_NCORES, n_cores);
setAttribute(art, ATTRIBUTE_L1i, l1i);
setAttribute(art, ATTRIBUTE_L1d, l1d);
setAttribute(art, ATTRIBUTE_L2, l2);
if(l3 != NULL) {
setAttribute(art,ATTRIBUTE_L3,l3);
}
}
}
char* pp = get_str_peak_performance(cpu,topo,get_freq(freq));
setAttribute(art,ATTRIBUTE_PEAK,pp);
if(art->n_attributes_set > NUMBER_OF_LINES) {
printBug("The number of attributes set is bigger than the max that can be displayed");
return false;
}
if(cpu->hv->present)
setAttribute(art, ATTRIBUTE_HYPERVISOR, cpu->hv->hv_name);
print_ascii(art);
free(manufacturing_process);
free(pp);
free(art->attributes);
free(art);
if(cs != NULL) free_colors_struct(cs);
free_cache_struct(cach);
free_topo_struct(topo);
free_freq_struct(freq);
free_cpuinfo_struct(cpu);
return true;
}
#endif
bool print_cpufetch(struct cpuInfo* cpu, struct cache* cach, struct frequency* freq, struct topology* topo, STYLE s, struct colors* cs) {
struct ascii* art = set_ascii(get_cpu_vendor(cpu), s, cs);
if(art == NULL)
return false;
#ifdef ARCH_X86
return print_cpufetch_x86(art, cpu, cach, freq, topo, cs);
#elif ARCH_ARM
return print_cpufetch_arm(art, cpu, cach, freq, topo, cs);
#endif
}