[v0.8][ARM] Building support in ARM

This commit is contained in:
Dr-Noob
2020-11-05 09:28:41 +01:00
parent 5cc9038f3d
commit 1fad4fd10b
25 changed files with 442 additions and 172 deletions

253
src/common/args.c Normal file
View File

@@ -0,0 +1,253 @@
#include <getopt.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "args.h"
#include "global.h"
#define COLOR_STR_INTEL "intel"
#define COLOR_STR_AMD "amd"
static const char *SYTLES_STR_LIST[] = {
[STYLE_EMPTY] = NULL,
[STYLE_FANCY] = "fancy",
[STYLE_RETRO] = "retro",
[STYLE_LEGACY] = "legacy",
[STYLE_INVALID] = NULL
};
enum {
ARG_CHAR_STYLE,
ARG_CHAR_COLOR,
ARG_CHAR_HELP,
ARG_CHAR_LEVELS,
ARG_CHAR_VERBOSE,
ARG_CHAR_VERSION
};
struct args_struct {
bool levels_flag;
bool help_flag;
bool verbose_flag;
bool version_flag;
STYLE style;
struct colors* colors;
};
static struct args_struct args;
STYLE get_style() {
return args.style;
}
struct colors* get_colors() {
return args.colors;
}
bool show_help() {
return args.help_flag;
}
bool show_version() {
return args.version_flag;
}
bool show_levels() {
return args.levels_flag;
}
bool verbose_enabled() {
return args.verbose_flag;
}
STYLE parse_style(char* style) {
uint8_t i = 0;
uint8_t styles_count = sizeof(SYTLES_STR_LIST) / sizeof(SYTLES_STR_LIST[0]);
while(i != styles_count && (SYTLES_STR_LIST[i] == NULL || strcmp(SYTLES_STR_LIST[i], style) != 0))
i++;
if(i == styles_count)
return STYLE_INVALID;
return i;
}
void free_colors_struct(struct colors* cs) {
free(cs->c1);
free(cs->c2);
free(cs->c3);
free(cs->c4);
free(cs);
}
bool parse_color(char* optarg, struct colors** cs) {
*cs = malloc(sizeof(struct colors));
(*cs)->c1 = malloc(sizeof(struct color));
(*cs)->c2 = malloc(sizeof(struct color));
(*cs)->c3 = malloc(sizeof(struct color));
(*cs)->c4 = malloc(sizeof(struct color));
struct color** c1 = &((*cs)->c1);
struct color** c2 = &((*cs)->c2);
struct color** c3 = &((*cs)->c3);
struct color** c4 = &((*cs)->c4);
int32_t ret;
char* str_to_parse = NULL;
bool free_ptr;
if(strcmp(optarg, COLOR_STR_INTEL) == 0) {
str_to_parse = malloc(sizeof(char) * 46);
strcpy(str_to_parse, COLOR_DEFAULT_INTEL);
free_ptr = true;
}
else if(strcmp(optarg, COLOR_STR_AMD) == 0) {
str_to_parse = malloc(sizeof(char) * 44);
strcpy(str_to_parse, COLOR_DEFAULT_AMD);
free_ptr = true;
}
else {
str_to_parse = optarg;
free_ptr = false;
}
ret = sscanf(str_to_parse, "%d,%d,%d:%d,%d,%d:%d,%d,%d:%d,%d,%d",
&(*c1)->R, &(*c1)->G, &(*c1)->B,
&(*c2)->R, &(*c2)->G, &(*c2)->B,
&(*c3)->R, &(*c3)->G, &(*c3)->B,
&(*c4)->R, &(*c4)->G, &(*c4)->B);
if(ret != 12) {
printErr("Expected to read 12 values for color but read %d", ret);
return false;
}
//TODO: Refactor c1->R c2->R ... to c[i]->R
if((*c1)->R < 0 || (*c1)->R > 255) {
printErr("Red in color 1 is invalid. Must be in range (0, 255)");
return false;
}
if((*c1)->G < 0 || (*c1)->G > 255) {
printErr("Green in color 1 is invalid. Must be in range (0, 255)");
return false;
}
if((*c1)->B < 0 || (*c1)->B > 255) {
printErr("Blue in color 1 is invalid. Must be in range (0, 255)");
return false;
}
if((*c2)->R < 0 || (*c2)->R > 255) {
printErr("Red in color 2 is invalid. Must be in range (0, 255)");
return false;
}
if((*c2)->G < 0 || (*c2)->G > 255) {
printErr("Green in color 2 is invalid. Must be in range (0, 255)");
return false;
}
if((*c2)->B < 0 || (*c2)->B > 255) {
printErr("Blue in color 2 is invalid. Must be in range (0, 255)");
return false;
}
if(free_ptr) free (str_to_parse);
return true;
}
bool parse_args(int argc, char* argv[]) {
int c;
int option_index = 0;
opterr = 0;
bool color_flag = false;
args.levels_flag = false;
args.verbose_flag = false;
args.help_flag = false;
args.style = STYLE_EMPTY;
args.colors = NULL;
static struct option long_options[] = {
{"style", required_argument, 0, ARG_CHAR_STYLE },
{"color", required_argument, 0, ARG_CHAR_COLOR },
{"help", no_argument, 0, ARG_CHAR_HELP },
{"levels", no_argument, 0, ARG_CHAR_LEVELS },
{"verbose", no_argument, 0, ARG_CHAR_VERBOSE },
{"version", no_argument, 0, ARG_CHAR_VERSION },
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "", long_options, &option_index);
while (c != -1) {
if(c == ARG_CHAR_COLOR) {
if(color_flag) {
printErr("Color option specified more than once");
return false;
}
color_flag = true;
if(!parse_color(optarg, &args.colors)) {
printErr("Color parsing failed");
return false;
}
}
else if(c == ARG_CHAR_STYLE) {
if(args.style != STYLE_EMPTY) {
printErr("Style option specified more than once");
return false;
}
args.style = parse_style(optarg);
if(args.style == STYLE_INVALID) {
printErr("Invalid style '%s'",optarg);
return false;
}
}
else if(c == ARG_CHAR_HELP) {
if(args.help_flag) {
printErr("Help option specified more than once");
return false;
}
args.help_flag = true;
}
else if(c == ARG_CHAR_VERBOSE) {
if(args.verbose_flag) {
printErr("Verbose option specified more than once");
return false;
}
args.verbose_flag = true;
}
else if(c == ARG_CHAR_LEVELS) {
if(args.levels_flag) {
printErr("Levels option specified more than once");
return false;
}
args.levels_flag = true;
}
else if (c == ARG_CHAR_VERSION) {
if(args.version_flag) {
printErr("Version option specified more than once");
return false;
}
args.version_flag = true;
}
else if(c == '?') {
printWarn("Invalid options");
args.help_flag = true;
break;
}
else
printBug("Bug at line number %d in file %s", __LINE__, __FILE__);
option_index = 0;
c = getopt_long(argc, argv,"",long_options, &option_index);
}
if (optind < argc) {
printWarn("Invalid options");
args.help_flag = true;
}
if((args.help_flag + args.version_flag + color_flag) > 1) {
printWarn("You should specify just one option");
args.help_flag = true;
}
return true;
}

40
src/common/args.h Normal file
View File

@@ -0,0 +1,40 @@
#ifndef __ARGS__
#define __ARGS__
#include <stdbool.h>
#include <stdint.h>
struct color {
int32_t R;
int32_t G;
int32_t B;
};
struct colors {
struct color* c1;
struct color* c2;
struct color* c3;
struct color* c4;
};
enum {
STYLE_EMPTY,
STYLE_FANCY,
STYLE_WILD,
STYLE_RETRO,
STYLE_LEGACY,
STYLE_INVALID
};
#include "printer.h"
bool parse_args(int argc, char* argv[]);
bool show_help();
bool show_levels();
bool show_version();
bool verbose_enabled();
void free_colors_struct(struct colors* cs);
struct colors* get_colors();
STYLE get_style();
#endif

70
src/common/ascii.h Normal file
View File

@@ -0,0 +1,70 @@
#ifndef __ASCII__
#define __ASCII__
#define NUMBER_OF_LINES 19
#define LINE_SIZE 62
#define AMD_ASCII \
" \
\
\
\
\
\
@@@@ @@@ @@@ @@@@@@@@ ############ \
@@@@@@ @@@@@ @@@@ @@@ @@@@ ########## \
@@@ @@@ @@@@@@@@@@@@@ @@@ @@ # #### \
@@@ @@@ @@@ @@@ @@@ @@@ @@@ ### #### \
@@@@@@@@@@@@ @@@ @@@ @@@ @@@ #### ## ### \
@@@ @@@ @@@ @@@ @@@@@@@@@ ######## ## \
\
\
\
\
\
\
"
#define INTEL_ASCII \
" ################ \
####### ####### \
#### #### \
### #### \
### ### \
### ### \
# ### ### ### \
## ### ######### ###### ###### ### ### \
## ### ### ### ### #### #### ### ### \
## ### ### ### ### ### ### ### ### \
## ### ### ### ### ########## ### #### \
## ### ### ### ### ### ### ##### \
## ## ### ### ##### ######### ## ### \
### \
### \
#### #### \
##### ########## \
########## ################ \
############################### "
#define UNKNOWN_ASCII \
" \
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
\
"
#endif

