diff --git a/src/arm/midr.c b/src/arm/midr.c index d71da12..aa23ad6 100644 --- a/src/arm/midr.c +++ b/src/arm/midr.c @@ -85,6 +85,7 @@ struct cpuInfo* get_cpu_info() { ptr->arch = get_uarch_from_midr(ptr->midr, ptr); } + cpu->num_cpus = sockets; cpu->hv = malloc(sizeof(struct hypervisor)); cpu->hv->present = false; cpu->soc = SOC_VENDOR_UNKNOWN; diff --git a/src/common/cpu.h b/src/common/cpu.h index 15d030f..f1ab813 100644 --- a/src/common/cpu.h +++ b/src/common/cpu.h @@ -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 }; diff --git a/src/common/main.c b/src/common/main.c index b87d287..62fe137 100644 --- a/src/common/main.c +++ b/src/common/main.c @@ -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]); diff --git a/src/common/printer.c b/src/common/printer.c index 1b0eee3..ace28c8 100644 --- a/src/common/printer.c +++ b/src/common/printer.c @@ -21,6 +21,8 @@ #include #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 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;nart[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;nart[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 +}