diff --git a/README.md b/README.md index c2c2a37..5208928 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,32 @@ For cross compile platforms please adjust `core_portme.mak`, `core_portme.h` (an % make PORT_DIR= ~~~ +## Zephyr RTOS port +The [zephyr RTOS](https://zephyrproject.org) is supported as a target for coremark. +Zephyr being a unikernel operation system, it needs to be built and linked against coremark directly. +To this end, the zephyr port uses zephyr's CMake build system. + +In order to run corebench on a zephyr target, start by configuring a zephyr workplace in accordance with the [zephyr getting started guide](https://docs.zephyrproject.org/latest/develop/getting_started/index.html). +Note that especially the correct installation of the toolchain using its `setup.sh` and the `west zephyr-export` step are important for being able to build coremark. Ideally, run one of the zephyr samples on your board *before trying to run the coremark port* to test that everything was set up properly. +The port was tested with version 3.7.0 of zephyr, but should work with later versions as well. + +In order to build the port, run zephyr's build command *from the top of the coremark directory*: + +```bash + west build -p always -b zephyr/ +``` + +You can then load and execute zephyr with coremark using, e.g., the *flash* and *debug* commands that come with zephyr's build tool west: + +```bash + west debug # launches into GDB shell, stopped at first instruction + west flash # launches without debugger +``` + +The make flags below except `REBUILD` are supported. +Be sure to provide the flag `-p` (*pristine*) to `west build` to force a re-build. +If unsure, delete the *build* directory as well. + ## Make Targets * `run` - Default target, creates `run1.log` and `run2.log`. * `run1.log` - Run the benchmark with performance parameters, and output to `run1.log` diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt new file mode 100644 index 0000000..33ff9d5 --- /dev/null +++ b/zephyr/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright 2025 CISPA Helmholtz Center for Information Security gGmbH +# +# 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: Eric Ackermann + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(coremark) + +set(ZEPHYR_PORT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(COREMARK_DIR ${ZEPHYR_PORT_DIR}/../) + +target_sources(app PRIVATE + # core sources + ${COREMARK_DIR}/core_list_join.c + ${COREMARK_DIR}/core_main.c + ${COREMARK_DIR}/core_matrix.c + ${COREMARK_DIR}/core_state.c + ${COREMARK_DIR}/core_util.c + # port-specific sources + ${ZEPHYR_PORT_DIR}/core_portme.c +) + +target_include_directories(app PRIVATE ${ZEPHYR_PORT_DIR}) +target_include_directories(app PRIVATE ${COREMARK_DIR}) + +if($ENV{ITERATIONS}) + target_compile_definitions(app PRIVATE -DITERATIONS=$ENV{ITERATIONS}) +else() + target_compile_definitions(app PRIVATE -DITERATIONS=0) +endif() + +if($ENV{XCFLAGS}) + target_compile_options(app $ENV{XCFLAGS}) +endif() diff --git a/zephyr/core_portme.c b/zephyr/core_portme.c new file mode 100644 index 0000000..e5b6654 --- /dev/null +++ b/zephyr/core_portme.c @@ -0,0 +1,224 @@ +/* +Copyright 2025 CISPA Helmholtz Center for Information Security gGmbH + +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: Eric Ackermann +*/ + +#include +#include +#include "coremark.h" + +#include +#include +#include + +#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; + +#if (MEM_METHOD == MEM_MALLOC) +/* Function: portable_malloc + Provide malloc() functionality in a platform specific way. +*/ +void * +portable_malloc(size_t size) +{ + return malloc(size); +} +/* Function: portable_free + Provide free() functionality in a platform specific way. +*/ +void +portable_free(void *p) +{ + free(p); +} +#else +void * +portable_malloc(size_t size) +{ + return NULL; +} +void +portable_free(void *p) +{ + p = NULL; +} +#endif + + +/* 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. + */ +#define CORETIMETYPE timing_t +#define GETMYTIME(_t) (*_t = timing_counter_get()) +#define MYTIMEDIFF(fin, ini) (timing_cycles_get(ini, fin)) +#define TIMER_RES_DIVIDER 1 +#define SAMPLE_TIME_IMPLEMENTATION 1 +#define EE_TICKS_PER_SEC (NSECS_PER_SEC / TIMER_RES_DIVIDER) + +/** Define Host specific (POSIX), or target specific global time variables. */ +static CORETIMETYPE start_time_val, stop_time_val; + +/* Function : start_time + This function will be called right before starting the timed portion of + the benchmark. + + 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) +{ + timing_start(); + start_time_val = timing_counter_get(); +} +/* 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) +{ + timing_stop(); + stop_time_val = timing_counter_get(); +} +/* 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 accommodate 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 + = timing_cycles_get(&start_time_val, &stop_time_val); + return elapsed; +} +/* Function : time_in_secs + Convert the value returned by get_time to seconds. + + The type is used to accommodate 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) +{ + uint64_t time_ns = timing_cycles_to_ns(ticks); + uint64_t time_ms = DIV_ROUND_UP(time_ns, NSEC_PER_MSEC); + + /* one input being float will result in float computation as well */ + secs_ret retval = (secs_ret) time_ms / (secs_ret)MSEC_PER_SEC; + return retval; +} + +ee_u32 default_num_contexts = 1; + +/* Function : portable_init + Target specific initialization code + Test for some common mistakes. +*/ +void +portable_init(core_portable *p, int *argc, char *argv[]) +{ + + (void)argc; // prevent unused warning + (void)argv; // prevent unused warning + + timing_init(); + + BUILD_ASSERT(sizeof(ee_ptr_int) == sizeof(ee_u8 *)); + BUILD_ASSERT(sizeof(ee_u32) == 4); + + 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); +} +#else /* no standard multicore implementation */ +#error "Zephyr port currently only supports pthread for multicore operation!" +#endif +#endif /* MULTITHREAD */ diff --git a/zephyr/core_portme.h b/zephyr/core_portme.h new file mode 100644 index 0000000..81db21d --- /dev/null +++ b/zephyr/core_portme.h @@ -0,0 +1,209 @@ +/* +Copyright 2025 CISPA Helmholtz Center for Information Security gGmbH + +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: Eric Ackermann +*/ + +#include + +/* Topic : Description + This file maps coremark defines to zephyr's according Kconfig options +*/ +#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 CONFIG_FPU +#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 1 +#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. + */ +#include +typedef uint64_t CORE_TICKS; + +/* 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 CONFIG_COMPILER_OPT +#endif +#ifndef MEM_LOCATION +#define MEM_LOCATION "MALLOC" +#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 intptr_t 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_VOLATILE +#endif + +/* Configuration : MEM_METHOD + Defines method to get a block of memry. + + Valid values : + MEM_MALLOC - for platforms that implement malloc and have malloc.h. + MEM_STATIC - to use a static memory array. + MEM_STACK - to allocate the data block on the stack (NYI). +*/ +#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 +/* CONFIG_POSIX_THREADS for supporting pthread is always set in prj.conf */ +#define MULTITHREAD 1 +#define USE_PTHREAD MULTITHREAD +#define USE_FORK 0 +#define USE_SOCKET 0 +#endif + +/* Configuration : MAIN_HAS_NOARGC + Needed if platform does not support getting arguments to main. + + Valid values : + 0 - argc/argv to main is supported + 1 - argc/argv to main is not supported + + Note : + This flag only matters if MULTITHREAD has been defined to a value + greater then 1. +*/ +#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 + Not used for this simple port, must contain the value 1. +*/ +extern ee_u32 default_num_contexts; + +typedef struct CORE_PORTABLE_S +{ + ee_u8 portable_id; +} core_portable; + +/* target specific init/fini */ +void portable_init(core_portable *p, int *argc, char *argv[]); +void portable_fini(core_portable *p); + +#if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) \ + && !defined(VALIDATION_RUN) +#if (TOTAL_DATA_SIZE == 1200) +#define PROFILE_RUN 1 +#elif (TOTAL_DATA_SIZE == 2000) +#define PERFORMANCE_RUN 1 +#else +#define VALIDATION_RUN 1 +#endif +#endif + +#endif /* CORE_PORTME_H */ diff --git a/zephyr/prj.conf b/zephyr/prj.conf new file mode 100644 index 0000000..e6a788f --- /dev/null +++ b/zephyr/prj.conf @@ -0,0 +1,20 @@ +# Copyright 2025 CISPA Helmholtz Center for Information Security gGmbH +# +# 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: Eric Ackermann +# +# This file sets required zephyr configuration options + +CONFIG_POSIX_THREADS=y +CONFIG_TIMING_FUNCTIONS=y