95
src/common/cpu.h Normal file
View File

@@ -0,0 +1,95 @@
#ifndef __CPU__
#define __CPU__
#include <stdint.h>
#include <stdbool.h>
enum {
CPU_VENDOR_INTEL,
CPU_VENDOR_AMD,
CPU_VENDOR_UNKNOWN,
CPU_VENDOR_INVALID
};
enum {
HV_VENDOR_KVM,
HV_VENDOR_QEMU,
HV_VENDOR_HYPERV,
HV_VENDOR_VMWARE,
HV_VENDOR_XEN,
HV_VENDOR_PARALLELS,
HV_VENDOR_INVALID
};
#define UNKNOWN_FREQ -1
#define CPU_NAME_MAX_LENGTH 64
typedef int32_t VENDOR;
struct frequency;
struct hypervisor {
bool present;
char* hv_name;
VENDOR hv_vendor;
};
struct cpuInfo {
bool AVX;
bool AVX2;
bool AVX512;
bool SSE;
bool SSE2;
bool SSE3;
bool SSSE3;
bool SSE4a;
bool SSE4_1;
bool SSE4_2;
bool FMA3;
bool FMA4;
bool AES;
bool SHA;
VENDOR cpu_vendor;
char* cpu_name;
// Max cpuids levels
uint32_t maxLevels;
// Max cpuids extended levels
uint32_t maxExtendedLevels;
struct uarch* arch;
struct hypervisor* hv;
};
struct cach {
int32_t size;
uint8_t num_caches;
bool exists;
// plenty of more properties to include in the future...
};
struct cache {
struct cach* L1i;
struct cach* L1d;
struct cach* L2;
struct cach* L3;
struct cach** cach_arr;
uint8_t max_cache_level;
};
struct topology {
int64_t total_cores;
uint32_t physical_cores;
uint32_t logical_cores;
uint32_t smt_available; // Number of SMT that is currently enabled
uint32_t smt_supported; // Number of SMT that CPU supports (equal to smt_available if SMT is enabled)
uint32_t sockets;
struct cache* cach;
#ifdef _ARCH_X86
struct apic* apic;
#endif
};
#endif

62
src/common/global.c Normal file
View File

@@ -0,0 +1,62 @@
#include <stdarg.h>
#include <stdio.h>
#include "global.h"
#ifdef _WIN32
#define RED ""
#define BOLD ""
#define RESET ""
#else
#define RED "\x1b[31;1m"
#define BOLD "\x1b[;1m"
#define RESET "\x1b[0m"
#endif
enum {
LOG_LEVEL_NORMAL,
LOG_LEVEL_VERBOSE
};
int LOG_LEVEL;
void printWarn(const char *fmt, ...) {
if(LOG_LEVEL == LOG_LEVEL_VERBOSE) {
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,BOLD "[WARNING]: "RESET "%s\n",buffer);
}
}
void printErr(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);
}
void printBug(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);
fprintf(stderr,"Please, create a new issue with this error message and your CPU model in https://github.com/Dr-Noob/cpufetch/issues\n");
}
void set_log_level(bool verbose) {
if(verbose) LOG_LEVEL = LOG_LEVEL_VERBOSE;
else LOG_LEVEL = LOG_LEVEL_NORMAL;
}

