mirror of
https://github.com/Dr-Noob/cpufetch.git
synced 2026-03-25 07:50:40 +01:00
Divide source code from other stuff
This commit is contained in:
93
src/args.c
Normal file
93
src/args.c
Normal file
@@ -0,0 +1,93 @@
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "args.h"
|
||||
|
||||
#define ARG_STR_STYLE "style"
|
||||
#define ARG_STR_HELP "help"
|
||||
#define ARG_CHAR_STYLE 's'
|
||||
#define ARG_CHAR_HELP 'h'
|
||||
#define STYLE_STR_1 "default"
|
||||
#define STYLE_STR_2 "dark"
|
||||
|
||||
struct args_struct {
|
||||
int help_flag;
|
||||
STYLE style;
|
||||
};
|
||||
|
||||
static const char* SYTLES_STR_LIST[STYLES_COUNT] = { STYLE_STR_1, STYLE_STR_2 };
|
||||
static struct args_struct args;
|
||||
|
||||
STYLE parseStyle(char* style) {
|
||||
int i = 0;
|
||||
while(i != STYLES_COUNT && strcmp(SYTLES_STR_LIST[i],style) != 0)
|
||||
i++;
|
||||
|
||||
if(i == STYLES_COUNT)
|
||||
return STYLE_INVALID;
|
||||
return i;
|
||||
}
|
||||
|
||||
STYLE getStyle() {
|
||||
return args.style;
|
||||
}
|
||||
|
||||
int showHelp() {
|
||||
return args.help_flag;
|
||||
}
|
||||
|
||||
int parseArgs(int argc, char* argv[]) {
|
||||
int c;
|
||||
int digit_optind = 0;
|
||||
int option_index = 0;
|
||||
opterr = 0;
|
||||
|
||||
args.help_flag = BOOLEAN_FALSE;
|
||||
args.style = STYLE_EMPTY;
|
||||
|
||||
static struct option long_options[] = {
|
||||
{ARG_STR_STYLE, required_argument, 0, ARG_CHAR_STYLE},
|
||||
{ARG_STR_HELP, no_argument, 0, ARG_CHAR_HELP },
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv,"",long_options, &option_index);
|
||||
|
||||
while (c != -1) {
|
||||
if(c == ARG_CHAR_STYLE) {
|
||||
if(args.style != STYLE_EMPTY) {
|
||||
printf("ERROR: Style option specified more than once\n");
|
||||
return BOOLEAN_FALSE;
|
||||
}
|
||||
args.style = parseStyle(optarg);
|
||||
if(args.style == STYLE_INVALID) {
|
||||
printf("ERROR: Invalid style '%s'\n",optarg);
|
||||
return BOOLEAN_FALSE;
|
||||
}
|
||||
}
|
||||
else if(c == ARG_CHAR_HELP) {
|
||||
if(args.help_flag) {
|
||||
printf("ERROR: Help option specified more than once\n");
|
||||
return BOOLEAN_FALSE;
|
||||
}
|
||||
args.help_flag = BOOLEAN_TRUE;
|
||||
}
|
||||
else if(c == '?') {
|
||||
printf("WARNING: Invalid options\n");
|
||||
args.help_flag = BOOLEAN_TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
printf("Bug at line number %d in file %s\n", __LINE__, __FILE__);
|
||||
|
||||
option_index = 0;
|
||||
c = getopt_long(argc, argv,"",long_options, &option_index);
|
||||
}
|
||||
|
||||
if (optind < argc) {
|
||||
printf("WARNING: Invalid options\n");
|
||||
args.help_flag = BOOLEAN_TRUE;
|
||||
}
|
||||
|
||||
return BOOLEAN_TRUE;
|
||||
}
|
||||
10
src/args.h
Normal file
10
src/args.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef __ARGS__
|
||||
#define __ARGS__
|
||||
|
||||
#include "printer.h"
|
||||
|
||||
int parseArgs(int argc, char* argv[]);
|
||||
STYLE getStyle();
|
||||
int showHelp();
|
||||
|
||||
#endif
|
||||
49
src/ascii.h
Normal file
49
src/ascii.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef __ASCII__
|
||||
#define __ASCII__
|
||||
|
||||
#define NUMBER_OF_LINES 20
|
||||
#define LINE_SIZE 63
|
||||
|
||||
#define AMD1 " \0"
|
||||
#define AMD2 " \0"
|
||||
#define AMD3 " \0"
|
||||
#define AMD4 " \0"
|
||||
#define AMD5 " \0"
|
||||
#define AMD6 " \0"
|
||||
#define AMD7 " @@@@ @@@ @@@ @@@@@@@@ ############ \0"
|
||||
#define AMD8 " @@@@@@ @@@@@ @@@@ @@@ @@@@ ########## \0"
|
||||
#define AMD9 " @@@ @@@ @@@@@@@@@@@@@ @@@ @@ # #### \0"
|
||||
#define AMD10 " @@@ @@@ @@@ @@@ @@@ @@@ @@@ ### #### \0"
|
||||
#define AMD11 " @@@@@@@@@@@@ @@@ @@@ @@@ @@@ #### ## ### \0"
|
||||
#define AMD12 " @@@ @@@ @@@ @@@ @@@@@@@@@ ######## ## \0"
|
||||
#define AMD13 " \0"
|
||||
#define AMD14 " \0"
|
||||
#define AMD15 " \0"
|
||||
#define AMD16 " \0"
|
||||
#define AMD17 " \0"
|
||||
#define AMD18 " \0"
|
||||
#define AMD19 " \0"
|
||||
#define AMD20 " \0"
|
||||
|
||||
#define INTEL1 " ################ \0"
|
||||
#define INTEL2 " ####### ####### \0"
|
||||
#define INTEL3 " #### #### \0"
|
||||
#define INTEL4 " ### #### \0"
|
||||
#define INTEL5 " ### ### \0"
|
||||
#define INTEL6 " ### ### \0"
|
||||
#define INTEL7 " # ### ### ### \0"
|
||||
#define INTEL8 " ## ### ######### ###### ###### ### ### \0"
|
||||
#define INTEL9 " ## ### ### ### ### #### #### ### ### \0"
|
||||
#define INTEL10 " ## ### ### ### ### ### ### ### ### \0"
|
||||
#define INTEL11 "## ### ### ### ### ########## ### #### \0"
|
||||
#define INTEL12 "## ### ### ### ### ### ### ##### \0"
|
||||
#define INTEL13 "## ## ### ### ##### ######### ## ### \0"
|
||||
#define INTEL14 "### \0"
|
||||
#define INTEL15 " ### \0"
|
||||
#define INTEL16 " #### #### \0"
|
||||
#define INTEL17 " ##### ########## \0"
|
||||
#define INTEL18 " ########## ################ \0"
|
||||
#define INTEL19 " ############################### \0"
|
||||
#define INTEL20 " \0"
|
||||
|
||||
#endif
|
||||
12
src/cpuid.c
Normal file
12
src/cpuid.c
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "cpuid.h"
|
||||
|
||||
void cpuid(unsigned int *eax, unsigned int *ebx,
|
||||
unsigned int *ecx, unsigned int *edx)
|
||||
{
|
||||
asm volatile("cpuid"
|
||||
: "=a" (*eax),
|
||||
"=b" (*ebx),
|
||||
"=c" (*ecx),
|
||||
"=d" (*edx)
|
||||
: "0" (*eax), "2" (*ecx));
|
||||
}
|
||||
6
src/cpuid.h
Normal file
6
src/cpuid.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef __CPUID__
|
||||
#define __CPUID__
|
||||
|
||||
void cpuid(unsigned int *eax, unsigned int *ebx,unsigned int *ecx, unsigned int *edx);
|
||||
|
||||
#endif
|
||||
94
src/extended.c
Normal file
94
src/extended.c
Normal file
@@ -0,0 +1,94 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "extended.h"
|
||||
|
||||
char* getString_CPUName() {
|
||||
unsigned eax = 0;
|
||||
unsigned ebx = 0;
|
||||
unsigned ecx = 0;
|
||||
unsigned edx = 0;
|
||||
|
||||
char name[64];
|
||||
memset(name,0,64);
|
||||
|
||||
//First, check we can use extended
|
||||
eax = 0x80000000;
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
if(eax < 0x80000001) {
|
||||
char* none = malloc(sizeof(char)*64);
|
||||
sprintf(none,"Unknown");
|
||||
return none;
|
||||
}
|
||||
|
||||
|
||||
//We can, fetch name
|
||||
eax = 0x80000002;
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
|
||||
name[__COUNTER__] = eax & MASK;
|
||||
name[__COUNTER__] = (eax>>8) & MASK;
|
||||
name[__COUNTER__] = (eax>>16) & MASK;
|
||||
name[__COUNTER__] = (eax>>24) & MASK;
|
||||
name[__COUNTER__] = ebx & MASK;
|
||||
name[__COUNTER__] = (ebx>>8) & MASK;
|
||||
name[__COUNTER__] = (ebx>>16) & MASK;
|
||||
name[__COUNTER__] = (ebx>>24) & MASK;
|
||||
name[__COUNTER__] = ecx & MASK;
|
||||
name[__COUNTER__] = (ecx>>8) & MASK;
|
||||
name[__COUNTER__] = (ecx>>16) & MASK;
|
||||
name[__COUNTER__] = (ecx>>24) & MASK;
|
||||
name[__COUNTER__] = edx & MASK;
|
||||
name[__COUNTER__] = (edx>>8) & MASK;
|
||||
name[__COUNTER__] = (edx>>16) & MASK;
|
||||
name[__COUNTER__] = (edx>>24) & MASK;
|
||||
|
||||
eax = 0x80000003;
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
|
||||
name[__COUNTER__] = eax & MASK;
|
||||
name[__COUNTER__] = (eax>>8) & MASK;
|
||||
name[__COUNTER__] = (eax>>16) & MASK;
|
||||
name[__COUNTER__] = (eax>>24) & MASK;
|
||||
name[__COUNTER__] = ebx & MASK;
|
||||
name[__COUNTER__] = (ebx>>8) & MASK;
|
||||
name[__COUNTER__] = (ebx>>16) & MASK;
|
||||
name[__COUNTER__] = (ebx>>24) & MASK;
|
||||
name[__COUNTER__] = ecx & MASK;
|
||||
name[__COUNTER__] = (ecx>>8) & MASK;
|
||||
name[__COUNTER__] = (ecx>>16) & MASK;
|
||||
name[__COUNTER__] = (ecx>>24) & MASK;
|
||||
name[__COUNTER__] = edx & MASK;
|
||||
name[__COUNTER__] = (edx>>8) & MASK;
|
||||
name[__COUNTER__] = (edx>>16) & MASK;
|
||||
name[__COUNTER__] = (edx>>24) & MASK;
|
||||
|
||||
eax = 0x80000004;
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
|
||||
name[__COUNTER__] = eax & MASK;
|
||||
name[__COUNTER__] = (eax>>8) & MASK;
|
||||
name[__COUNTER__] = (eax>>16) & MASK;
|
||||
name[__COUNTER__] = (eax>>24) & MASK;
|
||||
name[__COUNTER__] = ebx & MASK;
|
||||
name[__COUNTER__] = (ebx>>8) & MASK;
|
||||
name[__COUNTER__] = (ebx>>16) & MASK;
|
||||
name[__COUNTER__] = (ebx>>24) & MASK;
|
||||
name[__COUNTER__] = ecx & MASK;
|
||||
name[__COUNTER__] = (ecx>>8) & MASK;
|
||||
name[__COUNTER__] = (ecx>>16) & MASK;
|
||||
name[__COUNTER__] = (ecx>>24) & MASK;
|
||||
name[__COUNTER__] = edx & MASK;
|
||||
name[__COUNTER__] = (edx>>8) & MASK;
|
||||
name[__COUNTER__] = (edx>>16) & MASK;
|
||||
name[__COUNTER__] = (edx>>24) & MASK;
|
||||
|
||||
name[__COUNTER__] = '\0';
|
||||
|
||||
//Remove unused characters
|
||||
int i = 0;
|
||||
while(name[i] == ' ')i++;
|
||||
|
||||
char* name_withoutblank = malloc(sizeof(char)*64);
|
||||
strcpy(name_withoutblank,name+i);
|
||||
return name_withoutblank;
|
||||
}
|
||||
10
src/extended.h
Normal file
10
src/extended.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef __EXTENDED__
|
||||
#define __EXTENDED__
|
||||
|
||||
#define MASK 0xFF
|
||||
#include "cpuid.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
char* getString_CPUName();
|
||||
|
||||
#endif
|
||||
16
src/global.c
Normal file
16
src/global.c
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include "global.h"
|
||||
|
||||
#define RED "\x1b[31;1m"
|
||||
#define RESET "\x1b[0m"
|
||||
|
||||
void printError(const char *fmt, ...) {
|
||||
int buffer_size = 4096;
|
||||
char buffer[buffer_size];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buffer,buffer_size, fmt, args);
|
||||
va_end(args);
|
||||
fprintf(stderr,RED "ERROR: "RESET "%s\n",buffer);
|
||||
}
|
||||
6
src/global.h
Normal file
6
src/global.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef __GLOBAL__
|
||||
#define __GLOBAL__
|
||||
|
||||
void printError(const char *fmt, ...);
|
||||
|
||||
#endif
|
||||
105
src/main.c
Normal file
105
src/main.c
Normal file
@@ -0,0 +1,105 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "args.h"
|
||||
#include "printer.h"
|
||||
#include "standart.h"
|
||||
#include "udev.h"
|
||||
#include "extended.h"
|
||||
#include "global.h"
|
||||
|
||||
/***
|
||||
SAMPLE OUTPUT
|
||||
|
||||
Name: Intel Core i7-4790K
|
||||
Frequency: 4.0 GHz
|
||||
NºCores: 4 cores(8 threads)
|
||||
AXV: AVX,AVX2
|
||||
SSE: SSE,SSE2,SSE4.1,SSE4.2
|
||||
FMA: FMA3
|
||||
AES: Yes
|
||||
SHA: No
|
||||
L1 Size: 32KB(Data)32KB(Instructions)
|
||||
L2 Size: 512KB
|
||||
L3 Size: 8MB
|
||||
Peak FLOPS: 512 GFLOP/s(in simple precision)
|
||||
|
||||
***/
|
||||
|
||||
void help(int argc, char *argv[])
|
||||
{
|
||||
printf("Usage: %s [--help] [--style STYLE]\n\
|
||||
Options: \n\
|
||||
--style Set logo style color\n\
|
||||
default: Default style color\n\
|
||||
dark: Dark style color\n\n\
|
||||
--help Print this help and exit\n",
|
||||
argv[0]);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if(!parseArgs(argc,argv))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if(showHelp()) {
|
||||
help(argc,argv);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
struct cpuInfo* cpu = getCPUInfo();
|
||||
if(cpu == NULL)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
struct cache* cach = new_cache();
|
||||
struct frequency* freq = new_frequency();
|
||||
struct ascii* art = set_ascii(getCPUVendorInternal(cpu),getStyle());
|
||||
if(art == NULL)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
char* cpuName = getString_CPUName();
|
||||
char* maxFrequency = getString_MaxFrequency(freq);
|
||||
char* nCores = getString_NumberCores(cpu);
|
||||
char* avx = getString_AVX(cpu);
|
||||
char* sse = getString_SSE(cpu);
|
||||
char* fma = getString_FMA(cpu);
|
||||
char* aes = getString_AES(cpu);
|
||||
char* sha = getString_SHA(cpu);
|
||||
char* l1 = getString_L1(cach);
|
||||
char* l2 = getString_L2(cach);
|
||||
char* l3 = getString_L3(cach);
|
||||
char* pp = getPeakPerformance(cpu,getFrequency(freq));
|
||||
|
||||
setAttribute(art,ATTRIBUTE_NAME,cpuName);
|
||||
setAttribute(art,ATTRIBUTE_FREQUENCY,maxFrequency);
|
||||
setAttribute(art,ATTRIBUTE_NCORES,nCores);
|
||||
setAttribute(art,ATTRIBUTE_AVX,avx);
|
||||
setAttribute(art,ATTRIBUTE_SSE,sse);
|
||||
setAttribute(art,ATTRIBUTE_FMA,fma);
|
||||
setAttribute(art,ATTRIBUTE_AES,aes);
|
||||
setAttribute(art,ATTRIBUTE_SHA,sha);
|
||||
setAttribute(art,ATTRIBUTE_L1,l1);
|
||||
setAttribute(art,ATTRIBUTE_L2,l2);
|
||||
setAttribute(art,ATTRIBUTE_L3,l3);
|
||||
setAttribute(art,ATTRIBUTE_PEAK,pp);
|
||||
|
||||
print_ascii(art);
|
||||
|
||||
free(cpuName);
|
||||
free(maxFrequency);
|
||||
free(nCores);
|
||||
free(avx);
|
||||
free(sse);
|
||||
free(fma);
|
||||
free(aes);
|
||||
free(sha);
|
||||
free(l1);
|
||||
free(l2);
|
||||
free(l3);
|
||||
free(pp);
|
||||
|
||||
free(cpu);
|
||||
free(art);
|
||||
freeCache(cach);
|
||||
freeFrequency(freq);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
213
src/printer.c
Normal file
213
src/printer.c
Normal file
@@ -0,0 +1,213 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "printer.h"
|
||||
#include "ascii.h"
|
||||
#include "global.h"
|
||||
|
||||
#define COL_INTEL_DEFAULT_1 "\x1b[36;1m"
|
||||
#define COL_INTEL_DEFAULT_2 "\x1b[37;1m"
|
||||
#define COL_INTEL_DARK_1 "\x1b[34;1m"
|
||||
#define COL_INTEL_DARK_2 "\x1b[30m"
|
||||
#define COL_AMD_DEFAULT_1 "\x1b[37;1m"
|
||||
#define COL_AMD_DEFAULT_2 "\x1b[31;1m"
|
||||
#define COL_AMD_DARK_1 "\x1b[30;1m"
|
||||
#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_L1 "L1 Size: "
|
||||
#define TITLE_L2 "L2 Size: "
|
||||
#define TITLE_L3 "L3 Size: "
|
||||
#define TITLE_PEAK "Peak FLOPS: "
|
||||
|
||||
/*** CENTER TEXT ***/
|
||||
#define LINES_SPACE_UP 4
|
||||
#define LINES_SPACE_DOWN 4
|
||||
|
||||
static const char* ATTRIBUTE_FIELDS [ATTRIBUTE_COUNT] = { TITLE_NAME, TITLE_FREQUENCY,
|
||||
TITLE_NCORES, TITLE_AVX, TITLE_SSE,
|
||||
TITLE_FMA, TITLE_AES, TITLE_SHA,
|
||||
TITLE_L1, 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,
|
||||
ATTRIBUTE_L1, ATTRIBUTE_L2, ATTRIBUTE_L3,
|
||||
ATTRIBUTE_PEAK };
|
||||
|
||||
struct ascii {
|
||||
char art[NUMBER_OF_LINES][LINE_SIZE];
|
||||
char color1[10];
|
||||
char color2[10];
|
||||
char* atributes[ATTRIBUTE_COUNT];
|
||||
VENDOR vendor;
|
||||
};
|
||||
|
||||
int setAttribute(struct ascii* art, int type, char* value) {
|
||||
int i = 0;
|
||||
while(i < ATTRIBUTE_COUNT && type != ATTRIBUTE_LIST[i])
|
||||
i++;
|
||||
if(i == ATTRIBUTE_COUNT)
|
||||
return BOOLEAN_FALSE;
|
||||
art->atributes[i] = value;
|
||||
return BOOLEAN_TRUE;
|
||||
}
|
||||
|
||||
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) {
|
||||
printError("Number of lines do not match (%d vs %d)",LINES_SPACE_UP+LINES_SPACE_DOWN+ATTRIBUTE_COUNT,NUMBER_OF_LINES);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ascii* art = malloc(sizeof(struct ascii));
|
||||
art->vendor = cpuVendor;
|
||||
if(cpuVendor == VENDOR_INTEL) {
|
||||
/*** CHECK STYLE ***/
|
||||
switch (style) {
|
||||
case STYLE_EMPTY:
|
||||
case STYLE_DEFAULT:
|
||||
strcpy(art->color1,COL_INTEL_DEFAULT_1);
|
||||
strcpy(art->color2,COL_INTEL_DEFAULT_2);
|
||||
break;
|
||||
case STYLE_DARK:
|
||||
strcpy(art->color1,COL_INTEL_DARK_1);
|
||||
strcpy(art->color2,COL_INTEL_DARK_2);
|
||||
break;
|
||||
default:
|
||||
printError("Found invalid style (%d)",style);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*** COPY ASCII-ART ***/
|
||||
strcpy(art->art[0],INTEL1);
|
||||
strcpy(art->art[1],INTEL2);
|
||||
strcpy(art->art[2],INTEL3);
|
||||
strcpy(art->art[3],INTEL4);
|
||||
strcpy(art->art[4],INTEL5);
|
||||
strcpy(art->art[5],INTEL6);
|
||||
strcpy(art->art[6],INTEL7);
|
||||
strcpy(art->art[7],INTEL8);
|
||||
strcpy(art->art[8],INTEL9);
|
||||
strcpy(art->art[9],INTEL10);
|
||||
strcpy(art->art[10],INTEL11);
|
||||
strcpy(art->art[11],INTEL12);
|
||||
strcpy(art->art[12],INTEL13);
|
||||
strcpy(art->art[13],INTEL14);
|
||||
strcpy(art->art[14],INTEL15);
|
||||
strcpy(art->art[15],INTEL16);
|
||||
strcpy(art->art[16],INTEL17);
|
||||
strcpy(art->art[17],INTEL18);
|
||||
strcpy(art->art[18],INTEL19);
|
||||
strcpy(art->art[19],INTEL20);
|
||||
}
|
||||
else {
|
||||
/*** CHECK STYLE ***/
|
||||
switch (style) {
|
||||
case STYLE_EMPTY:
|
||||
case STYLE_DEFAULT:
|
||||
strcpy(art->color1,COL_AMD_DEFAULT_1);
|
||||
strcpy(art->color2,COL_AMD_DEFAULT_2);
|
||||
break;
|
||||
case STYLE_DARK:
|
||||
strcpy(art->color1,COL_AMD_DARK_1);
|
||||
strcpy(art->color2,COL_AMD_DARK_2);
|
||||
break;
|
||||
default:
|
||||
printError("Found invalid style (%d)",style);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(art->art[0],AMD1);
|
||||
strcpy(art->art[1],AMD2);
|
||||
strcpy(art->art[2],AMD3);
|
||||
strcpy(art->art[3],AMD4);
|
||||
strcpy(art->art[4],AMD5);
|
||||
strcpy(art->art[5],AMD6);
|
||||
strcpy(art->art[6],AMD7);
|
||||
strcpy(art->art[7],AMD8);
|
||||
strcpy(art->art[8],AMD9);
|
||||
strcpy(art->art[9],AMD10);
|
||||
strcpy(art->art[10],AMD11);
|
||||
strcpy(art->art[11],AMD12);
|
||||
strcpy(art->art[12],AMD13);
|
||||
strcpy(art->art[13],AMD14);
|
||||
strcpy(art->art[14],AMD15);
|
||||
strcpy(art->art[15],AMD16);
|
||||
strcpy(art->art[16],AMD17);
|
||||
strcpy(art->art[17],AMD18);
|
||||
strcpy(art->art[18],AMD19);
|
||||
strcpy(art->art[19],AMD20);
|
||||
}
|
||||
return art;
|
||||
}
|
||||
|
||||
void print_ascii_intel(struct ascii* art) {
|
||||
int flag = BOOLEAN_FALSE;
|
||||
|
||||
for(int n=0;n<NUMBER_OF_LINES;n++) {
|
||||
|
||||
/*** PRINT ASCII-ART ***/
|
||||
for(int i=0;i<LINE_SIZE;i++) {
|
||||
if(flag) {
|
||||
if(art->art[n][i] == ' ') {
|
||||
flag = BOOLEAN_FALSE;
|
||||
printf("%c",art->art[n][i]);
|
||||
}
|
||||
else
|
||||
printf("%s%c" RESET,art->color1,art->art[n][i]);
|
||||
}
|
||||
else {
|
||||
if(art->art[n][i] != ' ') {
|
||||
flag = BOOLEAN_TRUE;
|
||||
printf("%s%c" RESET,art->color2,art->art[n][i]);
|
||||
}
|
||||
else
|
||||
printf("%c",art->art[n][i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*** PRINT ATTRIBUTE ***/
|
||||
if(n>LINES_SPACE_UP-1 && n<NUMBER_OF_LINES-LINES_SPACE_DOWN)printf("%s%s%s%s"RESET"\n",art->color1,ATTRIBUTE_FIELDS[n-LINES_SPACE_UP],art->color2,art->atributes[n-LINES_SPACE_UP]);
|
||||
else printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void print_ascii_amd(struct ascii* art) {
|
||||
int flag = BOOLEAN_FALSE;
|
||||
|
||||
for(int n=0;n<NUMBER_OF_LINES;n++) {
|
||||
/*** PRINT ASCII-ART ***/
|
||||
for(int i=0;i<LINE_SIZE;i++) {
|
||||
if(art->art[n][i] == '@')
|
||||
printf("%s%c" RESET,art->color1,art->art[n][i]);
|
||||
else if(art->art[n][i] == '#')
|
||||
printf("%s%c" RESET,art->color2,art->art[n][i]);
|
||||
else
|
||||
printf("%c",art->art[n][i]);
|
||||
}
|
||||
|
||||
/*** PRINT ATTRIBUTE ***/
|
||||
if(n>2 && n<NUMBER_OF_LINES-4)printf("%s%s%s%s"RESET"\n",art->color1,ATTRIBUTE_FIELDS[n-3],art->color2,art->atributes[n-3]);
|
||||
else printf("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void print_ascii(struct ascii* art) {
|
||||
if(art->vendor == VENDOR_INTEL)
|
||||
print_ascii_intel(art);
|
||||
else
|
||||
print_ascii_amd(art);
|
||||
}
|
||||
39
src/printer.h
Normal file
39
src/printer.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef __PRINTER__
|
||||
#define __PRINTER__
|
||||
|
||||
#include "standart.h"
|
||||
#include "ascii.h"
|
||||
|
||||
#define BOOLEAN_TRUE 1
|
||||
#define BOOLEAN_FALSE 0
|
||||
|
||||
#define ATTRIBUTE_COUNT 12
|
||||
#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_L1 8
|
||||
#define ATTRIBUTE_L2 9
|
||||
#define ATTRIBUTE_L3 10
|
||||
#define ATTRIBUTE_PEAK 11
|
||||
|
||||
typedef int STYLE;
|
||||
#define STYLES_COUNT 2
|
||||
|
||||
#define STYLE_EMPTY -2
|
||||
#define STYLE_INVALID -1
|
||||
#define STYLE_DEFAULT 0
|
||||
#define STYLE_DARK 1
|
||||
|
||||
struct ascii;
|
||||
|
||||
static const int STYLES_CODE_LIST [STYLES_COUNT] = {STYLE_DEFAULT, STYLE_DARK};
|
||||
struct ascii* set_ascii(VENDOR cpuVendor, STYLE style);
|
||||
void print_ascii(struct ascii* art);
|
||||
int setAttribute(struct ascii* art, int type, char* value);
|
||||
|
||||
#endif
|
||||
366
src/standart.c
Normal file
366
src/standart.c
Normal file
@@ -0,0 +1,366 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "standart.h"
|
||||
#include "cpuid.h"
|
||||
#include "udev.h"
|
||||
|
||||
#define BOOLEAN_TRUE 1
|
||||
#define BOOLEAN_FALSE 0
|
||||
|
||||
/***
|
||||
|
||||
MASTER PAGE
|
||||
http://www.sandpile.org/x86/cpuid.htm
|
||||
|
||||
***/
|
||||
|
||||
struct cpuInfo {
|
||||
/*** BOOLEAN VALUES ***/
|
||||
|
||||
/* (256 bits) */
|
||||
int AVX;
|
||||
int AVX2;
|
||||
|
||||
/* (512 bits) */
|
||||
int AVX512;
|
||||
|
||||
/* (128 bits) */
|
||||
int SSE;
|
||||
int SSE2;
|
||||
int SSE3;
|
||||
int SSSE3;
|
||||
int SSE4a;
|
||||
int SSE4_1;
|
||||
int SSE4_2;
|
||||
|
||||
int FMA3;
|
||||
int FMA4;
|
||||
|
||||
int AES;
|
||||
int SHA;
|
||||
|
||||
VENDOR cpu_vendor;
|
||||
/*** Number of threads ***/
|
||||
int nThreads;
|
||||
/*** Threads per core(Intel HyperThreading) ***/
|
||||
int HT;
|
||||
/*** Max CPUIDs levels ***/
|
||||
unsigned maxLevels;
|
||||
/*** Max CPUIDs extended levels ***/
|
||||
unsigned maxExtendedLevels;
|
||||
};
|
||||
|
||||
void initializeCpuInfo(struct cpuInfo* cpu) {
|
||||
cpu->AVX = BOOLEAN_FALSE;
|
||||
cpu->AVX2 = BOOLEAN_FALSE;
|
||||
cpu->AVX512 = BOOLEAN_FALSE;
|
||||
cpu->SSE = BOOLEAN_FALSE;
|
||||
cpu->SSE2 = BOOLEAN_FALSE;
|
||||
cpu->SSE3 = BOOLEAN_FALSE;
|
||||
cpu->SSSE3 = BOOLEAN_FALSE;
|
||||
cpu->SSE4a = BOOLEAN_FALSE;
|
||||
cpu->SSE4_1 = BOOLEAN_FALSE;
|
||||
cpu->SSE4_2 = BOOLEAN_FALSE;
|
||||
cpu->FMA3 = BOOLEAN_FALSE;
|
||||
cpu->FMA4 = BOOLEAN_FALSE;
|
||||
cpu->AES = BOOLEAN_FALSE;
|
||||
cpu->SHA = BOOLEAN_FALSE;
|
||||
}
|
||||
|
||||
#define MASK 0xFF
|
||||
VENDOR getCPUVendor(unsigned eax,unsigned ebx,unsigned ecx,unsigned edx) {
|
||||
char name[13];
|
||||
memset(name,0,13);
|
||||
name[__COUNTER__] = ebx & MASK;
|
||||
name[__COUNTER__] = (ebx>>8) & MASK;
|
||||
name[__COUNTER__] = (ebx>>16) & MASK;
|
||||
name[__COUNTER__] = (ebx>>24) & MASK;
|
||||
|
||||
name[__COUNTER__] = edx & MASK;
|
||||
name[__COUNTER__] = (edx>>8) & MASK;
|
||||
name[__COUNTER__] = (edx>>16) & MASK;
|
||||
name[__COUNTER__] = (edx>>24) & MASK;
|
||||
|
||||
name[__COUNTER__] = ecx & MASK;
|
||||
name[__COUNTER__] = (ecx>>8) & MASK;
|
||||
name[__COUNTER__] = (ecx>>16) & MASK;
|
||||
name[__COUNTER__] = (ecx>>24) & MASK;
|
||||
|
||||
if(strcmp(VENDOR_INTEL_STRING,name) == 0)
|
||||
return VENDOR_INTEL;
|
||||
|
||||
else if (strcmp(VENDOR_AMD_STRING,name) == 0)
|
||||
return VENDOR_AMD;
|
||||
|
||||
return VENDOR_INVALID;
|
||||
}
|
||||
|
||||
struct cpuInfo* getCPUInfo() {
|
||||
struct cpuInfo* cpu = malloc(sizeof(struct cpuInfo));
|
||||
memset(cpu,0,sizeof(struct cpuInfo));
|
||||
initializeCpuInfo(cpu);
|
||||
|
||||
unsigned eax = 0;
|
||||
unsigned ebx = 0;
|
||||
unsigned ecx = 0;
|
||||
unsigned edx = 0;
|
||||
|
||||
//Get max cpuid level
|
||||
eax = 0x0000000;
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
cpu->maxLevels = eax;
|
||||
|
||||
//Fill vendor
|
||||
cpu->cpu_vendor = getCPUVendor(eax,ebx,ecx,edx);
|
||||
if(cpu->cpu_vendor == VENDOR_INVALID) {
|
||||
printf("ERROR: CPU vendor is neither AMD nor INTEL\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Get max extended level
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
cpu->maxExtendedLevels = eax;
|
||||
|
||||
//Fill cores and threads
|
||||
cpu->nThreads = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
|
||||
//Always check we can fetch data
|
||||
if (cpu->maxLevels >= 0x0000000B) {
|
||||
eax = 0x0000000B;
|
||||
ecx = 0x00000000;
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
cpu->HT = ebx & 0xF;
|
||||
if(cpu->HT == 0) {
|
||||
//AMD should not work with this, returning 0
|
||||
//Suppose we have 1
|
||||
cpu->HT = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//We can afford this check, assume 1
|
||||
cpu->HT = 1;
|
||||
}
|
||||
|
||||
//Fill instructions support
|
||||
if (cpu->maxLevels >= 0x00000001){
|
||||
eax = 0x00000001;
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
cpu->SSE = (edx & ((int)1 << 25)) != 0;
|
||||
cpu->SSE2 = (edx & ((int)1 << 26)) != 0;
|
||||
cpu->SSE3 = (ecx & ((int)1 << 0)) != 0;
|
||||
|
||||
cpu->SSSE3 = (ecx & ((int)1 << 9)) != 0;
|
||||
cpu->SSE4_1 = (ecx & ((int)1 << 19)) != 0;
|
||||
cpu->SSE4_2 = (ecx & ((int)1 << 20)) != 0;
|
||||
|
||||
cpu->AES = (ecx & ((int)1 << 25)) != 0;
|
||||
|
||||
cpu->AVX = (ecx & ((int)1 << 28)) != 0;
|
||||
cpu->FMA3 = (ecx & ((int)1 << 12)) != 0;
|
||||
}
|
||||
if (cpu->maxLevels >= 0x00000007){
|
||||
eax = 0x00000007;
|
||||
ecx = 0x00000000;
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
cpu->AVX2 = (ebx & ((int)1 << 5)) != 0;
|
||||
cpu->SHA = (ebx & ((int)1 << 29)) != 0;
|
||||
cpu->AVX512 = (((ebx & ((int)1 << 16)) != 0) ||
|
||||
((ebx & ((int)1 << 28)) != 0) ||
|
||||
((ebx & ((int)1 << 26)) != 0) ||
|
||||
((ebx & ((int)1 << 27)) != 0) ||
|
||||
((ebx & ((int)1 << 31)) != 0) ||
|
||||
((ebx & ((int)1 << 30)) != 0) ||
|
||||
((ebx & ((int)1 << 17)) != 0) ||
|
||||
((ebx & ((int)1 << 21)) != 0));
|
||||
}
|
||||
if (cpu->maxExtendedLevels >= 0x80000001){
|
||||
eax = 0x80000001;
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
cpu->SSE4a = (ecx & ((int)1 << 6)) != 0;
|
||||
cpu->FMA4 = (ecx & ((int)1 << 16)) != 0;
|
||||
}
|
||||
|
||||
return cpu;
|
||||
}
|
||||
|
||||
void debugCpuInfo(struct cpuInfo* cpu) {
|
||||
printf("AVX=%s\n", cpu->AVX ? "true" : "false");
|
||||
printf("AVX2=%s\n", cpu->AVX2 ? "true" : "false");
|
||||
printf("AVX512=%s\n\n", cpu->AVX512 ? "true" : "false");
|
||||
|
||||
printf("SSE=%s\n", cpu->SSE ? "true" : "false");
|
||||
printf("SSE2=%s\n", cpu->SSE2 ? "true" : "false");
|
||||
printf("SSE3=%s\n", cpu->SSE3 ? "true" : "false");
|
||||
printf("SSSE3=%s\n", cpu->SSSE3 ? "true" : "false");
|
||||
printf("SSE4a=%s\n", cpu->SSE4a ? "true" : "false");
|
||||
printf("SSE4_1=%s\n", cpu->SSE4_1 ? "true" : "false");
|
||||
printf("SSE4_2=%s\n\n", cpu->SSE4_2 ? "true" : "false");
|
||||
|
||||
printf("FMA3=%s\n", cpu->FMA3 ? "true" : "false");
|
||||
printf("FMA4=%s\n\n", cpu->FMA4 ? "true" : "false");
|
||||
|
||||
printf("AES=%s\n", cpu->AES ? "true" : "false");
|
||||
printf("SHA=%s\n", cpu->SHA ? "true" : "false");
|
||||
}
|
||||
|
||||
/*** STRING FUNCTIONS ***/
|
||||
|
||||
char* getPeakPerformance(struct cpuInfo* cpu, long freq) {
|
||||
/***
|
||||
PP = PeakPerformance
|
||||
SP = SinglePrecision
|
||||
|
||||
PP(SP) =
|
||||
N_CORES *
|
||||
FREQUENCY *
|
||||
2(Two vector units) *
|
||||
2(If cpu has fma) *
|
||||
16(If AVX512), 8(If AVX), 4(If SSE) *
|
||||
|
||||
***/
|
||||
|
||||
//7 for GFLOP/s and 6 for digits,eg 412.14
|
||||
unsigned int size = 7+6+1+1;
|
||||
assert(strlen(STRING_UNKNOWN)+1 <= size);
|
||||
char* string = malloc(sizeof(char)*size);
|
||||
|
||||
//First check we have consistent data
|
||||
if(freq == UNKNOWN) {
|
||||
snprintf(string,strlen(STRING_UNKNOWN)+1,STRING_UNKNOWN);
|
||||
return string;
|
||||
}
|
||||
|
||||
float flops = (cpu->nThreads/cpu->HT)*freq*2;
|
||||
|
||||
if(cpu->FMA3 || cpu->FMA4)
|
||||
flops = flops*2;
|
||||
|
||||
if(cpu->AVX512)
|
||||
flops = flops*16;
|
||||
else if(cpu->AVX || cpu->AVX2)
|
||||
flops = flops*8;
|
||||
else if(cpu->SSE)
|
||||
flops = flops*4;
|
||||
|
||||
if(flops >= (double)1000000000000.0)
|
||||
snprintf(string,size,"%.2f TFLOP/s",flops/1000000000000);
|
||||
else if(flops >= 1000000000.0)
|
||||
snprintf(string,size,"%.2f GFLOP/s",flops/1000000000);
|
||||
else
|
||||
snprintf(string,size,"%.2f MFLOP/s",flops/1000000);
|
||||
return string;
|
||||
}
|
||||
|
||||
VENDOR getCPUVendorInternal(struct cpuInfo* cpu) {
|
||||
return cpu->cpu_vendor;
|
||||
}
|
||||
|
||||
char* getString_NumberCores(struct cpuInfo* cpu) {
|
||||
if(cpu->HT > 1) {
|
||||
//2(N.Cores)7(' cores(')3(N.Threads)9(' threads)')
|
||||
int size = 2+7+3+9+1;
|
||||
char* string = malloc(sizeof(char)*size);
|
||||
snprintf(string,size,"%d cores(%d threads)",cpu->nThreads/cpu->HT,cpu->nThreads);
|
||||
return string;
|
||||
}
|
||||
else {
|
||||
char* string = malloc(sizeof(char)*2+7+1);
|
||||
snprintf(string,2+7+1,"%d cores",cpu->nThreads);
|
||||
return string;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
char* getString_AVX(struct cpuInfo* cpu) {
|
||||
//If all AVX are available, it will use up to 15
|
||||
char* string = malloc(sizeof(char)*15+1);
|
||||
if(cpu->AVX == BOOLEAN_FALSE)
|
||||
snprintf(string,2+1,"No");
|
||||
else if(cpu->AVX2 == BOOLEAN_FALSE)
|
||||
snprintf(string,3+1,"AVX");
|
||||
else if(cpu->AVX512 == BOOLEAN_FALSE)
|
||||
snprintf(string,8+1,"AVX,AVX2");
|
||||
else
|
||||
snprintf(string,15+1,"AVX,AVX2,AVX512");
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
char* getString_SSE(struct cpuInfo* cpu) {
|
||||
int last = 0;
|
||||
int SSE_sl = 4;
|
||||
int SSE2_sl = 5;
|
||||
int SSE3_sl = 5;
|
||||
int SSSE3_sl = 6;
|
||||
int SSE4a_sl = 6;
|
||||
int SSE4_1_sl = 7;
|
||||
int SSE4_2_sl = 7;
|
||||
char* string = malloc(sizeof(char)*SSE_sl+SSE2_sl+SSE3_sl+SSSE3_sl+SSE4a_sl+SSE4_1_sl+SSE4_2_sl+1);
|
||||
|
||||
if(cpu->SSE == BOOLEAN_TRUE) {
|
||||
snprintf(string+last,SSE_sl+1,"SSE,");
|
||||
last+=SSE_sl;
|
||||
}
|
||||
if(cpu->SSE2 == BOOLEAN_TRUE) {
|
||||
snprintf(string+last,SSE2_sl+1,"SSE2,");
|
||||
last+=SSE2_sl;
|
||||
}
|
||||
if(cpu->SSE3 == BOOLEAN_TRUE) {
|
||||
snprintf(string+last,SSE3_sl+1,"SSE3,");
|
||||
last+=SSE3_sl;
|
||||
}
|
||||
if(cpu->SSSE3 == BOOLEAN_TRUE) {
|
||||
snprintf(string+last,SSSE3_sl+1,"SSSE3,");
|
||||
last+=SSSE3_sl;
|
||||
}
|
||||
if(cpu->SSE4a == BOOLEAN_TRUE) {
|
||||
snprintf(string+last,SSE4a_sl+1,"SSE4a,");
|
||||
last+=SSE4a_sl;
|
||||
}
|
||||
if(cpu->SSE4_1 == BOOLEAN_TRUE) {
|
||||
snprintf(string+last,SSE4_1_sl+1,"SSE4_1,");
|
||||
last+=SSE4_1_sl;
|
||||
}
|
||||
if(cpu->SSE4_2 == BOOLEAN_TRUE) {
|
||||
snprintf(string+last,SSE4_2_sl+1,"SSE4_2,");
|
||||
last+=SSE4_2_sl;
|
||||
}
|
||||
|
||||
//Purge last comma
|
||||
string[last-1] = '\0';
|
||||
return string;
|
||||
}
|
||||
|
||||
char* getString_FMA(struct cpuInfo* cpu) {
|
||||
char* string = malloc(sizeof(char)*9+1);
|
||||
if(cpu->FMA3 == BOOLEAN_FALSE)
|
||||
snprintf(string,2+1,"No");
|
||||
else if(cpu->FMA4 == BOOLEAN_FALSE)
|
||||
snprintf(string,4+1,"FMA3");
|
||||
else
|
||||
snprintf(string,9+1,"FMA3,FMA4");
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
char* getString_AES(struct cpuInfo* cpu) {
|
||||
char* string = malloc(sizeof(char)*3+1);
|
||||
if(cpu->AES == BOOLEAN_TRUE)
|
||||
snprintf(string,3+1,STRING_YES);
|
||||
else
|
||||
snprintf(string,2+1,STRING_NO);
|
||||
return string;
|
||||
}
|
||||
|
||||
char* getString_SHA(struct cpuInfo* cpu) {
|
||||
char* string = malloc(sizeof(char)*3+1);
|
||||
if(cpu->SHA == BOOLEAN_TRUE)
|
||||
snprintf(string,3+1,STRING_YES);
|
||||
else
|
||||
snprintf(string,2+1,STRING_NO);
|
||||
return string;
|
||||
}
|
||||
30
src/standart.h
Normal file
30
src/standart.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef __01h__
|
||||
#define __01h__
|
||||
|
||||
#define STRING_YES "Yes"
|
||||
#define STRING_NO "No"
|
||||
|
||||
#define VENDOR_EMPTY 0
|
||||
#define VENDOR_INTEL 1
|
||||
#define VENDOR_AMD 2
|
||||
#define VENDOR_INVALID 3
|
||||
#define VENDOR_INTEL_STRING "GenuineIntel"
|
||||
#define VENDOR_AMD_STRING "AuthenticAMD"
|
||||
typedef int VENDOR;
|
||||
|
||||
struct cpuInfo;
|
||||
|
||||
struct cpuInfo* getCPUInfo();
|
||||
void debugCpuInfo(struct cpuInfo* cpu);
|
||||
|
||||
VENDOR getCPUVendorInternal(struct cpuInfo* cpu);
|
||||
char* getPeakPerformance(struct cpuInfo* cpu, long freq);
|
||||
|
||||
char* getString_NumberCores(struct cpuInfo* cpu);
|
||||
char* getString_AVX(struct cpuInfo* cpu);
|
||||
char* getString_SSE(struct cpuInfo* cpu);
|
||||
char* getString_FMA(struct cpuInfo* cpu);
|
||||
char* getString_AES(struct cpuInfo* cpu);
|
||||
char* getString_SHA(struct cpuInfo* cpu);
|
||||
|
||||
#endif
|
||||
214
src/udev.c
Normal file
214
src/udev.c
Normal file
@@ -0,0 +1,214 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "udev.h"
|
||||
|
||||
struct cache {
|
||||
int L1i;
|
||||
int L1d;
|
||||
int L2;
|
||||
int L3;
|
||||
};
|
||||
|
||||
struct frequency {
|
||||
long max;
|
||||
long min;
|
||||
};
|
||||
|
||||
/***
|
||||
|
||||
Parses buf which should be expressed in the way:
|
||||
xxxxK where 'x' are numbers and 'K' refers to kilobytes.
|
||||
Returns the size as a int in bytes
|
||||
|
||||
***/
|
||||
|
||||
int getSize(char* buf, int size) {
|
||||
char* end = strstr (buf,"K");
|
||||
if(end == NULL) {
|
||||
printf("ERROR in getSize(strstr)\n");
|
||||
return UNKNOWN;
|
||||
}
|
||||
*end = 0;
|
||||
int cachsize = atoi(buf);
|
||||
if(cachsize == 0) {
|
||||
printf("ERROR in getSize(atoi)\n");
|
||||
return UNKNOWN;
|
||||
}
|
||||
return cachsize;
|
||||
}
|
||||
|
||||
/***
|
||||
|
||||
Returns size(in bytes) of cache described by path or
|
||||
UNKNOWN if the cache doest no exists
|
||||
|
||||
***/
|
||||
|
||||
//Sacar factor comun lectura
|
||||
//Block pasar de 1 a 1000
|
||||
int getCache(char* path) {
|
||||
FILE *file = fopen(path, "r");
|
||||
|
||||
if(file == NULL) {
|
||||
//Doest not exist
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
//File exists, read it
|
||||
int fd = fileno(file);
|
||||
int bytes_read = 0;
|
||||
int offset = 0;
|
||||
int block = DEFAULT_BLOCK_SIZE;
|
||||
char* buf = malloc(sizeof(char)*DEFAULT_FILE_SIZE);
|
||||
memset(buf, 0, sizeof(char)*DEFAULT_FILE_SIZE);
|
||||
|
||||
do {
|
||||
bytes_read = read(fd, buf+offset, block);
|
||||
offset += bytes_read;
|
||||
} while(bytes_read > 0);
|
||||
|
||||
//Move size from kb to bytes
|
||||
int ret = getSize(buf,offset)*1024;
|
||||
free(buf);
|
||||
fclose(file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***
|
||||
|
||||
Returns CPU frequency in Hz
|
||||
|
||||
***/
|
||||
|
||||
long getFrequencyFromFile(char* path) {
|
||||
FILE *file = fopen(path, "r");
|
||||
|
||||
if(file == NULL) {
|
||||
//Doest not exist
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
//File exists, read it
|
||||
int fd = fileno(file);
|
||||
int bytes_read = 0;
|
||||
int offset = 0;
|
||||
int block = 1;
|
||||
char* buf = malloc(sizeof(char)*DEFAULT_FILE_SIZE);
|
||||
memset(buf, 0, sizeof(char)*DEFAULT_FILE_SIZE);
|
||||
|
||||
while ( (bytes_read = read(fd, buf+offset, block)) > 0 ) {
|
||||
offset += bytes_read;
|
||||
}
|
||||
|
||||
int ret = atoi(buf);
|
||||
free(buf);
|
||||
if(ret == 0) {
|
||||
printf("error in getFrequencyFromFile\n");
|
||||
return UNKNOWN;
|
||||
}
|
||||
fclose(file);
|
||||
return (long)ret*1000;
|
||||
}
|
||||
|
||||
long getFrequency(struct frequency* freq) {
|
||||
return freq->max;
|
||||
}
|
||||
|
||||
/*** GET_STRING ***/
|
||||
|
||||
char* getString_L1(struct cache* cach) {
|
||||
//Max 2 digits,2 for 'KB',6 for '(Data)'
|
||||
//and 14 for '(Instructions)'
|
||||
int size = (2*(2+2)+6+14+1);
|
||||
char* string = malloc(sizeof(char)*size);
|
||||
snprintf(string,size,"%d"STRING_KILOBYTES"(Data)%d"STRING_KILOBYTES"(Instructions)",cach->L1d/1024,cach->L1i/1024);
|
||||
return string;
|
||||
}
|
||||
|
||||
char* getString_L2(struct cache* cach) {
|
||||
if(cach->L2 == UNKNOWN) {
|
||||
char* string = malloc(sizeof(char)*5);
|
||||
snprintf(string,5,STRING_NONE);
|
||||
return string;
|
||||
}
|
||||
else {
|
||||
//Max 4 digits and 2 for 'KB'
|
||||
int size = (4+2+1);
|
||||
char* string = malloc(sizeof(char)*size);
|
||||
snprintf(string,size,"%d"STRING_KILOBYTES,cach->L2/1024);
|
||||
return string;
|
||||
}
|
||||
}
|
||||
|
||||
char* getString_L3(struct cache* cach) {
|
||||
if(cach->L3 == UNKNOWN) {
|
||||
char* string = malloc(sizeof(char)*5);
|
||||
snprintf(string,5,STRING_NONE);
|
||||
return string;
|
||||
}
|
||||
else {
|
||||
//Max 4 digits and 2 for 'KB'
|
||||
int size = (4+2+1);
|
||||
char* string = malloc(sizeof(char)*size);
|
||||
snprintf(string,size,"%d"STRING_KILOBYTES,cach->L3/1024);
|
||||
return string;
|
||||
}
|
||||
}
|
||||
|
||||
char* getString_MaxFrequency(struct frequency* freq) {
|
||||
//Max 3 digits and 3 for '(M/G)Hz' plus 1 for '\0'
|
||||
unsigned int size = (4+3+1);
|
||||
assert(strlen(STRING_UNKNOWN)+1 <= size);
|
||||
char* string = malloc(sizeof(char)*size);
|
||||
if(freq->max == UNKNOWN)
|
||||
snprintf(string,strlen(STRING_UNKNOWN)+1,STRING_UNKNOWN);
|
||||
else if(freq->max >= 1000000000)
|
||||
snprintf(string,size,"%.2f"STRING_GIGAHERZ,(float)(freq->max)/1000000000);
|
||||
else
|
||||
snprintf(string,size,"%.2f"STRING_MEGAHERZ,(float)(freq->max)/1000000);
|
||||
return string;
|
||||
}
|
||||
|
||||
/*** CREATES AND FREES ***/
|
||||
|
||||
struct cache* new_cache() {
|
||||
struct cache* cach = malloc(sizeof(struct cache));
|
||||
cach->L1i = getCache(_PATH_CACHE_L1i);
|
||||
cach->L1d = getCache(_PATH_CACHE_L1d);
|
||||
cach->L2 = getCache(_PATH_CACHE_L2);
|
||||
cach->L3 = getCache(_PATH_CACHE_L3);
|
||||
return cach;
|
||||
}
|
||||
|
||||
struct frequency* new_frequency() {
|
||||
struct frequency* freq = malloc(sizeof(struct frequency));
|
||||
freq->max = getFrequencyFromFile(_PATH_FREQUENCY_MAX);
|
||||
freq->min = getFrequencyFromFile(_PATH_FREQUENCY_MIN);
|
||||
return freq;
|
||||
}
|
||||
|
||||
void freeCache(struct cache* cach) {
|
||||
free(cach);
|
||||
}
|
||||
|
||||
void freeFrequency(struct frequency* freq) {
|
||||
free(freq);
|
||||
}
|
||||
|
||||
/*** DEBUGING ***/
|
||||
|
||||
void debugCache(struct cache* cach) {
|
||||
printf("L1i=%dB\n",cach->L1i);
|
||||
printf("L1d=%dB\n",cach->L1d);
|
||||
printf("L2=%dB\n",cach->L2);
|
||||
printf("L3=%dB\n",cach->L3);
|
||||
}
|
||||
|
||||
void debugFrequency(struct frequency* freq) {
|
||||
printf("max f=%ldMhz\n",freq->max);
|
||||
printf("min f=%ldMhz\n",freq->min);
|
||||
}
|
||||
53
src/udev.h
Normal file
53
src/udev.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef __UDEV__
|
||||
#define __UDEV__
|
||||
|
||||
/*** PATHS ***/
|
||||
|
||||
#define _PATH_SYS_SYSTEM "/sys/devices/system"
|
||||
#define _PATH_SYS_CPU _PATH_SYS_SYSTEM"/cpu"
|
||||
#define _PATH_ONE_CPU _PATH_SYS_CPU"/cpu0"
|
||||
|
||||
#define _PATH_FREQUENCY _PATH_ONE_CPU"/cpufreq"
|
||||
#define _PATH_FREQUENCY_MAX _PATH_FREQUENCY"/cpuinfo_max_freq"
|
||||
#define _PATH_FREQUENCY_MIN _PATH_FREQUENCY"/cpuinfo_min_freq"
|
||||
|
||||
#define _PATH_CPU_CACHE _PATH_ONE_CPU"/cache"
|
||||
#define _PATH_CACHE_L1d _PATH_CPU_CACHE"/index0/size"
|
||||
#define _PATH_CACHE_L1i _PATH_CPU_CACHE"/index1/size"
|
||||
#define _PATH_CACHE_L2 _PATH_CPU_CACHE"/index2/size"
|
||||
#define _PATH_CACHE_L3 _PATH_CPU_CACHE"/index3/size"
|
||||
|
||||
/*** CONSTANTS ***/
|
||||
|
||||
#define UNKNOWN -1
|
||||
#define DEFAULT_FILE_SIZE 4096
|
||||
#define DEFAULT_BLOCK_SIZE 128
|
||||
|
||||
/*** STRINGS ***/
|
||||
#define STRING_UNKNOWN "Unknown"
|
||||
#define STRING_NONE "None"
|
||||
#define STRING_MEGAHERZ "MHz"
|
||||
#define STRING_GIGAHERZ "GHz"
|
||||
#define STRING_KILOBYTES "KB"
|
||||
|
||||
/*** STRUCTS ***/
|
||||
|
||||
struct cache;
|
||||
struct frequency;
|
||||
|
||||
/*** FUNCTIONS ***/
|
||||
|
||||
struct cache* new_cache();
|
||||
void debugCache(struct cache* cach);
|
||||
void freeCache(struct cache* cach);
|
||||
char* getString_L1(struct cache* cach);
|
||||
char* getString_L2(struct cache* cach);
|
||||
char* getString_L3(struct cache* cach);
|
||||
|
||||
struct frequency* new_frequency();
|
||||
void debugFrequency(struct frequency* freq);
|
||||
void freeFrequency(struct frequency* freq);
|
||||
char* getString_MaxFrequency(struct frequency* freq);
|
||||
long getFrequency(struct frequency* freq);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user