Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: CoreMark benchmark sample #55461

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions modules/coremark/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# SPDX-License-Identifier: Apache-2.0

if(NOT CONFIG_COREMARK)
return()
endif()

zephyr_library_named(coremark)

zephyr_include_directories(${ZEPHYR_COREMARK_MODULE_DIR} .)

zephyr_library_sources(${ZEPHYR_COREMARK_MODULE_DIR}/core_main.c
${ZEPHYR_COREMARK_MODULE_DIR}/core_matrix.c
${ZEPHYR_COREMARK_MODULE_DIR}/core_state.c
${ZEPHYR_COREMARK_MODULE_DIR}/core_util.c
${ZEPHYR_COREMARK_MODULE_DIR}/core_list_join.c
core_portme.c)
86 changes: 86 additions & 0 deletions modules/coremark/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#
# Copyright (c) 2023 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: Apache-2.0
#

menuconfig COREMARK
bool "Coremark benchmark"

if COREMARK

config COREMARK_ITERATIONS
int "Number of the iterations to run"
range 100 10000
default 1000
help
Option is used to specify the number of the iterations to run the benchmark.
Coremark should execute at least 10 seconds to have the valid results.
The minimum number of interations depends on the platform and its configuration.

config COREMARK_THREADS_NUMBER
int "Number of the threads for the parallel benchmark execution"
default 1
range 1 4
help
Specify the number of the threads to use for the coremark execution.
1 - means the execution only from the main thread.

choice COREMARK_RUN_TYPE
prompt "Coremark run type"
default COREMARK_RUN_TYPE_PERFORMANCE
help
Specify the purpose of the coremark execution. Depending on the type
different memory size is required to operate with.

config COREMARK_RUN_TYPE_PERFORMANCE
bool "Performance run"

config COREMARK_RUN_TYPE_PROFILE
bool "Profile run"

config COREMARK_RUN_TYPE_VALIDATION
bool "Validation run"

endchoice # COREMARK_RUN_TYPE

config COREMARK_DATA_SIZE
int "Total size for the data algorithms will operate on"
default 500 if COREMARK_RUN_TYPE_VALIDATION
default 1200 if COREMARK_RUN_TYPE_PROFILE
default 2000 if COREMARK_RUN_TYPE_PERFORMANCE
range 100 2000
help
Specifies size for the data algorithms. You can choose different values
for it. But note, that for registering your results it is required to
run CoreMark with default values for PROFILE and PERFORMANCE run types.

choice COREMARK_MEMORY_METHOD
prompt "Memory Method"
default COREMARK_MEMORY_METHOD_STACK
help
Option defines the method to get a block of memory.

config COREMARK_MEMORY_METHOD_STACK
bool "Stack"
help
Main thread stack is used for this memory method. Be sure, that there
is enough memory allocated with MAIN_STACK_SIZE option. Size depends
on data size, coremarks operates on and number of threads. It should
be higher than:
COREMARK_DATA_SIZE * COREMARK_THREADS_NUMBER + main thread context.

config COREMARK_MEMORY_METHOD_STATIC
bool "Static"

config COREMARK_MEMORY_METHOD_MALLOC
bool "Malloc"
help
in order to use this option you need to set up system heap size using
HEAP_MEM_POOL_SIZE option. Size depends on number of parallel
contexts executed and COREMARK_RUN_TYPE. It should be higher than
COREMARK_DATA_SIZE * COREMARK_THREADS_NUMBER.

endchoice # COREMARK_MEMORY_METHOD

endif
136 changes: 136 additions & 0 deletions modules/coremark/core_portme.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

#include "coremark.h"

#if CONFIG_COREMARK_RUN_TYPE_VALIDATION
volatile ee_s32 seed1_volatile = 0x3415;
volatile ee_s32 seed2_volatile = 0x3415;
volatile ee_s32 seed3_volatile = 0x66;
#endif

#if CONFIG_COREMARK_RUN_TYPE_PERFORMANCE
volatile ee_s32 seed1_volatile = 0x0;
volatile ee_s32 seed2_volatile = 0x0;
volatile ee_s32 seed3_volatile = 0x66;
#endif

#if CONFIG_COREMARK_RUN_TYPE_PROFILE
volatile ee_s32 seed1_volatile = 0x8;
volatile ee_s32 seed2_volatile = 0x8;
volatile ee_s32 seed3_volatile = 0x8;
#endif

volatile ee_s32 seed4_volatile = CONFIG_COREMARK_ITERATIONS;
volatile ee_s32 seed5_volatile = 0;

ee_u32 default_num_contexts = CONFIG_COREMARK_THREADS_NUMBER;

static CORE_TICKS start_time_val;
static CORE_TICKS stop_time_val;

void start_time(void)
{
start_time_val = k_cycle_get_32();
}

void stop_time(void)
{
stop_time_val = k_cycle_get_32();
}

CORE_TICKS get_time(void)
{
return (stop_time_val - start_time_val);
}

secs_ret time_in_secs(CORE_TICKS ticks)
{
secs_ret retval = (secs_ret)(k_cyc_to_ns_floor64(ticks) / 1000) / 1000000UL;
return retval;
}

void portable_init(core_portable *p, int *argc, char *argv[])
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);

if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) {
ee_printf(
"ERROR! Please define ee_ptr_int to a type that holds a "
"pointer!\n");
}

if (sizeof(ee_u32) != 4) {
ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n");
}

p->portable_id = 1;
}

void portable_fini(core_portable *p)
{
p->portable_id = 0;
}