11
src/common/global.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef __GLOBAL__
#define __GLOBAL__
#include <stdbool.h>
void set_log_level(bool verbose);
void printWarn(const char *fmt, ...);
void printErr(const char *fmt, ...);
void printBug(const char *fmt, ...);
#endif

92
src/common/main.c Normal file
View File

@@ -0,0 +1,92 @@
#include <stdio.h>
#include <stdlib.h>
#include "args.h"
#include "printer.h"
#include "global.h"
#ifdef _ARCH_X86
static const char* ARCH_STR = "x86_64 build";
#include "../x86/cpuid.h"
#else
static const char* ARCH_STR = "ARM build";
#include "../arm/cpuid.h"
#endif
static const char* VERSION = "0.8";
void print_help(char *argv[]) {
printf("Usage: %s [--version] [--help] [--levels] [--style \"fancy\"|\"retro\"|\"legacy\"] [--color \"intel\"|\"amd\"|'R,G,B:R,G,B:R,G,B:R,G,B']\n\n\
Options: \n\
--color Set the color scheme. By default, cpufetch uses the system color scheme. This option \n\
lets the user use different colors to print the CPU art: \n\
* \"intel\": Use intel default color scheme \n\
* \"amd\": Use amd default color scheme \n\
* custom: If color do not match \"intel\" or \"amd\", a custom scheme can be specified: \n\
4 colors must be given in RGB with the format: R,G,B:R,G,B:... \n\
These colors correspond to CPU art color (2 colors) and for the text colors (following 2) \n\
For example: --color 239,90,45:210,200,200:100,200,45:0,200,200 \n\n\
--style Set the style of CPU art: \n\
* \"fancy\": Default style \n\
* \"retro\": Old cpufetch style \n\
* \"legacy\": Fallback style for terminals that does not support colors \n\n\
--levels Prints CPU model and cpuid levels (debug purposes)\n\n\
--verbose Prints extra information (if available) about how cpufetch tried fetching information\n\n\
--help Prints this help and exit\n\n\
--version Prints cpufetch version and exit\n\n\
\n\
NOTES: \n\
- Bugs or improvements should be submitted to: github.com/Dr-Noob/cpufetch/issues \n\
- Peak performance information is NOT accurate. cpufetch computes peak performance using the max \n\
frequency. However, to properly compute peak performance, you need to know the frequency of the \n\
CPU running AVX code, which is not be fetched by cpufetch since it depends on each specific CPU. \n",
argv[0]);
}
void print_version() {
printf("cpufetch v%s (%s)\n",VERSION, ARCH_STR);
}
int main(int argc, char* argv[]) {
if(!parse_args(argc,argv))
return EXIT_FAILURE;
if(show_help()) {
print_help(argv);
return EXIT_SUCCESS;
}
if(show_version()) {
print_version();
return EXIT_SUCCESS;
}
set_log_level(verbose_enabled());
struct cpuInfo* cpu = get_cpu_info();
if(cpu == NULL)
return EXIT_FAILURE;
if(show_levels()) {
print_version();
print_levels(cpu);
return EXIT_SUCCESS;
}
struct frequency* freq = get_frequency_info(cpu);
if(freq == NULL)
return EXIT_FAILURE;
struct cache* cach = get_cache_info(cpu);
if(cach == NULL)
return EXIT_FAILURE;
struct topology* topo = get_topology_info(cpu, cach);
if(topo == NULL)
return EXIT_FAILURE;
if(print_cpufetch(cpu, cach, freq, topo, get_style(), get_colors()))
return EXIT_SUCCESS;
else
return EXIT_FAILURE;
}

457
src/common/printer.c Normal file
View File

