diff options
-rw-r--r-- | tests/include/test_asm_inline_gcc.h | 39 | ||||
-rw-r--r-- | tests/include/timestamp.h | 115 |
2 files changed, 154 insertions, 0 deletions
diff --git a/tests/include/test_asm_inline_gcc.h b/tests/include/test_asm_inline_gcc.h new file mode 100644 index 000000000..647631960 --- /dev/null +++ b/tests/include/test_asm_inline_gcc.h @@ -0,0 +1,39 @@ +/* GCC specific test inline assembler functions and macros */ + +/* + * Copyright (c) 2015, Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _TEST_ASM_INLINE_GCC_H +#define _TEST_ASM_INLINE_GCC_H + +#if !defined(__GNUC__) +#error test_asm_inline_gcc.h goes only with GCC +#endif + +#if defined(CONFIG_X86) +static inline void timestamp_serialize(void) +{ + __asm__ __volatile__ (/* serialize */ + "xorl %%eax,%%eax;\n\t" + "cpuid;\n\t" + : + : + : "%eax", "%ebx", "%ecx", "%edx"); +} +#elif defined(CONFIG_CPU_CORTEX_M) +#include <arch/arm/cortex_m/cmsis.h> +static inline void timestamp_serialize(void) +{ + /* isb is avaialble in all Cortex-M */ + __ISB(); +} +#elif defined(CONFIG_CPU_ARCV2) +#define timestamp_serialize() +#else +#error implementation of timestamp_serialize() not provided for your CPU target +#endif + +#endif /* _TEST_ASM_INLINE_GCC_H */ diff --git a/tests/include/timestamp.h b/tests/include/timestamp.h new file mode 100644 index 000000000..ee1e2d196 --- /dev/null +++ b/tests/include/timestamp.h @@ -0,0 +1,115 @@ +/* timestamp.h - macroses for measuring time in benchmarking tests */ + +/* + * Copyright (c) 2012-2015 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * DESCRIPTION + * This file contains the macroses for taking and converting time for + * benchmarking tests. + */ + +#ifndef _TIMESTAMP_H_ +#define _TIMESTAMP_H_ +#include <zephyr.h> + +#include <limits.h> +#if defined(__GNUC__) +#include <test_asm_inline_gcc.h> +#else +#include <test_asm_inline_other.h> +#endif + + +#define TICK_SYNCH() k_sleep(1) + +#define OS_GET_TIME() k_cycle_get_32() + +/* time necessary to read the time */ +extern uint32_t tm_off; + +static inline uint32_t TIME_STAMP_DELTA_GET(uint32_t ts) +{ + uint32_t t; + + /* serialize so OS_GET_TIME() is not reordered */ + timestamp_serialize(); + + t = OS_GET_TIME(); + uint32_t res = (t >= ts) ? (t - ts) : (ULONG_MAX - ts + t); + + if (ts > 0) { + res -= tm_off; + } + return res; +} + +/* + * Routine initializes the benchmark timing measurement + * The function sets up the global variable tm_off + */ +static inline void bench_test_init(void) +{ + uint32_t t = OS_GET_TIME(); + + tm_off = OS_GET_TIME() - t; +} + + +/* timestamp for checks */ +static int64_t tCheck; + +/* + * Routines are invoked before and after the benchmark and check + * if penchmarking code took less time than necessary for the + * high precision timer register overflow. + * Functions modify the tCheck global variable. + */ +static inline void bench_test_start(void) +{ + tCheck = 0; + /* before reading time we synchronize to the start of the timer tick */ + TICK_SYNCH(); + tCheck = k_uptime_delta(&tCheck); +} + + +/* returns 0 if the completed within a second and -1 if not */ +static inline int bench_test_end(void) +{ + tCheck = k_uptime_delta(&tCheck); + + /* Flag an error if the test ran for more than a second. + * (Note: Existing benchmarks have CONFIG_SYS_CLOCK_TICKS_PER_SEC=1 set, + * in such configs this check can be an indicator of whether + * timer tick interrupt overheads too are getting accounted towards + * benchmark time) + */ + if (tCheck >= MSEC_PER_SEC) { + return -1; + } + return 0; +} + +/* + * Returns -1 if number of ticks cause high precision timer counter + * overflow and 0 otherwise + * Called after bench_test_end to see if we still can use timing + * results or is it completely invalid + */ +static inline int high_timer_overflow(void) +{ + /* Check if the time elapsed in msec is sufficient to trigger an + * overflow of the high precision timer + */ + if (tCheck >= (SYS_CLOCK_HW_CYCLES_TO_NS64(UINT_MAX) / + (NSEC_PER_USEC * USEC_PER_MSEC))) { + return -1; + } + return 0; +} + +#endif /* _TIMESTAMP_H_ */ |