diff --git a/.gitignore b/.gitignore index 353977d1..a015fb3f 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,10 @@ wally-pipelined/linux-testgen/nohup* wally-pipelined/linux-testgen/x* !wally-pipelined/linux-testgen/linux-testvectors/tvCopier.py !wally-pipelined/linux-testgen/linux-testvectors/tvLinker.sh +!wally-pipelined/linux-testgen/linux-testvectors/tvUnlinker.sh +!wally-pipelined/linux-testgen/linux-testvectors/intermediate-outputs +wally-pipelined/linux-testgen/linux-testvectors/intermediate-outputs/* +!wally-pipelined/linux-testgen/linux-testvectors/intermediate-outputs/git_create_dir.txt wally-pipelined/linux-testgen/buildroot/ wally-pipelined/linux-testgen/buildroot-image-output wally-pipelined/linux-testgen/buildroot-config-src/main.config.old diff --git a/riscv-coremark/coremark/README.md b/riscv-coremark/coremark/README.md index 26636f48..16b54b7b 100644 --- a/riscv-coremark/coremark/README.md +++ b/riscv-coremark/coremark/README.md @@ -3,6 +3,8 @@ CoreMark's primary goals are simplicity and providing a method for testing only a processor's core features. For more information about EEMBC's comprehensive embedded benchmark suites, please see www.eembc.org. +For a more compute-intensive version of CoreMark that uses larger datasets and execution loops taken from common applications, please check out EEMBC's [CoreMark-PRO](https://www.github.com/eembc/coremark-pro) benchmark, also on GitHub. + # Building and Running To build and run the benchmark, type @@ -83,7 +85,9 @@ Use `XCFLAGS=-DMULTITHREAD=N` where N is number of threads to run in parallel. S % make XCFLAGS="-DMULTITHREAD=4 -DUSE_PTHREAD" ~~~ -Above will compile the benchmark for execution on 4 cores, using POSIX Threads API. +The above will compile the benchmark for execution on 4 cores, using POSIX Threads API. + +Note: linking may fail on the previous command if your linker does not automatically add the `pthread` library. If you encounter `undefined reference` errors, please modify the `core_portme.mak` file for your platform, (e.g. `linux/core_portme.mak`) and add `-lpthread` to the `LFLAGS_END` parameter. # Run Parameters for the Benchmark Executable CoreMark's executable takes several parameters as follows (but only if `main()` accepts arguments): @@ -109,7 +113,7 @@ The default for such a target when testing different configurations could be: # Submitting Results -CoreMark results can be submitted on the web. Open a web browser and go to https://www.eembc.org/coremark/login.php?url=enter_score.php. After registering an account you may enter a score. +CoreMark results can be submitted on the web. Open a web browser and go to the [submission page](https://www.eembc.org/coremark/submit.php). After registering an account you may enter a score. # Run Rules What is and is not allowed. diff --git a/riscv-coremark/coremark/barebones/core_portme.c b/riscv-coremark/coremark/barebones/core_portme.c old mode 100755 new mode 100644 index 33646819..18967676 --- a/riscv-coremark/coremark/barebones/core_portme.c +++ b/riscv-coremark/coremark/barebones/core_portme.c @@ -19,110 +19,135 @@ Original Author: Shay Gal-on #include "core_portme.h" #if VALIDATION_RUN - volatile ee_s32 seed1_volatile=0x3415; - volatile ee_s32 seed2_volatile=0x3415; - volatile ee_s32 seed3_volatile=0x66; +volatile ee_s32 seed1_volatile = 0x3415; +volatile ee_s32 seed2_volatile = 0x3415; +volatile ee_s32 seed3_volatile = 0x66; #endif #if PERFORMANCE_RUN - volatile ee_s32 seed1_volatile=0x0; - volatile ee_s32 seed2_volatile=0x0; - volatile ee_s32 seed3_volatile=0x66; +volatile ee_s32 seed1_volatile = 0x0; +volatile ee_s32 seed2_volatile = 0x0; +volatile ee_s32 seed3_volatile = 0x66; #endif #if PROFILE_RUN - volatile ee_s32 seed1_volatile=0x8; - volatile ee_s32 seed2_volatile=0x8; - volatile ee_s32 seed3_volatile=0x8; +volatile ee_s32 seed1_volatile = 0x8; +volatile ee_s32 seed2_volatile = 0x8; +volatile ee_s32 seed3_volatile = 0x8; #endif - volatile ee_s32 seed4_volatile=ITERATIONS; - volatile ee_s32 seed5_volatile=0; +volatile ee_s32 seed4_volatile = ITERATIONS; +volatile ee_s32 seed5_volatile = 0; /* Porting : Timing functions - How to capture time and convert to seconds must be ported to whatever is supported by the platform. - e.g. Read value from on board RTC, read value from cpu clock cycles performance counter etc. - Sample implementation for standard time.h and windows.h definitions included. + How to capture time and convert to seconds must be ported to whatever is + supported by the platform. e.g. Read value from on board RTC, read value from + cpu clock cycles performance counter etc. Sample implementation for standard + time.h and windows.h definitions included. */ -CORETIMETYPE barebones_clock() { - #error "You must implement a method to measure time in barebones_clock()! This function should return current time.\n" +CORETIMETYPE +barebones_clock() +{ +#error \ + "You must implement a method to measure time in barebones_clock()! This function should return current time.\n" } /* Define : TIMER_RES_DIVIDER - Divider to trade off timer resolution and total time that can be measured. + Divider to trade off timer resolution and total time that can be + measured. - Use lower values to increase resolution, but make sure that overflow does not occur. - If there are issues with the return value overflowing, increase this value. - */ -#define GETMYTIME(_t) (*_t=barebones_clock()) -#define MYTIMEDIFF(fin,ini) ((fin)-(ini)) -#define TIMER_RES_DIVIDER 1 + Use lower values to increase resolution, but make sure that overflow + does not occur. If there are issues with the return value overflowing, + increase this value. + */ +#define GETMYTIME(_t) (*_t = barebones_clock()) +#define MYTIMEDIFF(fin, ini) ((fin) - (ini)) +#define TIMER_RES_DIVIDER 1 #define SAMPLE_TIME_IMPLEMENTATION 1 -#define EE_TICKS_PER_SEC (CLOCKS_PER_SEC / TIMER_RES_DIVIDER) +#define EE_TICKS_PER_SEC (CLOCKS_PER_SEC / TIMER_RES_DIVIDER) /** Define Host specific (POSIX), or target specific global time variables. */ static CORETIMETYPE start_time_val, stop_time_val; /* Function : start_time - This function will be called right before starting the timed portion of the benchmark. + This function will be called right before starting the timed portion of + the benchmark. - Implementation may be capturing a system timer (as implemented in the example code) - or zeroing some system parameters - e.g. setting the cpu clocks cycles to 0. + Implementation may be capturing a system timer (as implemented in the + example code) or zeroing some system parameters - e.g. setting the cpu clocks + cycles to 0. */ -void start_time(void) { - GETMYTIME(&start_time_val ); +void +start_time(void) +{ + GETMYTIME(&start_time_val); } /* Function : stop_time - This function will be called right after ending the timed portion of the benchmark. + This function will be called right after ending the timed portion of the + benchmark. - Implementation may be capturing a system timer (as implemented in the example code) - or other system parameters - e.g. reading the current value of cpu cycles counter. + Implementation may be capturing a system timer (as implemented in the + example code) or other system parameters - e.g. reading the current value of + cpu cycles counter. */ -void stop_time(void) { - GETMYTIME(&stop_time_val ); +void +stop_time(void) +{ + GETMYTIME(&stop_time_val); } /* Function : get_time - Return an abstract "ticks" number that signifies time on the system. - - Actual value returned may be cpu cycles, milliseconds or any other value, - as long as it can be converted to seconds by . - This methodology is taken to accomodate any hardware or simulated platform. - The sample implementation returns millisecs by default, - and the resolution is controlled by + Return an abstract "ticks" number that signifies time on the system. + + Actual value returned may be cpu cycles, milliseconds or any other + value, as long as it can be converted to seconds by . This + methodology is taken to accomodate any hardware or simulated platform. The + sample implementation returns millisecs by default, and the resolution is + controlled by */ -CORE_TICKS get_time(void) { - CORE_TICKS elapsed=(CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val)); - return elapsed; +CORE_TICKS +get_time(void) +{ + CORE_TICKS elapsed + = (CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val)); + return elapsed; } /* Function : time_in_secs - Convert the value returned by get_time to seconds. + Convert the value returned by get_time to seconds. - The type is used to accomodate systems with no support for floating point. - Default implementation implemented by the EE_TICKS_PER_SEC macro above. + The type is used to accomodate systems with no support for + floating point. Default implementation implemented by the EE_TICKS_PER_SEC + macro above. */ -secs_ret time_in_secs(CORE_TICKS ticks) { - secs_ret retval=((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC; - return retval; +secs_ret +time_in_secs(CORE_TICKS ticks) +{ + secs_ret retval = ((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC; + return retval; } -ee_u32 default_num_contexts=1; +ee_u32 default_num_contexts = 1; /* Function : portable_init - Target specific initialization code - Test for some common mistakes. + Target specific initialization code + Test for some common mistakes. */ -void portable_init(core_portable *p, int *argc, char *argv[]) +void +portable_init(core_portable *p, int *argc, char *argv[]) { - #error "Call board initialization routines in portable init (if needed), in particular initialize UART!\n" - if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) { - ee_printf("ERROR! Please define ee_ptr_int to a type that holds a pointer!\n"); - } - if (sizeof(ee_u32) != 4) { - ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n"); - } - p->portable_id=1; +#error \ + "Call board initialization routines in portable init (if needed), in particular initialize UART!\n" + if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) + { + ee_printf( + "ERROR! Please define ee_ptr_int to a type that holds a " + "pointer!\n"); + } + if (sizeof(ee_u32) != 4) + { + ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n"); + } + p->portable_id = 1; } /* Function : portable_fini - Target specific final code + Target specific final code */ -void portable_fini(core_portable *p) +void +portable_fini(core_portable *p) { - p->portable_id=0; + p->portable_id = 0; } - - diff --git a/riscv-coremark/coremark/barebones/core_portme.h b/riscv-coremark/coremark/barebones/core_portme.h old mode 100755 new mode 100644 index 23a15588..55f643bf --- a/riscv-coremark/coremark/barebones/core_portme.h +++ b/riscv-coremark/coremark/barebones/core_portme.h @@ -16,178 +16,189 @@ limitations under the License. Original Author: Shay Gal-on */ /* Topic : Description - This file contains configuration constants required to execute on different platforms + This file contains configuration constants required to execute on + different platforms */ #ifndef CORE_PORTME_H #define CORE_PORTME_H /************************/ /* Data types and settings */ /************************/ -/* Configuration : HAS_FLOAT - Define to 1 if the platform supports floating point. +/* Configuration : HAS_FLOAT + Define to 1 if the platform supports floating point. */ -#ifndef HAS_FLOAT +#ifndef HAS_FLOAT #define HAS_FLOAT 1 #endif /* Configuration : HAS_TIME_H - Define to 1 if platform has the time.h header file, - and implementation of functions thereof. + Define to 1 if platform has the time.h header file, + and implementation of functions thereof. */ #ifndef HAS_TIME_H #define HAS_TIME_H 1 #endif /* Configuration : USE_CLOCK - Define to 1 if platform has the time.h header file, - and implementation of functions thereof. + Define to 1 if platform has the time.h header file, + and implementation of functions thereof. */ #ifndef USE_CLOCK #define USE_CLOCK 1 #endif /* Configuration : HAS_STDIO - Define to 1 if the platform has stdio.h. + Define to 1 if the platform has stdio.h. */ #ifndef HAS_STDIO #define HAS_STDIO 0 #endif /* Configuration : HAS_PRINTF - Define to 1 if the platform has stdio.h and implements the printf function. + Define to 1 if the platform has stdio.h and implements the printf + function. */ #ifndef HAS_PRINTF #define HAS_PRINTF 0 #endif - /* Definitions : COMPILER_VERSION, COMPILER_FLAGS, MEM_LOCATION - Initialize these strings per platform + Initialize these strings per platform */ -#ifndef COMPILER_VERSION - #ifdef __GNUC__ - #define COMPILER_VERSION "GCC"__VERSION__ - #else - #define COMPILER_VERSION "Please put compiler version here (e.g. gcc 4.1)" - #endif +#ifndef COMPILER_VERSION +#ifdef __GNUC__ +#define COMPILER_VERSION "GCC"__VERSION__ +#else +#define COMPILER_VERSION "Please put compiler version here (e.g. gcc 4.1)" #endif -#ifndef COMPILER_FLAGS - #define COMPILER_FLAGS FLAGS_STR /* "Please put compiler flags here (e.g. -o3)" */ #endif -#ifndef MEM_LOCATION - #define MEM_LOCATION "STACK" +#ifndef COMPILER_FLAGS +#define COMPILER_FLAGS \ + FLAGS_STR /* "Please put compiler flags here (e.g. -o3)" */ +#endif +#ifndef MEM_LOCATION +#define MEM_LOCATION "STACK" #endif /* Data Types : - To avoid compiler issues, define the data types that need ot be used for 8b, 16b and 32b in . - - *Imprtant* : - ee_ptr_int needs to be the data type used to hold pointers, otherwise coremark may fail!!! + To avoid compiler issues, define the data types that need ot be used for + 8b, 16b and 32b in . + + *Imprtant* : + ee_ptr_int needs to be the data type used to hold pointers, otherwise + coremark may fail!!! */ -typedef signed short ee_s16; +typedef signed short ee_s16; typedef unsigned short ee_u16; -typedef signed int ee_s32; -typedef double ee_f32; -typedef unsigned char ee_u8; -typedef unsigned int ee_u32; -typedef ee_u32 ee_ptr_int; -typedef size_t ee_size_t; +typedef signed int ee_s32; +typedef double ee_f32; +typedef unsigned char ee_u8; +typedef unsigned int ee_u32; +typedef ee_u32 ee_ptr_int; +typedef size_t ee_size_t; #define NULL ((void *)0) /* align_mem : - This macro is used to align an offset to point to a 32b value. It is used in the Matrix algorithm to initialize the input memory blocks. + This macro is used to align an offset to point to a 32b value. It is + used in the Matrix algorithm to initialize the input memory blocks. */ -#define align_mem(x) (void *)(4 + (((ee_ptr_int)(x) - 1) & ~3)) +#define align_mem(x) (void *)(4 + (((ee_ptr_int)(x)-1) & ~3)) /* Configuration : CORE_TICKS - Define type of return from the timing functions. + Define type of return from the timing functions. */ -#define CORETIMETYPE ee_u32 +#define CORETIMETYPE ee_u32 typedef ee_u32 CORE_TICKS; /* Configuration : SEED_METHOD - Defines method to get seed values that cannot be computed at compile time. - - Valid values : - SEED_ARG - from command line. - SEED_FUNC - from a system function. - SEED_VOLATILE - from volatile variables. + Defines method to get seed values that cannot be computed at compile + time. + + Valid values : + SEED_ARG - from command line. + SEED_FUNC - from a system function. + SEED_VOLATILE - from volatile variables. */ #ifndef SEED_METHOD #define SEED_METHOD SEED_VOLATILE #endif /* Configuration : MEM_METHOD - Defines method to get a block of memry. - - Valid values : - MEM_MALLOC - for platforms that implement malloc and have malloc.h. - MEM_STATIC - to use a static memory array. - MEM_STACK - to allocate the data block on the stack (NYI). + Defines method to get a block of memry. + + Valid values : + MEM_MALLOC - for platforms that implement malloc and have malloc.h. + MEM_STATIC - to use a static memory array. + MEM_STACK - to allocate the data block on the stack (NYI). */ #ifndef MEM_METHOD #define MEM_METHOD MEM_STACK #endif /* Configuration : MULTITHREAD - Define for parallel execution - - Valid values : - 1 - only one context (default). - N>1 - will execute N copies in parallel. - - Note : - If this flag is defined to more then 1, an implementation for launching parallel contexts must be defined. - - Two sample implementations are provided. Use or to enable them. - - It is valid to have a different implementation of and in , - to fit a particular architecture. + Define for parallel execution + + Valid values : + 1 - only one context (default). + N>1 - will execute N copies in parallel. + + Note : + If this flag is defined to more then 1, an implementation for launching + parallel contexts must be defined. + + Two sample implementations are provided. Use or + to enable them. + + It is valid to have a different implementation of + and in , to fit a particular architecture. */ #ifndef MULTITHREAD #define MULTITHREAD 1 #define USE_PTHREAD 0 -#define USE_FORK 0 -#define USE_SOCKET 0 +#define USE_FORK 0 +#define USE_SOCKET 0 #endif /* Configuration : MAIN_HAS_NOARGC - Needed if platform does not support getting arguments to main. - - Valid values : - 0 - argc/argv to main is supported - 1 - argc/argv to main is not supported - - Note : - This flag only matters if MULTITHREAD has been defined to a value greater then 1. + Needed if platform does not support getting arguments to main. + + Valid values : + 0 - argc/argv to main is supported + 1 - argc/argv to main is not supported + + Note : + This flag only matters if MULTITHREAD has been defined to a value + greater then 1. */ -#ifndef MAIN_HAS_NOARGC +#ifndef MAIN_HAS_NOARGC #define MAIN_HAS_NOARGC 0 #endif /* Configuration : MAIN_HAS_NORETURN - Needed if platform does not support returning a value from main. - - Valid values : - 0 - main returns an int, and return value will be 0. - 1 - platform does not support returning a value from main + Needed if platform does not support returning a value from main. + + Valid values : + 0 - main returns an int, and return value will be 0. + 1 - platform does not support returning a value from main */ #ifndef MAIN_HAS_NORETURN #define MAIN_HAS_NORETURN 0 #endif /* Variable : default_num_contexts - Not used for this simple port, must cintain the value 1. + Not used for this simple port, must cintain the value 1. */ extern ee_u32 default_num_contexts; -typedef struct CORE_PORTABLE_S { - ee_u8 portable_id; +typedef struct CORE_PORTABLE_S +{ + ee_u8 portable_id; } core_portable; /* target specific init/fini */ void portable_init(core_portable *p, int *argc, char *argv[]); void portable_fini(core_portable *p); -#if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) && !defined(VALIDATION_RUN) -#if (TOTAL_DATA_SIZE==1200) +#if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) \ + && !defined(VALIDATION_RUN) +#if (TOTAL_DATA_SIZE == 1200) #define PROFILE_RUN 1 -#elif (TOTAL_DATA_SIZE==2000) +#elif (TOTAL_DATA_SIZE == 2000) #define PERFORMANCE_RUN 1 #else #define VALIDATION_RUN 1 diff --git a/riscv-coremark/coremark/barebones/cvt.c b/riscv-coremark/coremark/barebones/cvt.c old mode 100755 new mode 100644 index ee0506d5..333e8ead --- a/riscv-coremark/coremark/barebones/cvt.c +++ b/riscv-coremark/coremark/barebones/cvt.c @@ -17,101 +17,111 @@ limitations under the License. #define CVTBUFSIZE 80 static char CVTBUF[CVTBUFSIZE]; -static char *cvt(double arg, int ndigits, int *decpt, int *sign, char *buf, int eflag) +static char * +cvt(double arg, int ndigits, int *decpt, int *sign, char *buf, int eflag) { - int r2; - double fi, fj; - char *p, *p1; + int r2; + double fi, fj; + char * p, *p1; - if (ndigits < 0) ndigits = 0; - if (ndigits >= CVTBUFSIZE - 1) ndigits = CVTBUFSIZE - 2; - r2 = 0; - *sign = 0; - p = &buf[0]; - if (arg < 0) - { - *sign = 1; - arg = -arg; - } - arg = modf(arg, &fi); - p1 = &buf[CVTBUFSIZE]; + if (ndigits < 0) + ndigits = 0; + if (ndigits >= CVTBUFSIZE - 1) + ndigits = CVTBUFSIZE - 2; + r2 = 0; + *sign = 0; + p = &buf[0]; + if (arg < 0) + { + *sign = 1; + arg = -arg; + } + arg = modf(arg, &fi); + p1 = &buf[CVTBUFSIZE]; - if (fi != 0) - { - p1 = &buf[CVTBUFSIZE]; - while (fi != 0) + if (fi != 0) { - fj = modf(fi / 10, &fi); - *--p1 = (int)((fj + .03) * 10) + '0'; - r2++; + p1 = &buf[CVTBUFSIZE]; + while (fi != 0) + { + fj = modf(fi / 10, &fi); + *--p1 = (int)((fj + .03) * 10) + '0'; + r2++; + } + while (p1 < &buf[CVTBUFSIZE]) + *p++ = *p1++; } - while (p1 < &buf[CVTBUFSIZE]) *p++ = *p1++; - } - else if (arg > 0) - { - while ((fj = arg * 10) < 1) + else if (arg > 0) { - arg = fj; - r2--; + while ((fj = arg * 10) < 1) + { + arg = fj; + r2--; + } } - } - p1 = &buf[ndigits]; - if (eflag == 0) p1 += r2; - *decpt = r2; - if (p1 < &buf[0]) - { - buf[0] = '\0'; + p1 = &buf[ndigits]; + if (eflag == 0) + p1 += r2; + *decpt = r2; + if (p1 < &buf[0]) + { + buf[0] = '\0'; + return buf; + } + while (p <= p1 && p < &buf[CVTBUFSIZE]) + { + arg *= 10; + arg = modf(arg, &fj); + *p++ = (int)fj + '0'; + } + if (p1 >= &buf[CVTBUFSIZE]) + { + buf[CVTBUFSIZE - 1] = '\0'; + return buf; + } + p = p1; + *p1 += 5; + while (*p1 > '9') + { + *p1 = '0'; + if (p1 > buf) + ++*--p1; + else + { + *p1 = '1'; + (*decpt)++; + if (eflag == 0) + { + if (p > buf) + *p = '0'; + p++; + } + } + } + *p = '\0'; return buf; - } - while (p <= p1 && p < &buf[CVTBUFSIZE]) - { - arg *= 10; - arg = modf(arg, &fj); - *p++ = (int) fj + '0'; - } - if (p1 >= &buf[CVTBUFSIZE]) - { - buf[CVTBUFSIZE - 1] = '\0'; - return buf; - } - p = p1; - *p1 += 5; - while (*p1 > '9') - { - *p1 = '0'; - if (p1 > buf) - ++*--p1; - else - { - *p1 = '1'; - (*decpt)++; - if (eflag == 0) - { - if (p > buf) *p = '0'; - p++; - } - } - } - *p = '\0'; - return buf; } -char *ecvt(double arg, int ndigits, int *decpt, int *sign) +char * +ecvt(double arg, int ndigits, int *decpt, int *sign) { - return cvt(arg, ndigits, decpt, sign, CVTBUF, 1); + return cvt(arg, ndigits, decpt, sign, CVTBUF, 1); } -char *ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf) +char * +ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf) { - return cvt(arg, ndigits, decpt, sign, buf, 1); + return cvt(arg, ndigits, decpt, sign, buf, 1); } -char *fcvt(double arg, int ndigits, int *decpt, int *sign) +char * +fcvt(double arg, int ndigits, int *decpt, int *sign) { - return cvt(arg, ndigits, decpt, sign, CVTBUF, 0); + return cvt(arg, ndigits, decpt, sign, CVTBUF, 0); } -char *fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf) +char * +fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf) { - return cvt(arg, ndigits, decpt, sign, buf, 0); + return cvt(arg, ndigits, decpt, sign, buf, 0); } diff --git a/riscv-coremark/coremark/barebones/ee_printf.c b/riscv-coremark/coremark/barebones/ee_printf.c old mode 100755 new mode 100644 index b08f59db..f2d362dc --- a/riscv-coremark/coremark/barebones/ee_printf.c +++ b/riscv-coremark/coremark/barebones/ee_printf.c @@ -17,581 +17,684 @@ limitations under the License. #include #include -#define ZEROPAD (1<<0) /* Pad with zero */ -#define SIGN (1<<1) /* Unsigned/signed long */ -#define PLUS (1<<2) /* Show plus */ -#define SPACE (1<<3) /* Spacer */ -#define LEFT (1<<4) /* Left justified */ -#define HEX_PREP (1<<5) /* 0x */ -#define UPPERCASE (1<<6) /* 'ABCDEF' */ +#define ZEROPAD (1 << 0) /* Pad with zero */ +#define SIGN (1 << 1) /* Unsigned/signed long */ +#define PLUS (1 << 2) /* Show plus */ +#define SPACE (1 << 3) /* Spacer */ +#define LEFT (1 << 4) /* Left justified */ +#define HEX_PREP (1 << 5) /* 0x */ +#define UPPERCASE (1 << 6) /* 'ABCDEF' */ #define is_digit(c) ((c) >= '0' && (c) <= '9') -static char *digits = "0123456789abcdefghijklmnopqrstuvwxyz"; -static char *upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static char * digits = "0123456789abcdefghijklmnopqrstuvwxyz"; +static char * upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static ee_size_t strnlen(const char *s, ee_size_t count); -static ee_size_t strnlen(const char *s, ee_size_t count) +static ee_size_t +strnlen(const char *s, ee_size_t count) { - const char *sc; - for (sc = s; *sc != '\0' && count--; ++sc); - return sc - s; + const char *sc; + for (sc = s; *sc != '\0' && count--; ++sc) + ; + return sc - s; } -static int skip_atoi(const char **s) +static int +skip_atoi(const char **s) { - int i = 0; - while (is_digit(**s)) i = i*10 + *((*s)++) - '0'; - return i; + int i = 0; + while (is_digit(**s)) + i = i * 10 + *((*s)++) - '0'; + return i; } -static char *number(char *str, long num, int base, int size, int precision, int type) +static char * +number(char *str, long num, int base, int size, int precision, int type) { - char c, sign, tmp[66]; - char *dig = digits; - int i; + char c, sign, tmp[66]; + char *dig = digits; + int i; - if (type & UPPERCASE) dig = upper_digits; - if (type & LEFT) type &= ~ZEROPAD; - if (base < 2 || base > 36) return 0; - - c = (type & ZEROPAD) ? '0' : ' '; - sign = 0; - if (type & SIGN) - { - if (num < 0) + if (type & UPPERCASE) + dig = upper_digits; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return 0; + + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { - sign = '-'; - num = -num; - size--; + if (num < 0) + { + sign = '-'; + num = -num; + size--; + } + else if (type & PLUS) + { + sign = '+'; + size--; + } + else if (type & SPACE) + { + sign = ' '; + size--; + } } - else if (type & PLUS) + + if (type & HEX_PREP) { - sign = '+'; - size--; + if (base == 16) + size -= 2; + else if (base == 8) + size--; } - else if (type & SPACE) - { - sign = ' '; - size--; - } - } - if (type & HEX_PREP) - { - if (base == 16) - size -= 2; - else if (base == 8) - size--; - } + i = 0; - i = 0; - - if (num == 0) - tmp[i++] = '0'; - else - { - while (num != 0) - { - tmp[i++] = dig[((unsigned long) num) % (unsigned) base]; - num = ((unsigned long) num) / (unsigned) base; - } - } - - if (i > precision) precision = i; - size -= precision; - if (!(type & (ZEROPAD | LEFT))) while (size-- > 0) *str++ = ' '; - if (sign) *str++ = sign; - - if (type & HEX_PREP) - { - if (base == 8) - *str++ = '0'; - else if (base == 16) - { - *str++ = '0'; - *str++ = digits[33]; - } - } - - if (!(type & LEFT)) while (size-- > 0) *str++ = c; - while (i < precision--) *str++ = '0'; - while (i-- > 0) *str++ = tmp[i]; - while (size-- > 0) *str++ = ' '; - - return str; -} - -static char *eaddr(char *str, unsigned char *addr, int size, int precision, int type) -{ - char tmp[24]; - char *dig = digits; - int i, len; - - if (type & UPPERCASE) dig = upper_digits; - len = 0; - for (i = 0; i < 6; i++) - { - if (i != 0) tmp[len++] = ':'; - tmp[len++] = dig[addr[i] >> 4]; - tmp[len++] = dig[addr[i] & 0x0F]; - } - - if (!(type & LEFT)) while (len < size--) *str++ = ' '; - for (i = 0; i < len; ++i) *str++ = tmp[i]; - while (len < size--) *str++ = ' '; - - return str; -} - -static char *iaddr(char *str, unsigned char *addr, int size, int precision, int type) -{ - char tmp[24]; - int i, n, len; - - len = 0; - for (i = 0; i < 4; i++) - { - if (i != 0) tmp[len++] = '.'; - n = addr[i]; - - if (n == 0) - tmp[len++] = digits[0]; + if (num == 0) + tmp[i++] = '0'; else { - if (n >= 100) - { - tmp[len++] = digits[n / 100]; - n = n % 100; - tmp[len++] = digits[n / 10]; - n = n % 10; - } - else if (n >= 10) - { - tmp[len++] = digits[n / 10]; - n = n % 10; - } - - tmp[len++] = digits[n]; + while (num != 0) + { + tmp[i++] = dig[((unsigned long)num) % (unsigned)base]; + num = ((unsigned long)num) / (unsigned)base; + } } - } - if (!(type & LEFT)) while (len < size--) *str++ = ' '; - for (i = 0; i < len; ++i) *str++ = tmp[i]; - while (len < size--) *str++ = ' '; + if (i > precision) + precision = i; + size -= precision; + if (!(type & (ZEROPAD | LEFT))) + while (size-- > 0) + *str++ = ' '; + if (sign) + *str++ = sign; - return str; + if (type & HEX_PREP) + { + if (base == 8) + *str++ = '0'; + else if (base == 16) + { + *str++ = '0'; + *str++ = digits[33]; + } + } + + if (!(type & LEFT)) + while (size-- > 0) + *str++ = c; + while (i < precision--) + *str++ = '0'; + while (i-- > 0) + *str++ = tmp[i]; + while (size-- > 0) + *str++ = ' '; + + return str; +} + +static char * +eaddr(char *str, unsigned char *addr, int size, int precision, int type) +{ + char tmp[24]; + char *dig = digits; + int i, len; + + if (type & UPPERCASE) + dig = upper_digits; + len = 0; + for (i = 0; i < 6; i++) + { + if (i != 0) + tmp[len++] = ':'; + tmp[len++] = dig[addr[i] >> 4]; + tmp[len++] = dig[addr[i] & 0x0F]; + } + + if (!(type & LEFT)) + while (len < size--) + *str++ = ' '; + for (i = 0; i < len; ++i) + *str++ = tmp[i]; + while (len < size--) + *str++ = ' '; + + return str; +} + +static char * +iaddr(char *str, unsigned char *addr, int size, int precision, int type) +{ + char tmp[24]; + int i, n, len; + + len = 0; + for (i = 0; i < 4; i++) + { + if (i != 0) + tmp[len++] = '.'; + n = addr[i]; + + if (n == 0) + tmp[len++] = digits[0]; + else + { + if (n >= 100) + { + tmp[len++] = digits[n / 100]; + n = n % 100; + tmp[len++] = digits[n / 10]; + n = n % 10; + } + else if (n >= 10) + { + tmp[len++] = digits[n / 10]; + n = n % 10; + } + + tmp[len++] = digits[n]; + } + } + + if (!(type & LEFT)) + while (len < size--) + *str++ = ' '; + for (i = 0; i < len; ++i) + *str++ = tmp[i]; + while (len < size--) + *str++ = ' '; + + return str; } #if HAS_FLOAT -char *ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf); -char *fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf); -static void ee_bufcpy(char *d, char *s, int count); - -void ee_bufcpy(char *pd, char *ps, int count) { - char *pe=ps+count; - while (ps!=pe) - *pd++=*ps++; +char * ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf); +char * fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf); +static void ee_bufcpy(char *d, char *s, int count); + +void +ee_bufcpy(char *pd, char *ps, int count) +{ + char *pe = ps + count; + while (ps != pe) + *pd++ = *ps++; } -static void parse_float(double value, char *buffer, char fmt, int precision) +static void +parse_float(double value, char *buffer, char fmt, int precision) { - int decpt, sign, exp, pos; - char *digits = NULL; - char cvtbuf[80]; - int capexp = 0; - int magnitude; + int decpt, sign, exp, pos; + char *digits = NULL; + char cvtbuf[80]; + int capexp = 0; + int magnitude; - if (fmt == 'G' || fmt == 'E') - { - capexp = 1; - fmt += 'a' - 'A'; - } - - if (fmt == 'g') - { - digits = ecvtbuf(value, precision, &decpt, &sign, cvtbuf); - magnitude = decpt - 1; - if (magnitude < -4 || magnitude > precision - 1) + if (fmt == 'G' || fmt == 'E') { - fmt = 'e'; - precision -= 1; + capexp = 1; + fmt += 'a' - 'A'; } - else + + if (fmt == 'g') { - fmt = 'f'; - precision -= decpt; - } - } - - if (fmt == 'e') - { - digits = ecvtbuf(value, precision + 1, &decpt, &sign, cvtbuf); - - if (sign) *buffer++ = '-'; - *buffer++ = *digits; - if (precision > 0) *buffer++ = '.'; - ee_bufcpy(buffer, digits + 1, precision); - buffer += precision; - *buffer++ = capexp ? 'E' : 'e'; - - if (decpt == 0) - { - if (value == 0.0) - exp = 0; - else - exp = -1; - } - else - exp = decpt - 1; - - if (exp < 0) - { - *buffer++ = '-'; - exp = -exp; - } - else - *buffer++ = '+'; - - buffer[2] = (exp % 10) + '0'; - exp = exp / 10; - buffer[1] = (exp % 10) + '0'; - exp = exp / 10; - buffer[0] = (exp % 10) + '0'; - buffer += 3; - } - else if (fmt == 'f') - { - digits = fcvtbuf(value, precision, &decpt, &sign, cvtbuf); - if (sign) *buffer++ = '-'; - if (*digits) - { - if (decpt <= 0) - { - *buffer++ = '0'; - *buffer++ = '.'; - for (pos = 0; pos < -decpt; pos++) *buffer++ = '0'; - while (*digits) *buffer++ = *digits++; - } - else - { - pos = 0; - while (*digits) + digits = ecvtbuf(value, precision, &decpt, &sign, cvtbuf); + magnitude = decpt - 1; + if (magnitude < -4 || magnitude > precision - 1) { - if (pos++ == decpt) *buffer++ = '.'; - *buffer++ = *digits++; + fmt = 'e'; + precision -= 1; + } + else + { + fmt = 'f'; + precision -= decpt; } - } } - else + + if (fmt == 'e') { - *buffer++ = '0'; - if (precision > 0) - { - *buffer++ = '.'; - for (pos = 0; pos < precision; pos++) *buffer++ = '0'; - } + digits = ecvtbuf(value, precision + 1, &decpt, &sign, cvtbuf); + + if (sign) + *buffer++ = '-'; + *buffer++ = *digits; + if (precision > 0) + *buffer++ = '.'; + ee_bufcpy(buffer, digits + 1, precision); + buffer += precision; + *buffer++ = capexp ? 'E' : 'e'; + + if (decpt == 0) + { + if (value == 0.0) + exp = 0; + else + exp = -1; + } + else + exp = decpt - 1; + + if (exp < 0) + { + *buffer++ = '-'; + exp = -exp; + } + else + *buffer++ = '+'; + + buffer[2] = (exp % 10) + '0'; + exp = exp / 10; + buffer[1] = (exp % 10) + '0'; + exp = exp / 10; + buffer[0] = (exp % 10) + '0'; + buffer += 3; } - } - - *buffer = '\0'; -} - -static void decimal_point(char *buffer) -{ - while (*buffer) - { - if (*buffer == '.') return; - if (*buffer == 'e' || *buffer == 'E') break; - buffer++; - } - - if (*buffer) - { - int n = strnlen(buffer,256); - while (n > 0) + else if (fmt == 'f') { - buffer[n + 1] = buffer[n]; - n--; + digits = fcvtbuf(value, precision, &decpt, &sign, cvtbuf); + if (sign) + *buffer++ = '-'; + if (*digits) + { + if (decpt <= 0) + { + *buffer++ = '0'; + *buffer++ = '.'; + for (pos = 0; pos < -decpt; pos++) + *buffer++ = '0'; + while (*digits) + *buffer++ = *digits++; + } + else + { + pos = 0; + while (*digits) + { + if (pos++ == decpt) + *buffer++ = '.'; + *buffer++ = *digits++; + } + } + } + else + { + *buffer++ = '0'; + if (precision > 0) + { + *buffer++ = '.'; + for (pos = 0; pos < precision; pos++) + *buffer++ = '0'; + } + } } - *buffer = '.'; - } - else - { - *buffer++ = '.'; *buffer = '\0'; - } } -static void cropzeros(char *buffer) +static void +decimal_point(char *buffer) { - char *stop; + while (*buffer) + { + if (*buffer == '.') + return; + if (*buffer == 'e' || *buffer == 'E') + break; + buffer++; + } - while (*buffer && *buffer != '.') buffer++; - if (*buffer++) - { - while (*buffer && *buffer != 'e' && *buffer != 'E') buffer++; - stop = buffer--; - while (*buffer == '0') buffer--; - if (*buffer == '.') buffer--; - while (buffer!=stop) - *++buffer=0; - } + if (*buffer) + { + int n = strnlen(buffer, 256); + while (n > 0) + { + buffer[n + 1] = buffer[n]; + n--; + } + + *buffer = '.'; + } + else + { + *buffer++ = '.'; + *buffer = '\0'; + } } -static char *flt(char *str, double num, int size, int precision, char fmt, int flags) +static void +cropzeros(char *buffer) { - char tmp[80]; - char c, sign; - int n, i; + char *stop; - // Left align means no zero padding - if (flags & LEFT) flags &= ~ZEROPAD; - - // Determine padding and sign char - c = (flags & ZEROPAD) ? '0' : ' '; - sign = 0; - if (flags & SIGN) - { - if (num < 0.0) + while (*buffer && *buffer != '.') + buffer++; + if (*buffer++) { - sign = '-'; - num = -num; - size--; + while (*buffer && *buffer != 'e' && *buffer != 'E') + buffer++; + stop = buffer--; + while (*buffer == '0') + buffer--; + if (*buffer == '.') + buffer--; + while (buffer != stop) + *++buffer = 0; } - else if (flags & PLUS) +} + +static char * +flt(char *str, double num, int size, int precision, char fmt, int flags) +{ + char tmp[80]; + char c, sign; + int n, i; + + // Left align means no zero padding + if (flags & LEFT) + flags &= ~ZEROPAD; + + // Determine padding and sign char + c = (flags & ZEROPAD) ? '0' : ' '; + sign = 0; + if (flags & SIGN) { - sign = '+'; - size--; + if (num < 0.0) + { + sign = '-'; + num = -num; + size--; + } + else if (flags & PLUS) + { + sign = '+'; + size--; + } + else if (flags & SPACE) + { + sign = ' '; + size--; + } } - else if (flags & SPACE) - { - sign = ' '; - size--; - } - } - // Compute the precision value - if (precision < 0) - precision = 6; // Default precision: 6 + // Compute the precision value + if (precision < 0) + precision = 6; // Default precision: 6 - // Convert floating point number to text - parse_float(num, tmp, fmt, precision); + // Convert floating point number to text + parse_float(num, tmp, fmt, precision); - if ((flags & HEX_PREP) && precision == 0) decimal_point(tmp); - if (fmt == 'g' && !(flags & HEX_PREP)) cropzeros(tmp); + if ((flags & HEX_PREP) && precision == 0) + decimal_point(tmp); + if (fmt == 'g' && !(flags & HEX_PREP)) + cropzeros(tmp); - n = strnlen(tmp,256); + n = strnlen(tmp, 256); - // Output number with alignment and padding - size -= n; - if (!(flags & (ZEROPAD | LEFT))) while (size-- > 0) *str++ = ' '; - if (sign) *str++ = sign; - if (!(flags & LEFT)) while (size-- > 0) *str++ = c; - for (i = 0; i < n; i++) *str++ = tmp[i]; - while (size-- > 0) *str++ = ' '; + // Output number with alignment and padding + size -= n; + if (!(flags & (ZEROPAD | LEFT))) + while (size-- > 0) + *str++ = ' '; + if (sign) + *str++ = sign; + if (!(flags & LEFT)) + while (size-- > 0) + *str++ = c; + for (i = 0; i < n; i++) + *str++ = tmp[i]; + while (size-- > 0) + *str++ = ' '; - return str; + return str; } #endif -static int ee_vsprintf(char *buf, const char *fmt, va_list args) +static int +ee_vsprintf(char *buf, const char *fmt, va_list args) { - int len; - unsigned long num; - int i, base; - char *str; - char *s; + int len; + unsigned long num; + int i, base; + char * str; + char * s; - int flags; // Flags to number() + int flags; // Flags to number() - int field_width; // Width of output field - int precision; // Min. # of digits for integers; max number of chars for from string - int qualifier; // 'h', 'l', or 'L' for integer fields + int field_width; // Width of output field + int precision; // Min. # of digits for integers; max number of chars for + // from string + int qualifier; // 'h', 'l', or 'L' for integer fields - for (str = buf; *fmt; fmt++) - { - if (*fmt != '%') + for (str = buf; *fmt; fmt++) { - *str++ = *fmt; - continue; - } - - // Process flags - flags = 0; -repeat: - fmt++; // This also skips first '%' - switch (*fmt) - { - case '-': flags |= LEFT; goto repeat; - case '+': flags |= PLUS; goto repeat; - case ' ': flags |= SPACE; goto repeat; - case '#': flags |= HEX_PREP; goto repeat; - case '0': flags |= ZEROPAD; goto repeat; - } - - // Get field width - field_width = -1; - if (is_digit(*fmt)) - field_width = skip_atoi(&fmt); - else if (*fmt == '*') - { - fmt++; - field_width = va_arg(args, int); - if (field_width < 0) - { - field_width = -field_width; - flags |= LEFT; - } - } - - // Get the precision - precision = -1; - if (*fmt == '.') - { - ++fmt; - if (is_digit(*fmt)) - precision = skip_atoi(&fmt); - else if (*fmt == '*') - { - ++fmt; - precision = va_arg(args, int); - } - if (precision < 0) precision = 0; - } - - // Get the conversion qualifier - qualifier = -1; - if (*fmt == 'l' || *fmt == 'L') - { - qualifier = *fmt; - fmt++; - } - - // Default base - base = 10; - - switch (*fmt) - { - case 'c': - if (!(flags & LEFT)) while (--field_width > 0) *str++ = ' '; - *str++ = (unsigned char) va_arg(args, int); - while (--field_width > 0) *str++ = ' '; - continue; - - case 's': - s = va_arg(args, char *); - if (!s) s = ""; - len = strnlen(s, precision); - if (!(flags & LEFT)) while (len < field_width--) *str++ = ' '; - for (i = 0; i < len; ++i) *str++ = *s++; - while (len < field_width--) *str++ = ' '; - continue; - - case 'p': - if (field_width == -1) + if (*fmt != '%') { - field_width = 2 * sizeof(void *); - flags |= ZEROPAD; + *str++ = *fmt; + continue; } - str = number(str, (unsigned long) va_arg(args, void *), 16, field_width, precision, flags); - continue; - case 'A': - flags |= UPPERCASE; + // Process flags + flags = 0; + repeat: + fmt++; // This also skips first '%' + switch (*fmt) + { + case '-': + flags |= LEFT; + goto repeat; + case '+': + flags |= PLUS; + goto repeat; + case ' ': + flags |= SPACE; + goto repeat; + case '#': + flags |= HEX_PREP; + goto repeat; + case '0': + flags |= ZEROPAD; + goto repeat; + } - case 'a': - if (qualifier == 'l') - str = eaddr(str, va_arg(args, unsigned char *), field_width, precision, flags); - else - str = iaddr(str, va_arg(args, unsigned char *), field_width, precision, flags); - continue; + // Get field width + field_width = -1; + if (is_digit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') + { + fmt++; + field_width = va_arg(args, int); + if (field_width < 0) + { + field_width = -field_width; + flags |= LEFT; + } + } - // Integer number formats - set up the flags and "break" - case 'o': - base = 8; - break; + // Get the precision + precision = -1; + if (*fmt == '.') + { + ++fmt; + if (is_digit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') + { + ++fmt; + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } - case 'X': - flags |= UPPERCASE; + // Get the conversion qualifier + qualifier = -1; + if (*fmt == 'l' || *fmt == 'L') + { + qualifier = *fmt; + fmt++; + } - case 'x': - base = 16; - break; + // Default base + base = 10; - case 'd': - case 'i': - flags |= SIGN; + switch (*fmt) + { + case 'c': + if (!(flags & LEFT)) + while (--field_width > 0) + *str++ = ' '; + *str++ = (unsigned char)va_arg(args, int); + while (--field_width > 0) + *str++ = ' '; + continue; - case 'u': - break; + case 's': + s = va_arg(args, char *); + if (!s) + s = ""; + len = strnlen(s, precision); + if (!(flags & LEFT)) + while (len < field_width--) + *str++ = ' '; + for (i = 0; i < len; ++i) + *str++ = *s++; + while (len < field_width--) + *str++ = ' '; + continue; + + case 'p': + if (field_width == -1) + { + field_width = 2 * sizeof(void *); + flags |= ZEROPAD; + } + str = number(str, + (unsigned long)va_arg(args, void *), + 16, + field_width, + precision, + flags); + continue; + + case 'A': + flags |= UPPERCASE; + + case 'a': + if (qualifier == 'l') + str = eaddr(str, + va_arg(args, unsigned char *), + field_width, + precision, + flags); + else + str = iaddr(str, + va_arg(args, unsigned char *), + field_width, + precision, + flags); + continue; + + // Integer number formats - set up the flags and "break" + case 'o': + base = 8; + break; + + case 'X': + flags |= UPPERCASE; + + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + + case 'u': + break; #if HAS_FLOAT - case 'f': - str = flt(str, va_arg(args, double), field_width, precision, *fmt, flags | SIGN); - continue; + case 'f': + str = flt(str, + va_arg(args, double), + field_width, + precision, + *fmt, + flags | SIGN); + continue; #endif - default: - if (*fmt != '%') *str++ = '%'; - if (*fmt) - *str++ = *fmt; + default: + if (*fmt != '%') + *str++ = '%'; + if (*fmt) + *str++ = *fmt; + else + --fmt; + continue; + } + + if (qualifier == 'l') + num = va_arg(args, unsigned long); + else if (flags & SIGN) + num = va_arg(args, int); else - --fmt; - continue; + num = va_arg(args, unsigned int); + + str = number(str, num, base, field_width, precision, flags); } - if (qualifier == 'l') - num = va_arg(args, unsigned long); - else if (flags & SIGN) - num = va_arg(args, int); - else - num = va_arg(args, unsigned int); - - str = number(str, num, base, field_width, precision, flags); - } - - *str = '\0'; - return str - buf; + *str = '\0'; + return str - buf; } -void uart_send_char(char c) { -#error "You must implement the method uart_send_char to use this file!\n"; -/* Output of a char to a UART usually follows the following model: - Wait until UART is ready - Write char to UART - Wait until UART is done - - Or in code: - while (*UART_CONTROL_ADDRESS != UART_READY); - *UART_DATA_ADDRESS = c; - while (*UART_CONTROL_ADDRESS != UART_READY); - - Check the UART sample code on your platform or the board documentation. -*/ -} - -int ee_printf(const char *fmt, ...) +void +uart_send_char(char c) { - char buf[256],*p; - va_list args; - int n=0; +#error "You must implement the method uart_send_char to use this file!\n"; + /* Output of a char to a UART usually follows the following model: + Wait until UART is ready + Write char to UART + Wait until UART is done - va_start(args, fmt); - ee_vsprintf(buf, fmt, args); - va_end(args); - p=buf; - while (*p) { - uart_send_char(*p); - n++; - p++; - } + Or in code: + while (*UART_CONTROL_ADDRESS != UART_READY); + *UART_DATA_ADDRESS = c; + while (*UART_CONTROL_ADDRESS != UART_READY); - return n; + Check the UART sample code on your platform or the board + documentation. + */ } +int +ee_printf(const char *fmt, ...) +{ + char buf[1024], *p; + va_list args; + int n = 0; + + va_start(args, fmt); + ee_vsprintf(buf, fmt, args); + va_end(args); + p = buf; + while (*p) + { + uart_send_char(*p); + n++; + p++; + } + + return n; +} diff --git a/riscv-coremark/coremark/core_list_join.c b/riscv-coremark/coremark/core_list_join.c index e5dba39e..4bffeecc 100644 --- a/riscv-coremark/coremark/core_list_join.c +++ b/riscv-coremark/coremark/core_list_join.c @@ -17,8 +17,8 @@ Original Author: Shay Gal-on */ #include "coremark.h" -#include -#include +//#include +//#include /* Topic: Description Benchmark using a linked list. @@ -118,7 +118,7 @@ ee_s32 cmp_idx(list_data *a, list_data *b, core_results *res) { return a->idx - b->idx; } -void ehitoa(int value, char *str, int base){ +/*void ehitoa(int value, char *str, int base){ if (value>100000) strcpy(str,"too big"); else{ int places[6] = {100000, 10000, 1000, 100, 10, 1}; @@ -135,7 +135,7 @@ void ehitoa(int value, char *str, int base){ } str[6]=0; } -} +}*/ void copy_info(list_data *to,list_data *from) { to->data16=from->data16; @@ -158,22 +158,22 @@ ee_u16 core_bench_list(core_results *res, ee_s16 finder_idx) { list_head *finder, *remover; list_data info; ee_s16 i; - ee_printf("entered corebenchlist \n"); + //ee_printf("entered corebenchlist \n"); info.idx=finder_idx; /* find values in the list, and change the list each time (reverse and cache if value found) */ for (i=0; inext->info->data16 >> 8) & 1; - ee_printf("if statement \n"); + //ee_printf("if statement \n"); } else { found++; - ee_printf("else statement \n"); + //ee_printf("else statement \n"); if (this_find->info->data16 & 0x1) /* use found value */ retval+=(this_find->info->data16 >> 9) & 1; /* and cache next item at the head of the list (if any) */ @@ -187,7 +187,7 @@ ee_u16 core_bench_list(core_results *res, ee_s16 finder_idx) { if (info.idx>=0) info.idx++; #if CORE_DEBUG - ee_printf("List find %d: [%d,%d,%d]\n",i,retval,missed,found); + //ee_printf("List find %d: [%d,%d,%d]\n",i,retval,missed,found); #endif } retval+=found*4-missed; @@ -204,7 +204,7 @@ ee_u16 core_bench_list(core_results *res, ee_s16 finder_idx) { finder=finder->next; } #if CORE_DEBUG - ee_printf("List sort 1: %04x\n",retval); + //ee_printf("List sort 1: %04x\n",retval); #endif remover=core_list_undo_remove(remover,list->next); /* sort the list by index, in effect returning the list to original state */ @@ -216,7 +216,7 @@ ee_u16 core_bench_list(core_results *res, ee_s16 finder_idx) { finder=finder->next; } #if CORE_DEBUG - ee_printf("List sort 2: %04x\n",retval); + //ee_printf("List sort 2: %04x\n",retval); #endif return retval; } @@ -235,26 +235,26 @@ ee_u16 core_bench_list(core_results *res, ee_s16 finder_idx) { */ list_head *core_list_init(ee_u32 blksize, list_head *memblock, ee_s16 seed) { /* calculated pointers for the list */ - ee_printf("%d \n blksize", blksize); + //ee_printf("%d \n blksize", blksize); ee_u32 per_item=16+sizeof(struct list_data_s); - ee_printf("%d \n sizeof", sizeof(struct list_data_s)); - ee_printf("%d \n per_item", per_item); + //ee_printf("%d \n sizeof", sizeof(struct list_data_s)); + //ee_printf("%d \n per_item", per_item); ee_u32 size=(blksize/per_item)-2; - char bufftwo[200]; - ehitoa(size, bufftwo, 10); - ee_printf(" size = %s done \n", bufftwo); - ee_printf("%d", size);/* to accomodate systems with 64b pointers, and make sure same code is executed, set max list elements */ + //char bufftwo[200]; + //ehitoa(size, bufftwo, 10); + //ee_printf(" size = %s done \n", bufftwo); + //ee_printf("%d", size);/* to accomodate systems with 64b pointers, and make sure same code is executed, set max list elements */ list_head *memblock_end=memblock+size; list_data *datablock=(list_data *)(memblock_end); list_data *datablock_end=datablock+size; - ee_printf("datablock_end"); + //ee_printf("datablock_end"); /* some useful variables */ ee_u32 i; list_head *finder,*list=memblock; list_data info; - ehitoa(size, bufftwo, 10); - ee_printf(" size2 = %s done \n", bufftwo); + //ehitoa(size, bufftwo, 10); + //ee_printf(" size2 = %s done \n", bufftwo); /* create a fake items for the list head and tail */ list->next=NULL; @@ -265,58 +265,58 @@ list_head *core_list_init(ee_u32 blksize, list_head *memblock, ee_s16 seed) { datablock++; info.idx=0x7fff; info.data16=(ee_s16)0xffff; - ehitoa(size, bufftwo, 10); - ee_printf(" size3 = %s done \n", bufftwo); + //ehitoa(size, bufftwo, 10); + //ee_printf(" size3 = %s done \n", bufftwo); core_list_insert_new(list,&info,&memblock,&datablock,memblock_end,datablock_end); - ehitoa(size, bufftwo, 10); - ee_printf(" size4 = %s done \n", bufftwo);; + //ehitoa(size, bufftwo, 10); + //ee_printf(" size4 = %s done \n", bufftwo);; /* then insert size items */ for (i=0; inext; i=1; - ehitoa(i, bufftwo, 10); - ee_printf(" i = %s done \n", bufftwo); + //ehitoa(i, bufftwo, 10); + //ee_printf(" i = %s done \n", bufftwo); while (finder->next!=NULL) { - ee_printf("enter while statement \n"); + //ee_printf("enter while statement \n"); if (iinfo->idx=i++; - ehitoa(i, bufftwo, 10); - ee_printf(" if i = %s done \n", bufftwo); + //ehitoa(i, bufftwo, 10); + //ee_printf(" if i = %s done \n", bufftwo); } else { ee_u16 pat=(ee_u16)(i++ ^ seed); /* get a pseudo random number */ finder->info->idx=0x3fff & (((i & 0x07) << 8) | pat); /* make sure the mixed items end up after the ones in sequence */ - ehitoa(i, bufftwo, 10); - ee_printf(" else i = %s done \n", bufftwo); + //ehitoa(i, bufftwo, 10); + //ee_printf(" else i = %s done \n", bufftwo); } finder=finder->next; } - ehitoa(i, bufftwo, 10); - ee_printf(" i2 = %s done \n", bufftwo); + //ehitoa(i, bufftwo, 10); + //ee_printf(" i2 = %s done \n", bufftwo); list = core_list_mergesort(list,cmp_idx,NULL); #if CORE_DEBUG - ee_printf("Initialized list:\n"); + //ee_printf("Initialized list:\n"); finder=list; while (finder) { - ee_printf("[%04x,%04x]",finder->info->idx,(ee_u16)finder->info->data16); + //ee_printf("[%04x,%04x]",finder->info->idx,(ee_u16)finder->info->data16); finder=finder->next; } - ee_printf("\n"); + //ee_printf("\n"); #endif return list; } @@ -424,20 +424,22 @@ list_head *core_list_undo_remove(list_head *item_removed, list_head *item_modifi Found item, or NULL if not found. */ list_head *core_list_find(list_head *list,list_data *info) { - ee_printf("entered core_list_find \n"); + //ee_printf("entered core_list_find \n"); if (info->idx>=0) { - ee_printf("find if \n"); + //ee_printf("find if \n"); while (list && (list->info->idx != info->idx)){ list=list->next; - ee_printf("find while if \n");} - ee_printf("core_list_find end \n"); + //ee_printf("find while if \n"); + } + //ee_printf("core_list_find end \n"); return list; } else { - ee_printf("find else"); + //ee_printf("find else"); while (list && ((list->info->data16 & 0xff) != info->data16)){ list=list->next; - ee_printf("find while else \n");} - ee_printf("core list find end \n"); + //ee_printf("find while else \n"); + } + //ee_printf("core list find end \n"); return list; } } @@ -456,7 +458,7 @@ list_head *core_list_find(list_head *list,list_data *info) { */ list_head *core_list_reverse(list_head *list) { - ee_printf("entered core_list_reverse"); +// ee_printf("entered core_list_reverse"); list_head *next=NULL, *tmp; while (list) { tmp=list->next; @@ -464,7 +466,7 @@ list_head *core_list_reverse(list_head *list) { next=list; list=tmp; } - ee_printf("core_list_reverse done"); + //ee_printf("core_list_reverse done"); return next; } /* Function: core_list_mergesort @@ -493,27 +495,27 @@ list_head *core_list_mergesort(list_head *list, list_cmp cmp, core_results *res) ee_s32 insize, nmerges, psize, qsize, i; insize = 1; - char bufftwo[200]; + //char bufftwo[200]; while (1) { p = list; list = NULL; tail = NULL; nmerges = 0; /* count number of merges we do in this pass */ - ehitoa(nmerges, bufftwo, 10); - ee_printf(" nmerges default value = %s done \n", bufftwo); + //ehitoa(nmerges, bufftwo, 10); + //ee_printf(" nmerges default value = %s done \n", bufftwo); while (p) { nmerges++; /* there exists a merge to be done */ - ehitoa(nmerges, bufftwo, 10); - ee_printf(" current nmerges = %s done \n", bufftwo); + //ehitoa(nmerges, bufftwo, 10); + //ee_printf(" current nmerges = %s done \n", bufftwo); /* step `insize' places along from p */ q = p; psize = 0; - ehitoa(insize, bufftwo, 10); - ee_printf(" insize = %s done \n", bufftwo); + //ehitoa(insize, bufftwo, 10); + //ee_printf(" insize = %s done \n", bufftwo); for (i = 0; i < insize; i++) { - ehitoa(i, bufftwo, 10); - ee_printf(" i = %s done \n", bufftwo); + //ehitoa(i, bufftwo, 10); + //ee_printf(" i = %s done \n", bufftwo); psize++; q = q->next; if (!q) break; @@ -521,37 +523,37 @@ list_head *core_list_mergesort(list_head *list, list_cmp cmp, core_results *res) /* if q hasn't fallen off end, we have two lists to merge */ qsize = insize; - ehitoa(qsize, bufftwo, 10); - ee_printf(" qsize = %s done \n", bufftwo); + //ehitoa(qsize, bufftwo, 10); + //ee_printf(" qsize = %s done \n", bufftwo); /* now we have two lists; merge them */ while (psize > 0 || (qsize > 0 && q)) { /* decide whether next element of merge comes from p or q */ if (psize == 0) { - ee_printf("if \n"); + //ee_printf("if \n"); /* p is empty; e must come from q. */ e = q; q = q->next; qsize--; } else if (qsize == 0 || !q) { - ee_printf("else if \n"); + //ee_printf("else if \n"); /* q is empty; e must come from p. */ e = p; p = p->next; psize--; } else if (cmp(p->info,q->info,res) <= 0) { - ee_printf("else if 2 \n"); + //ee_printf("else if 2 \n"); /* First element of p is lower (or same); e must come from p. */ e = p; p = p->next; psize--; } else { - ee_printf("else \n"); + //ee_printf("else \n"); /* First element of q is lower; e must come from q. */ e = q; q = q->next; qsize--; } /* add the next element to the merged list */ if (tail) { - ee_printf("tail if \n"); + //ee_printf("tail if \n"); tail->next = e; } else { - ee_printf("tail else \n"); + //ee_printf("tail else \n"); list = e; } tail = e; @@ -569,8 +571,8 @@ list_head *core_list_mergesort(list_head *list, list_cmp cmp, core_results *res) /* Otherwise repeat, merging lists twice the size */ insize *= 2; - ehitoa(insize, bufftwo, 10); - ee_printf(" insize2 = %s done \n", bufftwo); + //ehitoa(insize, bufftwo, 10); + //ee_printf(" insize2 = %s done \n", bufftwo); } #if COMPILER_REQUIRES_SORT_RETURN return list; diff --git a/riscv-coremark/coremark/core_main.c b/riscv-coremark/coremark/core_main.c index b5d5e6da..b1ec758b 100644 --- a/riscv-coremark/coremark/core_main.c +++ b/riscv-coremark/coremark/core_main.c @@ -17,383 +17,431 @@ Original Author: Shay Gal-on */ /* File: core_main.c - This file contains the framework to acquire a block of memory, seed initial parameters, tun t he benchmark and report the results. + This file contains the framework to acquire a block of memory, seed + initial parameters, tun t he benchmark and report the results. */ #include "coremark.h" /* Function: iterate - Run the benchmark for a specified number of iterations. + Run the benchmark for a specified number of iterations. - Operation: - For each type of benchmarked algorithm: - a - Initialize the data block for the algorithm. - b - Execute the algorithm N times. + Operation: + For each type of benchmarked algorithm: + a - Initialize the data block for the algorithm. + b - Execute the algorithm N times. - Returns: - NULL. + Returns: + NULL. */ -static ee_u16 list_known_crc[] = {(ee_u16)0xd4b0,(ee_u16)0x3340,(ee_u16)0x6a79,(ee_u16)0xe714,(ee_u16)0xe3c1}; -static ee_u16 matrix_known_crc[] = {(ee_u16)0xbe52,(ee_u16)0x1199,(ee_u16)0x5608,(ee_u16)0x1fd7,(ee_u16)0x0747}; -static ee_u16 state_known_crc[] = {(ee_u16)0x5e47,(ee_u16)0x39bf,(ee_u16)0xe5a4,(ee_u16)0x8e3a,(ee_u16)0x8d84}; -int gg_printf(const char *fmt, ...); -int sendstring(const char *p); -void _send_char(char c); -void *iterate(void *pres) { - ee_u32 i; - ee_u16 crc; - core_results *res=(core_results *)pres; - ee_u32 iterations=res->iterations; - res->crc=0; - res->crclist=0; - res->crcmatrix=0; - res->crcstate=0; +static ee_u16 list_known_crc[] = { (ee_u16)0xd4b0, + (ee_u16)0x3340, + (ee_u16)0x6a79, + (ee_u16)0xe714, + (ee_u16)0xe3c1 }; +static ee_u16 matrix_known_crc[] = { (ee_u16)0xbe52, + (ee_u16)0x1199, + (ee_u16)0x5608, + (ee_u16)0x1fd7, + (ee_u16)0x0747 }; +static ee_u16 state_known_crc[] = { (ee_u16)0x5e47, + (ee_u16)0x39bf, + (ee_u16)0xe5a4, + (ee_u16)0x8e3a, + (ee_u16)0x8d84 }; +void * +iterate(void *pres) +{ + ee_u32 i; + ee_u16 crc; + core_results *res = (core_results *)pres; + ee_u32 iterations = res->iterations; + res->crc = 0; + res->crclist = 0; + res->crcmatrix = 0; + res->crcstate = 0; - for (i=0; icrc=crcu16(crc,res->crc); - crc=core_bench_list(res,-1); - res->crc=crcu16(crc,res->crc); - if (i==0) res->crclist=res->crc; - } - return NULL; + for (i = 0; i < iterations; i++) + { + crc = core_bench_list(res, 1); + res->crc = crcu16(crc, res->crc); + crc = core_bench_list(res, -1); + res->crc = crcu16(crc, res->crc); + if (i == 0) + res->crclist = res->crc; + } + return NULL; } -#if (SEED_METHOD==SEED_ARG) +#if (SEED_METHOD == SEED_ARG) ee_s32 get_seed_args(int i, int argc, char *argv[]); -#define get_seed(x) (ee_s16)get_seed_args(x,argc,argv) -#define get_seed_32(x) get_seed_args(x,argc,argv) +#define get_seed(x) (ee_s16) get_seed_args(x, argc, argv) +#define get_seed_32(x) get_seed_args(x, argc, argv) #else /* via function or volatile */ ee_s32 get_seed_32(int i); -#define get_seed(x) (ee_s16)get_seed_32(x) +#define get_seed(x) (ee_s16) get_seed_32(x) #endif -#if (MEM_METHOD==MEM_STATIC) +#if (MEM_METHOD == MEM_STATIC) ee_u8 static_memblk[TOTAL_DATA_SIZE]; #endif -char *mem_name[3] = {"Static","Heap","Stack"}; +char *mem_name[3] = { "Static", "Heap", "Stack" }; /* Function: main - Main entry routine for the benchmark. - This function is responsible for the following steps: + Main entry routine for the benchmark. + This function is responsible for the following steps: - 1 - Initialize input seeds from a source that cannot be determined at compile time. - 2 - Initialize memory block for use. - 3 - Run and time the benchmark. - 4 - Report results, testing the validity of the output if the seeds are known. + 1 - Initialize input seeds from a source that cannot be determined at + compile time. 2 - Initialize memory block for use. 3 - Run and time the + benchmark. 4 - Report results, testing the validity of the output if the + seeds are known. - Arguments: - 1 - first seed : Any value - 2 - second seed : Must be identical to first for iterations to be identical - 3 - third seed : Any value, should be at least an order of magnitude less then the input size, but bigger then 32. - 4 - Iterations : Special, if set to 0, iterations will be automatically determined such that the benchmark will run between 10 to 100 secs + Arguments: + 1 - first seed : Any value + 2 - second seed : Must be identical to first for iterations to be + identical 3 - third seed : Any value, should be at least an order of + magnitude less then the input size, but bigger then 32. 4 - Iterations : + Special, if set to 0, iterations will be automatically determined such that + the benchmark will run between 10 to 100 secs */ #if MAIN_HAS_NOARGC -MAIN_RETURN_TYPE main(void) { - int argc=0; - char *argv[1]; +MAIN_RETURN_TYPE +main(void) +{ + int argc = 0; + char *argv[1]; #else -MAIN_RETURN_TYPE main(int argc, char *argv[]) { +MAIN_RETURN_TYPE +main(int argc, char *argv[]) +{ #endif - //const char s[] = "Elizabeth"; - ee_printf("eeprint"); - //ee_printf("Trying to print: %d", 0); - /*gg_printf("Elizabeth");*/ - //sendstring("Elizabeth"); - - //sendstring(s); - //return(0); - ee_u16 i,j=0,num_algorithms=0; - ee_s16 known_id=-1,total_errors=0; - ee_u16 seedcrc=0; - CORE_TICKS total_time; - core_results results[MULTITHREAD]; -#if (MEM_METHOD==MEM_STACK) - ee_u8 stack_memblock[TOTAL_DATA_SIZE*MULTITHREAD]; + ee_printf("SHOWTIME\n"); + ee_u16 i, j = 0, num_algorithms = 0; + ee_s16 known_id = -1, total_errors = 0; + ee_u16 seedcrc = 0; + CORE_TICKS total_time; + core_results results[MULTITHREAD]; +#if (MEM_METHOD == MEM_STACK) + ee_u8 stack_memblock[TOTAL_DATA_SIZE * MULTITHREAD]; #endif - /* first call any initializations needed */ - portable_init(&(results[0].port), &argc, argv); - /* First some checks to make sure benchmark will run ok */ - if (sizeof(struct list_head_s)>128) { - ee_printf("list_head structure too big for comparable data!\n"); - return MAIN_RETURN_VAL; - } - results[0].seed1=get_seed(1); - results[0].seed2=get_seed(2); - results[0].seed3=get_seed(3); - results[0].iterations=get_seed_32(4); + /* first call any initializations needed */ + portable_init(&(results[0].port), &argc, argv); + /* First some checks to make sure benchmark will run ok */ + if (sizeof(struct list_head_s) > 128) + { + ee_printf("list_head structure too big for comparable data!\n"); + return MAIN_RETURN_VAL; + } + results[0].seed1 = get_seed(1); + results[0].seed2 = get_seed(2); + results[0].seed3 = get_seed(3); + results[0].iterations = get_seed_32(4); #if CORE_DEBUG - results[0].iterations=1; + results[0].iterations = 1; #endif - results[0].execs=get_seed_32(5); - if (results[0].execs==0) { /* if not supplied, execute all algorithms */ - results[0].execs=ALL_ALGORITHMS_MASK; - } - /* put in some default values based on one seed only for easy testing */ - if ((results[0].seed1==0) && (results[0].seed2==0) && (results[0].seed3==0)) { /* validation run */ - results[0].seed1=0; - results[0].seed2=0; - results[0].seed3=0x66; - } - if ((results[0].seed1==1) && (results[0].seed2==0) && (results[0].seed3==0)) { /* perfromance run */ - results[0].seed1=0x3415; - results[0].seed2=0x3415; - results[0].seed3=0x66; - } -#if (MEM_METHOD==MEM_STATIC) - results[0].memblock[0]=(void *)static_memblk; - results[0].size=TOTAL_DATA_SIZE; - ee_printf("%d \n total data size", TOTAL_DATA_SIZE); - results[0].err=0; - #if (MULTITHREAD>1) - #error "Cannot use a static data area with multiple contexts!" - #endif -#elif (MEM_METHOD==MEM_MALLOC) - for (i=0 ; i 1) +#error "Cannot use a static data area with multiple contexts!" +#endif +#elif (MEM_METHOD == MEM_MALLOC) + for (i = 0; i < MULTITHREAD; i++) + { + ee_s32 malloc_override = get_seed(7); + if (malloc_override != 0) + results[i].size = malloc_override; + else + results[i].size = TOTAL_DATA_SIZE; + results[i].memblock[0] = portable_malloc(results[i].size); + results[i].seed1 = results[0].seed1; + results[i].seed2 = results[0].seed2; + results[i].seed3 = results[0].seed3; + results[i].err = 0; + results[i].execs = results[0].execs; + } +#elif (MEM_METHOD == MEM_STACK) +for (i = 0; i < MULTITHREAD; i++) +{ + results[i].memblock[0] = stack_memblock + i * TOTAL_DATA_SIZE; + results[i].size = TOTAL_DATA_SIZE; + results[i].seed1 = results[0].seed1; + results[i].seed2 = results[0].seed2; + results[i].seed3 = results[0].seed3; + results[i].err = 0; + results[i].execs = results[0].execs; +} #else #error "Please define a way to initialize a memory block." #endif - /* Data init */ - /* Find out how space much we have based on number of algorithms */ - for (i=0; i1) - if (default_num_contexts>MULTITHREAD) { - default_num_contexts=MULTITHREAD; - } - for (i=0 ; i 1) + if (default_num_contexts > MULTITHREAD) + { + default_num_contexts = MULTITHREAD; + } + for (i = 0; i < default_num_contexts; i++) + { + results[i].iterations = results[0].iterations; + results[i].execs = results[0].execs; + core_start_parallel(&results[i]); + } + for (i = 0; i < default_num_contexts; i++) + { + core_stop_parallel(&results[i]); + } #else - iterate(&results[0]); + iterate(&results[0]); #endif - stop_time(); - total_time=get_time(); - ee_printf("total time is %u\n", total_time); - ee_printf("ending benchmark\n"); - /* get a function of the input to report */ - seedcrc=crc16(results[0].seed1,seedcrc); - seedcrc=crc16(results[0].seed2,seedcrc); - seedcrc=crc16(results[0].seed3,seedcrc); - seedcrc=crc16(results[0].size,seedcrc); - - switch (seedcrc) { /* test known output for common seeds */ - case 0x8a02: /* seed1=0, seed2=0, seed3=0x66, size 2000 per algorithm */ - known_id=0; - ee_printf("6k performance run parameters for coremark.\n"); - break; - case 0x7b05: /* seed1=0x3415, seed2=0x3415, seed3=0x66, size 2000 per algorithm */ - known_id=1; - ee_printf("6k validation run parameters for coremark.\n"); - break; - case 0x4eaf: /* seed1=0x8, seed2=0x8, seed3=0x8, size 400 per algorithm */ - known_id=2; - ee_printf("Profile generation run parameters for coremark.\n"); - break; - case 0xe9f5: /* seed1=0, seed2=0, seed3=0x66, size 666 per algorithm */ - known_id=3; - ee_printf("2K performance run parameters for coremark.\n"); - break; - case 0x18f2: /* seed1=0x3415, seed2=0x3415, seed3=0x66, size 666 per algorithm */ - known_id=4; - ee_printf("2K validation run parameters for coremark.\n"); - break; - default: - total_errors=-1; - break; - } - if (known_id>=0) { - for (i=0 ; i 0) - ee_printf("Iterations/Sec : %f\n",default_num_contexts*results[0].iterations/time_in_secs(total_time)); -#else - ee_printf("Total time (secs): %d\n,time_in_secs(total_time)"); - if (time_in_secs(total_time) > 0) - ee_printf("Iterations/Sec : %d\n",default_num_contexts*results[0].iterations/time_in_secs(total_time)); -#endif - if (time_in_secs(total_time) < 10) { - ee_printf("ERROR! Must execute for at least 10 secs for a valid result!\n"); - total_errors++; - } + stop_time(); + total_time = get_time(); + /* get a function of the input to report */ + seedcrc = crc16(results[0].seed1, seedcrc); + seedcrc = crc16(results[0].seed2, seedcrc); + seedcrc = crc16(results[0].seed3, seedcrc); + seedcrc = crc16(results[0].size, seedcrc); - ee_printf("Iterations : %lu\n", (long unsigned) default_num_contexts*results[0].iterations); - ee_printf("Compiler version : %s\n",COMPILER_VERSION); - ee_printf("Compiler flags : %s\n",COMPILER_FLAGS); -#if (MULTITHREAD>1) - ee_printf("Parallel %s : %d\n",PARALLEL_METHOD,default_num_contexts); -#endif - ee_printf("Memory location : %s\n",MEM_LOCATION); - /* output for verification */ - ee_printf("seedcrc : 0x%04x\n",seedcrc); - if (results[0].execs & ID_LIST) - for (i=0 ; i= 0) + { + for (i = 0; i < default_num_contexts; i++) + { + results[i].err = 0; + if ((results[i].execs & ID_LIST) + && (results[i].crclist != list_known_crc[known_id])) + { + ee_printf("[%u]ERROR! list crc 0x%04x - should be 0x%04x\n", + i, + results[i].crclist, + list_known_crc[known_id]); + results[i].err++; + } + if ((results[i].execs & ID_MATRIX) + && (results[i].crcmatrix != matrix_known_crc[known_id])) + { + ee_printf("[%u]ERROR! matrix crc 0x%04x - should be 0x%04x\n", + i, + results[i].crcmatrix, + matrix_known_crc[known_id]); + results[i].err++; + } + if ((results[i].execs & ID_STATE) + && (results[i].crcstate != state_known_crc[known_id])) + { + ee_printf("[%u]ERROR! state crc 0x%04x - should be 0x%04x\n", + i, + results[i].crcstate, + state_known_crc[known_id]); + results[i].err++; + } + total_errors += results[i].err; + } + } + total_errors += check_data_types(); + /* and report results */ + ee_printf("CoreMark Size : %lu\n", (long unsigned)results[0].size); + ee_printf("Total ticks : %lu\n", (long unsigned)total_time); #if HAS_FLOAT - if (known_id==3) { - unsigned long long tmp = (unsigned long long) 1000.0*default_num_contexts*results[0].iterations/time_in_secs(total_time); + ee_printf("Total time (secs): %f\n", time_in_secs(total_time)); + if (time_in_secs(total_time) > 0) + ee_printf("Iterations/Sec : %f\n", + default_num_contexts * results[0].iterations + / time_in_secs(total_time)); +#else + ee_printf("Total time (secs): %d\n", time_in_secs(total_time)); + if (time_in_secs(total_time) > 0) + ee_printf("Iterations/Sec : %d\n", + default_num_contexts * results[0].iterations + / time_in_secs(total_time)); +#endif + if (time_in_secs(total_time) < 10) + { + ee_printf( + "ERROR! Must execute for at least 10 secs for a valid result!\n"); + total_errors++; + } + + ee_printf("Iterations : %lu\n", + (long unsigned)default_num_contexts * results[0].iterations); + ee_printf("Compiler version : %s\n", COMPILER_VERSION); + ee_printf("Compiler flags : %s\n", COMPILER_FLAGS); +#if (MULTITHREAD > 1) + ee_printf("Parallel %s : %d\n", PARALLEL_METHOD, default_num_contexts); +#endif + ee_printf("Memory location : %s\n", MEM_LOCATION); + /* output for verification */ + ee_printf("seedcrc : 0x%04x\n", seedcrc); + if (results[0].execs & ID_LIST) + for (i = 0; i < default_num_contexts; i++) + ee_printf("[%d]crclist : 0x%04x\n", i, results[i].crclist); + if (results[0].execs & ID_MATRIX) + for (i = 0; i < default_num_contexts; i++) + ee_printf("[%d]crcmatrix : 0x%04x\n", i, results[i].crcmatrix); + if (results[0].execs & ID_STATE) + for (i = 0; i < default_num_contexts; i++) + ee_printf("[%d]crcstate : 0x%04x\n", i, results[i].crcstate); + for (i = 0; i < default_num_contexts; i++) + ee_printf("[%d]crcfinal : 0x%04x\n", i, results[i].crc); + if (total_errors == 0) + { + ee_printf( + "Correct operation validated. See README.md for run and reporting " + "rules.\n"); +#if HAS_FLOAT + if (known_id == 3) + { + unsigned long long tmp = (unsigned long long) 1000.0*default_num_contexts*results[0].iterations/time_in_secs(total_time); secs_ret totalmsecs = time_in_secs(total_time); int totalmint = (int) totalmsecs; ee_printf("ELAPSED TIME: %d\n", totalmint); - ee_printf("CoreMark 1.0 : %d / %s %s\n",tmp,COMPILER_VERSION,COMPILER_FLAGS); + ee_printf("CoreMark 1.0 : %d / %s %s", + tmp, + COMPILER_VERSION, + COMPILER_FLAGS); #if defined(MEM_LOCATION) && !defined(MEM_LOCATION_UNSPEC) - ee_printf(" / %s",MEM_LOCATION); + ee_printf(" / %s", MEM_LOCATION); #else - ee_printf(" / %s",mem_name[MEM_METHOD]); + ee_printf(" / %s", mem_name[MEM_METHOD]); #endif -#if (MULTITHREAD>1) - ee_printf(" / %d:%s",default_num_contexts,PARALLEL_METHOD); +#if (MULTITHREAD > 1) + ee_printf(" / %d:%s", default_num_contexts, PARALLEL_METHOD); #endif - ee_printf("\n"); - } + ee_printf("\n"); + } #endif - } - if (total_errors>0) - ee_printf("Errors detected\n"); - if (total_errors<0) - ee_printf("Cannot validate operation for these seed values, please compare with results on a known platform.\n"); + } + if (total_errors > 0) + ee_printf("Errors detected\n"); + if (total_errors < 0) + ee_printf( + "Cannot validate operation for these seed values, please compare " + "with results on a known platform.\n"); -#if (MEM_METHOD==MEM_MALLOC) - for (i=0 ; i>(from)) & (~(0xffffffff << (to)))) +#define matrix_test_next(x) (x + 1) +#define matrix_clip(x, y) ((y) ? (x)&0x0ff : (x)&0x0ffff) +#define matrix_big(x) (0xf000 | (x)) +#define bit_extract(x, from, to) (((x) >> (from)) & (~(0xffffffff << (to)))) #if CORE_DEBUG -void printmat(MATDAT *A, ee_u32 N, char *name) { - ee_u32 i,j; - ee_printf("Matrix %s [%dx%d]:\n",name,N,N); - for (i=0; i N times, - changing the matrix values slightly by a constant amount each time. + Iterate N times, + changing the matrix values slightly by a constant amount each time. */ -ee_u16 core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc) { - ee_u32 N=p->N; - MATRES *C=p->C; - MATDAT *A=p->A; - MATDAT *B=p->B; - MATDAT val=(MATDAT)seed; +ee_u16 +core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc) +{ + ee_u32 N = p->N; + MATRES *C = p->C; + MATDAT *A = p->A; + MATDAT *B = p->B; + MATDAT val = (MATDAT)seed; - crc=crc16(matrix_test(N,C,A,B,val),crc); + crc = crc16(matrix_test(N, C, A, B, val), crc); - return crc; + return crc; } /* Function: matrix_test - Perform matrix manipulation. + Perform matrix manipulation. - Parameters: - N - Dimensions of the matrix. - C - memory for result matrix. - A - input matrix - B - operator matrix (not changed during operations) + Parameters: + N - Dimensions of the matrix. + C - memory for result matrix. + A - input matrix + B - operator matrix (not changed during operations) - Returns: - A CRC value that captures all results calculated in the function. - In particular, crc of the value calculated on the result matrix - after each step by . + Returns: + A CRC value that captures all results calculated in the function. + In particular, crc of the value calculated on the result matrix + after each step by . - Operation: - - 1 - Add a constant value to all elements of a matrix. - 2 - Multiply a matrix by a constant. - 3 - Multiply a matrix by a vector. - 4 - Multiply a matrix by a matrix. - 5 - Add a constant value to all elements of a matrix. + Operation: - After the last step, matrix A is back to original contents. + 1 - Add a constant value to all elements of a matrix. + 2 - Multiply a matrix by a constant. + 3 - Multiply a matrix by a vector. + 4 - Multiply a matrix by a matrix. + 5 - Add a constant value to all elements of a matrix. + + After the last step, matrix A is back to original contents. */ -ee_s16 matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val) { - ee_u16 crc=0; - MATDAT clipval=matrix_big(val); +ee_s16 +matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val) +{ + ee_u16 crc = 0; + MATDAT clipval = matrix_big(val); - matrix_add_const(N,A,val); /* make sure data changes */ + matrix_add_const(N, A, val); /* make sure data changes */ #if CORE_DEBUG - printmat(A,N,"matrix_add_const"); + printmat(A, N, "matrix_add_const"); #endif - matrix_mul_const(N,C,A,val); - crc=crc16(matrix_sum(N,C,clipval),crc); + matrix_mul_const(N, C, A, val); + crc = crc16(matrix_sum(N, C, clipval), crc); #if CORE_DEBUG - printmatC(C,N,"matrix_mul_const"); + printmatC(C, N, "matrix_mul_const"); #endif - matrix_mul_vect(N,C,A,B); - crc=crc16(matrix_sum(N,C,clipval),crc); + matrix_mul_vect(N, C, A, B); + crc = crc16(matrix_sum(N, C, clipval), crc); #if CORE_DEBUG - printmatC(C,N,"matrix_mul_vect"); + printmatC(C, N, "matrix_mul_vect"); #endif - matrix_mul_matrix(N,C,A,B); - crc=crc16(matrix_sum(N,C,clipval),crc); + matrix_mul_matrix(N, C, A, B); + crc = crc16(matrix_sum(N, C, clipval), crc); #if CORE_DEBUG - printmatC(C,N,"matrix_mul_matrix"); + printmatC(C, N, "matrix_mul_matrix"); #endif - matrix_mul_matrix_bitextract(N,C,A,B); - crc=crc16(matrix_sum(N,C,clipval),crc); + matrix_mul_matrix_bitextract(N, C, A, B); + crc = crc16(matrix_sum(N, C, clipval), crc); #if CORE_DEBUG - printmatC(C,N,"matrix_mul_matrix_bitextract"); + printmatC(C, N, "matrix_mul_matrix_bitextract"); #endif - - matrix_add_const(N,A,-val); /* return matrix to initial value */ - return crc; + + matrix_add_const(N, A, -val); /* return matrix to initial value */ + return crc; } /* Function : matrix_init - Initialize the memory block for matrix benchmarking. + Initialize the memory block for matrix benchmarking. - Parameters: - blksize - Size of memory to be initialized. - memblk - Pointer to memory block. - seed - Actual values chosen depend on the seed parameter. - p - pointers to containing initialized matrixes. + Parameters: + blksize - Size of memory to be initialized. + memblk - Pointer to memory block. + seed - Actual values chosen depend on the seed parameter. + p - pointers to containing initialized matrixes. - Returns: - Matrix dimensions. - - Note: - The seed parameter MUST be supplied from a source that cannot be determined at compile time + Returns: + Matrix dimensions. + + Note: + The seed parameter MUST be supplied from a source that cannot be + determined at compile time */ -ee_u32 core_init_matrix(ee_u32 blksize, void *memblk, ee_s32 seed, mat_params *p) { - ee_u32 N=0; - MATDAT *A; - MATDAT *B; - ee_s32 order=1; - MATDAT val; - ee_u32 i=0,j=0; - if (seed==0) - seed=1; - while (jA=A; - p->B=B; - p->C=(MATRES *)align_mem(B+N*N); - p->N=N; + p->A = A; + p->B = B; + p->C = (MATRES *)align_mem(B + N * N); + p->N = N; #if CORE_DEBUG - printmat(A,N,"A"); - printmat(B,N,"B"); + printmat(A, N, "A"); + printmat(B, N, "B"); #endif - return N; + return N; } /* Function: matrix_sum - Calculate a function that depends on the values of elements in the matrix. + Calculate a function that depends on the values of elements in the + matrix. - For each element, accumulate into a temporary variable. - - As long as this value is under the parameter clipval, - add 1 to the result if the element is bigger then the previous. - - Otherwise, reset the accumulator and add 10 to the result. + For each element, accumulate into a temporary variable. + + As long as this value is under the parameter clipval, + add 1 to the result if the element is bigger then the previous. + + Otherwise, reset the accumulator and add 10 to the result. */ -ee_s16 matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval) { - MATRES tmp=0,prev=0,cur=0; - ee_s16 ret=0; - ee_u32 i,j; - for (i=0; iclipval) { - ret+=10; - tmp=0; - } else { - ret += (cur>prev) ? 1 : 0; - } - prev=cur; - } - } - return ret; +ee_s16 +matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval) +{ + MATRES tmp = 0, prev = 0, cur = 0; + ee_s16 ret = 0; + ee_u32 i, j; + for (i = 0; i < N; i++) + { + for (j = 0; j < N; j++) + { + cur = C[i * N + j]; + tmp += cur; + if (tmp > clipval) + { + ret += 10; + tmp = 0; + } + else + { + ret += (cur > prev) ? 1 : 0; + } + prev = cur; + } + } + return ret; } /* Function: matrix_mul_const - Multiply a matrix by a constant. - This could be used as a scaler for instance. + Multiply a matrix by a constant. + This could be used as a scaler for instance. */ -void matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val) { - ee_u32 i,j; - for (i=0; i0) { - for(i=0;i>3) & 0x3]; - next=4; - break; - case 3: /* float */ - case 4: /* float */ - buf=floatpat[(seed>>3) & 0x3]; - next=8; - break; - case 5: /* scientific */ - case 6: /* scientific */ - buf=scipat[(seed>>3) & 0x3]; - next=8; - break; - case 7: /* invalid */ - buf=errpat[(seed>>3) & 0x3]; - next=8; - break; - default: /* Never happen, just to make some compilers happy */ - break; - } - } - size++; - while (total 0) + { + for (i = 0; i < next; i++) + *(p + total + i) = buf[i]; + *(p + total + i) = ','; + total += next + 1; + } + seed++; + switch (seed & 0x7) + { + case 0: /* int */ + case 1: /* int */ + case 2: /* int */ + buf = intpat[(seed >> 3) & 0x3]; + next = 4; + break; + case 3: /* float */ + case 4: /* float */ + buf = floatpat[(seed >> 3) & 0x3]; + next = 8; + break; + case 5: /* scientific */ + case 6: /* scientific */ + buf = scipat[(seed >> 3) & 0x3]; + next = 8; + break; + case 7: /* invalid */ + buf = errpat[(seed >> 3) & 0x3]; + next = 8; + break; + default: /* Never happen, just to make some compilers happy */ + break; + } + } + size++; + while (total < size) + { /* fill the rest with 0 */ + *(p + total) = 0; + total++; + } #if CORE_DEBUG - ee_printf("State Input: %s\n",start); + ee_printf("State Input: %s\n", start); #endif } -static ee_u8 ee_isdigit(ee_u8 c) { - ee_u8 retval; - retval = ((c>='0') & (c<='9')) ? 1 : 0; - return retval; +static ee_u8 +ee_isdigit(ee_u8 c) +{ + ee_u8 retval; + retval = ((c >= '0') & (c <= '9')) ? 1 : 0; + return retval; } /* Function: core_state_transition - Actual state machine. + Actual state machine. - The state machine will continue scanning until either: - 1 - an invalid input is detcted. - 2 - a valid number has been detected. - - The input pointer is updated to point to the end of the token, and the end state is returned (either specific format determined or invalid). + The state machine will continue scanning until either: + 1 - an invalid input is detcted. + 2 - a valid number has been detected. + + The input pointer is updated to point to the end of the token, and the + end state is returned (either specific format determined or invalid). */ -enum CORE_STATE core_state_transition( ee_u8 **instr , ee_u32 *transition_count) { - ee_u8 *str=*instr; - ee_u8 NEXT_SYMBOL; - enum CORE_STATE state=CORE_START; - for( ; *str && state != CORE_INVALID; str++ ) { - NEXT_SYMBOL = *str; - if (NEXT_SYMBOL==',') /* end of this input */ { - str++; - break; - } - switch(state) { - case CORE_START: - if(ee_isdigit(NEXT_SYMBOL)) { - state = CORE_INT; - } - else if( NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-' ) { - state = CORE_S1; - } - else if( NEXT_SYMBOL == '.' ) { - state = CORE_FLOAT; - } - else { - state = CORE_INVALID; - transition_count[CORE_INVALID]++; - } - transition_count[CORE_START]++; - break; - case CORE_S1: - if(ee_isdigit(NEXT_SYMBOL)) { - state = CORE_INT; - transition_count[CORE_S1]++; - } - else if( NEXT_SYMBOL == '.' ) { - state = CORE_FLOAT; - transition_count[CORE_S1]++; - } - else { - state = CORE_INVALID; - transition_count[CORE_S1]++; - } - break; - case CORE_INT: - if( NEXT_SYMBOL == '.' ) { - state = CORE_FLOAT; - transition_count[CORE_INT]++; - } - else if(!ee_isdigit(NEXT_SYMBOL)) { - state = CORE_INVALID; - transition_count[CORE_INT]++; - } - break; - case CORE_FLOAT: - if( NEXT_SYMBOL == 'E' || NEXT_SYMBOL == 'e' ) { - state = CORE_S2; - transition_count[CORE_FLOAT]++; - } - else if(!ee_isdigit(NEXT_SYMBOL)) { - state = CORE_INVALID; - transition_count[CORE_FLOAT]++; - } - break; - case CORE_S2: - if( NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-' ) { - state = CORE_EXPONENT; - transition_count[CORE_S2]++; - } - else { - state = CORE_INVALID; - transition_count[CORE_S2]++; - } - break; - case CORE_EXPONENT: - if(ee_isdigit(NEXT_SYMBOL)) { - state = CORE_SCIENTIFIC; - transition_count[CORE_EXPONENT]++; - } - else { - state = CORE_INVALID; - transition_count[CORE_EXPONENT]++; - } - break; - case CORE_SCIENTIFIC: - if(!ee_isdigit(NEXT_SYMBOL)) { - state = CORE_INVALID; - transition_count[CORE_INVALID]++; - } - break; - default: - break; - } - } - *instr=str; - return state; +enum CORE_STATE +core_state_transition(ee_u8 **instr, ee_u32 *transition_count) +{ + ee_u8 * str = *instr; + ee_u8 NEXT_SYMBOL; + enum CORE_STATE state = CORE_START; + for (; *str && state != CORE_INVALID; str++) + { + NEXT_SYMBOL = *str; + if (NEXT_SYMBOL == ',') /* end of this input */ + { + str++; + break; + } + switch (state) + { + case CORE_START: + if (ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_INT; + } + else if (NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-') + { + state = CORE_S1; + } + else if (NEXT_SYMBOL == '.') + { + state = CORE_FLOAT; + } + else + { + state = CORE_INVALID; + transition_count[CORE_INVALID]++; + } + transition_count[CORE_START]++; + break; + case CORE_S1: + if (ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_INT; + transition_count[CORE_S1]++; + } + else if (NEXT_SYMBOL == '.') + { + state = CORE_FLOAT; + transition_count[CORE_S1]++; + } + else + { + state = CORE_INVALID; + transition_count[CORE_S1]++; + } + break; + case CORE_INT: + if (NEXT_SYMBOL == '.') + { + state = CORE_FLOAT; + transition_count[CORE_INT]++; + } + else if (!ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_INVALID; + transition_count[CORE_INT]++; + } + break; + case CORE_FLOAT: + if (NEXT_SYMBOL == 'E' || NEXT_SYMBOL == 'e') + { + state = CORE_S2; + transition_count[CORE_FLOAT]++; + } + else if (!ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_INVALID; + transition_count[CORE_FLOAT]++; + } + break; + case CORE_S2: + if (NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-') + { + state = CORE_EXPONENT; + transition_count[CORE_S2]++; + } + else + { + state = CORE_INVALID; + transition_count[CORE_S2]++; + } + break; + case CORE_EXPONENT: + if (ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_SCIENTIFIC; + transition_count[CORE_EXPONENT]++; + } + else + { + state = CORE_INVALID; + transition_count[CORE_EXPONENT]++; + } + break; + case CORE_SCIENTIFIC: + if (!ee_isdigit(NEXT_SYMBOL)) + { + state = CORE_INVALID; + transition_count[CORE_INVALID]++; + } + break; + default: + break; + } + } + *instr = str; + return state; } diff --git a/riscv-coremark/coremark/core_util.c b/riscv-coremark/coremark/core_util.c index 581adcc2..67c5d775 100644 --- a/riscv-coremark/coremark/core_util.c +++ b/riscv-coremark/coremark/core_util.c @@ -18,193 +18,232 @@ Original Author: Shay Gal-on #include "coremark.h" /* Function: get_seed - Get a values that cannot be determined at compile time. + Get a values that cannot be determined at compile time. - Since different embedded systems and compilers are used, 3 different methods are provided: - 1 - Using a volatile variable. This method is only valid if the compiler is forced to generate code that - reads the value of a volatile variable from memory at run time. - Please note, if using this method, you would need to modify core_portme.c to generate training profile. - 2 - Command line arguments. This is the preferred method if command line arguments are supported. - 3 - System function. If none of the first 2 methods is available on the platform, - a system function which is not a stub can be used. - - e.g. read the value on GPIO pins connected to switches, or invoke special simulator functions. + Since different embedded systems and compilers are used, 3 different + methods are provided: 1 - Using a volatile variable. This method is only + valid if the compiler is forced to generate code that reads the value of a + volatile variable from memory at run time. Please note, if using this method, + you would need to modify core_portme.c to generate training profile. 2 - + Command line arguments. This is the preferred method if command line + arguments are supported. 3 - System function. If none of the first 2 methods + is available on the platform, a system function which is not a stub can be + used. + + e.g. read the value on GPIO pins connected to switches, or invoke + special simulator functions. */ -#if (SEED_METHOD==SEED_VOLATILE) - extern volatile ee_s32 seed1_volatile; - extern volatile ee_s32 seed2_volatile; - extern volatile ee_s32 seed3_volatile; - extern volatile ee_s32 seed4_volatile; - extern volatile ee_s32 seed5_volatile; - ee_s32 get_seed_32(int i) { - ee_s32 retval; - switch (i) { - case 1: - retval=seed1_volatile; - break; - case 2: - retval=seed2_volatile; - break; - case 3: - retval=seed3_volatile; - break; - case 4: - retval=seed4_volatile; - break; - case 5: - retval=seed5_volatile; - break; - default: - retval=0; - break; - } - return retval; - } -#elif (SEED_METHOD==SEED_ARG) -ee_s32 parseval(char *valstring) { - ee_s32 retval=0; - ee_s32 neg=1; - int hexmode=0; - if (*valstring == '-') { - neg=-1; - valstring++; - } - if ((valstring[0] == '0') && (valstring[1] == 'x')) { - hexmode=1; - valstring+=2; - } - /* first look for digits */ - if (hexmode) { - while (((*valstring >= '0') && (*valstring <= '9')) || ((*valstring >= 'a') && (*valstring <= 'f'))) { - ee_s32 digit=*valstring-'0'; - if (digit>9) - digit=10+*valstring-'a'; - retval*=16; - retval+=digit; - valstring++; - } - } else { - while ((*valstring >= '0') && (*valstring <= '9')) { - ee_s32 digit=*valstring-'0'; - retval*=10; - retval+=digit; - valstring++; - } - } - /* now add qualifiers */ - if (*valstring=='K') - retval*=1024; - if (*valstring=='M') - retval*=1024*1024; +#if (SEED_METHOD == SEED_VOLATILE) +extern volatile ee_s32 seed1_volatile; +extern volatile ee_s32 seed2_volatile; +extern volatile ee_s32 seed3_volatile; +extern volatile ee_s32 seed4_volatile; +extern volatile ee_s32 seed5_volatile; +ee_s32 +get_seed_32(int i) +{ + ee_s32 retval; + switch (i) + { + case 1: + retval = seed1_volatile; + break; + case 2: + retval = seed2_volatile; + break; + case 3: + retval = seed3_volatile; + break; + case 4: + retval = seed4_volatile; + break; + case 5: + retval = seed5_volatile; + break; + default: + retval = 0; + break; + } + return retval; +} +#elif (SEED_METHOD == SEED_ARG) +ee_s32 +parseval(char *valstring) +{ + ee_s32 retval = 0; + ee_s32 neg = 1; + int hexmode = 0; + if (*valstring == '-') + { + neg = -1; + valstring++; + } + if ((valstring[0] == '0') && (valstring[1] == 'x')) + { + hexmode = 1; + valstring += 2; + } + /* first look for digits */ + if (hexmode) + { + while (((*valstring >= '0') && (*valstring <= '9')) + || ((*valstring >= 'a') && (*valstring <= 'f'))) + { + ee_s32 digit = *valstring - '0'; + if (digit > 9) + digit = 10 + *valstring - 'a'; + retval *= 16; + retval += digit; + valstring++; + } + } + else + { + while ((*valstring >= '0') && (*valstring <= '9')) + { + ee_s32 digit = *valstring - '0'; + retval *= 10; + retval += digit; + valstring++; + } + } + /* now add qualifiers */ + if (*valstring == 'K') + retval *= 1024; + if (*valstring == 'M') + retval *= 1024 * 1024; - retval*=neg; - return retval; + retval *= neg; + return retval; } -ee_s32 get_seed_args(int i, int argc, char *argv[]) { - if (argc>i) - return parseval(argv[i]); - return 0; +ee_s32 +get_seed_args(int i, int argc, char *argv[]) +{ + if (argc > i) + return parseval(argv[i]); + return 0; } -#elif (SEED_METHOD==SEED_FUNC) -/* If using OS based function, you must define and implement the functions below in core_portme.h and core_portme.c ! */ -ee_s32 get_seed_32(int i) { - ee_s32 retval; - switch (i) { - case 1: - retval=portme_sys1(); - break; - case 2: - retval=portme_sys2(); - break; - case 3: - retval=portme_sys3(); - break; - case 4: - retval=portme_sys4(); - break; - case 5: - retval=portme_sys5(); - break; - default: - retval=0; - break; - } - return retval; +#elif (SEED_METHOD == SEED_FUNC) +/* If using OS based function, you must define and implement the functions below + * in core_portme.h and core_portme.c ! */ +ee_s32 +get_seed_32(int i) +{ + ee_s32 retval; + switch (i) + { + case 1: + retval = portme_sys1(); + break; + case 2: + retval = portme_sys2(); + break; + case 3: + retval = portme_sys3(); + break; + case 4: + retval = portme_sys4(); + break; + case 5: + retval = portme_sys5(); + break; + default: + retval = 0; + break; + } + return retval; } #endif /* Function: crc* - Service functions to calculate 16b CRC code. + Service functions to calculate 16b CRC code. */ -ee_u16 crcu8(ee_u8 data, ee_u16 crc ) +ee_u16 +crcu8(ee_u8 data, ee_u16 crc) { - ee_u8 i=0,x16=0,carry=0; + ee_u8 i = 0, x16 = 0, carry = 0; - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { - x16 = (ee_u8)((data & 1) ^ ((ee_u8)crc & 1)); - data >>= 1; + x16 = (ee_u8)((data & 1) ^ ((ee_u8)crc & 1)); + data >>= 1; - if (x16 == 1) - { - crc ^= 0x4002; - carry = 1; - } - else - carry = 0; - crc >>= 1; - if (carry) - crc |= 0x8000; - else - crc &= 0x7fff; + if (x16 == 1) + { + crc ^= 0x4002; + carry = 1; + } + else + carry = 0; + crc >>= 1; + if (carry) + crc |= 0x8000; + else + crc &= 0x7fff; } - return crc; -} -ee_u16 crcu16(ee_u16 newval, ee_u16 crc) { - crc=crcu8( (ee_u8) (newval) ,crc); - crc=crcu8( (ee_u8) ((newval)>>8) ,crc); - return crc; + return crc; } -ee_u16 crcu32(ee_u32 newval, ee_u16 crc) { - crc=crc16((ee_s16) newval ,crc); - crc=crc16((ee_s16) (newval>>16) ,crc); - return crc; +ee_u16 +crcu16(ee_u16 newval, ee_u16 crc) +{ + crc = crcu8((ee_u8)(newval), crc); + crc = crcu8((ee_u8)((newval) >> 8), crc); + return crc; } -ee_u16 crc16(ee_s16 newval, ee_u16 crc) { - return crcu16((ee_u16)newval, crc); +ee_u16 +crcu32(ee_u32 newval, ee_u16 crc) +{ + crc = crc16((ee_s16)newval, crc); + crc = crc16((ee_s16)(newval >> 16), crc); + return crc; +} +ee_u16 +crc16(ee_s16 newval, ee_u16 crc) +{ + return crcu16((ee_u16)newval, crc); } -ee_u8 check_data_types() { - ee_u8 retval=0; - if (sizeof(ee_u8) != 1) { - ee_printf("ERROR: ee_u8 is not an 8b datatype!\n"); - retval++; - } - if (sizeof(ee_u16) != 2) { - ee_printf("ERROR: ee_u16 is not a 16b datatype!\n"); - retval++; - } - if (sizeof(ee_s16) != 2) { - ee_printf("ERROR: ee_s16 is not a 16b datatype!\n"); - retval++; - } - if (sizeof(ee_s32) != 4) { - ee_printf("ERROR: ee_s32 is not a 32b datatype!\n"); - retval++; - } - if (sizeof(ee_u32) != 4) { - ee_printf("ERROR: ee_u32 is not a 32b datatype!\n"); - retval++; - } - if (sizeof(ee_ptr_int) != sizeof(int *)) { - ee_printf("ERROR: ee_ptr_int is not a datatype that holds an int pointer!\n"); - retval++; - } - if (retval>0) { - ee_printf("ERROR: Please modify the datatypes in core_portme.h!\n"); - } - return retval; +ee_u8 +check_data_types() +{ + ee_u8 retval = 0; + if (sizeof(ee_u8) != 1) + { + ee_printf("ERROR: ee_u8 is not an 8b datatype!\n"); + retval++; + } + if (sizeof(ee_u16) != 2) + { + ee_printf("ERROR: ee_u16 is not a 16b datatype!\n"); + retval++; + } + if (sizeof(ee_s16) != 2) + { + ee_printf("ERROR: ee_s16 is not a 16b datatype!\n"); + retval++; + } + if (sizeof(ee_s32) != 4) + { + ee_printf("ERROR: ee_s32 is not a 32b datatype!\n"); + retval++; + } + if (sizeof(ee_u32) != 4) + { + ee_printf("ERROR: ee_u32 is not a 32b datatype!\n"); + retval++; + } + if (sizeof(ee_ptr_int) != sizeof(int *)) + { + ee_printf( + "ERROR: ee_ptr_int is not a datatype that holds an int pointer!\n"); + retval++; + } + if (retval > 0) + { + ee_printf("ERROR: Please modify the datatypes in core_portme.h!\n"); + } + return retval; } diff --git a/riscv-coremark/coremark/coremark.h b/riscv-coremark/coremark/coremark.h index dc9f8c7a..9c5e4060 100644 --- a/riscv-coremark/coremark/coremark.h +++ b/riscv-coremark/coremark/coremark.h @@ -17,23 +17,23 @@ Original Author: Shay Gal-on */ /* Topic: Description - This file contains declarations of the various benchmark functions. + This file contains declarations of the various benchmark functions. */ /* Configuration: TOTAL_DATA_SIZE - Define total size for data algorithms will operate on + Define total size for data algorithms will operate on */ -#ifndef TOTAL_DATA_SIZE -#define TOTAL_DATA_SIZE 2*1000 +#ifndef TOTAL_DATA_SIZE +#define TOTAL_DATA_SIZE 2 * 1000 #endif -#define SEED_ARG 0 -#define SEED_FUNC 1 +#define SEED_ARG 0 +#define SEED_FUNC 1 #define SEED_VOLATILE 2 #define MEM_STATIC 0 #define MEM_MALLOC 1 -#define MEM_STACK 2 +#define MEM_STACK 2 #include "core_portme.h" @@ -48,8 +48,8 @@ Original Author: Shay Gal-on void *iterate(void *pres); /* Typedef: secs_ret - For machines that have floating point support, get number of seconds as a double. - Otherwise an unsigned int. + For machines that have floating point support, get number of seconds as + a double. Otherwise an unsigned int. */ #if HAS_FLOAT typedef double secs_ret; @@ -58,47 +58,48 @@ typedef ee_u32 secs_ret; #endif #if MAIN_HAS_NORETURN -#define MAIN_RETURN_VAL +#define MAIN_RETURN_VAL #define MAIN_RETURN_TYPE void #else -#define MAIN_RETURN_VAL 0 +#define MAIN_RETURN_VAL 0 #define MAIN_RETURN_TYPE int -#endif +#endif -void start_time(void); -void stop_time(void); +void start_time(void); +void stop_time(void); CORE_TICKS get_time(void); -secs_ret time_in_secs(CORE_TICKS ticks); +secs_ret time_in_secs(CORE_TICKS ticks); /* Misc useful functions */ ee_u16 crcu8(ee_u8 data, ee_u16 crc); ee_u16 crc16(ee_s16 newval, ee_u16 crc); ee_u16 crcu16(ee_u16 newval, ee_u16 crc); ee_u16 crcu32(ee_u32 newval, ee_u16 crc); -ee_u8 check_data_types(); -void *portable_malloc(ee_size_t size); -void portable_free(void *p); +ee_u8 check_data_types(void); +void * portable_malloc(ee_size_t size); +void portable_free(void *p); ee_s32 parseval(char *valstring); /* Algorithm IDS */ -#define ID_LIST (1<<0) -#define ID_MATRIX (1<<1) -#define ID_STATE (1<<2) -#define ALL_ALGORITHMS_MASK (ID_LIST|ID_MATRIX|ID_STATE) -#define NUM_ALGORITHMS 3 +#define ID_LIST (1 << 0) +#define ID_MATRIX (1 << 1) +#define ID_STATE (1 << 2) +#define ALL_ALGORITHMS_MASK (ID_LIST | ID_MATRIX | ID_STATE) +#define NUM_ALGORITHMS 3 /* list data structures */ -typedef struct list_data_s { - ee_s16 data16; - ee_s16 idx; +typedef struct list_data_s +{ + ee_s16 data16; + ee_s16 idx; } list_data; -typedef struct list_head_s { - struct list_head_s *next; - struct list_data_s *info; +typedef struct list_head_s +{ + struct list_head_s *next; + struct list_data_s *info; } list_head; - /*matrix benchmark related stuff */ #define MATDAT_INT 1 #if MATDAT_INT @@ -109,66 +110,74 @@ typedef ee_f16 MATDAT; typedef ee_f32 MATRES; #endif -typedef struct MAT_PARAMS_S { - int N; - MATDAT *A; - MATDAT *B; - MATRES *C; +typedef struct MAT_PARAMS_S +{ + int N; + MATDAT *A; + MATDAT *B; + MATRES *C; } mat_params; /* state machine related stuff */ /* List of all the possible states for the FSM */ -typedef enum CORE_STATE { - CORE_START=0, - CORE_INVALID, - CORE_S1, - CORE_S2, - CORE_INT, - CORE_FLOAT, - CORE_EXPONENT, - CORE_SCIENTIFIC, - NUM_CORE_STATES -} core_state_e ; +typedef enum CORE_STATE +{ + CORE_START = 0, + CORE_INVALID, + CORE_S1, + CORE_S2, + CORE_INT, + CORE_FLOAT, + CORE_EXPONENT, + CORE_SCIENTIFIC, + NUM_CORE_STATES +} core_state_e; - /* Helper structure to hold results */ -typedef struct RESULTS_S { - /* inputs */ - ee_s16 seed1; /* Initializing seed */ - ee_s16 seed2; /* Initializing seed */ - ee_s16 seed3; /* Initializing seed */ - void *memblock[4]; /* Pointer to safe memory location */ - ee_u32 size; /* Size of the data */ - ee_u32 iterations; /* Number of iterations to execute */ - ee_u32 execs; /* Bitmask of operations to execute */ - struct list_head_s *list; - mat_params mat; - /* outputs */ - ee_u16 crc; - ee_u16 crclist; - ee_u16 crcmatrix; - ee_u16 crcstate; - ee_s16 err; - /* ultithread specific */ - core_portable port; +typedef struct RESULTS_S +{ + /* inputs */ + ee_s16 seed1; /* Initializing seed */ + ee_s16 seed2; /* Initializing seed */ + ee_s16 seed3; /* Initializing seed */ + void * memblock[4]; /* Pointer to safe memory location */ + ee_u32 size; /* Size of the data */ + ee_u32 iterations; /* Number of iterations to execute */ + ee_u32 execs; /* Bitmask of operations to execute */ + struct list_head_s *list; + mat_params mat; + /* outputs */ + ee_u16 crc; + ee_u16 crclist; + ee_u16 crcmatrix; + ee_u16 crcstate; + ee_s16 err; + /* ultithread specific */ + core_portable port; } core_results; /* Multicore execution handling */ -#if (MULTITHREAD>1) +#if (MULTITHREAD > 1) ee_u8 core_start_parallel(core_results *res); ee_u8 core_stop_parallel(core_results *res); #endif /* list benchmark functions */ list_head *core_list_init(ee_u32 blksize, list_head *memblock, ee_s16 seed); -ee_u16 core_bench_list(core_results *res, ee_s16 finder_idx); +ee_u16 core_bench_list(core_results *res, ee_s16 finder_idx); /* state benchmark functions */ -void core_init_state(ee_u32 size, ee_s16 seed, ee_u8 *p); -ee_u16 core_bench_state(ee_u32 blksize, ee_u8 *memblock, - ee_s16 seed1, ee_s16 seed2, ee_s16 step, ee_u16 crc); +void core_init_state(ee_u32 size, ee_s16 seed, ee_u8 *p); +ee_u16 core_bench_state(ee_u32 blksize, + ee_u8 *memblock, + ee_s16 seed1, + ee_s16 seed2, + ee_s16 step, + ee_u16 crc); /* matrix benchmark functions */ -ee_u32 core_init_matrix(ee_u32 blksize, void *memblk, ee_s32 seed, mat_params *p); +ee_u32 core_init_matrix(ee_u32 blksize, + void * memblk, + ee_s32 seed, + mat_params *p); ee_u16 core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc); - diff --git a/riscv-coremark/coremark/coremark.md5 b/riscv-coremark/coremark/coremark.md5 new file mode 100644 index 00000000..94160db2 --- /dev/null +++ b/riscv-coremark/coremark/coremark.md5 @@ -0,0 +1,6 @@ +8d082dc4a9676c02731a8cf209339072 core_list_join.c +c984863b84b59185d8b5fb81c1ca7535 core_main.c +5fa21a0f7c3964167c9691db531ca652 core_matrix.c +edcfc7a0b146a50028014f06e6826aa3 core_state.c +45540ba2145adea1ec7ea2c72a1fbbcb core_util.c +8ca974c013b380dc7f0d6d1afb76eb2d coremark.h diff --git a/riscv-coremark/coremark/cygwin/core_portme.mak b/riscv-coremark/coremark/cygwin/core_portme.mak old mode 100755 new mode 100644 index 721ba2e3..97b6d6ac --- a/riscv-coremark/coremark/cygwin/core_portme.mak +++ b/riscv-coremark/coremark/cygwin/core_portme.mak @@ -14,128 +14,4 @@ # # Original Author: Shay Gal-on -#File: core_portme.mak - -# Flag: OUTFLAG -# Use this flag to define how to to get an executable (e.g -o) -OUTFLAG= -o -# Flag: CC -# Use this flag to define compiler to use -CC = gcc -# Flag: CFLAGS -# Use this flag to define compiler options. Note, you can add compiler options from the command line using XCFLAGS="other flags" -PORT_CFLAGS = -O2 -FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)" -CFLAGS = $(PORT_CFLAGS) -I$(PORT_DIR) -I. -DFLAGS_STR=\"$(FLAGS_STR)\" -#Flag: LFLAGS_END -# Define any libraries needed for linking or other flags that should come at the end of the link line (e.g. linker scripts). -# Note: On certain platforms, the default clock_gettime implementation is supported but requires linking of librt. -LFLAGS_END = -# Flag: PORT_SRCS -# Port specific source files can be added here -PORT_SRCS = $(PORT_DIR)/core_portme.c -# Flag: LOAD -# Define this flag if you need to load to a target, as in a cross compile environment. - -# Flag: RUN -# Define this flag if running does not consist of simple invocation of the binary. -# In a cross compile environment, you need to define this. - -#For flashing and using a tera term macro, you could use -#LOAD = flash ADDR -#RUN = ttpmacro coremark.ttl - -#For copying to target and executing via SSH connection, you could use -#LOAD = scp $(OUTFILE) user@target:~ -#RUN = ssh user@target -c - -#For native compilation and execution -LOAD = echo Loading done -RUN = - -OEXT = .o -EXE = .exe - -# Flag: SEPARATE_COMPILE -# Define if you need to separate compilation from link stage. -# In this case, you also need to define below how to create an object file, and how to link. -ifdef SEPARATE_COMPILE - -LD = gcc -OBJOUT = -o -LFLAGS = -OFLAG = -o -COUT = -c -# Flag: PORT_OBJS -# Port specific object files can be added here -PORT_OBJS = $(PORT_DIR)/core_portme$(OEXT) -PORT_CLEAN = *$(OEXT) - -$(OPATH)%$(OEXT) : %.c - $(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@ - -endif - -# Target: port_prebuild -# Generate any files that are needed before actual build starts. -# E.g. generate profile guidance files. Sample PGO generation for gcc enabled with PGO=1 -# - First, check if PGO was defined on the command line, if so, need to add -fprofile-use to compile line. -# - Second, if PGO reference has not yet been generated, add a step to the prebuild that will build a profile-generate version and run it. -# Note - Using REBUILD=1 -# -# Use make PGO=1 to invoke this sample processing. - -ifdef PGO - ifeq (,$(findstring $(PGO),gen)) - PGO_STAGE=build_pgo_gcc - CFLAGS+=-fprofile-use - endif - PORT_CLEAN+=*.gcda *.gcno gmon.out -endif - -.PHONY: port_prebuild -port_prebuild: $(PGO_STAGE) - -.PHONY: build_pgo_gcc -build_pgo_gcc: - $(MAKE) PGO=gen XCFLAGS="$(XCFLAGS) -fprofile-generate -DTOTAL_DATA_SIZE=1200" ITERATIONS=10 gen_pgo_data REBUILD=1 - -# Target: port_postbuild -# Generate any files that are needed after actual build end. -# E.g. change format to srec, bin, zip in order to be able to load into flash -.PHONY: port_postbuild -port_postbuild: - -# Target: port_postrun -# Do platform specific after run stuff. -# E.g. reset the board, backup the logfiles etc. -.PHONY: port_postrun -port_postrun: - -# Target: port_prerun -# Do platform specific after run stuff. -# E.g. reset the board, backup the logfiles etc. -.PHONY: port_prerun -port_prerun: - -# Target: port_postload -# Do platform specific after load stuff. -# E.g. reset the reset power to the flash eraser -.PHONY: port_postload -port_postload: - -# Target: port_preload -# Do platform specific before load stuff. -# E.g. reset the reset power to the flash eraser -.PHONY: port_preload -port_preload: - - -# FLAG: OPATH -# Path to the output folder. Default - current folder. -OPATH = ./ -MKDIR = mkdir -p - -# FLAG: PERL -# Define perl executable to calculate the geomean if running separate. -PERL=perl +include posix/core_portme.mak diff --git a/riscv-coremark/coremark/freebsd/core_portme.mak b/riscv-coremark/coremark/freebsd/core_portme.mak new file mode 100644 index 00000000..97b6d6ac --- /dev/null +++ b/riscv-coremark/coremark/freebsd/core_portme.mak @@ -0,0 +1,17 @@ +# Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Original Author: Shay Gal-on + +include posix/core_portme.mak diff --git a/riscv-coremark/coremark/linux/core_portme.mak b/riscv-coremark/coremark/linux/core_portme.mak old mode 100755 new mode 100644 index 5cfabee3..97b6d6ac --- a/riscv-coremark/coremark/linux/core_portme.mak +++ b/riscv-coremark/coremark/linux/core_portme.mak @@ -14,127 +14,4 @@ # # Original Author: Shay Gal-on -#File: core_portme.mak - -# Flag: OUTFLAG -# Use this flag to define how to to get an executable (e.g -o) -OUTFLAG= -o -# Flag: CC -# Use this flag to define compiler to use -CC = gcc -# Flag: CFLAGS -# Use this flag to define compiler options. Note, you can add compiler options from the command line using XCFLAGS="other flags" -PORT_CFLAGS = -O2 -FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)" -CFLAGS = $(PORT_CFLAGS) -I$(PORT_DIR) -I. -DFLAGS_STR=\"$(FLAGS_STR)\" -#Flag: LFLAGS_END -# Define any libraries needed for linking or other flags that should come at the end of the link line (e.g. linker scripts). -# Note: On certain platforms, the default clock_gettime implementation is supported but requires linking of librt. -LFLAGS_END += -lrt -# Flag: PORT_SRCS -# Port specific source files can be added here -PORT_SRCS = $(PORT_DIR)/core_portme.c -# Flag: LOAD -# Define this flag if you need to load to a target, as in a cross compile environment. - -# Flag: RUN -# Define this flag if running does not consist of simple invocation of the binary. -# In a cross compile environment, you need to define this. - -#For flashing and using a tera term macro, you could use -#LOAD = flash ADDR -#RUN = ttpmacro coremark.ttl - -#For copying to target and executing via SSH connection, you could use -#LOAD = scp $(OUTFILE) user@target:~ -#RUN = ssh user@target -c - -#For native compilation and execution -LOAD = echo Loading done -RUN = - -OEXT = .o -EXE = .exe - -# Flag: SEPARATE_COMPILE -# Define if you need to separate compilation from link stage. -# In this case, you also need to define below how to create an object file, and how to link. -ifdef SEPARATE_COMPILE - -LD = gcc -OBJOUT = -o -LFLAGS = -OFLAG = -o -COUT = -c -# Flag: PORT_OBJS -# Port specific object files can be added here -PORT_OBJS = $(PORT_DIR)/core_portme$(OEXT) -PORT_CLEAN = *$(OEXT) - -$(OPATH)%$(OEXT) : %.c - $(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@ - -endif - -# Target: port_prebuild -# Generate any files that are needed before actual build starts. -# E.g. generate profile guidance files. Sample PGO generation for gcc enabled with PGO=1 -# - First, check if PGO was defined on the command line, if so, need to add -fprofile-use to compile line. -# - Second, if PGO reference has not yet been generated, add a step to the prebuild that will build a profile-generate version and run it. -# Note - Using REBUILD=1 -# -# Use make PGO=1 to invoke this sample processing. - -ifdef PGO - ifeq (,$(findstring $(PGO),gen)) - PGO_STAGE=build_pgo_gcc - CFLAGS+=-fprofile-use - endif - PORT_CLEAN+=*.gcda *.gcno gmon.out -endif - -.PHONY: port_prebuild -port_prebuild: $(PGO_STAGE) - -.PHONY: build_pgo_gcc -build_pgo_gcc: - $(MAKE) PGO=gen XCFLAGS="$(XCFLAGS) -fprofile-generate -DTOTAL_DATA_SIZE=1200" ITERATIONS=10 gen_pgo_data REBUILD=1 - -# Target: port_postbuild -# Generate any files that are needed after actual build end. -# E.g. change format to srec, bin, zip in order to be able to load into flash -.PHONY: port_postbuild -port_postbuild: - -# Target: port_postrun -# Do platform specific after run stuff. -# E.g. reset the board, backup the logfiles etc. -.PHONY: port_postrun -port_postrun: - -# Target: port_prerun -# Do platform specific after run stuff. -# E.g. reset the board, backup the logfiles etc. -.PHONY: port_prerun -port_prerun: - -# Target: port_postload -# Do platform specific after load stuff. -# E.g. reset the reset power to the flash eraser -.PHONY: port_postload -port_postload: - -# Target: port_preload -# Do platform specific before load stuff. -# E.g. reset the reset power to the flash eraser -.PHONY: port_preload -port_preload: - -# FLAG: OPATH -# Path to the output folder. Default - current folder. -OPATH = ./ -MKDIR = mkdir -p - -# FLAG: PERL -# Define perl executable to calculate the geomean if running separate. -PERL=/usr/bin/perl +include posix/core_portme.mak diff --git a/riscv-coremark/coremark/macos/core_portme.mak b/riscv-coremark/coremark/macos/core_portme.mak new file mode 100644 index 00000000..6b27c3c4 --- /dev/null +++ b/riscv-coremark/coremark/macos/core_portme.mak @@ -0,0 +1,18 @@ +# Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Original Author: Shay Gal-on + +NO_LIBRT = 1 +include posix/core_portme.mak diff --git a/riscv-coremark/coremark/posix/core_portme.c b/riscv-coremark/coremark/posix/core_portme.c new file mode 100644 index 00000000..f5a7f5b3 --- /dev/null +++ b/riscv-coremark/coremark/posix/core_portme.c @@ -0,0 +1,419 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +#include +#include +#include "coremark.h" +#if CALLGRIND_RUN +#include +#endif + +#if (MEM_METHOD == MEM_MALLOC) +/* Function: portable_malloc + Provide malloc() functionality in a platform specific way. +*/ +void * +portable_malloc(size_t size) +{ + return malloc(size); +} +/* Function: portable_free + Provide free() functionality in a platform specific way. +*/ +void +portable_free(void *p) +{ + free(p); +} +#else +void * +portable_malloc(size_t size) +{ + return NULL; +} +void +portable_free(void *p) +{ + p = NULL; +} +#endif + +#if (SEED_METHOD == SEED_VOLATILE) +#if VALIDATION_RUN +volatile ee_s32 seed1_volatile = 0x3415; +volatile ee_s32 seed2_volatile = 0x3415; +volatile ee_s32 seed3_volatile = 0x66; +#endif +#if PERFORMANCE_RUN +volatile ee_s32 seed1_volatile = 0x0; +volatile ee_s32 seed2_volatile = 0x0; +volatile ee_s32 seed3_volatile = 0x66; +#endif +#if PROFILE_RUN +volatile ee_s32 seed1_volatile = 0x8; +volatile ee_s32 seed2_volatile = 0x8; +volatile ee_s32 seed3_volatile = 0x8; +#endif +volatile ee_s32 seed4_volatile = ITERATIONS; +volatile ee_s32 seed5_volatile = 0; +#endif +/* Porting: Timing functions + How to capture time and convert to seconds must be ported to whatever is + supported by the platform. e.g. Read value from on board RTC, read value from + cpu clock cycles performance counter etc. Sample implementation for standard + time.h and windows.h definitions included. +*/ +/* Define: TIMER_RES_DIVIDER + Divider to trade off timer resolution and total time that can be + measured. + + Use lower values to increase resolution, but make sure that overflow + does not occur. If there are issues with the return value overflowing, + increase this value. + */ +#if USE_CLOCK +#define NSECS_PER_SEC CLOCKS_PER_SEC +#define EE_TIMER_TICKER_RATE 1000 +#define CORETIMETYPE clock_t +#define GETMYTIME(_t) (*_t = clock()) +#define MYTIMEDIFF(fin, ini) ((fin) - (ini)) +#define TIMER_RES_DIVIDER 1 +#define SAMPLE_TIME_IMPLEMENTATION 1 +#elif defined(_MSC_VER) +#define NSECS_PER_SEC 10000000 +#define EE_TIMER_TICKER_RATE 1000 +#define CORETIMETYPE FILETIME +#define GETMYTIME(_t) GetSystemTimeAsFileTime(_t) +#define MYTIMEDIFF(fin, ini) \ + (((*(__int64 *)&fin) - (*(__int64 *)&ini)) / TIMER_RES_DIVIDER) +/* setting to millisces resolution by default with MSDEV */ +#ifndef TIMER_RES_DIVIDER +#define TIMER_RES_DIVIDER 1000 +#endif +#define SAMPLE_TIME_IMPLEMENTATION 1 +#elif HAS_TIME_H +#define NSECS_PER_SEC 1000000000 +#define EE_TIMER_TICKER_RATE 1000 +#define CORETIMETYPE struct timespec +#define GETMYTIME(_t) clock_gettime(CLOCK_REALTIME, _t) +#define MYTIMEDIFF(fin, ini) \ + ((fin.tv_sec - ini.tv_sec) * (NSECS_PER_SEC / TIMER_RES_DIVIDER) \ + + (fin.tv_nsec - ini.tv_nsec) / TIMER_RES_DIVIDER) +/* setting to 1/1000 of a second resolution by default with linux */ +#ifndef TIMER_RES_DIVIDER +#define TIMER_RES_DIVIDER 1000000 +#endif +#define SAMPLE_TIME_IMPLEMENTATION 1 +#else +#define SAMPLE_TIME_IMPLEMENTATION 0 +#endif +#define EE_TICKS_PER_SEC (NSECS_PER_SEC / TIMER_RES_DIVIDER) + +#if SAMPLE_TIME_IMPLEMENTATION +/** Define Host specific (POSIX), or target specific global time variables. */ +static CORETIMETYPE start_time_val, stop_time_val; + +/* Function: start_time + This function will be called right before starting the timed portion of + the benchmark. + + Implementation may be capturing a system timer (as implemented in the + example code) or zeroing some system parameters - e.g. setting the cpu clocks + cycles to 0. +*/ +void +start_time(void) +{ + GETMYTIME(&start_time_val); +#if CALLGRIND_RUN + CALLGRIND_START_INSTRUMENTATION +#endif +#if MICA + asm volatile("int3"); /*1 */ +#endif +} +/* Function: stop_time + This function will be called right after ending the timed portion of the + benchmark. + + Implementation may be capturing a system timer (as implemented in the + example code) or other system parameters - e.g. reading the current value of + cpu cycles counter. +*/ +void +stop_time(void) +{ +#if CALLGRIND_RUN + CALLGRIND_STOP_INSTRUMENTATION +#endif +#if MICA + asm volatile("int3"); /*1 */ +#endif + GETMYTIME(&stop_time_val); +} +/* Function: get_time + Return an abstract "ticks" number that signifies time on the system. + + Actual value returned may be cpu cycles, milliseconds or any other + value, as long as it can be converted to seconds by . This + methodology is taken to accomodate any hardware or simulated platform. The + sample implementation returns millisecs by default, and the resolution is + controlled by +*/ +CORE_TICKS +get_time(void) +{ + CORE_TICKS elapsed + = (CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val)); + return elapsed; +} +/* Function: time_in_secs + Convert the value returned by get_time to seconds. + + The type is used to accomodate systems with no support for + floating point. Default implementation implemented by the EE_TICKS_PER_SEC + macro above. +*/ +secs_ret +time_in_secs(CORE_TICKS ticks) +{ + secs_ret retval = ((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC; + return retval; +} +#else +#error "Please implement timing functionality in core_portme.c" +#endif /* SAMPLE_TIME_IMPLEMENTATION */ + +ee_u32 default_num_contexts = MULTITHREAD; + +/* Function: portable_init + Target specific initialization code + Test for some common mistakes. +*/ +void +portable_init(core_portable *p, int *argc, char *argv[]) +{ +#if PRINT_ARGS + int i; + for (i = 0; i < *argc; i++) + { + ee_printf("Arg[%d]=%s\n", i, argv[i]); + } +#endif + if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) + { + ee_printf( + "ERROR! Please define ee_ptr_int to a type that holds a " + "pointer!\n"); + } + if (sizeof(ee_u32) != 4) + { + ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n"); + } +#if (MAIN_HAS_NOARGC && (SEED_METHOD == SEED_ARG)) + ee_printf( + "ERROR! Main has no argc, but SEED_METHOD defined to SEED_ARG!\n"); +#endif + +#if (MULTITHREAD > 1) && (SEED_METHOD == SEED_ARG) + int nargs = *argc, i; + if ((nargs > 1) && (*argv[1] == 'M')) + { + default_num_contexts = parseval(argv[1] + 1); + if (default_num_contexts > MULTITHREAD) + default_num_contexts = MULTITHREAD; + /* Shift args since first arg is directed to the portable part and not + * to coremark main */ + --nargs; + for (i = 1; i < nargs; i++) + argv[i] = argv[i + 1]; + *argc = nargs; + } +#endif /* sample of potential platform specific init via command line, reset \ + the number of contexts being used if first argument is M*/ + p->portable_id = 1; +} +/* Function: portable_fini + Target specific final code +*/ +void +portable_fini(core_portable *p) +{ + p->portable_id = 0; +} + +#if (MULTITHREAD > 1) + +/* Function: core_start_parallel + Start benchmarking in a parallel context. + + Three implementations are provided, one using pthreads, one using fork + and shared mem, and one using fork and sockets. Other implementations using + MCAPI or other standards can easily be devised. +*/ +/* Function: core_stop_parallel + Stop a parallel context execution of coremark, and gather the results. + + Three implementations are provided, one using pthreads, one using fork + and shared mem, and one using fork and sockets. Other implementations using + MCAPI or other standards can easily be devised. +*/ +#if USE_PTHREAD +ee_u8 +core_start_parallel(core_results *res) +{ + return (ee_u8)pthread_create( + &(res->port.thread), NULL, iterate, (void *)res); +} +ee_u8 +core_stop_parallel(core_results *res) +{ + void *retval; + return (ee_u8)pthread_join(res->port.thread, &retval); +} +#elif USE_FORK +static int key_id = 0; +ee_u8 +core_start_parallel(core_results *res) +{ + key_t key = 4321 + key_id; + key_id++; + res->port.pid = fork(); + res->port.shmid = shmget(key, 8, IPC_CREAT | 0666); + if (res->port.shmid < 0) + { + ee_printf("ERROR in shmget!\n"); + } + if (res->port.pid == 0) + { + iterate(res); + res->port.shm = shmat(res->port.shmid, NULL, 0); + /* copy the validation values to the shared memory area and quit*/ + if (res->port.shm == (char *)-1) + { + ee_printf("ERROR in child shmat!\n"); + } + else + { + memcpy(res->port.shm, &(res->crc), 8); + shmdt(res->port.shm); + } + exit(0); + } + return 1; +} +ee_u8 +core_stop_parallel(core_results *res) +{ + int status; + pid_t wpid = waitpid(res->port.pid, &status, WUNTRACED); + if (wpid != res->port.pid) + { + ee_printf("ERROR waiting for child.\n"); + if (errno == ECHILD) + ee_printf("errno=No such child %d\n", res->port.pid); + if (errno == EINTR) + ee_printf("errno=Interrupted\n"); + return 0; + } + /* after process is done, get the values from the shared memory area */ + res->port.shm = shmat(res->port.shmid, NULL, 0); + if (res->port.shm == (char *)-1) + { + ee_printf("ERROR in parent shmat!\n"); + return 0; + } + memcpy(&(res->crc), res->port.shm, 8); + shmdt(res->port.shm); + return 1; +} +#elif USE_SOCKET +static int key_id = 0; +ee_u8 +core_start_parallel(core_results *res) +{ + int bound, buffer_length = 8; + res->port.sa.sin_family = AF_INET; + res->port.sa.sin_addr.s_addr = htonl(0x7F000001); + res->port.sa.sin_port = htons(7654 + key_id); + key_id++; + res->port.pid = fork(); + if (res->port.pid == 0) + { /* benchmark child */ + iterate(res); + res->port.sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (-1 == res->port.sock) /* if socket failed to initialize, exit */ + { + ee_printf("Error Creating Socket"); + } + else + { + int bytes_sent = sendto(res->port.sock, + &(res->crc), + buffer_length, + 0, + (struct sockaddr *)&(res->port.sa), + sizeof(struct sockaddr_in)); + if (bytes_sent < 0) + ee_printf("Error sending packet: %s\n", strerror(errno)); + close(res->port.sock); /* close the socket */ + } + exit(0); + } + /* parent process, open the socket */ + res->port.sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + bound = bind(res->port.sock, + (struct sockaddr *)&(res->port.sa), + sizeof(struct sockaddr)); + if (bound < 0) + ee_printf("bind(): %s\n", strerror(errno)); + return 1; +} +ee_u8 +core_stop_parallel(core_results *res) +{ + int status; + int fromlen = sizeof(struct sockaddr); + int recsize = recvfrom(res->port.sock, + &(res->crc), + 8, + 0, + (struct sockaddr *)&(res->port.sa), + &fromlen); + if (recsize < 0) + { + ee_printf("Error in receive: %s\n", strerror(errno)); + return 0; + } + pid_t wpid = waitpid(res->port.pid, &status, WUNTRACED); + if (wpid != res->port.pid) + { + ee_printf("ERROR waiting for child.\n"); + if (errno == ECHILD) + ee_printf("errno=No such child %d\n", res->port.pid); + if (errno == EINTR) + ee_printf("errno=Interrupted\n"); + return 0; + } + return 1; +} +#else /* no standard multicore implementation */ +#error \ + "Please implement multicore functionality in core_portme.c to use multiple contexts." +#endif /* multithread implementations */ +#endif diff --git a/riscv-coremark/coremark/posix/core_portme.h b/riscv-coremark/coremark/posix/core_portme.h new file mode 100644 index 00000000..e49e474b --- /dev/null +++ b/riscv-coremark/coremark/posix/core_portme.h @@ -0,0 +1,314 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +/* Topic: Description + This file contains configuration constants required to execute on + different platforms +*/ +#ifndef CORE_PORTME_H +#define CORE_PORTME_H + +#include "core_portme_posix_overrides.h" + +/************************/ +/* Data types and settings */ +/************************/ +/* Configuration: HAS_FLOAT + Define to 1 if the platform supports floating point. +*/ +#ifndef HAS_FLOAT +#define HAS_FLOAT 1 +#endif +/* Configuration: HAS_TIME_H + Define to 1 if platform has the time.h header file, + and implementation of functions thereof. +*/ +#ifndef HAS_TIME_H +#define HAS_TIME_H 1 +#endif +/* Configuration: USE_CLOCK + Define to 1 if platform has the time.h header file, + and implementation of functions thereof. +*/ +#ifndef USE_CLOCK +#define USE_CLOCK 0 +#endif +/* Configuration: HAS_STDIO + Define to 1 if the platform has stdio.h. +*/ +#ifndef HAS_STDIO +#define HAS_STDIO 1 +#endif +/* Configuration: HAS_PRINTF + Define to 1 if the platform has stdio.h and implements the printf + function. +*/ +#ifndef HAS_PRINTF +#define HAS_PRINTF 1 +#endif + +/* Configuration: CORE_TICKS + Define type of return from the timing functions. + */ +#if defined(_MSC_VER) +#include +typedef size_t CORE_TICKS; +#elif HAS_TIME_H +#include +typedef clock_t CORE_TICKS; +#else +#error \ + "Please define type of CORE_TICKS and implement start_time, end_time get_time and time_in_secs functions!" +#endif + +/* Definitions: COMPILER_VERSION, COMPILER_FLAGS, MEM_LOCATION + Initialize these strings per platform +*/ +#ifndef COMPILER_VERSION +#ifdef __GNUC__ +#define COMPILER_VERSION "GCC"__VERSION__ +#else +#define COMPILER_VERSION "Please put compiler version here (e.g. gcc 4.1)" +#endif +#endif +#ifndef COMPILER_FLAGS +#define COMPILER_FLAGS \ + FLAGS_STR /* "Please put compiler flags here (e.g. -o3)" */ +#endif +#ifndef MEM_LOCATION +#define MEM_LOCATION \ + "Please put data memory location here\n\t\t\t(e.g. code in flash, data " \ + "on heap etc)" +#define MEM_LOCATION_UNSPEC 1 +#endif + +#include + +/* Data Types: + To avoid compiler issues, define the data types that need ot be used for + 8b, 16b and 32b in . + + *Imprtant*: + ee_ptr_int needs to be the data type used to hold pointers, otherwise + coremark may fail!!! +*/ +typedef signed short ee_s16; +typedef unsigned short ee_u16; +typedef signed int ee_s32; +typedef double ee_f32; +typedef unsigned char ee_u8; +typedef unsigned int ee_u32; +typedef uintptr_t ee_ptr_int; +typedef size_t ee_size_t; +/* align an offset to point to a 32b value */ +#define align_mem(x) (void *)(4 + (((ee_ptr_int)(x)-1) & ~3)) + +/* Configuration: SEED_METHOD + Defines method to get seed values that cannot be computed at compile + time. + + Valid values: + SEED_ARG - from command line. + SEED_FUNC - from a system function. + SEED_VOLATILE - from volatile variables. +*/ +#ifndef SEED_METHOD +#define SEED_METHOD SEED_ARG +#endif + +/* Configuration: MEM_METHOD + Defines method to get a block of memry. + + Valid values: + MEM_MALLOC - for platforms that implement malloc and have malloc.h. + MEM_STATIC - to use a static memory array. + MEM_STACK - to allocate the data block on the stack (NYI). +*/ +#ifndef MEM_METHOD +#define MEM_METHOD MEM_MALLOC +#endif + +/* Configuration: MULTITHREAD + Define for parallel execution + + Valid values: + 1 - only one context (default). + N>1 - will execute N copies in parallel. + + Note: + If this flag is defined to more then 1, an implementation for launching + parallel contexts must be defined. + + Two sample implementations are provided. Use or + to enable them. + + It is valid to have a different implementation of + and in , to fit a particular architecture. +*/ +#ifndef MULTITHREAD +#define MULTITHREAD 1 +#endif + +/* Configuration: USE_PTHREAD + Sample implementation for launching parallel contexts + This implementation uses pthread_thread_create and pthread_join. + + Valid values: + 0 - Do not use pthreads API. + 1 - Use pthreads API + + Note: + This flag only matters if MULTITHREAD has been defined to a value + greater then 1. +*/ +#ifndef USE_PTHREAD +#define USE_PTHREAD 0 +#endif + +/* Configuration: USE_FORK + Sample implementation for launching parallel contexts + This implementation uses fork, waitpid, shmget,shmat and shmdt. + + Valid values: + 0 - Do not use fork API. + 1 - Use fork API + + Note: + This flag only matters if MULTITHREAD has been defined to a value + greater then 1. +*/ +#ifndef USE_FORK +#define USE_FORK 0 +#endif + +/* Configuration: USE_SOCKET + Sample implementation for launching parallel contexts + This implementation uses fork, socket, sendto and recvfrom + + Valid values: + 0 - Do not use fork and sockets API. + 1 - Use fork and sockets API + + Note: + This flag only matters if MULTITHREAD has been defined to a value + greater then 1. +*/ +#ifndef USE_SOCKET +#define USE_SOCKET 0 +#endif + +/* Configuration: MAIN_HAS_NOARGC + Needed if platform does not support getting arguments to main. + + Valid values: + 0 - argc/argv to main is supported + 1 - argc/argv to main is not supported +*/ +#ifndef MAIN_HAS_NOARGC +#define MAIN_HAS_NOARGC 0 +#endif + +/* Configuration: MAIN_HAS_NORETURN + Needed if platform does not support returning a value from main. + + Valid values: + 0 - main returns an int, and return value will be 0. + 1 - platform does not support returning a value from main +*/ +#ifndef MAIN_HAS_NORETURN +#define MAIN_HAS_NORETURN 0 +#endif + +/* Variable: default_num_contexts + Number of contexts to spawn in multicore context. + Override this global value to change number of contexts used. + + Note: + This value may not be set higher then the define. + + To experiment, you can set the define to the highest value + expected, and use argc/argv in the to set this value from the + command line. +*/ +extern ee_u32 default_num_contexts; + +#if (MULTITHREAD > 1) +#if USE_PTHREAD +#include +#define PARALLEL_METHOD "PThreads" +#elif USE_FORK +#include +#include +#include +#include +#include /* for memcpy */ +#define PARALLEL_METHOD "Fork" +#elif USE_SOCKET +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define PARALLEL_METHOD "Sockets" +#else +#define PARALLEL_METHOD "Proprietary" +#error \ + "Please implement multicore functionality in core_portme.c to use multiple contexts." +#endif /* Method for multithreading */ +#endif /* MULTITHREAD > 1 */ + +typedef struct CORE_PORTABLE_S +{ +#if (MULTITHREAD > 1) +#if USE_PTHREAD + pthread_t thread; +#elif USE_FORK + pid_t pid; + int shmid; + void *shm; +#elif USE_SOCKET + pid_t pid; + int sock; + struct sockaddr_in sa; +#endif /* Method for multithreading */ +#endif /* MULTITHREAD>1 */ + ee_u8 portable_id; +} core_portable; + +/* target specific init/fini */ +void portable_init(core_portable *p, int *argc, char *argv[]); +void portable_fini(core_portable *p); + +#if (SEED_METHOD == SEED_VOLATILE) +#if (VALIDATION_RUN || PERFORMANCE_RUN || PROFILE_RUN) +#define RUN_TYPE_FLAG 1 +#else +#if (TOTAL_DATA_SIZE == 1200) +#define PROFILE_RUN 1 +#else +#define PERFORMANCE_RUN 1 +#endif +#endif +#endif /* SEED_METHOD==SEED_VOLATILE */ + +#endif /* CORE_PORTME_H */ diff --git a/riscv-coremark/coremark/posix/core_portme.mak b/riscv-coremark/coremark/posix/core_portme.mak new file mode 100755 index 00000000..e6be71a7 --- /dev/null +++ b/riscv-coremark/coremark/posix/core_portme.mak @@ -0,0 +1,151 @@ +# Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Original Author: Shay Gal-on + +#File: core_portme.mak + +# Flag: OUTFLAG +# Use this flag to define how to to get an executable (e.g -o) +OUTFLAG= -o +# Flag: CC +# Use this flag to define compiler to use +CC?= cc +# Flag: CFLAGS +# Use this flag to define compiler options. Note, you can add compiler options from the command line using XCFLAGS="other flags" +PORT_CFLAGS = -O2 +FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)" +CFLAGS = $(PORT_CFLAGS) -I$(PORT_DIR) -Iposix -I. -DFLAGS_STR=\"$(FLAGS_STR)\" +# Flag: NO_LIBRT +# Define if the platform does not provide a librt +ifndef NO_LIBRT +#Flag: LFLAGS_END +# Define any libraries needed for linking or other flags that should come at the end of the link line (e.g. linker scripts). +# Note: On certain platforms, the default clock_gettime implementation is supported but requires linking of librt. +LFLAGS_END += -lrt +endif +# Flag: PORT_SRCS +# Port specific source files can be added here +PORT_SRCS = posix/core_portme.c +vpath %.c posix +vpath %.h posix +vpath %.mak posix +# Flag: EXTRA_DEPENDS +# Port specific extra build dependencies. +# Some ports inherit from us, so ensure this Makefile is always a dependency. +EXTRA_DEPENDS += posix/core_portme.mak +# Flag: LOAD +# Define this flag if you need to load to a target, as in a cross compile environment. + +# Flag: RUN +# Define this flag if running does not consist of simple invocation of the binary. +# In a cross compile environment, you need to define this. + +#For flashing and using a tera term macro, you could use +#LOAD = flash ADDR +#RUN = ttpmacro coremark.ttl + +#For copying to target and executing via SSH connection, you could use +#LOAD = scp $(OUTFILE) user@target:~ +#RUN = ssh user@target -c + +#For native compilation and execution +LOAD = echo Loading done +RUN = + +OEXT = .o +EXE = .exe + +# Flag: SEPARATE_COMPILE +# Define if you need to separate compilation from link stage. +# In this case, you also need to define below how to create an object file, and how to link. +ifdef SEPARATE_COMPILE + +LD = gcc +OBJOUT = -o +LFLAGS = +OFLAG = -o +COUT = -c +# Flag: PORT_OBJS +# Port specific object files can be added here +PORT_OBJS = $(PORT_DIR)/core_portme$(OEXT) +PORT_CLEAN = *$(OEXT) + +$(OPATH)%$(OEXT) : %.c + $(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@ + +endif + +# Target: port_prebuild +# Generate any files that are needed before actual build starts. +# E.g. generate profile guidance files. Sample PGO generation for gcc enabled with PGO=1 +# - First, check if PGO was defined on the command line, if so, need to add -fprofile-use to compile line. +# - Second, if PGO reference has not yet been generated, add a step to the prebuild that will build a profile-generate version and run it. +# Note - Using REBUILD=1 +# +# Use make PGO=1 to invoke this sample processing. + +ifdef PGO + ifeq (,$(findstring $(PGO),gen)) + PGO_STAGE=build_pgo_gcc + CFLAGS+=-fprofile-use + endif + PORT_CLEAN+=*.gcda *.gcno gmon.out +endif + +.PHONY: port_prebuild +port_prebuild: $(PGO_STAGE) + +.PHONY: build_pgo_gcc +build_pgo_gcc: + $(MAKE) PGO=gen XCFLAGS="$(XCFLAGS) -fprofile-generate -DTOTAL_DATA_SIZE=1200" ITERATIONS=10 gen_pgo_data REBUILD=1 + +# Target: port_postbuild +# Generate any files that are needed after actual build end. +# E.g. change format to srec, bin, zip in order to be able to load into flash +.PHONY: port_postbuild +port_postbuild: + +# Target: port_postrun +# Do platform specific after run stuff. +# E.g. reset the board, backup the logfiles etc. +.PHONY: port_postrun +port_postrun: + +# Target: port_prerun +# Do platform specific after run stuff. +# E.g. reset the board, backup the logfiles etc. +.PHONY: port_prerun +port_prerun: + +# Target: port_postload +# Do platform specific after load stuff. +# E.g. reset the reset power to the flash eraser +.PHONY: port_postload +port_postload: + +# Target: port_preload +# Do platform specific before load stuff. +# E.g. reset the reset power to the flash eraser +.PHONY: port_preload +port_preload: + +# FLAG: OPATH +# Path to the output folder. Default - current folder. +OPATH = ./ +MKDIR = mkdir -p + +# FLAG: PERL +# Define perl executable to calculate the geomean if running separate. +PERL=/usr/bin/perl diff --git a/riscv-coremark/coremark/posix/core_portme_posix_overrides.h b/riscv-coremark/coremark/posix/core_portme_posix_overrides.h new file mode 100644 index 00000000..c0e998ad --- /dev/null +++ b/riscv-coremark/coremark/posix/core_portme_posix_overrides.h @@ -0,0 +1,28 @@ +/* +Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Original Author: Shay Gal-on +*/ + +/* Topic: Description + This file contains additional configuration constants required to execute on + different platforms over and above the POSIX defaults +*/ +#ifndef CORE_PORTME_POSIX_OVERRIDES_H +#define CORE_PORTME_POSIX_OVERRIDES_H + +/* None by default */ + +#endif diff --git a/riscv-coremark/coremark/rtems/core_portme.mak b/riscv-coremark/coremark/rtems/core_portme.mak new file mode 100644 index 00000000..6b27c3c4 --- /dev/null +++ b/riscv-coremark/coremark/rtems/core_portme.mak @@ -0,0 +1,18 @@ +# Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Original Author: Shay Gal-on + +NO_LIBRT = 1 +include posix/core_portme.mak diff --git a/riscv-coremark/coremark/rtems/init.c b/riscv-coremark/coremark/rtems/init.c new file mode 100644 index 00000000..64d3e59a --- /dev/null +++ b/riscv-coremark/coremark/rtems/init.c @@ -0,0 +1,63 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 Hesham Almatary + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory (Department of Computer Science and + * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the + * DARPA SSITH research programme. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +int main( + int argc, + void **args +); + +rtems_task Init( + rtems_task_argument ignored +); + +rtems_task Init( + rtems_task_argument ignored +) +{ + int ret = main(0, NULL); + exit(ret); +} + +/* configuration information */ +#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER + +#define CONFIGURE_MAXIMUM_TASKS 20 + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +#include diff --git a/riscv-coremark/coremark/simple/core_portme.c b/riscv-coremark/coremark/simple/core_portme.c old mode 100755 new mode 100644 index 33c863d1..b95e3b21 --- a/riscv-coremark/coremark/simple/core_portme.c +++ b/riscv-coremark/coremark/simple/core_portme.c @@ -21,108 +21,129 @@ Original Author: Shay Gal-on #include "coremark.h" #if VALIDATION_RUN - volatile ee_s32 seed1_volatile=0x3415; - volatile ee_s32 seed2_volatile=0x3415; - volatile ee_s32 seed3_volatile=0x66; +volatile ee_s32 seed1_volatile = 0x3415; +volatile ee_s32 seed2_volatile = 0x3415; +volatile ee_s32 seed3_volatile = 0x66; #endif #if PERFORMANCE_RUN - volatile ee_s32 seed1_volatile=0x0; - volatile ee_s32 seed2_volatile=0x0; - volatile ee_s32 seed3_volatile=0x66; +volatile ee_s32 seed1_volatile = 0x0; +volatile ee_s32 seed2_volatile = 0x0; +volatile ee_s32 seed3_volatile = 0x66; #endif #if PROFILE_RUN - volatile ee_s32 seed1_volatile=0x8; - volatile ee_s32 seed2_volatile=0x8; - volatile ee_s32 seed3_volatile=0x8; +volatile ee_s32 seed1_volatile = 0x8; +volatile ee_s32 seed2_volatile = 0x8; +volatile ee_s32 seed3_volatile = 0x8; #endif - volatile ee_s32 seed4_volatile=ITERATIONS; - volatile ee_s32 seed5_volatile=0; +volatile ee_s32 seed4_volatile = ITERATIONS; +volatile ee_s32 seed5_volatile = 0; /* Porting : Timing functions - How to capture time and convert to seconds must be ported to whatever is supported by the platform. - e.g. Read value from on board RTC, read value from cpu clock cycles performance counter etc. - Sample implementation for standard time.h and windows.h definitions included. + How to capture time and convert to seconds must be ported to whatever is + supported by the platform. e.g. Read value from on board RTC, read value from + cpu clock cycles performance counter etc. Sample implementation for standard + time.h and windows.h definitions included. */ /* Define : TIMER_RES_DIVIDER - Divider to trade off timer resolution and total time that can be measured. + Divider to trade off timer resolution and total time that can be + measured. - Use lower values to increase resolution, but make sure that overflow does not occur. - If there are issues with the return value overflowing, increase this value. - */ -#define NSECS_PER_SEC CLOCKS_PER_SEC -#define CORETIMETYPE clock_t -#define GETMYTIME(_t) (*_t=clock()) -#define MYTIMEDIFF(fin,ini) ((fin)-(ini)) -#define TIMER_RES_DIVIDER 1 + Use lower values to increase resolution, but make sure that overflow + does not occur. If there are issues with the return value overflowing, + increase this value. + */ +#define NSECS_PER_SEC CLOCKS_PER_SEC +#define CORETIMETYPE clock_t +#define GETMYTIME(_t) (*_t = clock()) +#define MYTIMEDIFF(fin, ini) ((fin) - (ini)) +#define TIMER_RES_DIVIDER 1 #define SAMPLE_TIME_IMPLEMENTATION 1 -#define EE_TICKS_PER_SEC (NSECS_PER_SEC / TIMER_RES_DIVIDER) +#define EE_TICKS_PER_SEC (NSECS_PER_SEC / TIMER_RES_DIVIDER) /** Define Host specific (POSIX), or target specific global time variables. */ static CORETIMETYPE start_time_val, stop_time_val; /* Function : start_time - This function will be called right before starting the timed portion of the benchmark. + This function will be called right before starting the timed portion of + the benchmark. - Implementation may be capturing a system timer (as implemented in the example code) - or zeroing some system parameters - e.g. setting the cpu clocks cycles to 0. + Implementation may be capturing a system timer (as implemented in the + example code) or zeroing some system parameters - e.g. setting the cpu clocks + cycles to 0. */ -void start_time(void) { - GETMYTIME(&start_time_val ); +void +start_time(void) +{ + GETMYTIME(&start_time_val); } /* Function : stop_time - This function will be called right after ending the timed portion of the benchmark. + This function will be called right after ending the timed portion of the + benchmark. - Implementation may be capturing a system timer (as implemented in the example code) - or other system parameters - e.g. reading the current value of cpu cycles counter. + Implementation may be capturing a system timer (as implemented in the + example code) or other system parameters - e.g. reading the current value of + cpu cycles counter. */ -void stop_time(void) { - GETMYTIME(&stop_time_val ); +void +stop_time(void) +{ + GETMYTIME(&stop_time_val); } /* Function : get_time - Return an abstract "ticks" number that signifies time on the system. - - Actual value returned may be cpu cycles, milliseconds or any other value, - as long as it can be converted to seconds by . - This methodology is taken to accomodate any hardware or simulated platform. - The sample implementation returns millisecs by default, - and the resolution is controlled by + Return an abstract "ticks" number that signifies time on the system. + + Actual value returned may be cpu cycles, milliseconds or any other + value, as long as it can be converted to seconds by . This + methodology is taken to accomodate any hardware or simulated platform. The + sample implementation returns millisecs by default, and the resolution is + controlled by */ -CORE_TICKS get_time(void) { - CORE_TICKS elapsed=(CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val)); - return elapsed; +CORE_TICKS +get_time(void) +{ + CORE_TICKS elapsed + = (CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val)); + return elapsed; } /* Function : time_in_secs - Convert the value returned by get_time to seconds. + Convert the value returned by get_time to seconds. - The type is used to accomodate systems with no support for floating point. - Default implementation implemented by the EE_TICKS_PER_SEC macro above. + The type is used to accomodate systems with no support for + floating point. Default implementation implemented by the EE_TICKS_PER_SEC + macro above. */ -secs_ret time_in_secs(CORE_TICKS ticks) { - secs_ret retval=((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC; - return retval; +secs_ret +time_in_secs(CORE_TICKS ticks) +{ + secs_ret retval = ((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC; + return retval; } -ee_u32 default_num_contexts=1; +ee_u32 default_num_contexts = 1; /* Function : portable_init - Target specific initialization code - Test for some common mistakes. + Target specific initialization code + Test for some common mistakes. */ -void portable_init(core_portable *p, int *argc, char *argv[]) +void +portable_init(core_portable *p, int *argc, char *argv[]) { - if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) { - ee_printf("ERROR! Please define ee_ptr_int to a type that holds a pointer!\n"); - } - if (sizeof(ee_u32) != 4) { - ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n"); - } - p->portable_id=1; + if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) + { + ee_printf( + "ERROR! Please define ee_ptr_int to a type that holds a " + "pointer!\n"); + } + if (sizeof(ee_u32) != 4) + { + ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n"); + } + p->portable_id = 1; } /* Function : portable_fini - Target specific final code + Target specific final code */ -void portable_fini(core_portable *p) +void +portable_fini(core_portable *p) { - p->portable_id=0; + p->portable_id = 0; } - - diff --git a/riscv-coremark/coremark/simple/core_portme.h b/riscv-coremark/coremark/simple/core_portme.h old mode 100755 new mode 100644 index a3607bfb..dfd94cbf --- a/riscv-coremark/coremark/simple/core_portme.h +++ b/riscv-coremark/coremark/simple/core_portme.h @@ -17,176 +17,188 @@ Original Author: Shay Gal-on */ /* Topic : Description - This file contains configuration constants required to execute on different platforms + This file contains configuration constants required to execute on + different platforms */ #ifndef CORE_PORTME_H #define CORE_PORTME_H /************************/ /* Data types and settings */ /************************/ -/* Configuration : HAS_FLOAT - Define to 1 if the platform supports floating point. +/* Configuration : HAS_FLOAT + Define to 1 if the platform supports floating point. */ -#ifndef HAS_FLOAT +#ifndef HAS_FLOAT #define HAS_FLOAT 1 #endif /* Configuration : HAS_TIME_H - Define to 1 if platform has the time.h header file, - and implementation of functions thereof. + Define to 1 if platform has the time.h header file, + and implementation of functions thereof. */ #ifndef HAS_TIME_H #define HAS_TIME_H 1 #endif /* Configuration : USE_CLOCK - Define to 1 if platform has the time.h header file, - and implementation of functions thereof. + Define to 1 if platform has the time.h header file, + and implementation of functions thereof. */ #ifndef USE_CLOCK #define USE_CLOCK 1 #endif /* Configuration : HAS_STDIO - Define to 1 if the platform has stdio.h. + Define to 1 if the platform has stdio.h. */ #ifndef HAS_STDIO #define HAS_STDIO 1 #endif /* Configuration : HAS_PRINTF - Define to 1 if the platform has stdio.h and implements the printf function. + Define to 1 if the platform has stdio.h and implements the printf + function. */ #ifndef HAS_PRINTF #define HAS_PRINTF 1 #endif /* Configuration : CORE_TICKS - Define type of return from the timing functions. + Define type of return from the timing functions. */ #include typedef clock_t CORE_TICKS; /* Definitions : COMPILER_VERSION, COMPILER_FLAGS, MEM_LOCATION - Initialize these strings per platform + Initialize these strings per platform */ -#ifndef COMPILER_VERSION - #ifdef __GNUC__ - #define COMPILER_VERSION "GCC"__VERSION__ - #else - #define COMPILER_VERSION "Please put compiler version here (e.g. gcc 4.1)" - #endif +#ifndef COMPILER_VERSION +#ifdef __GNUC__ +#define COMPILER_VERSION "GCC"__VERSION__ +#else +#define COMPILER_VERSION "Please put compiler version here (e.g. gcc 4.1)" #endif -#ifndef COMPILER_FLAGS - #define COMPILER_FLAGS FLAGS_STR /* "Please put compiler flags here (e.g. -o3)" */ #endif -#ifndef MEM_LOCATION - #define MEM_LOCATION "STACK" +#ifndef COMPILER_FLAGS +#define COMPILER_FLAGS \ + FLAGS_STR /* "Please put compiler flags here (e.g. -o3)" */ +#endif +#ifndef MEM_LOCATION +#define MEM_LOCATION "STACK" #endif /* Data Types : - To avoid compiler issues, define the data types that need ot be used for 8b, 16b and 32b in . - - *Imprtant* : - ee_ptr_int needs to be the data type used to hold pointers, otherwise coremark may fail!!! + To avoid compiler issues, define the data types that need ot be used for + 8b, 16b and 32b in . + + *Imprtant* : + ee_ptr_int needs to be the data type used to hold pointers, otherwise + coremark may fail!!! */ -typedef signed short ee_s16; +typedef signed short ee_s16; typedef unsigned short ee_u16; -typedef signed int ee_s32; -typedef double ee_f32; -typedef unsigned char ee_u8; -typedef unsigned int ee_u32; -typedef ee_u32 ee_ptr_int; -typedef size_t ee_size_t; +typedef signed int ee_s32; +typedef double ee_f32; +typedef unsigned char ee_u8; +typedef unsigned int ee_u32; +typedef ee_u32 ee_ptr_int; +typedef size_t ee_size_t; /* align_mem : - This macro is used to align an offset to point to a 32b value. It is used in the Matrix algorithm to initialize the input memory blocks. + This macro is used to align an offset to point to a 32b value. It is + used in the Matrix algorithm to initialize the input memory blocks. */ -#define align_mem(x) (void *)(4 + (((ee_ptr_int)(x) - 1) & ~3)) +#define align_mem(x) (void *)(4 + (((ee_ptr_int)(x)-1) & ~3)) /* Configuration : SEED_METHOD - Defines method to get seed values that cannot be computed at compile time. - - Valid values : - SEED_ARG - from command line. - SEED_FUNC - from a system function. - SEED_VOLATILE - from volatile variables. + Defines method to get seed values that cannot be computed at compile + time. + + Valid values : + SEED_ARG - from command line. + SEED_FUNC - from a system function. + SEED_VOLATILE - from volatile variables. */ #ifndef SEED_METHOD #define SEED_METHOD SEED_VOLATILE #endif /* Configuration : MEM_METHOD - Defines method to get a block of memry. - - Valid values : - MEM_MALLOC - for platforms that implement malloc and have malloc.h. - MEM_STATIC - to use a static memory array. - MEM_STACK - to allocate the data block on the stack (NYI). + Defines method to get a block of memry. + + Valid values : + MEM_MALLOC - for platforms that implement malloc and have malloc.h. + MEM_STATIC - to use a static memory array. + MEM_STACK - to allocate the data block on the stack (NYI). */ #ifndef MEM_METHOD #define MEM_METHOD MEM_STACK #endif /* Configuration : MULTITHREAD - Define for parallel execution - - Valid values : - 1 - only one context (default). - N>1 - will execute N copies in parallel. - - Note : - If this flag is defined to more then 1, an implementation for launching parallel contexts must be defined. - - Two sample implementations are provided. Use or to enable them. - - It is valid to have a different implementation of and in , - to fit a particular architecture. + Define for parallel execution + + Valid values : + 1 - only one context (default). + N>1 - will execute N copies in parallel. + + Note : + If this flag is defined to more then 1, an implementation for launching + parallel contexts must be defined. + + Two sample implementations are provided. Use or + to enable them. + + It is valid to have a different implementation of + and in , to fit a particular architecture. */ #ifndef MULTITHREAD #define MULTITHREAD 1 #define USE_PTHREAD 0 -#define USE_FORK 0 -#define USE_SOCKET 0 +#define USE_FORK 0 +#define USE_SOCKET 0 #endif /* Configuration : MAIN_HAS_NOARGC - Needed if platform does not support getting arguments to main. - - Valid values : - 0 - argc/argv to main is supported - 1 - argc/argv to main is not supported - - Note : - This flag only matters if MULTITHREAD has been defined to a value greater then 1. + Needed if platform does not support getting arguments to main. + + Valid values : + 0 - argc/argv to main is supported + 1 - argc/argv to main is not supported + + Note : + This flag only matters if MULTITHREAD has been defined to a value + greater then 1. */ -#ifndef MAIN_HAS_NOARGC +#ifndef MAIN_HAS_NOARGC #define MAIN_HAS_NOARGC 0 #endif /* Configuration : MAIN_HAS_NORETURN - Needed if platform does not support returning a value from main. - - Valid values : - 0 - main returns an int, and return value will be 0. - 1 - platform does not support returning a value from main + Needed if platform does not support returning a value from main. + + Valid values : + 0 - main returns an int, and return value will be 0. + 1 - platform does not support returning a value from main */ #ifndef MAIN_HAS_NORETURN #define MAIN_HAS_NORETURN 0 #endif /* Variable : default_num_contexts - Not used for this simple port, must cintain the value 1. + Not used for this simple port, must cintain the value 1. */ extern ee_u32 default_num_contexts; -typedef struct CORE_PORTABLE_S { - ee_u8 portable_id; +typedef struct CORE_PORTABLE_S +{ + ee_u8 portable_id; } core_portable; /* target specific init/fini */ void portable_init(core_portable *p, int *argc, char *argv[]); void portable_fini(core_portable *p); -#if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) && !defined(VALIDATION_RUN) -#if (TOTAL_DATA_SIZE==1200) +#if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) \ + && !defined(VALIDATION_RUN) +#if (TOTAL_DATA_SIZE == 1200) #define PROFILE_RUN 1 -#elif (TOTAL_DATA_SIZE==2000) +#elif (TOTAL_DATA_SIZE == 2000) #define PERFORMANCE_RUN 1 #else #define VALIDATION_RUN 1 diff --git a/wally-pipelined/linux-testgen/linux-testvectors/intermediate-outputs/git_create_dir.txt b/wally-pipelined/linux-testgen/linux-testvectors/intermediate-outputs/git_create_dir.txt new file mode 100644 index 00000000..8b0068e8 --- /dev/null +++ b/wally-pipelined/linux-testgen/linux-testvectors/intermediate-outputs/git_create_dir.txt @@ -0,0 +1 @@ +This file only exists so that git will create ./. diff --git a/wally-pipelined/linux-testgen/linux-testvectors/tvUnlinker.sh b/wally-pipelined/linux-testgen/linux-testvectors/tvUnlinker.sh new file mode 100755 index 00000000..183d6a6e --- /dev/null +++ b/wally-pipelined/linux-testgen/linux-testvectors/tvUnlinker.sh @@ -0,0 +1,10 @@ +# This could be nice to use if you want to mess with the testvectors +# without corrupting the stable copies on Tera. +unlink parsedCSRs.txt +unlink parsedMemRead.txt +unlink parsedMemWrite.txt +unlink parsedPC.txt +unlink parsedRegs.txt +unlink bootmem.txt +unlink ram.txt +echo "Done!" diff --git a/wally-pipelined/linux-testgen/testvector-generation/gdbinit_debug b/wally-pipelined/linux-testgen/testvector-generation/gdbinit_debug index b5791934..c7a03428 100644 --- a/wally-pipelined/linux-testgen/testvector-generation/gdbinit_debug +++ b/wally-pipelined/linux-testgen/testvector-generation/gdbinit_debug @@ -1,3 +1,3 @@ file ../buildroot-image-output/vmlinux set pagination off -target extended-remote :1234 +target extended-remote :1236 diff --git a/wally-pipelined/linux-testgen/testvector-generation/gdbinit_qemulog b/wally-pipelined/linux-testgen/testvector-generation/gdbinit_qemulog index ad9d9351..f4318ad1 100755 --- a/wally-pipelined/linux-testgen/testvector-generation/gdbinit_qemulog +++ b/wally-pipelined/linux-testgen/testvector-generation/gdbinit_qemulog @@ -1,6 +1,7 @@ set pagination off -target extended-remote :1234 -b *0xffffffe00020144e +target extended-remote :1236 +file ../buildroot-image-output/vmlinux +b arch_cpu_idle c c c diff --git a/wally-pipelined/linux-testgen/testvector-generation/logAllBuildroot.sh b/wally-pipelined/linux-testgen/testvector-generation/logAllBuildroot.sh index 035613c5..797b9f7d 100755 --- a/wally-pipelined/linux-testgen/testvector-generation/logAllBuildroot.sh +++ b/wally-pipelined/linux-testgen/testvector-generation/logAllBuildroot.sh @@ -11,16 +11,19 @@ intermedDir="../linux-testvectors/intermediate-outputs" outDir="../linux-testvectors" # =========== Debug the Process ========== -# Uncomment this version for GDB/QEMU debugging -# - Opens up GDB interactively -# - Logs raw QEMU output to qemu_output.txt -$customQemu -M virt -nographic -bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio -s -S & riscv64-unknown-elf-gdb -x gdbinit_debug -#($customQemu -M virt -nographic -bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -s -S 2> $intermedDir/qemu_output.txt) & riscv64-unknown-elf-gdb +# Uncomment this version for QEMU debugging of kernel +# - good for poking around VM if it boots up +# - good for running QEMU commands (press "Ctrl-A" then "c" to open QEMU command prompt) +#$customQemu -M virt -nographic -bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio +# Uncomment this version for GDB debugging of kernel +# - attempts to load in symbols from "vmlinux" +# - good for looking at backtraces when Linux gets stuck for some reason +#$customQemu -M virt -nographic -bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio -gdb tcp::1236 -S & riscv64-unknown-elf-gdb -x gdbinit_debug # Uncomment this version to generate qemu_output.txt # - Uses GDB script # - Logs raw QEMU output to qemu_output.txt -#($customQemu -M virt -nographic -bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -s -S 2> $intermedDir/qemu_output.txt) & riscv64-unknown-elf-gdb -x gdbinit_qemulog_debug +#($customQemu -M virt -nographic -bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -gdb tcp::1236 -S 2> $intermedDir/qemu_output.txt) & riscv64-unknown-elf-gdb -x gdbinit_qemulog_debug # Uncomment this version for parse_qemu.py debugging # - Uses qemu_output.txt @@ -33,10 +36,9 @@ $customQemu -M virt -nographic -bios $imageDir/fw_jump.elf -kernel $imageDir/Ima # Uncomment this version for parse_gdb_output.py debugging # - Uses qemu_in_gdb_format.txt -# - Makes testvectors -#cat $intermedDir/qemu_in_gdb_format.txt | ./parse_gdb_output.py "$outdir" +# - Makes testvectors#cat $intermedDir/qemu_in_gdb_format.txt | ./parse_gdb_output.py "$outDir" # =========== Just Do the Thing ========== # Uncomment this version for the whole thing # - Logs info needed by buildroot testbench -#($customQemu -M virt -nographic -bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -s -S 2>&1 >/dev/null | ./parse_qemu.py | ./parse_gdb_output.py "$outdir") & riscv64-unknown-elf-gdb -x gdbinit_qemulog +($customQemu -M virt -nographic -bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -gdb tcp::1236 -S 2>&1 >/dev/null | ./parse_qemu.py | ./parse_gdb_output.py "$outDir") & riscv64-unknown-elf-gdb -x gdbinit_qemulog diff --git a/wally-pipelined/linux-testgen/testvector-generation/parse_gdb_output.py b/wally-pipelined/linux-testgen/testvector-generation/parse_gdb_output.py index 7e48fa63..910358a9 100755 --- a/wally-pipelined/linux-testgen/testvector-generation/parse_gdb_output.py +++ b/wally-pipelined/linux-testgen/testvector-generation/parse_gdb_output.py @@ -9,7 +9,7 @@ csrs = ['fcsr','mcause','mcounteren','medeleg','mepc','mhartid','mideleg','mie', list(map(csrs.remove, ['fcsr','mhartid','pmpcfg0','pmpaddr0','mip'])) #output_path = '/courses/e190ax/busybear_boot_new/' #output_path = '/courses/e190ax/buildroot_boot/' -output_path = sys.argv[1] +output_path = sys.argv[1]+'/' print(f'output dir: {output_path}') instrs = -1 try: diff --git a/wally-pipelined/src/fpu/fdivsqrt.sv b/wally-pipelined/src/fpu/fdivsqrt.sv new file mode 100755 index 00000000..6d8da23f --- /dev/null +++ b/wally-pipelined/src/fpu/fdivsqrt.sv @@ -0,0 +1,256 @@ +// +// File name : fpdiv +// Title : Floating-Point Divider/Square-Root +// project : FPU +// Library : fpdiv +// Author(s) : James E. Stine, Jr. +// Purpose : definition of main unit to floating-point div/sqrt +// notes : +// +// Copyright Oklahoma State University +// +// Basic Operations +// +// Step 1: Load operands, set flags, and convert SP to DP +// Step 2: Check for special inputs ( +/- Infinity, NaN) +// Step 3: Exponent Logic +// Step 4: Divide/Sqrt using Goldschmidt +// Step 5: Normalize the result.// +// Shift left until normalized. Normalized when the value to the +// left of the binrary point is 1. +// Step 6: Round the result.// +// Step 7: Put quotient/remainder onto output. +// + +// `timescale 1ps/1ps +module fdivsqrt (FDivSqrtDoneE, FDivResultM, FDivSqrtFlgM, DivInput1E, DivInput2E, FrmE, DivOpType, FmtE, DivOvEn, DivUnEn, + FDivStartE, reset, clk, FDivBusyE, HoldInputs); + + input [63:0] DivInput1E; // 1st input operand (A) + input [63:0] DivInput2E; // 2nd input operand (B) + input [2:0] FrmE; // Rounding mode - specify values + input DivOpType; // Function opcode + input FmtE; // Result Precision (0 for double, 1 for single) //***will need to swap this + input DivOvEn; // Overflow trap enabled + input DivUnEn; // Underflow trap enabled + + input FDivStartE; + input reset; + input clk; + + output [63:0] FDivResultM; // Result of operation + output [4:0] FDivSqrtFlgM; // IEEE exception flags + output FDivSqrtDoneE; + output FDivBusyE, HoldInputs; + + supply1 vdd; + supply0 vss; + + wire [63:0] Float1; + wire [63:0] Float2; + wire [63:0] IntValue; + + wire DivDenormM; // DivDenormM on input or output + wire [12:0] exp1, exp2, expF; + wire [12:0] exp_diff, bias; + wire [13:0] exp_sqrt; + wire [12:0] exp_s; + wire [12:0] exp_c; + + wire [10:0] exponent, exp_pre; + wire [63:0] Result; + wire [52:0] mantissaA; + wire [52:0] mantissaB; + wire [63:0] sum, sum_tc, sum_corr, sum_norm; + + wire [5:0] align_shift; + wire [5:0] norm_shift; + wire [2:0] sel_inv; + wire op1_Norm, op2_Norm; + wire opA_Norm, opB_Norm; + wire Invalid; + wire DenormIn, DenormIO; + wire [4:0] FlagsIn; + wire exp_gt63; + wire Sticky_out; + wire signResult, sign_corr; + wire corr_sign; + wire zeroB; + wire convert; + wire swap; + wire sub; + + wire [63:0] q1, qm1, qp1, q0, qm0, qp0; + wire [63:0] rega_out, regb_out, regc_out, regd_out; + wire [127:0] regr_out; + wire [2:0] sel_muxa, sel_muxb; + wire sel_muxr; + wire load_rega, load_regb, load_regc, load_regd, load_regr, load_regs; + + wire donev, sel_muxrv, sel_muxsv; + wire [1:0] sel_muxav, sel_muxbv; + wire load_regav, load_regbv, load_regcv; + wire load_regrv, load_regsv; + + logic exp_cout1, exp_cout2, exp_odd, open; + + + // Convert the input operands to their appropriate forms based on + // the orignal operands, the DivOpType , and their precision FmtE. + // Single precision inputs are converted to double precision + // and the sign of the first operand is set appropratiately based on + // if the operation is absolute value or negation. + convert_inputs_div divconv1 (Float1, Float2, DivInput1E, DivInput2E, DivOpType, FmtE); + + // Test for exceptions and return the "Invalid Operation" and + // "Denormalized" Input FDivSqrtFlgM. The "sel_inv" is used in + // the third pipeline stage to select the result. Also, op1_Norm + // and op2_Norm are one if DivInput1E and DivInput2E are not zero or denormalized. + // sub is one if the effective operation is subtaction. + exception_div divexc1 (sel_inv, Invalid, DenormIn, op1_Norm, op2_Norm, + Float1, Float2, DivOpType); + + // Determine Sign/Mantissa + assign signResult = ((Float1[63]^Float2[63])&~DivOpType) | Float1[63]&DivOpType; + assign mantissaA = {vdd, Float1[51:0]}; + assign mantissaB = {vdd, Float2[51:0]}; + // Perform Exponent Subtraction - expA - expB + Bias + assign exp1 = {2'b0, Float1[62:52]}; + assign exp2 = {2'b0, Float2[62:52]}; + // bias : DP = 2^{11-1}-1 = 1023 + assign bias = {3'h0, 10'h3FF}; + // Divide exponent + csa #(13) csa1 (exp1, ~exp2, bias, exp_s, exp_c); //***adder + exp_add explogic1 (exp_cout1, {open, exp_diff}, //***adder? + {vss, exp_s}, {vss, exp_c}, 1'b1); + // Sqrt exponent (check if exponent is odd) + assign exp_odd = Float1[52] ? vss : vdd; + exp_add explogic2 (exp_cout2, exp_sqrt, //***adder? + {vss, exp1}, {4'h0, 10'h3ff}, exp_odd); + // Choose correct exponent + assign expF = DivOpType ? exp_sqrt[13:1] : exp_diff; + + // Main Goldschmidt/Division Routine + divconv goldy (q1, qm1, qp1, q0, qm0, qp0, + rega_out, regb_out, regc_out, regd_out, + regr_out, mantissaB, mantissaA, + sel_muxa, sel_muxb, sel_muxr, + reset, clk, + load_rega, load_regb, load_regc, load_regd, + load_regr, load_regs, FmtE, DivOpType, exp_odd); + + // FSM : control divider + fsm control (FDivSqrtDoneE, load_rega, load_regb, load_regc, load_regd, + load_regr, load_regs, sel_muxa, sel_muxb, sel_muxr, + clk, reset, FDivStartE, DivOpType, FDivBusyE, HoldInputs); + + // Round the mantissa to a 52-bit value, with the leading one + // removed. The rounding units also handles special cases and + // set the exception flags. + //***add max magnitude and swap negitive and positive infinity + rounder_div divround1 (Result, DenormIO, FlagsIn, + FrmE, FmtE, DivOvEn, DivUnEn, expF, + sel_inv, Invalid, DenormIn, signResult, + q1, qm1, qp1, q0, qm0, qp0, regr_out); + + // Store the final result and the exception flags in registers. + flopenr #(64) rega (clk, reset, FDivSqrtDoneE, Result, FDivResultM); + flopenr #(1) regb (clk, reset, FDivSqrtDoneE, DenormIO, DivDenormM); + flopenr #(5) regc (clk, reset, FDivSqrtDoneE, FlagsIn, FDivSqrtFlgM); + +endmodule // fpadd + +// +// Brent-Kung Prefix Adder +// (yes, it is 14 bits as my generator is broken for 13 bits :( +// assume, synthesizer will delete stuff not needed ) +// +module exp_add (cout, sum, a, b, cin); + + input [13:0] a, b; + input cin; + + output [13:0] sum; + output cout; + + wire [14:0] p,g; + wire [13:0] c; + + // pre-computation + assign p={a^b,1'b0}; + assign g={a&b, cin}; + + // prefix tree + brent_kung prefix_tree(c, p[13:0], g[13:0]); + + // post-computation + assign sum=p[14:1]^c; + assign cout=g[14]|(p[14]&c[13]); + +endmodule // exp_add + +module brent_kung (c, p, g); + + input [13:0] p; + input [13:0] g; + output [14:1] c; + + logic G_1_0, G_3_2,G_5_4,G_7_6,G_9_8,G_11_10,G_13_12,G_3_0,G_7_4,G_11_8; + logic P_3_2,P_5_4,P_7_6,P_9_8,P_11_10,P_13_12,P_7_4,P_11_8; + logic G_7_0,G_11_0,G_5_0,G_9_0,G_13_0,G_2_0,G_4_0,G_6_0,G_8_0,G_10_0,G_12_0; + // parallel-prefix, Brent-Kung + + // Stage 1: Generates G/FmtE pairs that span 1 bits + grey b_1_0 (G_1_0, {g[1],g[0]}, p[1]); + black b_3_2 (G_3_2, P_3_2, {g[3],g[2]}, {p[3],p[2]}); + black b_5_4 (G_5_4, P_5_4, {g[5],g[4]}, {p[5],p[4]}); + black b_7_6 (G_7_6, P_7_6, {g[7],g[6]}, {p[7],p[6]}); + black b_9_8 (G_9_8, P_9_8, {g[9],g[8]}, {p[9],p[8]}); + black b_11_10 (G_11_10, P_11_10, {g[11],g[10]}, {p[11],p[10]}); + black b_13_12 (G_13_12, P_13_12, {g[13],g[12]}, {p[13],p[12]}); + + // Stage 2: Generates G/FmtE pairs that span 2 bits + grey g_3_0 (G_3_0, {G_3_2,G_1_0}, P_3_2); + black b_7_4 (G_7_4, P_7_4, {G_7_6,G_5_4}, {P_7_6,P_5_4}); + black b_11_8 (G_11_8, P_11_8, {G_11_10,G_9_8}, {P_11_10,P_9_8}); + + // Stage 3: Generates G/FmtE pairs that span 4 bits + grey g_7_0 (G_7_0, {G_7_4,G_3_0}, P_7_4); + + // Stage 4: Generates G/FmtE pairs that span 8 bits + + // Stage 5: Generates G/FmtE pairs that span 4 bits + grey g_11_0 (G_11_0, {G_11_8,G_7_0}, P_11_8); + + // Stage 6: Generates G/FmtE pairs that span 2 bits + grey g_5_0 (G_5_0, {G_5_4,G_3_0}, P_5_4); + grey g_9_0 (G_9_0, {G_9_8,G_7_0}, P_9_8); + grey g_13_0 (G_13_0, {G_13_12,G_11_0}, P_13_12); + + // Last grey cell stage + grey g_2_0 (G_2_0, {g[2],G_1_0}, p[2]); + grey g_4_0 (G_4_0, {g[4],G_3_0}, p[4]); + grey g_6_0 (G_6_0, {g[6],G_5_0}, p[6]); + grey g_8_0 (G_8_0, {g[8],G_7_0}, p[8]); + grey g_10_0 (G_10_0, {g[10],G_9_0}, p[10]); + grey g_12_0 (G_12_0, {g[12],G_11_0}, p[12]); + + // Final Stage: Apply c_k+1=G_k_0 + assign c[1]=g[0]; + assign c[2]=G_1_0; + assign c[3]=G_2_0; + assign c[4]=G_3_0; + assign c[5]=G_4_0; + assign c[6]=G_5_0; + assign c[7]=G_6_0; + assign c[8]=G_7_0; + assign c[9]=G_8_0; + + assign c[10]=G_9_0; + assign c[11]=G_10_0; + assign c[12]=G_11_0; + assign c[13]=G_12_0; + assign c[14]=G_13_0; + +endmodule // brent_kung +