blob: 00028bd3729c66805d2333155c1be6c1407a6511 [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
28/**
29 * @brief Initialises the PMU and enables the cycle counter.
30 **/
31static void _init_ethosu_cyclecounter(void);
32
33/**
34 * @brief Gets the difference of total NPU cycle counts.
35 * (includes active and idle)
36 * @param[in] st Pointer to time_counter value at start time.
37 * @param[in] end Pointer to time_counter value at end.
38 * @return Total NPU cycle counts difference between the arguments expressed
39 * as unsigned 64 bit integer.
40 **/
41static uint64_t bm_get_npu_total_cycle_diff(time_counter *st,
42 time_counter *end);
43
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +010044/**
alexander3c798932021-03-26 21:42:19 +000045 * @brief Gets the difference in active NPU cycle counts.
46 * @param[in] st Pointer to time_counter value at start time.
47 * @param[in] end Pointer to time_counter value at end.
48 * @return Active NPU cycle counts difference between the arguments expressed
49 * as unsigned 64 bit integer.
50 **/
51static uint64_t bm_get_npu_active_cycle_diff(time_counter *st,
52 time_counter *end);
53
Isabella Gottardi8df12f32021-04-07 17:15:31 +010054/** @brief Gets the difference in idle NPU cycle counts
55 * @param[in] st Pointer to time_counter value at start time.
56 * @param[in] end Pointer to time_counter value at end.
57 * @return Idle NPU cycle counts difference between the arguments expressed
58 * as unsigned 64 bit integer.
59 **/
60static uint64_t bm_get_npu_idle_cycle_diff(time_counter *st,
61 time_counter *end);
62
63/** @brief Gets the difference in axi0 bus reads cycle counts
64 * @param[in] st Pointer to time_counter value at start time.
65 * @param[in] end Pointer to time_counter value at end.
66 * @return NPU AXI0 read cycle counts difference between the arguments expressed
67 * as unsigned 64 bit integer.
68 **/
69static uint64_t bm_get_npu_axi0_read_cycle_diff(time_counter *st,
70 time_counter *end);
71
72/** @brief Gets the difference in axi0 bus writes cycle counts
73 * @param[in] st Pointer to time_counter value at start time.
74 * @param[in] end Pointer to time_counter value at end.
75 * @return NPU AXI0 write cycle counts difference between the arguments expressed
76 * as unsigned 64 bit integer.
77 **/
78static uint64_t bm_get_npu_axi0_write_cycle_diff(time_counter *st,
79 time_counter *end);
80
81/** @brief Gets the difference in axi1 bus reads cycle counts
82 * @param[in] st Pointer to time_counter value at start time.
83 * @param[in] end Pointer to time_counter value at end.
84 * @return NPU AXI1 read cycle counts difference between the arguments expressed
85 * as unsigned 64 bit integer.
86 **/
87static uint64_t bm_get_npu_axi1_read_cycle_diff(time_counter *st,
88 time_counter *end);
89
90/** @brief Gets the difference for 6 collected cycle counts:
91 * 1) total NPU
92 * 2) active NPU
93 * 3) idle NPU
94 * 4) axi0 read
95 * 5) axi0 write
96 * 6) axi1 read
97 * */
98static int bm_get_npu_cycle_diff(time_counter *st, time_counter *end,
99 uint64_t* pmu_counters_values, const size_t size);
100
alexander3c798932021-03-26 21:42:19 +0000101#endif /* defined (ARM_NPU) */
102
103#if defined(MPS3_PLATFORM)
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100104/**
alexander3c798932021-03-26 21:42:19 +0000105 * @brief Wrapper for getting milliseconds duration between time counters
106 * @param[in] st Pointer to time_counter value at start time.
107 * @param[in] end Pointer to time_counter value at end.
108 * @return Difference in milliseconds between given time counters.
109 **/
110static time_t bm_get_duration_ms(time_counter *st, time_counter *end);
111
112/**
113 * @brief Wrapper for getting microseconds duration between time counters
114 * @param[in] st Pointer to time_counter value at start time.
115 * @param[in] end Pointer to time_counter value at end.
116 * @return Difference in microseconds between given time counters.
117 **/
118static time_t bm_get_duration_us(time_counter *st, time_counter *end);
119#endif /* defined(MPS3_PLATFORM) */
120
121/**
122 * @brief Wrapper for resetting timer.
123 **/
124static void bm_timer_reset(void);
125
126/**
127 * @brief Wrapper for getting the current timer counter.
128 * @return Current time counter value.
129 **/
130static time_counter bm_get_time_counter(void);
131
132/**
133 * @brief Wrapper for profiler start.
134 * @return Current profiler start timer counter.
135 **/
136static time_counter bm_start_profiling(void);
137
138/**
139 * @brief Wrapper for profiler end.
140 * @return Current profiler end timer counter.
141 **/
142static time_counter bm_stop_profiling(void);
143
144/**
145 * @brief Wrapper for getting CPU cycle difference between time counters.
146 * @return CPU cycle difference between given time counters expressed
147 * as unsigned 32 bit integer.
148 **/
Kshitij Sisodiaa3d87702021-05-14 17:34:09 +0100149static uint64_t bm_get_cpu_cycles_diff(time_counter *st, time_counter *end);
alexander3c798932021-03-26 21:42:19 +0000150
151/**
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100152 * @brief Initialiser for bare metal timer.
alexander3c798932021-03-26 21:42:19 +0000153 * @param[in] timer Platform timer to initialize.
154 **/
155void init_timer(platform_timer *timer)
156{
157 assert(timer);
158 memset(timer, 0, sizeof(*timer));
159
160 timer->reset = bm_timer_reset;
161 timer->get_time_counter = bm_get_time_counter;
162 timer->start_profiling = bm_start_profiling;
163 timer->stop_profiling = bm_stop_profiling;
164 timer->get_cpu_cycle_diff = bm_get_cpu_cycles_diff;
165 timer->cap.cpu_cycles = 1;
166
167#if defined (MPS3_PLATFORM)
168 timer->cap.duration_ms = 1;
169 timer->cap.duration_us = 1;
170 timer->get_duration_ms = bm_get_duration_ms;
171 timer->get_duration_us = bm_get_duration_us;
172#endif /* defined (MPS3_PLATFORM) */
173
174#if defined (ARM_NPU)
175 /* We are capable of reporting npu cycle counts. */
176 timer->cap.npu_cycles = 1;
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100177 timer->get_npu_cycles_diff = bm_get_npu_cycle_diff;
alexander3c798932021-03-26 21:42:19 +0000178 _init_ethosu_cyclecounter();
179#endif /* defined (ARM_NPU) */
180
181 timer->reset();
182 timer->inited = 1;
183}
184
185#if defined (ARM_NPU)
186
187static void _reset_ethosu_counters(void)
188{
189 /* Reset all cycle and event counters. */
190 ETHOSU_PMU_CYCCNT_Reset();
191 ETHOSU_PMU_EVCNTR_ALL_Reset();
192}
193
194static void _init_ethosu_cyclecounter(void)
195{
196 /* Reset overflow status. */
197 ETHOSU_PMU_Set_CNTR_OVS(ETHOSU_PMU_CNT1_Msk | ETHOSU_PMU_CCNT_Msk);
198
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100199 /* We can retrieve only 4 PMU counters: */
alexander3c798932021-03-26 21:42:19 +0000200 ETHOSU_PMU_Set_EVTYPER(0, ETHOSU_PMU_NPU_IDLE);
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100201 ETHOSU_PMU_Set_EVTYPER(1, ETHOSU_PMU_AXI0_RD_DATA_BEAT_RECEIVED);
202 ETHOSU_PMU_Set_EVTYPER(2, ETHOSU_PMU_AXI0_WR_DATA_BEAT_WRITTEN);
203 ETHOSU_PMU_Set_EVTYPER(3, ETHOSU_PMU_AXI1_RD_DATA_BEAT_RECEIVED);
alexander3c798932021-03-26 21:42:19 +0000204
205 /* Enable PMU. */
206 ETHOSU_PMU_Enable();
207
208 /* Enable counters for cycle and counter# 0. */
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100209 ETHOSU_PMU_CNTR_Enable(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 +0000210 _reset_ethosu_counters();
211}
212
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100213static int bm_get_npu_cycle_diff(time_counter *st, time_counter *end,
214 uint64_t* pmu_counters_values, const size_t size)
215{
216 if (size == 6) {
217 pmu_counters_values[0] = bm_get_npu_total_cycle_diff(st, end);
218 pmu_counters_values[1] = bm_get_npu_active_cycle_diff(st, end);
219 pmu_counters_values[2] = bm_get_npu_idle_cycle_diff(st, end);
220 pmu_counters_values[3] = bm_get_npu_axi0_read_cycle_diff(st, end);
221 pmu_counters_values[4] = bm_get_npu_axi0_write_cycle_diff(st, end);
222 pmu_counters_values[5] = bm_get_npu_axi1_read_cycle_diff(st, end);
223 return 0;
224 } else {
225 return 1;
226 }
227}
228
alexander3c798932021-03-26 21:42:19 +0000229static uint64_t bm_get_npu_total_cycle_diff(time_counter *st, time_counter *end)
230{
231 return end->npu_total_ccnt - st->npu_total_ccnt;
232}
233
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100234static uint32_t counter_overflow(uint32_t pmu_counter_mask)
alexander3c798932021-03-26 21:42:19 +0000235{
236 /* Check for overflow: The idle counter is 32 bit while the
237 total cycle count is 64 bit. */
238 const uint32_t overflow_status = ETHOSU_PMU_Get_CNTR_OVS();
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100239 return pmu_counter_mask & overflow_status;
240}
alexander3c798932021-03-26 21:42:19 +0000241
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100242static uint64_t bm_get_npu_idle_cycle_diff(time_counter *st, time_counter *end)
243{
244 if (counter_overflow(ETHOSU_PMU_CNT1_Msk)) {
alexander3c798932021-03-26 21:42:19 +0000245 printf_err("EthosU PMU idle counter overflow.\n");
246 return 0;
247 }
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100248 return (uint64_t)(end->npu_idle_ccnt - st->npu_idle_ccnt);
249}
alexander3c798932021-03-26 21:42:19 +0000250
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100251static uint64_t bm_get_npu_active_cycle_diff(time_counter *st, time_counter *end)
252{
alexander3c798932021-03-26 21:42:19 +0000253 /* Active NPU time = total time - idle time */
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100254 return bm_get_npu_total_cycle_diff(st, end) - bm_get_npu_idle_cycle_diff(st, end);
255}
256
257static uint64_t bm_get_npu_axi0_read_cycle_diff(time_counter *st, time_counter *end)
258{
259 if (counter_overflow(ETHOSU_PMU_CNT2_Msk)) {
260 printf_err("EthosU PMU axi0 read counter overflow.\n");
261 return 0;
262 }
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100263 return (uint64_t)(end->npu_axi0_read_beats - st->npu_axi0_read_beats);
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100264}
265
266static uint64_t bm_get_npu_axi0_write_cycle_diff(time_counter *st, time_counter *end)
267{
268 if (counter_overflow(ETHOSU_PMU_CNT3_Msk)) {
269 printf_err("EthosU PMU axi0 write counter overflow.\n");
270 return 0;
271 }
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100272 return (uint64_t)(end->npu_axi0_write_beats - st->npu_axi0_write_beats);
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100273}
274
275static uint64_t bm_get_npu_axi1_read_cycle_diff(time_counter *st, time_counter *end)
276{
277 if (counter_overflow(ETHOSU_PMU_CNT4_Msk)) {
278 printf_err("EthosU PMU axi1 read counter overflow.\n");
279 return 0;
280 }
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100281 return (uint64_t)(end->npu_axi1_read_beats - st->npu_axi1_read_beats);
alexander3c798932021-03-26 21:42:19 +0000282}
283
284#endif /* defined (ARM_NPU) */
285
286static void bm_timer_reset(void)
287{
288#if defined (ARM_NPU)
289 _init_ethosu_cyclecounter();
290#endif /* defined (ARM_NPU) */
291
292 timer_reset();
293}
294
295static time_counter bm_get_time_counter(void)
296{
297 time_counter t = {
298 .counter = get_time_counter(),
299
300#if defined (ARM_NPU)
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100301 .npu_total_ccnt = ETHOSU_PMU_Get_CCNTR(),
302 .npu_idle_ccnt = ETHOSU_PMU_Get_EVCNTR(0),
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100303 .npu_axi0_read_beats = ETHOSU_PMU_Get_EVCNTR(1),
304 .npu_axi0_write_beats = ETHOSU_PMU_Get_EVCNTR(2),
305 .npu_axi1_read_beats = ETHOSU_PMU_Get_EVCNTR(3)
alexander3c798932021-03-26 21:42:19 +0000306#endif /* defined (ARM_NPU) */
307
308 };
309
310#if defined (ARM_NPU)
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100311 debug("NPU total cc: %" PRIu64
312 "; NPU idle cc: %" PRIu32
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100313 "; NPU axi0 read beats: %" PRIu32
314 "; NPU axi0 write beats: %" PRIu32
315 "; NPU axi1 read beats: %" PRIu32 "\n",
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100316 t.npu_total_ccnt,
317 t.npu_idle_ccnt,
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100318 t.npu_axi0_read_beats,
319 t.npu_axi0_write_beats,
320 t.npu_axi1_read_beats);
alexander3c798932021-03-26 21:42:19 +0000321#endif /* defined (ARM_NPU) */
322
323 return t;
324}
325
326static time_counter bm_start_profiling(void)
327{
328 start_cycle_counter();
329 return bm_get_time_counter();
330}
331
332static time_counter bm_stop_profiling(void)
333{
334 stop_cycle_counter();
335 return bm_get_time_counter();
336}
337
Kshitij Sisodiaa3d87702021-05-14 17:34:09 +0100338static uint64_t bm_get_cpu_cycles_diff(time_counter *st, time_counter *end)
alexander3c798932021-03-26 21:42:19 +0000339{
340 return get_cycle_count_diff(&(st->counter), &(end->counter));
341}
342
343#if defined(MPS3_PLATFORM)
344static time_t bm_get_duration_ms(time_counter *st, time_counter *end)
345{
346 return get_duration_milliseconds(&(st->counter), &(end->counter));
347}
348
349static time_t bm_get_duration_us(time_counter *st, time_counter *end)
350{
351 return get_duration_microseconds(&(st->counter), &(end->counter));
352}
353#endif /* defined(MPS3_PLATFORM) */