diff --git a/modules/coremark/CMakeLists.txt b/modules/coremark/CMakeLists.txt new file mode 100644 index 0000000000000..e34aef492d849 --- /dev/null +++ b/modules/coremark/CMakeLists.txt @@ -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) diff --git a/modules/coremark/Kconfig b/modules/coremark/Kconfig new file mode 100644 index 0000000000000..d5dff6e39973e --- /dev/null +++ b/modules/coremark/Kconfig @@ -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 diff --git a/modules/coremark/core_portme.c b/modules/coremark/core_portme.c new file mode 100644 index 0000000000000..af82ba7e3e06c --- /dev/null +++ b/modules/coremark/core_portme.c @@ -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 diff --git a/modules/coremark/core_portme.h b/modules/coremark/core_portme.h new file mode 100644 index 0000000000000..bdfd2eceb6509 --- /dev/null +++ b/modules/coremark/core_portme.h @@ -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 +#include +#include + +/* 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 */ diff --git a/modules/coremark/coremark_zephyr.h b/modules/coremark/coremark_zephyr.h new file mode 100644 index 0000000000000..b52db1ee10fa3 --- /dev/null +++ b/modules/coremark/coremark_zephyr.h @@ -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 diff --git a/samples/benchmarks/benchmarks.rst b/samples/benchmarks/benchmarks.rst new file mode 100644 index 0000000000000..d0a6f00c74c75 --- /dev/null +++ b/samples/benchmarks/benchmarks.rst @@ -0,0 +1,10 @@ +.. _benchmarks-sample: + +Benchmarks Samples +################## + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/samples/benchmarks/coremark/CMakeLists.txt b/samples/benchmarks/coremark/CMakeLists.txt new file mode 100644 index 0000000000000..e43b188ab7d9c --- /dev/null +++ b/samples/benchmarks/coremark/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(app) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/benchmarks/coremark/Kconfig b/samples/benchmarks/coremark/Kconfig new file mode 100644 index 0000000000000..0d98dbfc2de84 --- /dev/null +++ b/samples/benchmarks/coremark/Kconfig @@ -0,0 +1,19 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +menu "Zephyr Kernel" + source "Kconfig.zephyr" +endmenu + +menu "CoreMark sample" + +config APP_MODE_FLASH_AND_RUN + bool "Run CoreMark benchmark on start up" + help + If enabled, CoreMark will start execution immidietly after CPU start up. + Otherwise, it will wait button to be pressed. + +endmenu diff --git a/samples/benchmarks/coremark/Kconfig.sysbuild b/samples/benchmarks/coremark/Kconfig.sysbuild new file mode 100644 index 0000000000000..693c53c7a8dd7 --- /dev/null +++ b/samples/benchmarks/coremark/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +source "share/sysbuild/Kconfig" + +config IMAGE_2_BOARD + string "Second additional board name to build sample for" + +config IMAGE_3_BOARD + string "Third additional board name to build sample for" diff --git a/samples/benchmarks/coremark/README.rst b/samples/benchmarks/coremark/README.rst new file mode 100644 index 0000000000000..fb59ea21af6eb --- /dev/null +++ b/samples/benchmarks/coremark/README.rst @@ -0,0 +1,170 @@ +.. _coremark_sample: + +CoreMark +######## + +.. contents:: + :local: + :depth: 2 + +The sample demonstrates how to run the `CoreMark®`_ benchmark to evaluate performance of a core. + +.. _CoreMark®: https://www.eembc.org/coremark/ + +Requirements +************ + +The sample supports the following development kits: + ++--------------------------------+-----------+------------------------------------------------+------------------------------------+ +|Hardware platforms |PCA |Board name |Build target | ++================================+===========+================================================+====================================+ +|`nRF52 DK`_ |PCA10040 |:ref:`nrf52dk_nrf52832 ` |``nrf52dk_nrf52832`` | ++--------------------------------+-----------+------------------------------------------------+------------------------------------+ +|`nRF52840 DK`_ |PCA10056 |:ref:`nrf52840dk_nrf52840 `|``nrf52840dk_nrf52840`` | ++--------------------------------+-----------+------------------------------------------------+------------------------------------+ +|`nRF5340 DK`_ |PCA10095 |:ref:`nrf5340dk_nrf5340 ` |``nrf5340dk_nrf5340_cpuapp`` | ++--------------------------------+-----------+------------------------------------------------+------------------------------------+ + +One button and one led are required to run the sample on the board, that is not listed here. + +Overview +******** + +The sample runs the CoreMark benchmark on the target CPU. +CoreMark evaluates the CPU efficiency by performing different algorithms, such as state machine, CRC calculation, matrix manipulation and list processing (find and sort). + +To run CoreMark benchmark on the preferred core, press the button that corresponds to the core. +When the benchmark finishes running, it can be started again by pressing the button assigned to the given core. +Button and led assignnment is done in devicetree. + +Enable ``COREMARK_MODE_FLASH_AND_RUN`` if you want the sample to run for the first time upon startup. + +User interface +************** + +Each target CPU has an assigned button and LED that are responsible for triggering the benchmark's start and ``test in progress``. + +Default configuration for nRF5340 DK is following: + +Button 1: + Start the benchmark run on the Application Core. +Button 2: + Start the benchmark run on the Network/Radio Core. +LED 1: + Indicates ``test in progress`` on the Application Core. +LED 2: + Indicates ``test in progress`` on the Network/Radio Core. + + +Configuration +************* + +CoreMark runs tests multiple times. The number of iterations is defined with the ``CONFIG_COREMARK_ITERATIONS`` option. +By default, the iteration quantity is set to the minimum time required for valid results. +For valid results, the test should be executed for at least 10 seconds. + +CoreMark has three predefined run types, with the predefined data sizes, that are used for data algorithms: + +* ``CONFIG_COREMARK_RUN_TYPE_PERFORMANCE`` - defines ``CONFIG_COREMARK_DATA_SIZE`` to 2000 bytes. +* ``CONFIG_COREMARK_RUN_TYPE_PROFILE`` - defines ``CONFIG_COREMARK_DATA_SIZE`` to 1200 bytes. +* ``CONFIG_COREMARK_RUN_TYPE_VALIDATION`` - defines ``CONFIG_COREMARK_DATA_SIZE`` to 500 bytes. + +However, you can specify a custom ``CONFIG_COREMARK_DATA_SIZE`` value. +If you want to register your results, see the Submitting Results chapter in the `CoreMark GitHub`_ repository. + +Additionally, the ``CONFIG_COREMARK_DATA_SIZE`` option requires available memory space. +By default, the ``CONFIG_COREMARK_MEMORY_METHOD_STACK`` option is selected. +In this case, the main thread stack is used for data allocation. +To change the main stack size, use the ``CONFIG_MAIN_STACK_SIZE`` option. + +If you select the ``CONFIG_COREMARK_MEMORY_METHOD_MALLOC`` option, Zephyr :c:func:`k_malloc\k_free` functions will be used to allocate the memory in the heap. +Adjust the heap size with the ``CONFIG_HEAP_MEM_POOL_SIZE`` config option. + +If you select the ``CONFIG_COREMARK_MEMORY_METHOD_STATIC`` option, data will be allocated to the RAM as a regular static variable. +In this case you do not need to be aware of the main thread stack size or heap memory pool size. + +CoreMark can be executed in a multithread mode. +To specify a number of threads, use the ``CONFIG_COREMARK_THREADS_NUMBER`` option. +You can configure up to four threads. +In the multithread mode, CoreMark is executed in all threads simultaneously. +By default ``CONFIG_TIMESLICE_SIZE`` is set to 10 ms which imitates RTOS multithread usage. +However, in the final report thread execution is combined. +In multithread mode, the ``CONFIG_COREMARK_DATA_SIZE`` option is allocated for each thread separately. +Only the ``CONFIG_COREMARK_MEMORY_METHOD_STACK`` and ``CONFIG_COREMARK_MEMORY_METHOD_MALLOC`` memory methods can be used with multiple threads. +In case of the ``CONFIG_COREMARK_MEMORY_METHOD_STACK`` option, the data for all threads are allocated to the main thread stack. + +Building and running +******************** + +An extra build flag ``CONFIG_COMPILER_OPT="-O3"`` is applied when running the benchmark build to achieve the best CoreMark results. + +.. zephyr-app-commands:: + :zephyr-app: samples/benchmark/coremark + :board: nrf52840dk_nrf52840 + :goals: build flash + :compact: + +After flashing, messages will appear in the corresponding console that describe the state of the benchmark. +To build for another board, change "nrf52840dk_nrf52840" above to that board's name. + +Sample can be built for multiple targets in one run, e.g. in case of multicore MCU using `Sysbuild`_. +Use ``SB_CONFIG_IMAGE_2_BOARD`` option to provide board name for the second image in ``sysbuild.conf``. + +To build the sample for the multicore target execute the following commands: + + .. code-block:: console + + west build -b nrf5340dk_nrf5340_cpuapp --sysbuild + +Testing +======= + +After programming the sample to your development kit, complete the following steps to test it: + +1. Connect to the development kit with a terminal emulator (for example, PuTTY). +#. Reset your development kit. +#. To start the test, press the button assigned to the respective core. + To see the assignment, refer to the User interface section. + All target cores work independently from each other. + It is possible to run the benchmark on several cores simultaneously. + Measurements running on a core will be indicated by the corresponding LED. + If the ``COREMARK_MODE_FLASH_AND_RUN`` option is enabled, the measurement will launch on the application's start automatically on all available cores. +#. Wait for all measurements to be complete. + By default test will take approximately 11-13 seconds. +#. Wait for the console output for both cores. + The results will be similar to the following example: + + .. code-block:: console + + *** Booting Zephyr OS build zephyr-v3.3.0-386-g8e18c5ce1d75 *** + [00:00:00.511,291] app: Coremark sample for nrf52dk_nrf52832 + [00:00:00.511,352] app: Press Push button switch 0 to start the test ... + [00:00:30.858,642] app: Push button switch 0 pressed! + [00:00:30.858,673] app: Coremark started! + [00:00:30.858,703] app: CPU FREQ: 64000000 Hz + [00:00:30.858,703] app: (threads: 1, data size: 2000; iterations: 2000) + + 2K performance run parameters for coremark. + CoreMark Size : 666 + Total ticks : 395984 + Total time (secs): 12.084472 + Iterations/Sec : 165.501645 + Iterations : 2000 + Compiler version : GCC12.1.0 + Compiler flags : -O3 + Memory location : STACK + seedcrc : 0xe9f5 + [0]crclist : 0xe714 + [0]crcmatrix : 0x1fd7 + [0]crcstate : 0x8e3a + [0]crcfinal : 0x4983 + Correct operation validated. See README.md for run and reporting rules. + CoreMark 1.0 : 165.501645 / GCC12.1.0 -O3 / STACK + [00:00:43.974,304] app: Coremark finished! Press Push button switch 0 to restart ... + +.. _CoreMark GitHub: https://github.com/eembc/coremark#submitting-results +.. _nRF52 DK: https://docs.zephyrproject.org/latest/boards/arm/nrf52dk_nrf52832/doc/index.html +.. _nRF52840 DK: https://docs.zephyrproject.org/latest/boards/arm/nrf52840dk_nrf52840/doc/index.html +.. _nRF5340 DK: https://docs.zephyrproject.org/latest/boards/arm/nrf5340dk_nrf5340/doc/index.html +.. _sysbuild: https://docs.zephyrproject.org/3.2.0/build/sysbuild/index.html \ No newline at end of file diff --git a/samples/benchmarks/coremark/app.overlay b/samples/benchmarks/coremark/app.overlay new file mode 100644 index 0000000000000..f38b8d1df1db8 --- /dev/null +++ b/samples/benchmarks/coremark/app.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + + / { + aliases { + button = &button0; + led = &led0; + }; + }; diff --git a/samples/benchmarks/coremark/boards/nrf5340dk_nrf5340_cpuapp.overlay b/samples/benchmarks/coremark/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 0000000000000..412ec173fed50 --- /dev/null +++ b/samples/benchmarks/coremark/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + + #include "../app.overlay" + + / { + gpio_fwd: nrf-gpio-forwarder { + compatible = "nordic,nrf-gpio-forwarder"; + status = "okay"; + button_1 { + gpios = < &gpio0 0x18 0x11 >; + }; + }; + + gpio_fwd: nrf-gpio-forwarder { + compatible = "nordic,nrf-gpio-forwarder"; + status = "okay"; + led_1 { + gpios = < &gpio0 0x1d 0x1 >; + }; + }; + }; diff --git a/samples/benchmarks/coremark/boards/nrf5340dk_nrf5340_cpunet.overlay b/samples/benchmarks/coremark/boards/nrf5340dk_nrf5340_cpunet.overlay new file mode 100644 index 0000000000000..0cadd73ff5f38 --- /dev/null +++ b/samples/benchmarks/coremark/boards/nrf5340dk_nrf5340_cpunet.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + + / { + aliases { + button = &button1; + led = &led1; + }; + }; diff --git a/samples/benchmarks/coremark/prj.conf b/samples/benchmarks/coremark/prj.conf new file mode 100644 index 0000000000000..f19236c6f95d3 --- /dev/null +++ b/samples/benchmarks/coremark/prj.conf @@ -0,0 +1,40 @@ +# Common coremark configuration +CONFIG_COREMARK=y + +CONFIG_COREMARK_ITERATIONS=2000 + +# Single thread execution +CONFIG_COREMARK_THREADS_NUMBER=1 +# Choose memory method +CONFIG_COREMARK_MEMORY_METHOD_STACK=y +#CONFIG_COREMARK_MEMORY_METHOD_MALLOC=y + +# Supported only for single thread. No stack or heap required +#CONFIG_COREMARK_MEMORY_METHOD_STATIC=y + +# Choose proper memory size based on memory method selected above +# For 1 thread +CONFIG_MAIN_STACK_SIZE=4096 +#CONFIG_HEAP_MEM_POOL_SIZE=4096 + +# For 4 threads +CONFIG_TIMESLICE_SIZE=10 +#CONFIG_MAIN_STACK_SIZE=10240 +#CONFIG_HEAP_MEM_POOL_SIZE=10240 + +# Compiler options +CONFIG_COMPILER_OPT="-O3" + +# Config results output +CONFIG_LOG=y +CONFIG_PRINTK=y +CONFIG_CBPRINTF_FP_SUPPORT=y +CONFIG_CONSOLE=y +CONFIG_PRINTK_SYNC=y + +CONFIG_RTT_CONSOLE=y +CONFIG_USE_SEGGER_RTT=y + +CONFIG_GPIO=y + +CONFIG_MAIN_THREAD_PRIORITY=-1 diff --git a/samples/benchmarks/coremark/sample.yaml b/samples/benchmarks/coremark/sample.yaml new file mode 100644 index 0000000000000..a2b65ae84099d --- /dev/null +++ b/samples/benchmarks/coremark/sample.yaml @@ -0,0 +1,17 @@ +sample: + name: CoreMark Benchmark + description: CoreMark sample for the CPU performance evaluation. + Sample runs the CoreMark benchmark that measures the CPU efficiency + performing different algorithms like state machine, crc calculation, + matrix manipulation and list processing (find and sort). +tests: + sample.benchmark.coremark: + platform_allow: nrf52dk_nrf52832 nrf52dk_nrf52840 + integration_platforms: + - nrf52dk_nrf52832 + - nrf52840dk_nrf52840 + sample.benchmark.coremark.sysbuild: + platform_allow: nrf5340dk_nrf5340_cpuapp + extra_args: --sysbuild + integration_platforms: + - nrf5340dk_nrf5340_cpuapp diff --git a/samples/benchmarks/coremark/src/main.c b/samples/benchmarks/coremark/src/main.c new file mode 100644 index 0000000000000..a0283be70a135 --- /dev/null +++ b/samples/benchmarks/coremark/src/main.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "coremark_zephyr.h" + +LOG_MODULE_REGISTER(app, LOG_LEVEL_INF); + +/* + * Get button and led configuration from the devicetree. + * Application expects to have button and led aliases present in devicetree. + */ +#define BUTTON_NODE DT_ALIAS(button) +#define LED_NODE DT_ALIAS(led) + +#if !DT_NODE_HAS_STATUS(BUTTON_NODE, okay) + #error "Unsupported board: /"button/" alias is not defined." +#endif + +#if !DT_NODE_HAS_STATUS(LED_NODE, okay) + #error "Unsupported board: /"led/" alias is not defined." +#endif + +#define BUTTON_LABEL DT_PROP(DT_ALIAS(button), label) + +static K_SEM_DEFINE(start_coremark, 0, 1); +static bool coremark_in_progress; + +static const struct gpio_dt_spec start_button = GPIO_DT_SPEC_GET(BUTTON_NODE, gpios); +static const struct gpio_dt_spec status_led = GPIO_DT_SPEC_GET(LED_NODE, gpios); + +static struct gpio_callback button_cb_data; + +static void flush_log(void) +{ + if (IS_ENABLED(CONFIG_LOG_PROCESS_THREAD)) { + while (log_data_pending()) { + k_sleep(K_MSEC(10)); + } + k_sleep(K_MSEC(10)); + } else { + while (LOG_PROCESS()) { + } + } +} + +static void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins) +{ + if (gpio_pin_get_dt(&start_button) && !coremark_in_progress) { + LOG_INF("%s pressed!", BUTTON_LABEL); + coremark_in_progress = true; + k_sem_give(&start_coremark); + } +} + +static void led_init(void) +{ + int ret; + + if (!device_is_ready(status_led.port)) { + LOG_INF("Error: led device %s is not ready", + status_led.port->name); + return; + } + + ret = gpio_pin_configure_dt(&status_led, GPIO_OUTPUT_ACTIVE); + if (ret != 0) { + LOG_INF("Error %d: failed to configure %s pin %d", + ret, status_led.port->name, status_led.pin); + return; + } + + gpio_pin_set_dt(&status_led, GPIO_ACTIVE_HIGH); +} + +static void button_init(void) +{ + int ret; + + if (!device_is_ready(start_button.port)) { + LOG_INF("Error: button1 device %s is not ready", + start_button.port->name); + return; + } + + ret = gpio_pin_configure_dt(&start_button, GPIO_INPUT); + if (ret != 0) { + LOG_INF("Error %d: failed to configure %s pin %d", + ret, start_button.port->name, start_button.pin); + return; + } + + ret = gpio_pin_interrupt_configure_dt(&start_button, GPIO_INT_EDGE_BOTH); + + if (ret != 0) { + LOG_INF("Error %d: failed to configure interrupt on %s pin %d", + ret, start_button.port->name, start_button.pin); + return; + } + + gpio_init_callback(&button_cb_data, button_pressed, BIT(start_button.pin)); + gpio_add_callback(start_button.port, &button_cb_data); +} + +int main(void) +{ + LOG_INF("Coremark sample for %s", CONFIG_BOARD); + + led_init(); + button_init(); + + if (IS_ENABLED(CONFIG_APP_MODE_FLASH_AND_RUN)) { + coremark_in_progress = true; + k_sem_give(&start_coremark); + } else { + LOG_INF("Press %s to start the test ...", BUTTON_LABEL); + } + + while (true) { + k_sem_take(&start_coremark, K_FOREVER); + LOG_INF("Coremark started!"); + LOG_INF("CPU FREQ: %d Hz", SystemCoreClock); + LOG_INF("(threads: %d, data size: %d; iterations: %d)\n", + CONFIG_COREMARK_THREADS_NUMBER, + CONFIG_COREMARK_DATA_SIZE, + CONFIG_COREMARK_ITERATIONS); + flush_log(); + + gpio_pin_set_dt(&status_led, GPIO_ACTIVE_LOW); + coremark_run(); + gpio_pin_set_dt(&status_led, GPIO_ACTIVE_HIGH); + + LOG_INF("Coremark finished! Press %s to restart ...\n", BUTTON_LABEL); + + coremark_in_progress = false; + }; + + return 0; +} diff --git a/samples/benchmarks/coremark/sysbuild.cmake b/samples/benchmarks/coremark/sysbuild.cmake new file mode 100644 index 0000000000000..caa0ce87a405f --- /dev/null +++ b/samples/benchmarks/coremark/sysbuild.cmake @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: Apache-2.0 + +include(${ZEPHYR_BASE}/share/sysbuild/cmake/modules/sysbuild_extensions.cmake) + +if(${images_added}) + # same source directory is used for all targets + # to avoid recursive calls do not add project if remote was already added + return() +endif() + +if(SB_CONFIG_IMAGE_2_BOARD) + + list(APPEND IMAGES coremark_image_2) + + ExternalZephyrProject_Add( + APPLICATION coremark_image_2 + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR} + BOARD ${SB_CONFIG_IMAGE_2_BOARD} + ) + +endif() + +if(SB_CONFIG_IMAGE_3_BOARD) + + list(APPEND IMAGES coremark_image_3) + + ExternalZephyrProject_Add( + APPLICATION coremark_image_3 + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR} + BOARD ${SB_CONFIG_IMAGE_3_BOARD} + ) + +endif() + +set(images_added 1) diff --git a/samples/benchmarks/coremark/sysbuild.conf b/samples/benchmarks/coremark/sysbuild.conf new file mode 100644 index 0000000000000..e9fc90803f7df --- /dev/null +++ b/samples/benchmarks/coremark/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_IMAGE_2_BOARD="nrf5340dk_nrf5340_cpunet" diff --git a/samples/index.rst b/samples/index.rst index 82d4af143a780..26c7b860f50ff 100644 --- a/samples/index.rst +++ b/samples/index.rst @@ -27,6 +27,7 @@ Samples and Demos tfm_integration/tfm_integration.rst modules/* compression/* + benchmarks/* .. comment To add a new sample document, please use the template available under diff --git a/west.yml b/west.yml index d8fa46aa30460..b077ad32965bc 100644 --- a/west.yml +++ b/west.yml @@ -21,6 +21,8 @@ manifest: remotes: - name: upstream url-base: https://github.com/zephyrproject-rtos + - name: eembc + url-base: https://github.com/eembc # # Please add items below based on alphabetical order @@ -36,6 +38,12 @@ manifest: path: modules/hal/cmsis groups: - hal + - name: coremark + remote: eembc + path: modules/benchmark/coremark + revision: d5fad6bd094899101a4e5fd53af7298160ced6ab + groups: + - benchmark - name: edtt revision: fc998bcaed44796c3800a3e62cf026bd9403d299 path: tools/edtt