blob: 0388198b7eb7e5fa088b59b8849b85f50f4c21f9 [file] [log] [blame]
alexander3c798932021-03-26 21:42:19 +00001/*
Isabella Gottardiee4920b2022-02-25 14:29:32 +00002 * Copyright (c) 2022 Arm Limited. All rights reserved.
alexander3c798932021-03-26 21:42:19 +00003 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
alexander3c798932021-03-26 21:42:19 +000017#include "timer.h"
Kshitij Sisodiaa1256e32022-02-23 14:40:45 +000018#include "log_macros.h"
Isabella Gottardiee4920b2022-02-25 14:29:32 +000019#include "platform_drivers.h"
alexander3c798932021-03-26 21:42:19 +000020
21#include <assert.h>
22#include <string.h>
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +010023#include <inttypes.h>
alexander3c798932021-03-26 21:42:19 +000024
25#if defined (ARM_NPU)
26
27#include "pmu_ethosu.h"
28
Isabella Gottardic5d8bda2021-07-21 10:35:08 +010029extern struct ethosu_driver ethosu_drv; /* Default Ethos-U55 device driver */
30
alexander3c798932021-03-26 21:42:19 +000031/**
32 * @brief Initialises the PMU and enables the cycle counter.
33 **/
34static void _init_ethosu_cyclecounter(void);
35
36/**
37 * @brief Gets the difference of total NPU cycle counts.
38 * (includes active and idle)
39 * @param[in] st Pointer to time_counter value at start time.
40 * @param[in] end Pointer to time_counter value at end.
41 * @return Total NPU cycle counts difference between the arguments expressed
42 * as unsigned 64 bit integer.
43 **/
44static uint64_t bm_get_npu_total_cycle_diff(time_counter *st,
45 time_counter *end);
46
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +010047/**
alexander3c798932021-03-26 21:42:19 +000048 * @brief Gets the difference in active NPU cycle counts.
49 * @param[in] st Pointer to time_counter value at start time.
50 * @param[in] end Pointer to time_counter value at end.
51 * @return Active NPU cycle counts difference between the arguments expressed
52 * as unsigned 64 bit integer.
53 **/
54static uint64_t bm_get_npu_active_cycle_diff(time_counter *st,
55 time_counter *end);
56
Isabella Gottardi8df12f32021-04-07 17:15:31 +010057/** @brief Gets the difference in idle NPU cycle counts
58 * @param[in] st Pointer to time_counter value at start time.
59 * @param[in] end Pointer to time_counter value at end.
60 * @return Idle NPU cycle counts difference between the arguments expressed
61 * as unsigned 64 bit integer.
62 **/
63static uint64_t bm_get_npu_idle_cycle_diff(time_counter *st,
64 time_counter *end);
65
66/** @brief Gets the difference in axi0 bus reads cycle counts
67 * @param[in] st Pointer to time_counter value at start time.
68 * @param[in] end Pointer to time_counter value at end.
69 * @return NPU AXI0 read cycle counts difference between the arguments expressed
70 * as unsigned 64 bit integer.
71 **/
72static uint64_t bm_get_npu_axi0_read_cycle_diff(time_counter *st,
73 time_counter *end);
74
75/** @brief Gets the difference in axi0 bus writes cycle counts
76 * @param[in] st Pointer to time_counter value at start time.
77 * @param[in] end Pointer to time_counter value at end.
78 * @return NPU AXI0 write cycle counts difference between the arguments expressed
79 * as unsigned 64 bit integer.
80 **/
81static uint64_t bm_get_npu_axi0_write_cycle_diff(time_counter *st,
82 time_counter *end);
83
84/** @brief Gets the difference in axi1 bus reads cycle counts
85 * @param[in] st Pointer to time_counter value at start time.
86 * @param[in] end Pointer to time_counter value at end.
87 * @return NPU AXI1 read cycle counts difference between the arguments expressed
88 * as unsigned 64 bit integer.
89 **/
90static uint64_t bm_get_npu_axi1_read_cycle_diff(time_counter *st,
91 time_counter *end);
92
93/** @brief Gets the difference for 6 collected cycle counts:
94 * 1) total NPU
95 * 2) active NPU
96 * 3) idle NPU
97 * 4) axi0 read
98 * 5) axi0 write
99 * 6) axi1 read
100 * */
101static int bm_get_npu_cycle_diff(time_counter *st, time_counter *end,
102 uint64_t* pmu_counters_values, const size_t size);
103
alexander3c798932021-03-26 21:42:19 +0000104#endif /* defined (ARM_NPU) */
105
106#if defined(MPS3_PLATFORM)
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100107/**
alexander3c798932021-03-26 21:42:19 +0000108 * @brief Wrapper for getting milliseconds duration between time counters
109 * @param[in] st Pointer to time_counter value at start time.
110 * @param[in] end Pointer to time_counter value at end.
111 * @return Difference in milliseconds between given time counters.
112 **/
113static time_t bm_get_duration_ms(time_counter *st, time_counter *end);
114
115/**
116 * @brief Wrapper for getting microseconds duration between time counters
117 * @param[in] st Pointer to time_counter value at start time.
118 * @param[in] end Pointer to time_counter value at end.
119 * @return Difference in microseconds between given time counters.
120 **/
121static time_t bm_get_duration_us(time_counter *st, time_counter *end);
122#endif /* defined(MPS3_PLATFORM) */
123
124/**
125 * @brief Wrapper for resetting timer.
126 **/
127static void bm_timer_reset(void);
128
129/**
130 * @brief Wrapper for getting the current timer counter.
131 * @return Current time counter value.
132 **/
133static time_counter bm_get_time_counter(void);
134
135/**
136 * @brief Wrapper for profiler start.
137 * @return Current profiler start timer counter.
138 **/
139static time_counter bm_start_profiling(void);
140
141/**
142 * @brief Wrapper for profiler end.
143 * @return Current profiler end timer counter.
144 **/
145static time_counter bm_stop_profiling(void);
146
147/**
148 * @brief Wrapper for getting CPU cycle difference between time counters.
149 * @return CPU cycle difference between given time counters expressed
150 * as unsigned 32 bit integer.
151 **/
Kshitij Sisodiaa3d87702021-05-14 17:34:09 +0100152static uint64_t bm_get_cpu_cycles_diff(time_counter *st, time_counter *end);
alexander3c798932021-03-26 21:42:19 +0000153
154/**
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100155 * @brief Initialiser for bare metal timer.
alexander3c798932021-03-26 21:42:19 +0000156 * @param[in] timer Platform timer to initialize.
157 **/
158void init_timer(platform_timer *timer)
159{
160 assert(timer);
161 memset(timer, 0, sizeof(*timer));
162
163 timer->reset = bm_timer_reset;
164 timer->get_time_counter = bm_get_time_counter;
165 timer->start_profiling = bm_start_profiling;
166 timer->stop_profiling = bm_stop_profiling;
167 timer->get_cpu_cycle_diff = bm_get_cpu_cycles_diff;
168 timer->cap.cpu_cycles = 1;
169
170#if defined (MPS3_PLATFORM)
171 timer->cap.duration_ms = 1;
172 timer->cap.duration_us = 1;
173 timer->get_duration_ms = bm_get_duration_ms;
174 timer->get_duration_us = bm_get_duration_us;
175#endif /* defined (MPS3_PLATFORM) */
176
177#if defined (ARM_NPU)
178 /* We are capable of reporting npu cycle counts. */
179 timer->cap.npu_cycles = 1;
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100180 timer->get_npu_cycles_diff = bm_get_npu_cycle_diff;
alexander3c798932021-03-26 21:42:19 +0000181 _init_ethosu_cyclecounter();
182#endif /* defined (ARM_NPU) */
183
184 timer->reset();
185 timer->inited = 1;
186}
187
188#if defined (ARM_NPU)
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100189static void _reset_ethosu_counters()
alexander3c798932021-03-26 21:42:19 +0000190{
191 /* Reset all cycle and event counters. */
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100192 ETHOSU_PMU_CYCCNT_Reset(&ethosu_drv);
193 ETHOSU_PMU_EVCNTR_ALL_Reset(&ethosu_drv);
alexander3c798932021-03-26 21:42:19 +0000194}
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100195static void _init_ethosu_cyclecounter()
alexander3c798932021-03-26 21:42:19 +0000196{
197 /* Reset overflow status. */
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100198 ETHOSU_PMU_Set_CNTR_OVS(&ethosu_drv, ETHOSU_PMU_CNT1_Msk | ETHOSU_PMU_CCNT_Msk);
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100199 /* We can retrieve only 4 PMU counters: */
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100200 ETHOSU_PMU_Set_EVTYPER(&ethosu_drv, 0, ETHOSU_PMU_NPU_IDLE);
201 ETHOSU_PMU_Set_EVTYPER(&ethosu_drv, 1, ETHOSU_PMU_AXI0_RD_DATA_BEAT_RECEIVED);
202 ETHOSU_PMU_Set_EVTYPER(&ethosu_drv, 2, ETHOSU_PMU_AXI0_WR_DATA_BEAT_WRITTEN);
203 ETHOSU_PMU_Set_EVTYPER(&ethosu_drv, 3, ETHOSU_PMU_AXI1_RD_DATA_BEAT_RECEIVED);
alexander3c798932021-03-26 21:42:19 +0000204 /* Enable PMU. */
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100205 ETHOSU_PMU_Enable(&ethosu_drv);
alexander3c798932021-03-26 21:42:19 +0000206 /* Enable counters for cycle and counter# 0. */
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100207 ETHOSU_PMU_CNTR_Enable(&ethosu_drv, ETHOSU_PMU_CNT1_Msk | ETHOSU_PMU_CNT2_Msk | ETHOSU_PMU_CNT3_Msk | ETHOSU_PMU_CNT4_Msk| ETHOSU_PMU_CCNT_Msk);
alexander3c798932021-03-26 21:42:19 +0000208 _reset_ethosu_counters();
209}
210
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100211static int bm_get_npu_cycle_diff(time_counter *st, time_counter *end,
212 uint64_t* pmu_counters_values, const size_t size)
213{
214 if (size == 6) {
215 pmu_counters_values[0] = bm_get_npu_total_cycle_diff(st, end);
216 pmu_counters_values[1] = bm_get_npu_active_cycle_diff(st, end);
217 pmu_counters_values[2] = bm_get_npu_idle_cycle_diff(st, end);
218 pmu_counters_values[3] = bm_get_npu_axi0_read_cycle_diff(st, end);
219 pmu_counters_values[4] = bm_get_npu_axi0_write_cycle_diff(st, end);
220 pmu_counters_values[5] = bm_get_npu_axi1_read_cycle_diff(st, end);
221 return 0;
222 } else {
223 return 1;
224 }
225}
226
alexander3c798932021-03-26 21:42:19 +0000227static uint64_t bm_get_npu_total_cycle_diff(time_counter *st, time_counter *end)
228{
229 return end->npu_total_ccnt - st->npu_total_ccnt;
230}
231
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100232static uint32_t counter_overflow(uint32_t pmu_counter_mask)
alexander3c798932021-03-26 21:42:19 +0000233{
234 /* Check for overflow: The idle counter is 32 bit while the
235 total cycle count is 64 bit. */
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100236 const uint32_t overflow_status = ETHOSU_PMU_Get_CNTR_OVS(&ethosu_drv);
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100237 return pmu_counter_mask & overflow_status;
238}
alexander3c798932021-03-26 21:42:19 +0000239
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100240static uint64_t bm_get_npu_idle_cycle_diff(time_counter *st, time_counter *end)
241{
242 if (counter_overflow(ETHOSU_PMU_CNT1_Msk)) {
alexander3c798932021-03-26 21:42:19 +0000243 printf_err("EthosU PMU idle counter overflow.\n");
244 return 0;
245 }
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100246 return (uint64_t)(end->npu_idle_ccnt - st->npu_idle_ccnt);
247}
alexander3c798932021-03-26 21:42:19 +0000248
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100249static uint64_t bm_get_npu_active_cycle_diff(time_counter *st, time_counter *end)
250{
alexander3c798932021-03-26 21:42:19 +0000251 /* Active NPU time = total time - idle time */
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100252 return bm_get_npu_total_cycle_diff(st, end) - bm_get_npu_idle_cycle_diff(st, end);
253}
254
255static uint64_t bm_get_npu_axi0_read_cycle_diff(time_counter *st, time_counter *end)
256{
257 if (counter_overflow(ETHOSU_PMU_CNT2_Msk)) {
258 printf_err("EthosU PMU axi0 read counter overflow.\n");
259 return 0;
260 }
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100261 return (uint64_t)(end->npu_axi0_read_beats - st->npu_axi0_read_beats);
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100262}
263
264static uint64_t bm_get_npu_axi0_write_cycle_diff(time_counter *st, time_counter *end)
265{
266 if (counter_overflow(ETHOSU_PMU_CNT3_Msk)) {
267 printf_err("EthosU PMU axi0 write counter overflow.\n");
268 return 0;
269 }
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100270 return (uint64_t)(end->npu_axi0_write_beats - st->npu_axi0_write_beats);
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100271}
272
273static uint64_t bm_get_npu_axi1_read_cycle_diff(time_counter *st, time_counter *end)
274{
275 if (counter_overflow(ETHOSU_PMU_CNT4_Msk)) {
276 printf_err("EthosU PMU axi1 read counter overflow.\n");
277 return 0;
278 }
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100279 return (uint64_t)(end->npu_axi1_read_beats - st->npu_axi1_read_beats);
alexander3c798932021-03-26 21:42:19 +0000280}
281
282#endif /* defined (ARM_NPU) */
283
284static void bm_timer_reset(void)
285{
286#if defined (ARM_NPU)
287 _init_ethosu_cyclecounter();
288#endif /* defined (ARM_NPU) */
289
290 timer_reset();
291}
292
293static time_counter bm_get_time_counter(void)
294{
295 time_counter t = {
296 .counter = get_time_counter(),
297
298#if defined (ARM_NPU)
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100299 .npu_total_ccnt = ETHOSU_PMU_Get_CCNTR(&ethosu_drv),
300 .npu_idle_ccnt = ETHOSU_PMU_Get_EVCNTR(&ethosu_drv, 0),
301 .npu_axi0_read_beats = ETHOSU_PMU_Get_EVCNTR(&ethosu_drv, 1),
302 .npu_axi0_write_beats = ETHOSU_PMU_Get_EVCNTR(&ethosu_drv, 2),
303 .npu_axi1_read_beats = ETHOSU_PMU_Get_EVCNTR(&ethosu_drv, 3)
alexander3c798932021-03-26 21:42:19 +0000304#endif /* defined (ARM_NPU) */
305
306 };
307
308#if defined (ARM_NPU)
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100309 debug("NPU total cc: %" PRIu64
310 "; NPU idle cc: %" PRIu32
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100311 "; NPU axi0 read beats: %" PRIu32
312 "; NPU axi0 write beats: %" PRIu32
313 "; NPU axi1 read beats: %" PRIu32 "\n",
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100314 t.npu_total_ccnt,
315 t.npu_idle_ccnt,
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100316 t.npu_axi0_read_beats,
317 t.npu_axi0_write_beats,
318 t.npu_axi1_read_beats);
alexander3c798932021-03-26 21:42:19 +0000319#endif /* defined (ARM_NPU) */
320
321 return t;
322}
323
324static time_counter bm_start_profiling(void)
325{
326 start_cycle_counter();
327 return bm_get_time_counter();
328}
329
330static time_counter bm_stop_profiling(void)
331{
332 stop_cycle_counter();
333 return bm_get_time_counter();
334}
335
Kshitij Sisodiaa3d87702021-05-14 17:34:09 +0100336static uint64_t bm_get_cpu_cycles_diff(time_counter *st, time_counter *end)
alexander3c798932021-03-26 21:42:19 +0000337{
338 return get_cycle_count_diff(&(st->counter), &(end->counter));
339}
340
341#if defined(MPS3_PLATFORM)
342static time_t bm_get_duration_ms(time_counter *st, time_counter *end)
343{
344 return get_duration_milliseconds(&(st->counter), &(end->counter));
345}
346
347static time_t bm_get_duration_us(time_counter *st, time_counter *end)
348{
349 return get_duration_microseconds(&(st->counter), &(end->counter));
350}
351#endif /* defined(MPS3_PLATFORM) */