From 25d828eb2862b9597cffb18b9b1e2fb5165c669d Mon Sep 17 00:00:00 2001 From: Abe Date: Thu, 12 Aug 2021 05:23:04 -0400 Subject: [PATCH] Made a backup folder accessible to everyone for 3 portme directories that would not be preserved in the case of a clean coremark installation. --- riscv-coremark/extraPortmes/README.md | 7 + .../extraPortmes/cygwin/core_portme.c | 336 +++++++++++++++++ .../extraPortmes/cygwin/core_portme.h | 293 +++++++++++++++ .../extraPortmes/cygwin/core_portme.mak | 17 + .../extraPortmes/linux/core_portme.c | 338 ++++++++++++++++++ .../extraPortmes/linux/core_portme.h | 290 +++++++++++++++ .../extraPortmes/linux/core_portme.mak | 17 + .../extraPortmes/linux64/core_portme.c | 336 +++++++++++++++++ .../extraPortmes/linux64/core_portme.h | 291 +++++++++++++++ .../extraPortmes/linux64/core_portme.mak | 140 ++++++++ 10 files changed, 2065 insertions(+) create mode 100644 riscv-coremark/extraPortmes/README.md create mode 100755 riscv-coremark/extraPortmes/cygwin/core_portme.c create mode 100755 riscv-coremark/extraPortmes/cygwin/core_portme.h create mode 100644 riscv-coremark/extraPortmes/cygwin/core_portme.mak create mode 100755 riscv-coremark/extraPortmes/linux/core_portme.c create mode 100755 riscv-coremark/extraPortmes/linux/core_portme.h create mode 100644 riscv-coremark/extraPortmes/linux/core_portme.mak create mode 100755 riscv-coremark/extraPortmes/linux64/core_portme.c create mode 100755 riscv-coremark/extraPortmes/linux64/core_portme.h create mode 100755 riscv-coremark/extraPortmes/linux64/core_portme.mak diff --git a/riscv-coremark/extraPortmes/README.md b/riscv-coremark/extraPortmes/README.md new file mode 100644 index 000000000..681fc4d8b --- /dev/null +++ b/riscv-coremark/extraPortmes/README.md @@ -0,0 +1,7 @@ +This directory is a backup for the portme files associated with cygwin, linux, and linux64 + +This backup is needed in the event that a user replaces the coremark directory with a clean version +from EEMBC's github page (the clean version does not have the cygwin, linux, +and linux64 files that our version does). + +Please do not delete this directory under any circumstance. \ No newline at end of file diff --git a/riscv-coremark/extraPortmes/cygwin/core_portme.c b/riscv-coremark/extraPortmes/cygwin/core_portme.c new file mode 100755 index 000000000..fe8d29983 --- /dev/null +++ b/riscv-coremark/extraPortmes/cygwin/core_portme.c @@ -0,0 +1,336 @@ +/* +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) +#include +/* 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*/ + 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/extraPortmes/cygwin/core_portme.h b/riscv-coremark/extraPortmes/cygwin/core_portme.h new file mode 100755 index 000000000..9471b12ec --- /dev/null +++ b/riscv-coremark/extraPortmes/cygwin/core_portme.h @@ -0,0 +1,293 @@ +/* +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 +/************************/ +/* 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 + +/* 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 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. +*/ +#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/extraPortmes/cygwin/core_portme.mak b/riscv-coremark/extraPortmes/cygwin/core_portme.mak new file mode 100644 index 000000000..97b6d6ace --- /dev/null +++ b/riscv-coremark/extraPortmes/cygwin/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/extraPortmes/linux/core_portme.c b/riscv-coremark/extraPortmes/linux/core_portme.c new file mode 100755 index 000000000..6b63610d1 --- /dev/null +++ b/riscv-coremark/extraPortmes/linux/core_portme.c @@ -0,0 +1,338 @@ +/* +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) +#include +/* 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*/ + 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/extraPortmes/linux/core_portme.h b/riscv-coremark/extraPortmes/linux/core_portme.h new file mode 100755 index 000000000..2cf4659a4 --- /dev/null +++ b/riscv-coremark/extraPortmes/linux/core_portme.h @@ -0,0 +1,290 @@ +/* +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 +*/ + +#ifndef CORE_PORTME_H +#define CORE_PORTME_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 + +/* 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 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. +*/ +#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/extraPortmes/linux/core_portme.mak b/riscv-coremark/extraPortmes/linux/core_portme.mak new file mode 100644 index 000000000..97b6d6ace --- /dev/null +++ b/riscv-coremark/extraPortmes/linux/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/extraPortmes/linux64/core_portme.c b/riscv-coremark/extraPortmes/linux64/core_portme.c new file mode 100755 index 000000000..fe8d29983 --- /dev/null +++ b/riscv-coremark/extraPortmes/linux64/core_portme.c @@ -0,0 +1,336 @@ +/* +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) +#include +/* 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*/ + 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/extraPortmes/linux64/core_portme.h b/riscv-coremark/extraPortmes/linux64/core_portme.h new file mode 100755 index 000000000..1228a679b --- /dev/null +++ b/riscv-coremark/extraPortmes/linux64/core_portme.h @@ -0,0 +1,291 @@ +/* +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 +/************************/ +/* 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 + +/* 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 unsigned long long 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/extraPortmes/linux64/core_portme.mak b/riscv-coremark/extraPortmes/linux64/core_portme.mak new file mode 100755 index 000000000..5cfabee32 --- /dev/null +++ b/riscv-coremark/extraPortmes/linux64/core_portme.mak @@ -0,0 +1,140 @@ +# 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 = 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