Divide source code from other stuff

This commit is contained in:
Dr-Noob
2018-06-23 13:04:42 +02:00
parent 3ded41ce44
commit 9f55672aa2
17 changed files with 3 additions and 2 deletions

93
src/args.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,6 @@
#ifndef __GLOBAL__
#define __GLOBAL__
void printError(const char *fmt, ...);
#endif

105
src/main.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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