diff --git a/samples/benchmarks/benchmarks.rst b/samples/benchmarks/benchmarks.rst new file mode 100644 index 000000000000000..d0a6f00c74c7515 --- /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 000000000000000..dae36fd390f811b --- /dev/null +++ b/samples/benchmarks/coremark/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +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 000000000000000..0d98dbfc2de841a --- /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 000000000000000..693c53c7a8dd7c8 --- /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 000000000000000..fb59ea21af6eb14 --- /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 000000000000000..605d4d19071da8c --- /dev/null +++ b/samples/benchmarks/coremark/app.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + + / { + 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 000000000000000..967cac7e07e7b11 --- /dev/null +++ b/samples/benchmarks/coremark/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + + #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 000000000000000..dc6625053eed102 --- /dev/null +++ b/samples/benchmarks/coremark/boards/nrf5340dk_nrf5340_cpunet.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + + / { + aliases { + button = &button1; + led = &led1; + }; + }; diff --git a/samples/benchmarks/coremark/prj.conf b/samples/benchmarks/coremark/prj.conf new file mode 100644 index 000000000000000..f19236c6f95d3ee --- /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 000000000000000..0c352ea166b7ad5 --- /dev/null +++ b/samples/benchmarks/coremark/sample.yaml @@ -0,0 +1,18 @@ +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: + filter: dt_enabled_alias_with_parent_compat("button0", "gpio-keys") + filter: dt_enabled_alias_with_parent_compat("led0", "gpio-led") + integration_platforms: + - nrf52dk_nrf52832 + - nrf5280dk_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 000000000000000..a0283be70a1355e --- /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 000000000000000..ce5bb4a99330005 --- /dev/null +++ b/samples/benchmarks/coremark/sysbuild.cmake @@ -0,0 +1,39 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# 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 000000000000000..e9fc90803f7dff5 --- /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 82d4af143a7800b..26c7b860f50fffc 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