1 /*
2 * Copyright (c) 2020 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #ifndef ZEPHYR_INCLUDE_TIMING_TIMING_H_
8 #define ZEPHYR_INCLUDE_TIMING_TIMING_H_
9
10 #include <zephyr/arch/arch_interface.h>
11 #include <zephyr/timing/types.h>
12
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16
17 /**
18 * @brief Timing Measurement APIs
19 * @defgroup timing_api Timing Measurement APIs
20 * @ingroup os_services
21 *
22 * The timing measurement APIs can be used to obtain execution
23 * time of a section of code to aid in analysis and optimization.
24 *
25 * Please note that the timing functions may use a different timer
26 * than the default kernel timer, where the timer being used is
27 * specified by architecture, SoC or board configuration.
28 */
29
30 /**
31 * @brief SoC specific Timing Measurement APIs
32 * @defgroup timing_api_soc SoC specific Timing Measurement APIs
33 * @ingroup timing_api
34 *
35 * Implements the necessary bits to support timing measurement
36 * using SoC specific timing measurement mechanism.
37 *
38 * @{
39 */
40
41 /**
42 * @brief Initialize the timing subsystem on SoC.
43 *
44 * Perform the necessary steps to initialize the timing subsystem.
45 *
46 * @see timing_init()
47 */
48 void soc_timing_init(void);
49
50 /**
51 * @brief Signal the start of the timing information gathering.
52 *
53 * Signal to the timing subsystem that timing information
54 * will be gathered from this point forward.
55 *
56 * @see timing_start()
57 */
58 void soc_timing_start(void);
59
60 /**
61 * @brief Signal the end of the timing information gathering.
62 *
63 * Signal to the timing subsystem that timing information
64 * is no longer being gathered from this point forward.
65 *
66 * @see timing_stop()
67 */
68 void soc_timing_stop(void);
69
70 /**
71 * @brief Return timing counter.
72 *
73 * @note Not all SoCs have timing counters with 64 bit precision. It
74 * is possible to see this value "go backwards" due to internal
75 * rollover. Timing code must be prepared to address the rollover
76 * (with SoC dependent code, e.g. by casting to a uint32_t before
77 * subtraction) or by using soc_timing_cycles_get() which is required
78 * to understand the distinction.
79 *
80 * @return Timing counter.
81 *
82 * @see timing_counter_get()
83 */
84 timing_t soc_timing_counter_get(void);
85
86 /**
87 * @brief Get number of cycles between @p start and @p end.
88 *
89 * @note The raw numbers from counter need to be scaled to
90 * obtain actual number of cycles, or may roll over internally.
91 * This function computes a positive-definite interval between two
92 * returned cycle values.
93 *
94 * @param start Pointer to counter at start of a measured execution.
95 * @param end Pointer to counter at stop of a measured execution.
96 * @return Number of cycles between start and end.
97 *
98 * @see timing_cycles_get()
99 */
100 uint64_t soc_timing_cycles_get(volatile timing_t *const start,
101 volatile timing_t *const end);
102
103 /**
104 * @brief Get frequency of counter used (in Hz).
105 *
106 * @return Frequency of counter used for timing in Hz.
107 *
108 * @see timing_freq_get()
109 */
110 uint64_t soc_timing_freq_get(void);
111
112 /**
113 * @brief Convert number of @p cycles into nanoseconds.
114 *
115 * @param cycles Number of cycles
116 * @return Converted time value
117 *
118 * @see timing_cycles_to_ns()
119 */
120 uint64_t soc_timing_cycles_to_ns(uint64_t cycles);
121
122 /**
123 * @brief Convert number of @p cycles into nanoseconds with averaging.
124 *
125 * @param cycles Number of cycles
126 * @param count Times of accumulated cycles to average over
127 * @return Converted time value
128 *
129 * @see timing_cycles_to_ns_avg()
130 */
131 uint64_t soc_timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count);
132
133 /**
134 * @brief Get frequency of counter used (in MHz).
135 *
136 * @return Frequency of counter used for timing in MHz.
137 *
138 * @see timing_freq_get_mhz()
139 */
140 uint32_t soc_timing_freq_get_mhz(void);
141
142 /**
143 * @}
144 */
145
146 /**
147 * @brief Board specific Timing Measurement APIs
148 * @defgroup timing_api_board Board specific Timing Measurement APIs
149 * @ingroup timing_api
150 *
151 * Implements the necessary bits to support timing measurement
152 * using board specific timing measurement mechanism.
153 *
154 * @{
155 */
156
157 /**
158 * @brief Initialize the timing subsystem.
159 *
160 * Perform the necessary steps to initialize the timing subsystem.
161 *
162 * @see timing_init()
163 */
164 void board_timing_init(void);
165
166 /**
167 * @brief Signal the start of the timing information gathering.
168 *
169 * Signal to the timing subsystem that timing information
170 * will be gathered from this point forward.
171 *
172 * @see timing_start()
173 */
174 void board_timing_start(void);
175
176 /**
177 * @brief Signal the end of the timing information gathering.
178 *
179 * Signal to the timing subsystem that timing information
180 * is no longer being gathered from this point forward.
181 *
182 * @see timing_stop()
183 */
184 void board_timing_stop(void);
185
186 /**
187 * @brief Return timing counter.
188 *
189 * @note Not all timing counters have 64 bit precision. It is
190 * possible to see this value "go backwards" due to internal
191 * rollover. Timing code must be prepared to address the rollover
192 * (with board dependent code, e.g. by casting to a uint32_t before
193 * subtraction) or by using board_timing_cycles_get() which is required
194 * to understand the distinction.
195 *
196 * @return Timing counter.
197 *
198 * @see timing_counter_get()
199 */
200 timing_t board_timing_counter_get(void);
201
202 /**
203 * @brief Get number of cycles between @p start and @p end.
204 *
205 * @note The raw numbers from counter need to be scaled to
206 * obtain actual number of cycles, or may roll over internally.
207 * This function computes a positive-definite interval between two
208 * returned cycle values.
209 *
210 * @param start Pointer to counter at start of a measured execution.
211 * @param end Pointer to counter at stop of a measured execution.
212 * @return Number of cycles between start and end.
213 *
214 * @see timing_cycles_get()
215 */
216 uint64_t board_timing_cycles_get(volatile timing_t *const start,
217 volatile timing_t *const end);
218
219 /**
220 * @brief Get frequency of counter used (in Hz).
221 *
222 * @return Frequency of counter used for timing in Hz.
223 *
224 * @see timing_freq_get()
225 */
226 uint64_t board_timing_freq_get(void);
227
228 /**
229 * @brief Convert number of @p cycles into nanoseconds.
230 *
231 * @param cycles Number of cycles
232 * @return Converted time value
233 *
234 * @see timing_cycles_to_ns()
235 */
236 uint64_t board_timing_cycles_to_ns(uint64_t cycles);
237
238 /**
239 * @brief Convert number of @p cycles into nanoseconds with averaging.
240 *
241 * @param cycles Number of cycles
242 * @param count Times of accumulated cycles to average over
243 * @return Converted time value
244 *
245 * @see timing_cycles_to_ns_avg()
246 */
247 uint64_t board_timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count);
248
249 /**
250 * @brief Get frequency of counter used (in MHz).
251 *
252 * @return Frequency of counter used for timing in MHz.
253 *
254 * @see timing_freq_get_mhz()
255 */
256 uint32_t board_timing_freq_get_mhz(void);
257
258 /**
259 * @}
260 */
261
262 /**
263 * @addtogroup timing_api
264 * @{
265 */
266
267 #ifdef CONFIG_TIMING_FUNCTIONS
268
269 /**
270 * @brief Initialize the timing subsystem.
271 *
272 * Perform the necessary steps to initialize the timing subsystem.
273 */
274 void timing_init(void);
275
276 /**
277 * @brief Signal the start of the timing information gathering.
278 *
279 * Signal to the timing subsystem that timing information
280 * will be gathered from this point forward.
281 */
282 void timing_start(void);
283
284 /**
285 * @brief Signal the end of the timing information gathering.
286 *
287 * Signal to the timing subsystem that timing information
288 * is no longer being gathered from this point forward.
289 */
290 void timing_stop(void);
291
292 /**
293 * @brief Return timing counter.
294 *
295 * @return Timing counter.
296 */
timing_counter_get(void)297 static inline timing_t timing_counter_get(void)
298 {
299 #if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
300 return board_timing_counter_get();
301 #elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
302 return soc_timing_counter_get();
303 #else
304 return arch_timing_counter_get();
305 #endif
306 }
307
308 /**
309 * @brief Get number of cycles between @p start and @p end.
310 *
311 * For some architectures or SoCs, the raw numbers from counter
312 * need to be scaled to obtain actual number of cycles.
313 *
314 * @param start Pointer to counter at start of a measured execution.
315 * @param end Pointer to counter at stop of a measured execution.
316 * @return Number of cycles between start and end.
317 */
timing_cycles_get(volatile timing_t * const start,volatile timing_t * const end)318 static inline uint64_t timing_cycles_get(volatile timing_t *const start,
319 volatile timing_t *const end)
320 {
321 #if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
322 return board_timing_cycles_get(start, end);
323 #elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
324 return soc_timing_cycles_get(start, end);
325 #else
326 return arch_timing_cycles_get(start, end);
327 #endif
328 }
329
330 /**
331 * @brief Get frequency of counter used (in Hz).
332 *
333 * @return Frequency of counter used for timing in Hz.
334 */
timing_freq_get(void)335 static inline uint64_t timing_freq_get(void)
336 {
337 #if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
338 return board_timing_freq_get();
339 #elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
340 return soc_timing_freq_get();
341 #else
342 return arch_timing_freq_get();
343 #endif
344 }
345
346 /**
347 * @brief Convert number of @p cycles into nanoseconds.
348 *
349 * @param cycles Number of cycles
350 * @return Converted time value
351 */
timing_cycles_to_ns(uint64_t cycles)352 static inline uint64_t timing_cycles_to_ns(uint64_t cycles)
353 {
354 #if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
355 return board_timing_cycles_to_ns(cycles);
356 #elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
357 return soc_timing_cycles_to_ns(cycles);
358 #else
359 return arch_timing_cycles_to_ns(cycles);
360 #endif
361 }
362
363 /**
364 * @brief Convert number of @p cycles into nanoseconds with averaging.
365 *
366 * @param cycles Number of cycles
367 * @param count Times of accumulated cycles to average over
368 * @return Converted time value
369 */
timing_cycles_to_ns_avg(uint64_t cycles,uint32_t count)370 static inline uint64_t timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count)
371 {
372 #if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
373 return board_timing_cycles_to_ns_avg(cycles, count);
374 #elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
375 return soc_timing_cycles_to_ns_avg(cycles, count);
376 #else
377 return arch_timing_cycles_to_ns_avg(cycles, count);
378 #endif
379 }
380
381 /**
382 * @brief Get frequency of counter used (in MHz).
383 *
384 * @return Frequency of counter used for timing in MHz.
385 */
timing_freq_get_mhz(void)386 static inline uint32_t timing_freq_get_mhz(void)
387 {
388 #if defined(CONFIG_BOARD_HAS_TIMING_FUNCTIONS)
389 return board_timing_freq_get_mhz();
390 #elif defined(CONFIG_SOC_HAS_TIMING_FUNCTIONS)
391 return soc_timing_freq_get_mhz();
392 #else
393 return arch_timing_freq_get_mhz();
394 #endif
395 }
396
397 #endif /* CONFIG_TIMING_FUNCTIONS */
398
399 /**
400 * @}
401 */
402
403 #ifdef __cplusplus
404 }
405 #endif
406
407 #endif /* ZEPHYR_INCLUDE_TIMING_TIMING_H_ */
408