@@ -0,0 +1,457 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include "printer.h"
#include "ascii.h"
#include "../common/global.h"
#ifdef _ARCH_X86
#include "../x86/uarch.h"
#include "../x86/cpuid.h"
#else
#include "../arm/cpuid.h"
#include "../arm/uarch.h"
#endif
#ifdef _WIN32
#define NOMINMAX
#include <Windows.h>
#endif
#define COL_NONE ""
#define COL_INTEL_FANCY_1 "\x1b[46;1m"
#define COL_INTEL_FANCY_2 "\x1b[47;1m"
#define COL_INTEL_FANCY_3 "\x1b[36;1m"
#define COL_INTEL_FANCY_4 "\x1b[37;1m"
#define COL_INTEL_RETRO_1 "\x1b[36;1m"
#define COL_INTEL_RETRO_2 "\x1b[37;1m"
#define COL_AMD_FANCY_1 "\x1b[47;1m"
#define COL_AMD_FANCY_2 "\x1b[42;1m"
#define COL_AMD_FANCY_3 "\x1b[37;1m"
#define COL_AMD_FANCY_4 "\x1b[32;1m"
#define COL_AMD_RETRO_1 "\x1b[37;1m"
#define COL_AMD_RETRO_2 "\x1b[32;1m"
#define COL_UNKNOWN_FANCY_1 "\x1b[47;1m"
#define COL_UNKNOWN_FANCY_2 "\x1b[47;1m"
#define COL_UNKNOWN_FANCY_3 "\x1b[37;1m"
#define COL_UNKNOWN_FANCY_4 "\x1b[31;1m"
#define COL_UNKNOWN_RETRO "\x1b[32;0m"
#define RESET "\x1b[m"
enum {
ATTRIBUTE_NAME,
ATTRIBUTE_HYPERVISOR,
ATTRIBUTE_UARCH,
ATTRIBUTE_TECHNOLOGY,
ATTRIBUTE_FREQUENCY,
ATTRIBUTE_SOCKETS,
ATTRIBUTE_NCORES,
ATTRIBUTE_NCORES_DUAL,
ATTRIBUTE_AVX,
ATTRIBUTE_FMA,
ATTRIBUTE_L1i,
ATTRIBUTE_L1d,
ATTRIBUTE_L2,
ATTRIBUTE_L3,
ATTRIBUTE_PEAK
};
static const char* ATTRIBUTE_FIELDS [] = {
"Name:",
"Hypervisor:",
"Microarchitecture:",
"Technology:",
"Max Frequency:",
"Sockets:",
"Cores:",
"Cores (Total):",
"AVX:",
"FMA:",
"L1i Size:",
"L1d Size:",
"L2 Size:",
"L3 Size:",
"Peak Performance:",
};
static const int ATTRIBUTE_LIST[] = {
ATTRIBUTE_NAME,
ATTRIBUTE_HYPERVISOR,
ATTRIBUTE_UARCH,
ATTRIBUTE_TECHNOLOGY,
ATTRIBUTE_FREQUENCY,
ATTRIBUTE_SOCKETS,
ATTRIBUTE_NCORES,
ATTRIBUTE_NCORES_DUAL,
ATTRIBUTE_AVX,
ATTRIBUTE_FMA,
ATTRIBUTE_L1i,
ATTRIBUTE_L1d,
ATTRIBUTE_L2,
ATTRIBUTE_L3,
ATTRIBUTE_PEAK
};
struct ascii {
char art[NUMBER_OF_LINES][LINE_SIZE];
char color1_ascii[100];
char color2_ascii[100];
char color1_text[100];
char color2_text[100];
char ascii_chars[2];
char reset[100];
char** attributes;
uint32_t max_attributes;
uint32_t n_attributes_set;
VENDOR vendor;
STYLE style;
};
void setAttribute(struct ascii* art, int type, char* value) {
art->attributes[type] = value;
art->n_attributes_set++;
}
char* rgb_to_ansi(struct color* c, bool background, bool bold) {
char* str = malloc(sizeof(char) * 100);
if(background) {
snprintf(str, 44, "\x1b[48;2;%.3d;%.3d;%.3dm", c->R, c->G, c->B);
}
else {
if(bold)
snprintf(str, 48, "\x1b[1m\x1b[38;2;%.3d;%.3d;%.3dm", c->R, c->G, c->B);
else
snprintf(str, 44, "\x1b[38;2;%.3d;%.3d;%.3dm", c->R, c->G, c->B);
}
return str;
}
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;
strcpy(art->reset,RESET);
if(art->vendor == CPU_VENDOR_INTEL) {
COL_FANCY_1 = COL_INTEL_FANCY_1;
COL_FANCY_2 = COL_INTEL_FANCY_2;
COL_FANCY_3 = COL_INTEL_FANCY_3;
COL_FANCY_4 = COL_INTEL_FANCY_4;
COL_RETRO_1 = COL_INTEL_RETRO_1;
COL_RETRO_2 = COL_INTEL_RETRO_2;
COL_RETRO_3 = COL_INTEL_RETRO_1;
COL_RETRO_4 = COL_INTEL_RETRO_2;
art->ascii_chars[0] = '#';
}
else if(art->vendor == CPU_VENDOR_AMD) {
COL_FANCY_1 = COL_AMD_FANCY_1;
COL_FANCY_2 = COL_AMD_FANCY_2;
COL_FANCY_3 = COL_AMD_FANCY_3;
COL_FANCY_4 = COL_AMD_FANCY_4;
COL_RETRO_1 = COL_AMD_RETRO_1;
COL_RETRO_2 = COL_AMD_RETRO_2;
COL_RETRO_3 = COL_AMD_RETRO_1;
COL_RETRO_4 = COL_AMD_RETRO_2;
art->ascii_chars[0] = '@';
}
else {
COL_FANCY_1 = COL_UNKNOWN_FANCY_1;
COL_FANCY_2 = COL_UNKNOWN_FANCY_2;
COL_FANCY_3 = COL_UNKNOWN_FANCY_3;
COL_FANCY_4 = COL_UNKNOWN_FANCY_4;
COL_RETRO_1 = COL_UNKNOWN_RETRO;
COL_RETRO_2 = COL_UNKNOWN_RETRO;
COL_RETRO_3 = COL_UNKNOWN_RETRO;
COL_RETRO_4 = COL_UNKNOWN_RETRO;
art->ascii_chars[0] = '#';
}
art->ascii_chars[1] = '#';
#ifdef _WIN32
HANDLE std_handle = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD console_mode;
// Attempt to enable the VT100-processing flag
GetConsoleMode(std_handle, &console_mode);
SetConsoleMode(std_handle, console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
// Get the console mode flag again, to see if it successfully enabled it
GetConsoleMode(std_handle, &console_mode);
#endif
if(style == STYLE_EMPTY) {
#ifdef _WIN32
// Use fancy style if VT100-processing is enabled,
// or legacy style in other case
art->style = (console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) ? STYLE_FANCY : STYLE_LEGACY;
#else
art->style = STYLE_FANCY;
#endif
}
else {
art->style = style;
}
switch(art->style) {
case STYLE_LEGACY:
strcpy(art->color1_ascii,COL_NONE);
strcpy(art->color2_ascii,COL_NONE);
strcpy(art->color1_text,COL_NONE);
strcpy(art->color2_text,COL_NONE);
art->reset[0] = '\0';
break;
case STYLE_FANCY:
if(cs != NULL) {
COL_FANCY_1 = rgb_to_ansi(cs->c1, true, true);
COL_FANCY_2 = rgb_to_ansi(cs->c2, true, true);
COL_FANCY_3 = rgb_to_ansi(cs->c3, false, true);
COL_FANCY_4 = rgb_to_ansi(cs->c4, false, true);
}
art->ascii_chars[0] = ' ';
art->ascii_chars[1] = ' ';
strcpy(art->color1_ascii,COL_FANCY_1);
strcpy(art->color2_ascii,COL_FANCY_2);
strcpy(art->color1_text,COL_FANCY_3);
strcpy(art->color2_text,COL_FANCY_4);
if(cs != NULL) {
free(COL_FANCY_1);
free(COL_FANCY_2);
free(COL_FANCY_3);
free(COL_FANCY_4);
}
break;
case STYLE_RETRO:
if(cs != NULL) {
COL_RETRO_1 = rgb_to_ansi(cs->c1, false, true);
COL_RETRO_2 = rgb_to_ansi(cs->c2, false, true);
COL_RETRO_3 = rgb_to_ansi(cs->c3, false, true);
COL_RETRO_4 = rgb_to_ansi(cs->c4, false, true);
}
strcpy(art->color1_ascii,COL_RETRO_1);
strcpy(art->color2_ascii,COL_RETRO_2);
strcpy(art->color1_text,COL_RETRO_3);
strcpy(art->color2_text,COL_RETRO_4);
if(cs != NULL) {
free(COL_RETRO_1);
free(COL_RETRO_2);
free(COL_RETRO_3);
free(COL_RETRO_4);
}
break;
case STYLE_INVALID:
default:
printBug("Found invalid style (%d)", art->style);
return NULL;
}
char tmp[NUMBER_OF_LINES*LINE_SIZE];
if(art->vendor == CPU_VENDOR_INTEL)
strcpy(tmp, INTEL_ASCII);
else if(art->vendor == CPU_VENDOR_AMD)
strcpy(tmp, AMD_ASCII);
else
strcpy(tmp, UNKNOWN_ASCII);
for(int i=0; i < NUMBER_OF_LINES; i++)
strncpy(art->art[i], tmp + i*LINE_SIZE, LINE_SIZE);
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;
}
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;
printf("\n");
for(uint32_t n=0;n<NUMBER_OF_LINES;n++) {
for(int i=0;i<LINE_SIZE;i++) {
if(flag) {
if(art->art[n][i] == ' ') {
flag = false;
printf("%s%c%s", art->color2_ascii, art->ascii_chars[1], art->reset);
}
else {
printf("%s%c%s", art->color1_ascii, art->ascii_chars[0], art->reset);
}
}
else {
if(art->art[n][i] != ' ' && art->art[n][i] != '\0') {
flag = true;
printf("%c",' ');
}
else
printf("%c",' ');
}
}
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");
}
void print_ascii_amd(struct ascii* art, uint32_t la) {
int attr_to_print = -1;
uint32_t space_right;
uint32_t space_up = (NUMBER_OF_LINES - art->n_attributes_set)/2;
uint32_t space_down = NUMBER_OF_LINES - art->n_attributes_set - space_up;
printf("\n");
for(uint32_t n=0;n<NUMBER_OF_LINES;n++) {
for(int i=0;i<LINE_SIZE;i++) {
if(art->art[n][i] == '@')
printf("%s%c%s", art->color1_ascii, art->ascii_chars[0], art->reset);
else if(art->art[n][i] == '#')
printf("%s%c%s", art->color2_ascii, art->ascii_chars[1], 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
print_ascii_amd(art, longest_attribute);
}
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;
char* cpu_name = get_str_cpu_name(cpu);
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);
char* avx = get_str_avx(cpu);
char* fma = get_str_fma(cpu);
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);
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_AVX,avx);
setAttribute(art,ATTRIBUTE_FMA,fma);
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_DUAL, n_cores_dual);
}
if(l3 != NULL) {
setAttribute(art,ATTRIBUTE_L3,l3);
}
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(max_frequency);
free(sockets);
free(n_cores);
free(n_cores_dual);
free(avx);
free(fma);
free(l1i);
free(l1d);
free(l2);
free(l3);
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;
}
void print_levels(struct cpuInfo* cpu) {
printf("%s\n", cpu->cpu_name);
printf("- Max standart level: 0x%.8X\n", cpu->maxLevels);
printf("- Max extended level: 0x%.8X\n", cpu->maxExtendedLevels);
free_cpuinfo_struct(cpu);
}

20
src/common/printer.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef __PRINTER__
#define __PRINTER__
typedef int STYLE;
#include "args.h"
#ifdef _ARCH_X86
#include "../x86/cpuid.h"
#else
#include "../arm/cpuid.h"
#endif
#define COLOR_DEFAULT_INTEL "15,125,194:230,230,230:40,150,220:230,230,230"
#define COLOR_DEFAULT_AMD "250,250,250:0,154,102:250,250,250:0,154,102"
void print_levels(struct cpuInfo* cpu);
bool print_cpufetch(struct cpuInfo* cpu, struct cache* cach, struct frequency* freq, struct topology* topo, STYLE s, struct colors* cs);
#endif