mirror of
https://github.com/openhwgroup/cvw.git
synced 2025-04-23 13:27:16 -04:00
Made a backup folder accessible to everyone for 3 portme directories that would not be preserved in the case of a clean coremark installation.
This commit is contained in:
parent
4dfe326761
commit
25d828eb28
10 changed files with 2065 additions and 0 deletions
7
riscv-coremark/extraPortmes/README.md
Normal file
7
riscv-coremark/extraPortmes/README.md
Normal file
|
@ -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.
|
336
riscv-coremark/extraPortmes/cygwin/core_portme.c
Executable file
336
riscv-coremark/extraPortmes/cygwin/core_portme.c
Executable file
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "coremark.h"
|
||||
#if CALLGRIND_RUN
|
||||
#include <valgrind/callgrind.h>
|
||||
#endif
|
||||
|
||||
#if (MEM_METHOD==MEM_MALLOC)
|
||||
#include <malloc.h>
|
||||
/* 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 <time_in_secs>.
|
||||
This methodology is taken to accomodate any hardware or simulated platform.
|
||||
The sample implementation returns millisecs by default,
|
||||
and the resolution is controlled by <TIMER_RES_DIVIDER>
|
||||
*/
|
||||
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 <secs_ret> 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<n>*/
|
||||
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
|
293
riscv-coremark/extraPortmes/cygwin/core_portme.h
Executable file
293
riscv-coremark/extraPortmes/cygwin/core_portme.h
Executable file
|
@ -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 <windows.h>
|
||||
typedef size_t CORE_TICKS;
|
||||
#elif HAS_TIME_H
|
||||
#include <time.h>
|
||||
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 <core_portme.h>.
|
||||
|
||||
*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 <USE_PTHREAD> or <USE_FORK> to enable them.
|
||||
|
||||
It is valid to have a different implementation of <core_start_parallel> and <core_end_parallel> in <core_portme.c>,
|
||||
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 <MULTITHREAD> define.
|
||||
|
||||
To experiment, you can set the <MULTITHREAD> define to the highest value expected, and use argc/argv in the <portable_init> to set this value from the command line.
|
||||
*/
|
||||
extern ee_u32 default_num_contexts;
|
||||
|
||||
#if (MULTITHREAD>1)
|
||||
#if USE_PTHREAD
|
||||
#include <pthread.h>
|
||||
#define PARALLEL_METHOD "PThreads"
|
||||
#elif USE_FORK
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/shm.h>
|
||||
#include <string.h> /* for memcpy */
|
||||
#define PARALLEL_METHOD "Fork"
|
||||
#elif USE_SOCKET
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#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 */
|
17
riscv-coremark/extraPortmes/cygwin/core_portme.mak
Normal file
17
riscv-coremark/extraPortmes/cygwin/core_portme.mak
Normal file
|
@ -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
|
338
riscv-coremark/extraPortmes/linux/core_portme.c
Executable file
338
riscv-coremark/extraPortmes/linux/core_portme.c
Executable file
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "coremark.h"
|
||||
#if CALLGRIND_RUN
|
||||
#include <valgrind/callgrind.h>
|
||||
#endif
|
||||
|
||||
#if (MEM_METHOD==MEM_MALLOC)
|
||||
#include <malloc.h>
|
||||
/* 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 <time_in_secs>.
|
||||
This methodology is taken to accomodate any hardware or simulated platform.
|
||||
The sample implementation returns millisecs by default,
|
||||
and the resolution is controlled by <TIMER_RES_DIVIDER>
|
||||
*/
|
||||
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 <secs_ret> 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<n>*/
|
||||
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
|
290
riscv-coremark/extraPortmes/linux/core_portme.h
Executable file
290
riscv-coremark/extraPortmes/linux/core_portme.h
Executable file
|
@ -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 <windows.h>
|
||||
typedef size_t CORE_TICKS;
|
||||
#elif HAS_TIME_H
|
||||
#include <time.h>
|
||||
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 <core_portme.h>.
|
||||
|
||||
*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 <USE_PTHREAD> or <USE_FORK> to enable them.
|
||||
|
||||
It is valid to have a different implementation of <core_start_parallel> and <core_end_parallel> in <core_portme.c>,
|
||||
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 <MULTITHREAD> define.
|
||||
|
||||
To experiment, you can set the <MULTITHREAD> define to the highest value expected, and use argc/argv in the <portable_init> to set this value from the command line.
|
||||
*/
|
||||
extern ee_u32 default_num_contexts;
|
||||
|
||||
#if (MULTITHREAD>1)
|
||||
#if USE_PTHREAD
|
||||
#include <pthread.h>
|
||||
#define PARALLEL_METHOD "PThreads"
|
||||
#elif USE_FORK
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/shm.h>
|
||||
#include <string.h> /* for memcpy */
|
||||
#define PARALLEL_METHOD "Fork"
|
||||
#elif USE_SOCKET
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#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 */
|
17
riscv-coremark/extraPortmes/linux/core_portme.mak
Normal file
17
riscv-coremark/extraPortmes/linux/core_portme.mak
Normal file
|
@ -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
|
336
riscv-coremark/extraPortmes/linux64/core_portme.c
Executable file
336
riscv-coremark/extraPortmes/linux64/core_portme.c
Executable file
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "coremark.h"
|
||||
#if CALLGRIND_RUN
|
||||
#include <valgrind/callgrind.h>
|
||||
#endif
|
||||
|
||||
#if (MEM_METHOD==MEM_MALLOC)
|
||||
#include <malloc.h>
|
||||
/* 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 <time_in_secs>.
|
||||
This methodology is taken to accomodate any hardware or simulated platform.
|
||||
The sample implementation returns millisecs by default,
|
||||
and the resolution is controlled by <TIMER_RES_DIVIDER>
|
||||
*/
|
||||
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 <secs_ret> 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<n>*/
|
||||
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
|
291
riscv-coremark/extraPortmes/linux64/core_portme.h
Executable file
291
riscv-coremark/extraPortmes/linux64/core_portme.h
Executable file
|
@ -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 <windows.h>
|
||||
typedef size_t CORE_TICKS;
|
||||
#elif HAS_TIME_H
|
||||
#include <time.h>
|
||||
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 <core_portme.h>.
|
||||
|
||||
*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 <USE_PTHREAD> or <USE_FORK> to enable them.
|
||||
|
||||
It is valid to have a different implementation of <core_start_parallel> and <core_end_parallel> in <core_portme.c>,
|
||||
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 <MULTITHREAD> define.
|
||||
|
||||
To experiment, you can set the <MULTITHREAD> define to the highest value expected, and use argc/argv in the <portable_init> to set this value from the command line.
|
||||
*/
|
||||
extern ee_u32 default_num_contexts;
|
||||
|
||||
#if (MULTITHREAD>1)
|
||||
#if USE_PTHREAD
|
||||
#include <pthread.h>
|
||||
#define PARALLEL_METHOD "PThreads"
|
||||
#elif USE_FORK
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/shm.h>
|
||||
#include <string.h> /* for memcpy */
|
||||
#define PARALLEL_METHOD "Fork"
|
||||
#elif USE_SOCKET
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#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 */
|
140
riscv-coremark/extraPortmes/linux64/core_portme.mak
Executable file
140
riscv-coremark/extraPortmes/linux64/core_portme.mak
Executable file
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue