Skip to content

Commit 15331ec

Browse files
Provide port for zephyr RTOS, facilitating running coremark as an application
1 parent d5fad6b commit 15331ec

File tree

5 files changed

+527
-0
lines changed

5 files changed

+527
-0
lines changed

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,32 @@ For cross compile platforms please adjust `core_portme.mak`, `core_portme.h` (an
2020
% make PORT_DIR=<platform>
2121
~~~
2222

23+
## Zephyr RTOS port
24+
The [zephyr RTOS](https://zephyrproject.org) is supported as a target for coremark.
25+
Zephyr being a unikernel operation system, it needs to be built and linked against coremark directly.
26+
To this end, the zephyr port uses zephyr's CMake build system.
27+
28+
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).
29+
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.
30+
The port was tested with version 3.7.0 of zephyr, but should work with later versions as well.
31+
32+
In order to build the port, run zephyr's build command *from the top of the coremark directory*:
33+
34+
```bash
35+
west build -p always -b <your board> zephyr/
36+
```
37+
38+
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:
39+
40+
```bash
41+
west debug # launches into GDB shell, stopped at first instruction
42+
west flash # launches without debugger
43+
```
44+
45+
The make flags below except `REBUILD` are supported.
46+
Be sure to provide the flag `-p` (*pristine*) to `west build` to force a re-build.
47+
If unsure, delete the *build* directory as well.
48+
2349
## Make Targets
2450
* `run` - Default target, creates `run1.log` and `run2.log`.
2551
* `run1.log` - Run the benchmark with performance parameters, and output to `run1.log`

zephyr/CMakeLists.txt

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Copyright 2025 CISPA Helmholtz Center for Information Security gGmbH
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
# Original Author: Eric Ackermann
16+
17+
cmake_minimum_required(VERSION 3.20.0)
18+
19+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
20+
21+
project(coremark)
22+
23+
set(ZEPHYR_PORT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
24+
set(COREMARK_DIR ${ZEPHYR_PORT_DIR}/../)
25+
26+
target_sources(app PRIVATE
27+
# core sources
28+
${COREMARK_DIR}/core_list_join.c
29+
${COREMARK_DIR}/core_main.c
30+
${COREMARK_DIR}/core_matrix.c
31+
${COREMARK_DIR}/core_state.c
32+
${COREMARK_DIR}/core_util.c
33+
# port-specific sources
34+
${ZEPHYR_PORT_DIR}/core_portme.c
35+
)
36+
37+
target_include_directories(app PRIVATE ${ZEPHYR_PORT_DIR})
38+
target_include_directories(app PRIVATE ${COREMARK_DIR})
39+
40+
if($ENV{ITERATIONS})
41+
target_compile_definitions(app PRIVATE -DITERATIONS=$ENV{ITERATIONS})
42+
else()
43+
target_compile_definitions(app PRIVATE -DITERATIONS=0)
44+
endif()
45+
46+
if($ENV{XCFLAGS})
47+
target_compile_options(app $ENV{XCFLAGS})
48+
endif()

zephyr/core_portme.c

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/*
2+
Copyright 2025 CISPA Helmholtz Center for Information Security gGmbH
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
16+
Original Author: Eric Ackermann
17+
*/
18+
19+
#include <stdio.h>
20+
#include <stdlib.h>
21+
#include "coremark.h"
22+
23+
#include <zephyr/kernel.h>
24+
#include <zephyr/timing/timing.h>
25+
#include <zephyr/sys_clock.h>
26+
27+
#if VALIDATION_RUN
28+
volatile ee_s32 seed1_volatile = 0x3415;
29+
volatile ee_s32 seed2_volatile = 0x3415;
30+
volatile ee_s32 seed3_volatile = 0x66;
31+
#endif
32+
#if PERFORMANCE_RUN
33+
volatile ee_s32 seed1_volatile = 0x0;
34+
volatile ee_s32 seed2_volatile = 0x0;
35+
volatile ee_s32 seed3_volatile = 0x66;
36+
#endif
37+
#if PROFILE_RUN
38+
volatile ee_s32 seed1_volatile = 0x8;
39+
volatile ee_s32 seed2_volatile = 0x8;
40+
volatile ee_s32 seed3_volatile = 0x8;
41+
#endif
42+
volatile ee_s32 seed4_volatile = ITERATIONS;
43+
volatile ee_s32 seed5_volatile = 0;
44+
45+
#if (MEM_METHOD == MEM_MALLOC)
46+
/* Function: portable_malloc
47+
Provide malloc() functionality in a platform specific way.
48+
*/
49+
void *
50+
portable_malloc(size_t size)
51+
{
52+
return malloc(size);
53+
}
54+
/* Function: portable_free
55+
Provide free() functionality in a platform specific way.
56+
*/
57+
void
58+
portable_free(void *p)
59+
{
60+
free(p);
61+
}
62+
#else
63+
void *
64+
portable_malloc(size_t size)
65+
{
66+
return NULL;
67+
}
68+
void
69+
portable_free(void *p)
70+
{
71+
p = NULL;
72+
}
73+
#endif
74+
75+
76+
/* Porting : Timing functions
77+
How to capture time and convert to seconds must be ported to whatever is
78+
supported by the platform. e.g. Read value from on board RTC, read value from
79+
cpu clock cycles performance counter etc. Sample implementation for standard
80+
time.h and windows.h definitions included.
81+
*/
82+
/* Define : TIMER_RES_DIVIDER
83+
Divider to trade off timer resolution and total time that can be
84+
measured.
85+
86+
Use lower values to increase resolution, but make sure that overflow
87+
does not occur. If there are issues with the return value overflowing,
88+
increase this value.
89+
*/
90+
#define CORETIMETYPE timing_t
91+
#define GETMYTIME(_t) (*_t = timing_counter_get())
92+
#define MYTIMEDIFF(fin, ini) (timing_cycles_get(ini, fin))
93+
#define TIMER_RES_DIVIDER 1
94+
#define SAMPLE_TIME_IMPLEMENTATION 1
95+
#define EE_TICKS_PER_SEC (NSECS_PER_SEC / TIMER_RES_DIVIDER)
96+
97+
/** Define Host specific (POSIX), or target specific global time variables. */
98+
static CORETIMETYPE start_time_val, stop_time_val;
99+
100+
/* Function : start_time
101+
This function will be called right before starting the timed portion of
102+
the benchmark.
103+
104+
Implementation may be capturing a system timer (as implemented in the
105+
example code) or zeroing some system parameters - e.g. setting the cpu clocks
106+
cycles to 0.
107+
*/
108+
void
109+
start_time(void)
110+
{
111+
timing_start();
112+
start_time_val = timing_counter_get();
113+
}
114+
/* Function : stop_time
115+
This function will be called right after ending the timed portion of the
116+
benchmark.
117+
118+
Implementation may be capturing a system timer (as implemented in the
119+
example code) or other system parameters - e.g. reading the current value of
120+
cpu cycles counter.
121+
*/
122+
void
123+
stop_time(void)
124+
{
125+
timing_stop();
126+
stop_time_val = timing_counter_get();
127+
}
128+
/* Function : get_time
129+
Return an abstract "ticks" number that signifies time on the system.
130+
131+
Actual value returned may be cpu cycles, milliseconds or any other
132+
value, as long as it can be converted to seconds by <time_in_secs>. This
133+
methodology is taken to accommodate any hardware or simulated platform. The
134+
sample implementation returns millisecs by default, and the resolution is
135+
controlled by <TIMER_RES_DIVIDER>
136+
*/
137+
CORE_TICKS
138+
get_time(void)
139+
{
140+
CORE_TICKS elapsed
141+
= timing_cycles_get(&start_time_val, &stop_time_val);
142+
return elapsed;
143+
}
144+
/* Function : time_in_secs
145+
Convert the value returned by get_time to seconds.
146+
147+
The <secs_ret> type is used to accommodate systems with no support for
148+
floating point. Default implementation implemented by the EE_TICKS_PER_SEC
149+
macro above.
150+
*/
151+
secs_ret
152+
time_in_secs(CORE_TICKS ticks)
153+
{
154+
uint64_t time_ns = timing_cycles_to_ns(ticks);
155+
uint64_t time_ms = DIV_ROUND_UP(time_ns, NSEC_PER_MSEC);
156+
157+
/* one input being float will result in float computation as well */
158+
secs_ret retval = (secs_ret) time_ms / (secs_ret)MSEC_PER_SEC;
159+
return retval;
160+
}
161+
162+
ee_u32 default_num_contexts = 1;
163+
164+
/* Function : portable_init
165+
Target specific initialization code
166+
Test for some common mistakes.
167+
*/
168+
void
169+
portable_init(core_portable *p, int *argc, char *argv[])
170+
{
171+
172+
(void)argc; // prevent unused warning
173+
(void)argv; // prevent unused warning
174+
175+
timing_init();
176+
177+
BUILD_ASSERT(sizeof(ee_ptr_int) == sizeof(ee_u8 *));
178+
BUILD_ASSERT(sizeof(ee_u32) == 4);
179+
180+
p->portable_id = 1;
181+
}
182+
/* Function : portable_fini
183+
Target specific final code
184+
*/
185+
void
186+
portable_fini(core_portable *p)
187+
{
188+
p->portable_id = 0;
189+
}
190+
191+
192+
#if (MULTITHREAD > 1)
193+
194+
/* Function: core_start_parallel
195+
Start benchmarking in a parallel context.
196+
197+
Three implementations are provided, one using pthreads, one using fork
198+
and shared mem, and one using fork and sockets. Other implementations using
199+
MCAPI or other standards can easily be devised.
200+
*/
201+
/* Function: core_stop_parallel
202+
Stop a parallel context execution of coremark, and gather the results.
203+
204+
Three implementations are provided, one using pthreads, one using fork
205+
and shared mem, and one using fork and sockets. Other implementations using
206+
MCAPI or other standards can easily be devised.
207+
*/
208+
#if USE_PTHREAD
209+
ee_u8
210+
core_start_parallel(core_results *res)
211+
{
212+
return (ee_u8)pthread_create(
213+
&(res->port.thread), NULL, iterate, (void *)res);
214+
}
215+
ee_u8
216+
core_stop_parallel(core_results *res)
217+
{
218+
void *retval;
219+
return (ee_u8)pthread_join(res->port.thread, &retval);
220+
}
221+
#else /* no standard multicore implementation */
222+
#error "Zephyr port currently only supports pthread for multicore operation!"
223+
#endif
224+
#endif /* MULTITHREAD */

0 commit comments

Comments
 (0)