/* * Copyright (c) 2020 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ #ifndef ZEPHYR_INCLUDE_TIMING_TIMING_H_ #define ZEPHYR_INCLUDE_TIMING_TIMING_H_ #include #include #ifdef __cplusplus extern "C" { #endif /** * @brief Timing Measurement APIs * @defgroup timing_api Timing Measurement APIs * @ingroup os_services * * The timing measurement APIs can be used to obtain execution * time of a section of code to aid in analysis and optimization. * * Please note that the timing functions may use a different timer * than the default kernel timer, where the timer being used is * specified by architecture, SoC or board configuration. */ /** * @brief SoC specific Timing Measurement APIs * @defgroup timing_api_soc SoC specific Timing Measurement APIs * @ingroup timing_api * * Implements the necessary bits to support timing measurement * using SoC specific timing measurement mechanism. * * @{ */ /** * @brief Initialize the timing subsystem on SoC. * * Perform the necessary steps to initialize the timing subsystem. * * @see timing_init() */ void soc_timing_init(void); /** * @brief Signal the start of the timing information gathering. * * Signal to the timing subsystem that timing information * will be gathered from this point forward. * * @see timing_start() */ void soc_timing_start(void); /** * @brief Signal the end of the timing information gathering. * * Signal to the timing subsystem that timing information * is no longer being gathered from this point forward. * * @see timing_stop() */ void soc_timing_stop(void); /** * @brief Return timing counter. * * @note Not all SoCs have timing counters with 64 bit precision. It * is possible to see this value "go backwards" due to internal * rollover. Timing code must be prepared to address the rollover * (with SoC dependent code, e.g. by casting to a uint32_t before * subtraction) or by using soc_timing_cycles_get() which is required * to understand the distinction. * * @return Timing counter. * * @see timing_counter_get() */ timing_t soc_timing_counter_get(void); /** * @brief Get number of cycles between @p start and @p end. * * @note The raw numbers from counter need to be scaled to * obtain actual number of cycles, or may roll over internally. * This function computes a positive-definite interval between two * returned cycle values. * * @param start Pointer to counter at start of a measured execution. * @param end Pointer to counter at stop of a measured execution. * @return Number of cycles between start and end. * * @see timing_cycles_get() */ uint64_t soc_timing_cycles_get(volatile timing_t *const start, volatile timing_t *const end); /** * @brief Get frequency of counter used (in Hz). * * @return Frequency of counter used for timing in Hz. * * @see timing_freq_get() */ uint64_t soc_timing_freq_get(void); /** * @brief Convert number of @p cycles into nanoseconds. * * @param cycles Number of cycles * @return Converted time value * * @see timing_cycles_to_ns() */ uint64_t soc_timing_cycles_to_ns(uint64_t cycles); /** * @brief Convert number of @p cycles into nanoseconds with averaging. * * @param cycles Number of cycles * @param count Times of accumulated cycles to average over * @return Converted time value * * @see timing_cycles_to_ns_avg() */ uint64_t soc_timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count); /** * @brief Get frequency of counter used (in MHz). * * @return Frequency of counter used for timing in MHz. * * @see timing_freq_get_mhz() */ uint32_t soc_timing_freq_get_mhz(void); /** * @} */ /** * @brief Board specific Timing Measurement APIs * @defgroup timing_api_board Board specific Timing Measurement APIs * @ingroup timing_api * * Implements the necessary bits to support timing measurement * using board specific timing measurement mechanism. * * @{ */ /** * @brief Initialize the timing subsystem. * * Perform the necessary steps to initialize the timing subsystem. * * @see timing_init() */ void board_timing_init(void); /** * @brief Signal the start of the timing information gathering. * * Signal to the timing subsystem that timing information * will be gathered from this point forward. * * @see timing_start() */ void board_timing_start(void); /** * @brief Signal the end of the timing information gathering. * * Signal to the timing subsystem that timing information * is no longer being gathered from this point forward. * * @see timing_stop() */ void board_timing_stop(void); /** * @brief Return timing counter. * * @note Not all timing counters have 64 bit precision. It is * possible to see this value "go backwards" due to internal * rollover. Timing code must be prepared to address the rollover * (with board dependent code, e.g. by casting to a uint32_t before * subtraction) or by using board_timing_cycles_get() which is required * to understand the distinction. * * @return Timing counter. * * @see timing_counter_get() */ timing_t board_timing_counter_get(void); /** * @brief Get number of cycles between @p start and @p end. * * @note The raw numbers from counter need to be scaled to * obtain actual number of cycles, or may roll over internally. * This function computes a positive-definite interval between two * returned cycle values. * * @param start Pointer to counter at start of a measured execution. * @param end Pointer to counter at stop of a measured execution. * @return Number of cycles between start and end. * * @see timing_cycles_get() */ uint64_t board_timing_cycles_get(volatile timing_t *const start, volatile timing_t *const end); /** * @brief Get frequency of counter used (in Hz). * * @return Frequency of counter used for timing in Hz. * * @see timing_freq_get() */ uint64_t board_timing_freq_get(void); /** * @brief Convert number of @p cycles into nanoseconds. * * @param cycles Number of cycles * @return Converted time value * * @see timing_cycles_to_ns() */ uint64_t board_timing_cycles_to_ns(uint64_t cycles); /** * @brief Convert number of @p cycles into nanoseconds with averaging. * * @param cycles Number of cycles * @param count Times of accumulated cycles to average over * @return Converted time value * * @see timing_cycles_to_ns_avg() */ uint64_t board_timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count); /** * @brief Get frequency of counter used (in MHz). * * @return Frequency of counter used for timing in MHz. * * @see timing_freq_get_mhz() */ uint32_t board_timing_freq_get_mhz(void); /** * @} */ /** * @addtogroup timing_api * @{ */ #ifdef CONFIG_TIMING_FUNCTIONS /** * @brief Initialize the timing subsystem. * * Perform the necessary steps to initialize the timing subsystem. */ void timing_init(void); /** * @brief Signal the start of the timing information gathering. * * Signal to the timing subsystem that timing information * will be gathered from this point forward. */ void timing_start(void); /** * @brief Signal the end of the timing information gathering. * * Signal to the timing subsystem that timing information * is no longer being gathered from this point forward. */ void timing_stop(void); /** * @brief Return timing counter. * * @return Timing counter. */ static inline timing_t timing_counter_get(void) { #if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS) return board_timing_counter_get(); #elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS) return soc_timing_counter_get(); #else return arch_timing_counter_get(); #endif } /** * @brief Get number of cycles between @p start and @p end. * * For some architectures or SoCs, the raw numbers from counter * need to be scaled to obtain actual number of cycles. * * @param start Pointer to counter at start of a measured execution. * @param end Pointer to counter at stop of a measured execution. * @return Number of cycles between start and end. */ static inline uint64_t timing_cycles_get(volatile timing_t *const start, volatile timing_t *const end) { #if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS) return board_timing_cycles_get(start, end); #elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS) return soc_timing_cycles_get(start, end); #else return arch_timing_cycles_get(start, end); #endif } /** * @brief Get frequency of counter used (in Hz). * * @return Frequency of counter used for timing in Hz. */ static inline uint64_t timing_freq_get(void) { #if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS) return board_timing_freq_get(); #elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS) return soc_timing_freq_get(); #else return arch_timing_freq_get(); #endif } /** * @brief Convert number of @p cycles into nanoseconds. * * @param cycles Number of cycles * @return Converted time value */ static inline uint64_t timing_cycles_to_ns(uint64_t cycles) { #if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS) return board_timing_cycles_to_ns(cycles); #elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS) return soc_timing_cycles_to_ns(cycles); #else return arch_timing_cycles_to_ns(cycles); #endif } /** * @brief Convert number of @p cycles into nanoseconds with averaging. * * @param cycles Number of cycles * @param count Times of accumulated cycles to average over * @return Converted time value */ static inline uint64_t timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count) { #if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS) return board_timing_cycles_to_ns_avg(cycles, count); #elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS) return soc_timing_cycles_to_ns_avg(cycles, count); #else return arch_timing_cycles_to_ns_avg(cycles, count); #endif } /** * @brief Get frequency of counter used (in MHz). * * @return Frequency of counter used for timing in MHz. */ static inline uint32_t timing_freq_get_mhz(void) { #if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS) return board_timing_freq_get_mhz(); #elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS) return soc_timing_freq_get_mhz(); #else return arch_timing_freq_get_mhz(); #endif } #endif /* CONFIG_TIMING_FUNCTIONS */ /** * @} */ #ifdef __cplusplus } #endif #endif /* ZEPHYR_INCLUDE_TIMING_TIMING_H_ */