diff --git a/src/cpuid.c b/src/cpuid.c index b70ac38..facdc25 100644 --- a/src/cpuid.c +++ b/src/cpuid.c @@ -445,19 +445,19 @@ struct cache* get_cache_info(struct cpuInfo* cpu) { // Sanity checks. If we read values greater than this, they can't be valid ones // The values were chosen by me if(cach->L1i > 64 * 1024) { - printBug("Invalid L1i size: %dKB\n", cach->L1i/1024); + printBug("Invalid L1i size: %dKB", cach->L1i/1024); return NULL; } if(cach->L1d > 64 * 1024) { - printBug("Invalid L1d size: %dKB\n", cach->L1d/1024); + printBug("Invalid L1d size: %dKB", cach->L1d/1024); return NULL; } if(cach->L2 != UNKNOWN && cach->L2 > 2 * 1048576) { - printBug("Invalid L2 size: %dMB\n", cach->L2/(1048576)); + printBug("Invalid L2 size: %dMB", cach->L2/(1048576)); return NULL; } if(cach->L3 != UNKNOWN && cach->L3 > 100 * 1048576) { - printBug("Invalid L3 size: %dMB\n", cach->L3/(1048576)); + printBug("Invalid L3 size: %dMB", cach->L3/(1048576)); return NULL; } @@ -493,6 +493,10 @@ struct frequency* get_frequency_info(struct cpuInfo* cpu) { return freq; } +uint32_t get_nsockets(struct topology* topo) { + return topo->sockets; +} + int64_t get_freq(struct frequency* freq) { return freq->max; } @@ -590,18 +594,34 @@ char* get_str_peak_performance(struct cpuInfo* cpu, struct topology* topo, int64 return string; } -char* get_str_topology(struct topology* topo) { +char* get_str_topology(struct topology* topo, bool dual_socket) { char* string; if(topo->smt > 1) { //3 for digits, 8 for ' cores (', 3 for digits, 9 for ' threads)' uint32_t size = 3+8+3+9+1; string = malloc(sizeof(char)*size); - snprintf(string, size, "%d cores (%d threads)",topo->physical_cores,topo->logical_cores); + if(dual_socket) + snprintf(string, size, "%d cores (%d threads)",topo->physical_cores * topo->sockets, topo->logical_cores * topo->sockets); + else + snprintf(string, size, "%d cores (%d threads)",topo->physical_cores,topo->logical_cores); } else { uint32_t size = 3+7+1; string = malloc(sizeof(char)*size); - snprintf(string, size, "%d cores",topo->physical_cores); + if(dual_socket) + snprintf(string, size, "%d cores",topo->physical_cores * topo->sockets); + else + snprintf(string, size, "%d cores",topo->physical_cores); + } + return string; +} + +char* get_str_sockets(struct topology* topo) { + char* string = malloc(sizeof(char) * 2); + int32_t sanity_ret = snprintf(string, 2, "%d", topo->sockets); + if(sanity_ret < 0) { + printBug("get_str_sockets: snprintf returned a negative value for input: '%d'", topo->sockets); + return NULL; } return string; } @@ -702,12 +722,12 @@ char* get_str_sha(struct cpuInfo* cpu) { int32_t get_value_as_smallest_unit(char ** str, uint32_t value) { int32_t sanity_ret; - *str = malloc(sizeof(char)* 7); //4 for digits, 2 for units + *str = malloc(sizeof(char)* 11); //8 for digits, 2 for units if(value/1024 >= 1024) - sanity_ret = snprintf(*str, 6,"%d"STRING_MEGABYTES,value/(1<<20)); + sanity_ret = snprintf(*str, 10,"%.4g"STRING_MEGABYTES, (double)value/(1<<20)); else - sanity_ret = snprintf(*str, 6,"%d"STRING_KILOBYTES,value/(1<<10)); + sanity_ret = snprintf(*str, 10,"%.4g"STRING_KILOBYTES, (double)value/(1<<10)); return sanity_ret; } @@ -754,7 +774,7 @@ char* get_str_cache_one(int32_t cache_size) { int32_t tmp_len = get_value_as_smallest_unit(&tmp, cache_size); if(tmp_len < 0) { - printBug("get_value_as_smallest_unit: snprintf returned a negative value for input: %d\n", cache_size); + printBug("get_value_as_smallest_unit: snprintf returned a negative value for input: %d", cache_size); return NULL; } @@ -762,7 +782,7 @@ char* get_str_cache_one(int32_t cache_size) { sanity_ret = snprintf(string, size, "%s", tmp); if(sanity_ret < 0) { - printBug("get_str_cache_one: snprintf returned a negative value for input: '%s'\n", tmp); + printBug("get_str_cache_one: snprintf returned a negative value for input: '%s'", tmp); return NULL; } free(tmp); @@ -770,14 +790,18 @@ char* get_str_cache_one(int32_t cache_size) { } char* get_str_cache(int32_t cache_size, struct topology* topo, bool llc) { - if(llc) { - if(topo->sockets == 1) + if(topo->sockets == 1) { + if(llc) return get_str_cache_one(cache_size); else - return get_str_cache_two(cache_size, topo->sockets); + return get_str_cache_two(cache_size, topo->physical_cores); + } + else { + if(llc) + return get_str_cache_two(cache_size, topo->sockets); + else + return get_str_cache_two(cache_size, topo->physical_cores * topo->sockets); } - else - return get_str_cache_two(cache_size, topo->physical_cores); } char* get_str_l1i(struct cache* cach, struct topology* topo) { diff --git a/src/cpuid.h b/src/cpuid.h index bc1b7a0..65cb69d 100644 --- a/src/cpuid.h +++ b/src/cpuid.h @@ -19,6 +19,7 @@ typedef int32_t VENDOR; struct cpuInfo* get_cpu_info(); VENDOR get_cpu_vendor(struct cpuInfo* cpu); +uint32_t get_nsockets(struct topology* topo); int64_t get_freq(struct frequency* freq); struct cache* get_cache_info(struct cpuInfo* cpu); struct frequency* get_frequency_info(struct cpuInfo* cpu); @@ -39,7 +40,8 @@ char* get_str_l3(struct cache* cach, struct topology* topo); char* get_str_freq(struct frequency* freq); -char* get_str_topology(struct topology* topo); +char* get_str_sockets(struct topology* topo); +char* get_str_topology(struct topology* topo, bool dual_socket); char* get_str_peak_performance(struct cpuInfo* cpu, struct topology* topo, int64_t freq); diff --git a/src/main.c b/src/main.c index aa42f22..5ed309d 100644 --- a/src/main.c +++ b/src/main.c @@ -6,30 +6,7 @@ #include "cpuid.h" #include "global.h" -/*** - ################ - ####### ####### - #### #### - ### #### - ### ### Name: Intel(R) Xeon(R) CPU E5-2698 v4 @ 2.20GHz - ### ### Sockets: 2 - Cores: 20 (40 threads) - Frequency: 3.60 GHz - ## ### ######### ###### ###### ### ### AVX: AVX,AVX2 - ## ### ### ### ### #### #### ### ### SSE: SSE,SSE2,SSE3,SSSE3,SSE4_1,SSE4_2 - ## ### ### ### ### ### ### ### ### FMA: FMA3 -## ## ### ### ##### ######### ## ### L1d Size: 32KB (1MB Total) -## ## L1i Size: 32KB (1MB Total) -### L2 Size: 256KB (4MB Total) - ### L3 Size: 50M (100MB Total) - #### #### Peak Perf.: 2.30 TFLOP/s - ##### ########## - ########## ################ - ############################### - -***/ - -static const char* VERSION = "0.411"; +static const char* VERSION = "0.5"; void print_help(char *argv[]) { printf("Usage: %s [--version] [--help] [--style STYLE]\n\ diff --git a/src/printer.c b/src/printer.c index 54ed916..48e9fcb 100644 --- a/src/printer.c +++ b/src/printer.c @@ -18,50 +18,52 @@ #define COL_AMD_DARK_2 "\x1b[32;1m" #define RESET "\x1b[0m" -#define TITLE_NAME "Name: " -#define TITLE_FREQUENCY "Frequency: " -#define TITLE_NCORES "N.Cores: " -#define TITLE_AVX "AVX: " -#define TITLE_SSE "SSE: " -#define TITLE_FMA "FMA: " -#define TITLE_AES "AES: " -#define TITLE_SHA "SHA: " -#define TITLE_L1i "L1i Size: " -#define TITLE_L1d "L1d Size: " -#define TITLE_L2 "L2 Size: " -#define TITLE_L3 "L3 Size: " -#define TITLE_PEAK "Peak FLOPS: " +#define TITLE_NAME "Name:" +#define TITLE_FREQUENCY "Frequency:" +#define TITLE_SOCKETS "Sockets:" +#define TITLE_NCORES "Cores:" +#define TITLE_NCORES_DUAL "Cores (Total):" +#define TITLE_AVX "AVX:" +#define TITLE_SSE "SSE:" +#define TITLE_FMA "FMA:" +#define TITLE_AES "AES:" +#define TITLE_SHA "SHA:" +#define TITLE_L1i "L1i Size:" +#define TITLE_L1d "L1d Size:" +#define TITLE_L2 "L2 Size:" +#define TITLE_L3 "L3 Size:" +#define TITLE_PEAK "Peak Perf.:" -/*** CENTER TEXT ***/ -#define LINES_SPACE_UP 3 -#define LINES_SPACE_DOWN 4 - -#define ATTRIBUTE_COUNT 13 -#define ATTRIBUTE_NAME 0 -#define ATTRIBUTE_FREQUENCY 1 -#define ATTRIBUTE_NCORES 2 -#define ATTRIBUTE_AVX 3 -#define ATTRIBUTE_SSE 4 -#define ATTRIBUTE_FMA 5 -#define ATTRIBUTE_AES 6 -#define ATTRIBUTE_SHA 7 -#define ATTRIBUTE_L1i 8 -#define ATTRIBUTE_L1d 9 -#define ATTRIBUTE_L2 10 -#define ATTRIBUTE_L3 11 -#define ATTRIBUTE_PEAK 12 +#define MAX_ATTRIBUTE_COUNT 15 +#define ATTRIBUTE_NAME 0 +#define ATTRIBUTE_FREQUENCY 1 +#define ATTRIBUTE_SOCKETS 2 +#define ATTRIBUTE_NCORES 3 +#define ATTRIBUTE_NCORES_DUAL 4 +#define ATTRIBUTE_AVX 5 +#define ATTRIBUTE_SSE 6 +#define ATTRIBUTE_FMA 7 +#define ATTRIBUTE_AES 8 +#define ATTRIBUTE_SHA 9 +#define ATTRIBUTE_L1i 10 +#define ATTRIBUTE_L1d 11 +#define ATTRIBUTE_L2 12 +#define ATTRIBUTE_L3 13 +#define ATTRIBUTE_PEAK 14 static const int STYLES_CODE_LIST [STYLES_COUNT] = {STYLE_DEFAULT, STYLE_DARK}; -static const char* ATTRIBUTE_FIELDS [ATTRIBUTE_COUNT] = { TITLE_NAME, TITLE_FREQUENCY, - TITLE_NCORES, TITLE_AVX, TITLE_SSE, - TITLE_FMA, TITLE_AES, TITLE_SHA, - TITLE_L1i, TITLE_L1d, TITLE_L2, TITLE_L3, - TITLE_PEAK }; +static const char* ATTRIBUTE_FIELDS [MAX_ATTRIBUTE_COUNT] = { TITLE_NAME, TITLE_FREQUENCY, TITLE_SOCKETS, + TITLE_NCORES, TITLE_NCORES_DUAL, + TITLE_AVX, TITLE_SSE, + TITLE_FMA, TITLE_AES, TITLE_SHA, + TITLE_L1i, TITLE_L1d, TITLE_L2, TITLE_L3, + TITLE_PEAK + }; -static const int ATTRIBUTE_LIST[ATTRIBUTE_COUNT] = { ATTRIBUTE_NAME, ATTRIBUTE_FREQUENCY, - ATTRIBUTE_NCORES, ATTRIBUTE_AVX, ATTRIBUTE_SSE, - ATTRIBUTE_FMA, ATTRIBUTE_AES, ATTRIBUTE_SHA, +static const int ATTRIBUTE_LIST[MAX_ATTRIBUTE_COUNT] = { ATTRIBUTE_NAME, ATTRIBUTE_FREQUENCY, ATTRIBUTE_SOCKETS, + ATTRIBUTE_NCORES, ATTRIBUTE_NCORES_DUAL, ATTRIBUTE_AVX, + ATTRIBUTE_SSE, ATTRIBUTE_FMA, ATTRIBUTE_AES, ATTRIBUTE_SHA, ATTRIBUTE_L1i, ATTRIBUTE_L1d, ATTRIBUTE_L2, ATTRIBUTE_L3, ATTRIBUTE_PEAK }; @@ -70,31 +72,35 @@ struct ascii { char color1[10]; char color2[10]; char reset[10]; - char* atributes[ATTRIBUTE_COUNT]; + char* attributes[MAX_ATTRIBUTE_COUNT]; + uint32_t n_attributes_set; VENDOR vendor; }; void setAttribute(struct ascii* art, int type, char* value) { - int i = 0; - while(i < ATTRIBUTE_COUNT && type != ATTRIBUTE_LIST[i]) - i++; - if(i != ATTRIBUTE_COUNT) - art->atributes[i] = value; - else - printBug("Setting attribute failed because it was not found"); + art->attributes[type] = value; + art->n_attributes_set++; } struct ascii* set_ascii(VENDOR cpuVendor, STYLE style) { - /*** Check that number of lines of ascii art matches the number - of spaces plus the number of lines filled with text ***/ - if(LINES_SPACE_UP+LINES_SPACE_DOWN+ATTRIBUTE_COUNT != NUMBER_OF_LINES) { - printBug("Number of lines do not match (%d vs %d)",LINES_SPACE_UP+LINES_SPACE_DOWN+ATTRIBUTE_COUNT,NUMBER_OF_LINES); - return NULL; + // Sanity checks // + for(int i=0; i < MAX_ATTRIBUTE_COUNT; 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_DEFAULT_1, *COL_DEFAULT_2, *COL_DARK_1, *COL_DARK_2; struct ascii* art = malloc(sizeof(struct ascii)); + art->n_attributes_set = 0; art->vendor = cpuVendor; + for(int i=0; i < MAX_ATTRIBUTE_COUNT; i++) + art->attributes[i] = NULL; strcpy(art->reset,RESET); if(cpuVendor == VENDOR_INTEL) { @@ -144,12 +150,21 @@ struct ascii* set_ascii(VENDOR cpuVendor, STYLE style) { return art; } -void print_ascii_intel(struct ascii* 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; +} + +void print_ascii_intel(struct ascii* art, uint32_t la) { bool flag = false; + 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; - for(int n=0;nart[n][i] == ' ') { @@ -169,17 +184,22 @@ void print_ascii_intel(struct ascii* art) { } } - /*** PRINT ATTRIBUTE ***/ - if(n>LINES_SPACE_UP-1 && ncolor1,ATTRIBUTE_FIELDS[n-LINES_SPACE_UP],art->color2,art->atributes[n-LINES_SPACE_UP],art->reset); + + 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\n",art->color1, ATTRIBUTE_FIELDS[attr_to_print], space_right, "", art->color2, art->attributes[attr_to_print], art->reset); + } else printf("\n"); } } -void print_ascii_amd(struct ascii* art) { - - for(int n=0;nn_attributes_set)/2; + uint32_t space_down = NUMBER_OF_LINES - art->n_attributes_set - space_up; + + for(uint32_t n=0;nart[n][i] == '@') printf("%s%c%s", art->color1, art->art[n][i], art->reset); @@ -189,29 +209,47 @@ void print_ascii_amd(struct ascii* art) { printf("%c",art->art[n][i]); } - /*** PRINT ATTRIBUTE ***/ - if(n>LINES_SPACE_UP-1 && ncolor1,ATTRIBUTE_FIELDS[n-LINES_SPACE_UP],art->color2,art->atributes[n-LINES_SPACE_UP], art->reset); + if(n > space_up-1 && n < NUMBER_OF_LINES-space_down) { + attr_to_print = get_next_attribute(art, attr_to_print); + printf("%s%s%s%s%s\n",art->color1, ATTRIBUTE_FIELDS[attr_to_print], art->color2, art->attributes[attr_to_print], art->reset); + } else printf("\n"); } } +uint32_t longest_attribute_length(struct ascii* art) { + uint32_t max = 0; + uint64_t len = 0; + + for(int i=0; i < MAX_ATTRIBUTE_COUNT; 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 == VENDOR_INTEL) - print_ascii_intel(art); + print_ascii_intel(art, longest_attribute); else - print_ascii_amd(art); + print_ascii_amd(art, longest_attribute); } bool print_cpufetch(struct cpuInfo* cpu, struct cache* cach, struct frequency* freq, struct topology* topo, STYLE s) { - struct ascii* art = set_ascii(get_cpu_vendor(cpu),s); + struct ascii* art = set_ascii(get_cpu_vendor(cpu), s); if(art == NULL) return false; char* cpu_name = get_str_cpu_name(cpu); + char* sockets = get_str_sockets(topo); char* max_frequency = get_str_freq(freq); - char* nCores = get_str_topology(topo); + char* n_cores = get_str_topology(topo, false); + char* n_cores_dual = get_str_topology(topo, true); char* avx = get_str_avx(cpu); char* sse = get_str_sse(cpu); char* fma = get_str_fma(cpu); @@ -225,7 +263,7 @@ bool print_cpufetch(struct cpuInfo* cpu, struct cache* cach, struct frequency* f setAttribute(art,ATTRIBUTE_NAME,cpu_name); setAttribute(art,ATTRIBUTE_FREQUENCY,max_frequency); - setAttribute(art,ATTRIBUTE_NCORES,nCores); + setAttribute(art,ATTRIBUTE_NCORES,n_cores); setAttribute(art,ATTRIBUTE_AVX,avx); setAttribute(art,ATTRIBUTE_SSE,sse); setAttribute(art,ATTRIBUTE_FMA,fma); @@ -236,12 +274,25 @@ bool print_cpufetch(struct cpuInfo* cpu, struct cache* cach, struct frequency* f setAttribute(art,ATTRIBUTE_L2,l2); setAttribute(art,ATTRIBUTE_L3,l3); 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_DUAL, n_cores_dual); + } + + 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; + } print_ascii(art); free(cpu_name); free(max_frequency); - free(nCores); + free(sockets); + free(n_cores); + free(n_cores_dual); free(avx); free(sse); free(fma);