#if (CONFIG_COREMARK_THREADS_NUMBER > 1)

#define THREAD_STACK_SIZE (512)
static K_THREAD_STACK_DEFINE(coremark_thread1_stack, THREAD_STACK_SIZE);
static K_THREAD_STACK_DEFINE(coremark_thread2_stack, THREAD_STACK_SIZE);
static K_THREAD_STACK_DEFINE(coremark_thread3_stack, THREAD_STACK_SIZE);
static K_THREAD_STACK_DEFINE(coremark_thread4_stack, THREAD_STACK_SIZE);

static k_thread_stack_t *pstack[] = {
coremark_thread1_stack,
coremark_thread2_stack,
coremark_thread3_stack,
coremark_thread4_stack
};

static struct k_thread coremark_thread_data[CONFIG_COREMARK_THREADS_NUMBER];

static int active_threads;

static void coremark_thread(void *id, void *pres, void *p3)
{
iterate(pres);
}

ee_u8 core_start_parallel(core_results *res)
{
k_thread_create(&coremark_thread_data[active_threads],
pstack[active_threads],
THREAD_STACK_SIZE,
coremark_thread,
(void *)active_threads,
res,
NULL,
0, 0, K_NO_WAIT);

/* Thread creation is done from single thread.
* CoreMark guarantees number of active thread is limited to defined bound.
*/
active_threads++;

return 0;
}

ee_u8 core_stop_parallel(core_results *res)
{
active_threads--;

/* Order in which threads are joined does not matter.
* CoreMark will never start threads unless all previously started are joined.
* Stack is guaranteed to be used by one thread only.
*/

k_thread_join(&coremark_thread_data[active_threads], K_FOREVER);

return 0;
}

#endif
135 changes: 135 additions & 0 deletions modules/coremark/core_portme.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef CORE_PORTME_H
#define CORE_PORTME_H

#include <zephyr/kernel.h>
#include <stdint.h>
#include <stdlib.h>

/* Basic coremark configuration */
#ifndef HAS_FLOAT
#define HAS_FLOAT 1
#endif

#ifndef HAS_TIME_H
#define HAS_TIME_H 0
#endif

#ifndef USE_CLOCK
#define USE_CLOCK 0
#endif

#ifndef HAS_STDIO
#define HAS_STDIO 0
#endif

#ifndef HAS_PRINTF
#define HAS_PRINTF 0
#endif

#ifndef MAIN_HAS_NOARGC
#define MAIN_HAS_NOARGC 1
#endif

#ifndef MAIN_HAS_NORETURN
#define MAIN_HAS_NORETURN 1
#endif

#ifndef SEED_METHOD
#define SEED_METHOD SEED_VOLATILE
#endif

/* Compiler information setup */
#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

/* Definition of the method to get a block of memory */
#ifndef MEM_METHOD
#ifdef CONFIG_COREMARK_MEMORY_METHOD_STACK
#define MEM_METHOD MEM_STACK
#define MEM_LOCATION "STACK"
#elif defined(CONFIG_COREMARK_MEMORY_METHOD_STATIC)
#define MEM_METHOD MEM_STATIC
#define MEM_LOCATION "STATIC"
#elif defined(CONFIG_COREMARK_MEMORY_METHOD_MALLOC)
#define MEM_METHOD MEM_MALLOC
#define MEM_LOCATION "MALLOC"
#endif
#endif

#ifndef MULTITHREAD
#define MULTITHREAD CONFIG_COREMARK_THREADS_NUMBER
#endif

#if (MULTITHREAD > 1)
#define PARALLEL_METHOD "PThreads"
#endif

/* Depending on the benchmark run type different data size is required.
* Default values for TOTAL_DATA_SIZE is predefined in coremark.h
* Redefine it here and get value according to coremark configuraion.
*/
#undef TOTAL_DATA_SIZE
#define TOTAL_DATA_SIZE CONFIG_COREMARK_DATA_SIZE

/* Coremark's entry point by default called 'main'.
* As CoreMark sources are readonly we need to solve this conflict in other way.
* In order to use it we need somehow to rename coremark main functon.
*/
#define main coremark_run

/* crc16 function is present also in zephyr and coremark.
* To avoid multiple definition error without changing benchmark's code,
* coremark crc16 instance is renamed.
*/
#define crc16 coremark_crc16

/* This function will be used to output benchmark results */
#define ee_printf printk

/* Functions used by coremark for MEM_METHOD MALLOC case */
#define portable_malloc k_malloc
#define portable_free k_free

/* Coremark specific data types definition
* Note, that ee_ptr_int is required to be the data type used to hold pointers
*/
typedef signed short ee_s16;
typedef unsigned short ee_u16;
typedef signed int ee_s32;
typedef double ee_f32;
typedef unsigned char ee_u8;
typedef unsigned int ee_u32;
typedef ee_u32 ee_ptr_int;
typedef size_t ee_size_t;
typedef uint32_t CORE_TICKS;

/* align_mem 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))

typedef struct CORE_PORTABLE_S {
ee_u8 portable_id;
} core_portable;

extern ee_u32 default_num_contexts;

void portable_init(core_portable *p, int *argc, char *argv[]);
void portable_fini(core_portable *p);

#endif /* CORE_PORTME_H */
12 changes: 12 additions & 0 deletions modules/coremark/coremark_zephyr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef CORE_PORTME_ZEPHYR_H
#define CORE_PORTME_ZEPHYR_H

void coremark_run(void);

#endif
Loading