blob: c8e7252af0709553830a723af5788524de559fc1 [file] [log] [blame]
alexander3c798932021-03-26 21:42:19 +00001/*
2 * Copyright (c) 2021 Arm Limited. All rights reserved.
3 * 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 */
17#include "bsp.h"
18#include "timer.h"
19
20#include <assert.h>
21#include <string.h>
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +010022#include <inttypes.h>
alexander3c798932021-03-26 21:42:19 +000023
24#if defined (ARM_NPU)
25
26#include "pmu_ethosu.h"
27
Isabella Gottardic5d8bda2021-07-21 10:35:08 +010028extern struct ethosu_driver ethosu_drv; /* Default Ethos-U55 device driver */
29
alexander3c798932021-03-26 21:42:19 +000030/**
31 * @brief Initialises the PMU and enables the cycle counter.
32 **/
33static void _init_ethosu_cyclecounter(void);
34
35/**
36 * @brief Gets the difference of total NPU cycle counts.
37 * (includes active and idle)
38 * @param[in] st Pointer to time_counter value at start time.
39 * @param[in] end Pointer to time_counter value at end.
40 * @return Total NPU cycle counts difference between the arguments expressed
41 * as unsigned 64 bit integer.
42 **/
43static uint64_t bm_get_npu_total_cycle_diff(time_counter *st,
44 time_counter *end);
45
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +010046/**
alexander3c798932021-03-26 21:42:19 +000047 * @brief Gets the difference in active NPU cycle counts.
48 * @param[in] st Pointer to time_counter value at start time.
49 * @param[in] end Pointer to time_counter value at end.
50 * @return Active NPU cycle counts difference between the arguments expressed
51 * as unsigned 64 bit integer.
52 **/
53static uint64_t bm_get_npu_active_cycle_diff(time_counter *st,
54 time_counter *end);
55
Isabella Gottardi8df12f32021-04-07 17:15:31 +010056/** @brief Gets the difference in idle NPU cycle counts
57 * @param[in] st Pointer to time_counter value at start time.
58 * @param[in] end Pointer to time_counter value at end.
59 * @return Idle NPU cycle counts difference between the arguments expressed
60 * as unsigned 64 bit integer.
61 **/
62static uint64_t bm_get_npu_idle_cycle_diff(time_counter *st,
63 time_counter *end);
64
65/** @brief Gets the difference in axi0 bus reads cycle counts
66 * @param[in] st Pointer to time_counter value at start time.
67 * @param[in] end Pointer to time_counter value at end.
68 * @return NPU AXI0 read cycle counts difference between the arguments expressed
69 * as unsigned 64 bit integer.
70 **/
71static uint64_t bm_get_npu_axi0_read_cycle_diff(time_counter *st,
72 time_counter *end);
73
74/** @brief Gets the difference in axi0 bus writes cycle counts
75 * @param[in] st Pointer to time_counter value at start time.
76 * @param[in] end Pointer to time_counter value at end.
77 * @return NPU AXI0 write cycle counts difference between the arguments expressed
78 * as unsigned 64 bit integer.
79 **/
80static uint64_t bm_get_npu_axi0_write_cycle_diff(time_counter *st,
81 time_counter *end);
82
83/** @brief Gets the difference in axi1 bus reads cycle counts
84 * @param[in] st Pointer to time_counter value at start time.
85 * @param[in] end Pointer to time_counter value at end.
86 * @return NPU AXI1 read cycle counts difference between the arguments expressed
87 * as unsigned 64 bit integer.
88 **/
89static uint64_t bm_get_npu_axi1_read_cycle_diff(time_counter *st,
90 time_counter *end);
91
92/** @brief Gets the difference for 6 collected cycle counts:
93 * 1) total NPU
94 * 2) active NPU
95 * 3) idle NPU
96 * 4) axi0 read
97 * 5) axi0 write
98 * 6) axi1 read
99 * */
100static int bm_get_npu_cycle_diff(time_counter *st, time_counter *end,
101 uint64_t* pmu_counters_values, const size_t size);
102
alexander3c798932021-03-26 21:42:19 +0000103#endif /* defined (ARM_NPU) */
104
105#if defined(MPS3_PLATFORM)
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100106/**
alexander3c798932021-03-26 21:42:19 +0000107 * @brief Wrapper for getting milliseconds duration between time counters
108 * @param[in] st Pointer to time_counter value at start time.
109 * @param[in] end Pointer to time_counter value at end.
110 * @return Difference in milliseconds between given time counters.
111 **/
112static time_t bm_get_duration_ms(time_counter *st, time_counter *end);
113
114/**
115 * @brief Wrapper for getting microseconds duration between time counters
116 * @param[in] st Pointer to time_counter value at start time.
117 * @param[in] end Pointer to time_counter value at end.
118 * @return Difference in microseconds between given time counters.
119 **/
120static time_t bm_get_duration_us(time_counter *st, time_counter *end);
121#endif /* defined(MPS3_PLATFORM) */
122
123/**
124 * @brief Wrapper for resetting timer.
125 **/
126static void bm_timer_reset(void);
127
128/**
129 * @brief Wrapper for getting the current timer counter.
130 * @return Current time counter value.
131 **/
132static time_counter bm_get_time_counter(void);
133
134/**
135 * @brief Wrapper for profiler start.
136 * @return Current profiler start timer counter.
137 **/
138static time_counter bm_start_profiling(void);
139
140/**
141 * @brief Wrapper for profiler end.
142 * @return Current profiler end timer counter.
143 **/
144static time_counter bm_stop_profiling(void);
145
146/**
147 * @brief Wrapper for getting CPU cycle difference between time counters.
148 * @return CPU cycle difference between given time counters expressed
149 * as unsigned 32 bit integer.
150 **/
Kshitij Sisodiaa3d87702021-05-14 17:34:09 +0100151static uint64_t bm_get_cpu_cycles_diff(time_counter *st, time_counter *end);
alexander3c798932021-03-26 21:42:19 +0000152
153/**
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100154 * @brief Initialiser for bare metal timer.
alexander3c798932021-03-26 21:42:19 +0000155 * @param[in] timer Platform timer to initialize.
156 **/
157void init_timer(platform_timer *timer)
158{
159 assert(timer);
160 memset(timer, 0, sizeof(*timer));
161
162 timer->reset = bm_timer_reset;
163 timer->get_time_counter = bm_get_time_counter;
164 timer->start_profiling = bm_start_profiling;
165 timer->stop_profiling = bm_stop_profiling;
166 timer->get_cpu_cycle_diff = bm_get_cpu_cycles_diff;
167 timer->cap.cpu_cycles = 1;
168
169#if defined (MPS3_PLATFORM)
170 timer->cap.duration_ms = 1;
171 timer->cap.duration_us = 1;
172 timer->get_duration_ms = bm_get_duration_ms;
173 timer->get_duration_us = bm_get_duration_us;
174#endif /* defined (MPS3_PLATFORM) */
175
176#if defined (ARM_NPU)
177 /* We are capable of reporting npu cycle counts. */
178 timer->cap.npu_cycles = 1;
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100179 timer->get_npu_cycles_diff = bm_get_npu_cycle_diff;
alexander3c798932021-03-26 21:42:19 +0000180 _init_ethosu_cyclecounter();
181#endif /* defined (ARM_NPU) */
182
183 timer->reset();
184 timer->inited = 1;
185}
186
187#if defined (ARM_NPU)
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100188static void _reset_ethosu_counters()
alexander3c798932021-03-26 21:42:19 +0000189{
190 /* Reset all cycle and event counters. */
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100191 ETHOSU_PMU_CYCCNT_Reset(&ethosu_drv);
192 ETHOSU_PMU_EVCNTR_ALL_Reset(&ethosu_drv);
alexander3c798932021-03-26 21:42:19 +0000193}
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100194static void _init_ethosu_cyclecounter()
alexander3c798932021-03-26 21:42:19 +0000195{
196 /* Reset overflow status. */
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100197 ETHOSU_PMU_Set_CNTR_OVS(&ethosu_drv, ETHOSU_PMU_CNT1_Msk | ETHOSU_PMU_CCNT_Msk);
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100198 /* We can retrieve only 4 PMU counters: */
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100199 ETHOSU_PMU_Set_EVTYPER(&ethosu_drv, 0, ETHOSU_PMU_NPU_IDLE);
200 ETHOSU_PMU_Set_EVTYPER(&ethosu_drv, 1, ETHOSU_PMU_AXI0_RD_DATA_BEAT_RECEIVED);
201 ETHOSU_PMU_Set_EVTYPER(&ethosu_drv, 2, ETHOSU_PMU_AXI0_WR_DATA_BEAT_WRITTEN);
202 ETHOSU_PMU_Set_EVTYPER(&ethosu_drv, 3, ETHOSU_PMU_AXI1_RD_DATA_BEAT_RECEIVED);
alexander3c798932021-03-26 21:42:19 +0000203 /* Enable PMU. */
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100204 ETHOSU_PMU_Enable(&ethosu_drv);
alexander3c798932021-03-26 21:42:19 +0000205 /* Enable counters for cycle and counter# 0. */
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100206 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 +0000207 _reset_ethosu_counters();
208}
209
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100210static int bm_get_npu_cycle_diff(time_counter *st, time_counter *end,
211 uint64_t* pmu_counters_values, const size_t size)
212{
213 if (size == 6) {
214 pmu_counters_values[0] = bm_get_npu_total_cycle_diff(st, end);
215 pmu_counters_values[1] = bm_get_npu_active_cycle_diff(st, end);
216 pmu_counters_values[2] = bm_get_npu_idle_cycle_diff(st, end);
217 pmu_counters_values[3] = bm_get_npu_axi0_read_cycle_diff(st, end);
218 pmu_counters_values[4] = bm_get_npu_axi0_write_cycle_diff(st, end);
219 pmu_counters_values[5] = bm_get_npu_axi1_read_cycle_diff(st, end);
220 return 0;
221 } else {
222 return 1;
223 }
224}
225
alexander3c798932021-03-26 21:42:19 +0000226static uint64_t bm_get_npu_total_cycle_diff(time_counter *st, time_counter *end)
227{
228 return end->npu_total_ccnt - st->npu_total_ccnt;
229}
230
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100231static uint32_t counter_overflow(uint32_t pmu_counter_mask)
alexander3c798932021-03-26 21:42:19 +0000232{
233 /* Check for overflow: The idle counter is 32 bit while the
234 total cycle count is 64 bit. */
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100235 const uint32_t overflow_status = ETHOSU_PMU_Get_CNTR_OVS(&ethosu_drv);
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100236 return pmu_counter_mask & overflow_status;
237}
alexander3c798932021-03-26 21:42:19 +0000238
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100239static uint64_t bm_get_npu_idle_cycle_diff(time_counter *st, time_counter *end)
240{
241 if (counter_overflow(ETHOSU_PMU_CNT1_Msk)) {
alexander3c798932021-03-26 21:42:19 +0000242 printf_err("EthosU PMU idle counter overflow.\n");
243 return 0;
244 }
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100245 return (uint64_t)(end->npu_idle_ccnt - st->npu_idle_ccnt);
246}
alexander3c798932021-03-26 21:42:19 +0000247
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100248static uint64_t bm_get_npu_active_cycle_diff(time_counter *st, time_counter *end)
249{
alexander3c798932021-03-26 21:42:19 +0000250 /* Active NPU time = total time - idle time */
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100251 return bm_get_npu_total_cycle_diff(st, end) - bm_get_npu_idle_cycle_diff(st, end);
252}
253
254static uint64_t bm_get_npu_axi0_read_cycle_diff(time_counter *st, time_counter *end)
255{
256 if (counter_overflow(ETHOSU_PMU_CNT2_Msk)) {
257 printf_err("EthosU PMU axi0 read counter overflow.\n");
258 return 0;
259 }
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100260 return (uint64_t)(end->npu_axi0_read_beats - st->npu_axi0_read_beats);
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100261}
262
263static uint64_t bm_get_npu_axi0_write_cycle_diff(time_counter *st, time_counter *end)
264{
265 if (counter_overflow(ETHOSU_PMU_CNT3_Msk)) {
266 printf_err("EthosU PMU axi0 write counter overflow.\n");
267 return 0;
268 }
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100269 return (uint64_t)(end->npu_axi0_write_beats - st->npu_axi0_write_beats);
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100270}
271
272static uint64_t bm_get_npu_axi1_read_cycle_diff(time_counter *st, time_counter *end)
273{
274 if (counter_overflow(ETHOSU_PMU_CNT4_Msk)) {
275 printf_err("EthosU PMU axi1 read counter overflow.\n");
276 return 0;
277 }
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100278 return (uint64_t)(end->npu_axi1_read_beats - st->npu_axi1_read_beats);
alexander3c798932021-03-26 21:42:19 +0000279}
280
281#endif /* defined (ARM_NPU) */
282
283static void bm_timer_reset(void)
284{
285#if defined (ARM_NPU)
286 _init_ethosu_cyclecounter();
287#endif /* defined (ARM_NPU) */
288
289 timer_reset();
290}
291
292static time_counter bm_get_time_counter(void)
293{
294 time_counter t = {
295 .counter = get_time_counter(),
296
297#if defined (ARM_NPU)
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100298 .npu_total_ccnt = ETHOSU_PMU_Get_CCNTR(&ethosu_drv),
299 .npu_idle_ccnt = ETHOSU_PMU_Get_EVCNTR(&ethosu_drv, 0),
300 .npu_axi0_read_beats = ETHOSU_PMU_Get_EVCNTR(&ethosu_drv, 1),
301 .npu_axi0_write_beats = ETHOSU_PMU_Get_EVCNTR(&ethosu_drv, 2),
302 .npu_axi1_read_beats = ETHOSU_PMU_Get_EVCNTR(&ethosu_drv, 3)
alexander3c798932021-03-26 21:42:19 +0000303#endif /* defined (ARM_NPU) */
304
305 };
306
307#if defined (ARM_NPU)
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100308 debug("NPU total cc: %" PRIu64
309 "; NPU idle cc: %" PRIu32
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100310 "; NPU axi0 read beats: %" PRIu32
311 "; NPU axi0 write beats: %" PRIu32
312 "; NPU axi1 read beats: %" PRIu32 "\n",
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100313 t.npu_total_ccnt,
314 t.npu_idle_ccnt,
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100315 t.npu_axi0_read_beats,
316 t.npu_axi0_write_beats,
317 t.npu_axi1_read_beats);
alexander3c798932021-03-26 21:42:19 +0000318#endif /* defined (ARM_NPU) */
319
320 return t;
321}
322
323static time_counter bm_start_profiling(void)
324{
325 start_cycle_counter();
326 return bm_get_time_counter();
327}
328
329static time_counter bm_stop_profiling(void)
330{
331 stop_cycle_counter();
332 return bm_get_time_counter();
333}
334
Kshitij Sisodiaa3d87702021-05-14 17:34:09 +0100335static uint64_t bm_get_cpu_cycles_diff(time_counter *st, time_counter *end)
alexander3c798932021-03-26 21:42:19 +0000336{
337 return get_cycle_count_diff(&(st->counter), &(end->counter));
338}
339
340#if defined(MPS3_PLATFORM)
341static time_t bm_get_duration_ms(time_counter *st, time_counter *end)
342{
343 return get_duration_milliseconds(&(st->counter), &(end->counter));
344}
345
346static time_t bm_get_duration_us(time_counter *st, time_counter *end)
347{
348 return get_duration_microseconds(&(st->counter), &(end->counter));
349}
350#endif /* defined(MPS3_PLATFORM) */