Sound Open Firmware
Loading...
Searching...
No Matches
perf_cnt.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-3-Clause
2 *
3 * Copyright(c) 2019 Intel Corporation. All rights reserved.
4 *
5 * Author: Marcin Maka <marcin.maka@linux.intel.com>
6 */
7
13
14#ifndef __SOF_LIB_PERF_CNT_H__
15#define __SOF_LIB_PERF_CNT_H__
16
17#include <rtos/timer.h>
18
20 /* current platform clock */
21 uint32_t plat_ts;
22 /* current cpu clock */
23 uint32_t cpu_ts;
24 /* one period module cycles */
26 /* period module peak cycles within period_cnt */
28 /* one period module cycles from cpu clock */
30 /* period module peak cycles within period_cnt from cpu clock */
32 /* total cycles within period_cnt */
33 uint32_t cpu_delta_sum;
34 /* accumulate period passed and calculate avg cycles */
35 uint32_t period_cnt;
36 /* indicate which period have peak mcps in current module */
38};
39
40#if CONFIG_PERFORMANCE_COUNTERS
41
42#define perf_cnt_trace(ctx, pcd) \
43 tr_info(ctx, "perf plat last %u peak %u cpu last %u, peak %u", \
44 (uint32_t)((pcd)->plat_delta_last), \
45 (uint32_t)((pcd)->plat_delta_peak), \
46 (uint32_t)((pcd)->cpu_delta_last), \
47 (uint32_t)((pcd)->cpu_delta_peak))
48
50#define perf_cnt_clear(pcd) memset((pcd), 0, sizeof(struct perf_cnt_data))
51
52/* NOTE: Zephyr's arch_timing_counter_get() might not be implemented
53 * for a particular platform. In this case let's fallback to use
54 * Zephyr's k_cycle_get_64(). This will result in both "platform" and
55 * "cpu" timestamps to be equal.
56 */
57#ifdef __ZEPHYR__
58 #include <zephyr/timing/timing.h>
59 #ifdef CONFIG_TIMING_FUNCTIONS
60 #define perf_cnt_get_cpu_ts timing_counter_get
61 #else
62 #define perf_cnt_get_cpu_ts sof_cycle_get_64
63 #endif /* CONFIG_TIMING_FUNCTIONS */
64#else
65 #define perf_cnt_get_cpu_ts() timer_get_system(cpu_timer_get())
66#endif /* __ZEPHYR__ */
67
69#define perf_cnt_init(pcd) do { \
70 (pcd)->plat_ts = sof_cycle_get_64(); \
71 (pcd)->cpu_ts = perf_cnt_get_cpu_ts(); \
72 } while (0)
73
74/* Trace macros that can be used as trace_m argument of the perf_cnt_stamp()
75 * to trace PCD values if the last arch timer reading exceeds the previous
76 * peak value.
77 *
78 * arg passed to perf_cnt_stamp() is forwarded to the trace_m() macro
79 * as the second argument.
80 */
81
83#define perf_trace_null(pcd, arg)
84
87#define perf_trace_simple(pcd, arg) perf_cnt_trace(arg, pcd)
88
89/* perf measurement windows size 2^x */
90#define PERF_CNT_CHECK_WINDOW_SIZE 10
91#define task_perf_avg_info(pcd, task_p, class) \
92 tr_info(task_p, "perf_cycle task %p, %pU cpu avg %u peak %u",\
93 class, (class)->uid, \
94 (uint32_t)((pcd)->cpu_delta_sum), \
95 (uint32_t)((pcd)->cpu_delta_peak))
96#define task_perf_cnt_avg(pcd, trace_m, arg, class) do { \
97 (pcd)->cpu_delta_sum += (pcd)->cpu_delta_last; \
98 if (!(++(pcd)->period_cnt & MASK(PERF_CNT_CHECK_WINDOW_SIZE - 1, 0))) { \
99 (pcd)->cpu_delta_sum >>= PERF_CNT_CHECK_WINDOW_SIZE; \
100 if ((pcd)->period_cnt & BIT(PERF_CNT_CHECK_WINDOW_SIZE)) \
101 trace_m(pcd, arg, class); \
102 (pcd)->cpu_delta_sum = 0; \
103 (pcd)->plat_delta_peak = 0; \
104 (pcd)->cpu_delta_peak = 0; \
105 } \
106 } while (0)
107
116#define perf_cnt_average(pcd, trace_m, arg) do { \
117 (pcd)->cpu_delta_sum += (pcd)->cpu_delta_last; \
118 if (!(++(pcd)->period_cnt & MASK(PERF_CNT_CHECK_WINDOW_SIZE - 1, 0))) { \
119 (pcd)->cpu_delta_sum >>= PERF_CNT_CHECK_WINDOW_SIZE; \
120 (pcd)->peak_mcps_period_cnt &= MASK(PERF_CNT_CHECK_WINDOW_SIZE - 1, 0); \
121 if ((pcd)->period_cnt & BIT(PERF_CNT_CHECK_WINDOW_SIZE)) { \
122 trace_m(pcd, arg); \
123 } \
124 (pcd)->cpu_delta_sum = 0; \
125 (pcd)->plat_delta_peak = 0; \
126 (pcd)->cpu_delta_peak = 0; \
127 (pcd)->peak_mcps_period_cnt = 0; \
128 } \
129 } while (0)
130
139#define perf_cnt_stamp(pcd, trace_m, arg) do { \
140 uint32_t plat_ts = \
141 (uint32_t)sof_cycle_get_64(); \
142 uint32_t cpu_ts = \
143 (uint32_t)perf_cnt_get_cpu_ts(); \
144 (pcd)->plat_delta_last = plat_ts - (pcd)->plat_ts; \
145 (pcd)->cpu_delta_last = cpu_ts - (pcd)->cpu_ts; \
146 if ((pcd)->plat_delta_last > (pcd)->plat_delta_peak) { \
147 (pcd)->plat_delta_peak = (pcd)->plat_delta_last; \
148 (pcd)->peak_mcps_period_cnt = (pcd)->period_cnt; \
149 } \
150 if ((pcd)->cpu_delta_last > (pcd)->cpu_delta_peak) { \
151 (pcd)->cpu_delta_peak = (pcd)->cpu_delta_last; \
152 trace_m(pcd, arg); \
153 } \
154 } while (0)
155
171
176#define perf_tic(pcd) \
177 perf_cnt_init(pcd)
178
184#define perf_toc(pcd, comp) do { \
185 perf_cnt_stamp(pcd, perf_trace_null, NULL); \
186 perf_trace_simple(pcd, trace_comp_get_tr_ctx(comp)); \
187 } while (0)
188
189#else
190#define perf_cnt_clear(pcd)
191#define perf_cnt_init(pcd)
192#define perf_cnt_stamp(pcd, trace_m, arg)
193#define perf_cnt_average(pcd, trace_m, arg)
194#endif
195
196#endif /* __SOF_LIB_PERF_CNT_H__ */
Definition perf_cnt.h:19
uint32_t peak_mcps_period_cnt
Definition perf_cnt.h:37
uint32_t cpu_delta_peak
Definition perf_cnt.h:31
uint32_t cpu_ts
Definition perf_cnt.h:23
uint32_t plat_ts
Definition perf_cnt.h:21
uint32_t period_cnt
Definition perf_cnt.h:35
uint32_t plat_delta_peak
Definition perf_cnt.h:27
uint32_t plat_delta_last
Definition perf_cnt.h:25
uint32_t cpu_delta_last
Definition perf_cnt.h:29
uint32_t cpu_delta_sum
Definition perf_cnt.h:33