blob: dea704c9cf40cf72aea8679fcf25e8d73b10c9bf [file] [log] [blame]
Kshitij Sisodiada2ec062022-04-01 14:43:53 +01001/*
Kshitij Sisodiade54e162022-12-20 16:09:15 +00002 * SPDX-FileCopyrightText: Copyright 2022 Arm Limited and/or its affiliates
3 * <open-source-office@arm.com> SPDX-License-Identifier: Apache-2.0
Kshitij Sisodiada2ec062022-04-01 14:43:53 +01004 *
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
18#include "ethosu_profiler.h"
Kshitij Sisodiade54e162022-12-20 16:09:15 +000019#include "ethosu_cpu_cache.h"
Kshitij Sisodiada2ec062022-04-01 14:43:53 +010020#include "log_macros.h"
21
22#include <string.h>
23
Kshitij Sisodiade54e162022-12-20 16:09:15 +000024extern struct ethosu_driver ethosu_drv; /* Default Arm Ethos-U NPU device driver object */
25static ethosu_pmu_counters s_npu_counters; /* NPU counter local instance */
26static uint32_t s_evt_mask = 0; /* PMU event mask */
27
28static const char* unit_beats = "beats";
Kshitij Sisodia4cc40212022-04-08 09:54:53 +010029static const char* unit_cycles = "cycles";
Kshitij Sisodiada2ec062022-04-01 14:43:53 +010030
31/**
32 * @brief Gets the npu counter instance to be used.
33 * @return Pointer to the npu counter instance.
34 */
35static ethosu_pmu_counters* get_counter_instance(void)
36{
Kshitij Sisodiade54e162022-12-20 16:09:15 +000037 return &s_npu_counters;
38}
39
40/**
41 * @brief Gets the enabled event mask from the PMU driver.
42 * @return Event mask as an unsigned 32 bit integer.
43 */
44static uint32_t get_event_mask(void)
45{
46 return s_evt_mask;
47}
48
49/**
50 * @brief Sets the enabled event mask for the PMU driver.
51 * @param[in] mask event mask as an unsigned 32 bit integer.
52 * @return none.
53 */
54static void set_event_mask(uint32_t mask)
55{
56 s_evt_mask = mask;
Kshitij Sisodiada2ec062022-04-01 14:43:53 +010057}
58
59/**
60 * @brief Checks if the counter has overflown.
61 * @param pmu_counter_mask Mask for the event counter.
62 * @return true if overflow is detected, false otherwise.
63 */
64static bool counter_overflow(uint32_t pmu_counter_mask)
65{
66 /* Check for overflow: The idle counter is 32 bit while the
67 total cycle count is 64 bit. */
68 const uint32_t overflow_status = ETHOSU_PMU_Get_CNTR_OVS(&ethosu_drv);
69 return pmu_counter_mask & overflow_status ? true : false;
70}
71
72void ethosu_pmu_init(void)
73{
Kshitij Sisodiade54e162022-12-20 16:09:15 +000074 uint32_t i = 0;
75 uint32_t evt_mask = ETHOSU_PMU_CCNT_Msk;
Kshitij Sisodiada2ec062022-04-01 14:43:53 +010076 ethosu_pmu_counters* counters = get_counter_instance();
77 memset(counters, 0, sizeof(*counters));
78
79 /* Total counters = event counters + derived counters + total cycle count */
80 counters->num_total_counters = ETHOSU_PROFILER_NUM_COUNTERS;
81
82#if ETHOSU_PMU_NCOUNTERS >= 4
Kshitij Sisodiade54e162022-12-20 16:09:15 +000083 counters->npu_evt_counters[0].event_type = ETHOSU_PMU_NPU_ACTIVE;
Kshitij Sisodiada2ec062022-04-01 14:43:53 +010084 counters->npu_evt_counters[0].event_mask = ETHOSU_PMU_CNT1_Msk;
Kshitij Sisodiade54e162022-12-20 16:09:15 +000085 counters->npu_evt_counters[0].name = "NPU ACTIVE";
86 counters->npu_evt_counters[0].unit = unit_cycles;
Kshitij Sisodiada2ec062022-04-01 14:43:53 +010087
88 counters->npu_evt_counters[1].event_type = ETHOSU_PMU_AXI0_RD_DATA_BEAT_RECEIVED;
89 counters->npu_evt_counters[1].event_mask = ETHOSU_PMU_CNT2_Msk;
Kshitij Sisodiade54e162022-12-20 16:09:15 +000090 counters->npu_evt_counters[1].name = "NPU AXI0_RD_DATA_BEAT_RECEIVED";
91 counters->npu_evt_counters[1].unit = unit_beats;
Kshitij Sisodiada2ec062022-04-01 14:43:53 +010092
93 counters->npu_evt_counters[2].event_type = ETHOSU_PMU_AXI0_WR_DATA_BEAT_WRITTEN;
94 counters->npu_evt_counters[2].event_mask = ETHOSU_PMU_CNT3_Msk;
Kshitij Sisodiade54e162022-12-20 16:09:15 +000095 counters->npu_evt_counters[2].name = "NPU AXI0_WR_DATA_BEAT_WRITTEN";
96 counters->npu_evt_counters[2].unit = unit_beats;
Kshitij Sisodiada2ec062022-04-01 14:43:53 +010097
98 counters->npu_evt_counters[3].event_type = ETHOSU_PMU_AXI1_RD_DATA_BEAT_RECEIVED;
99 counters->npu_evt_counters[3].event_mask = ETHOSU_PMU_CNT4_Msk;
Kshitij Sisodiade54e162022-12-20 16:09:15 +0000100 counters->npu_evt_counters[3].name = "NPU AXI1_RD_DATA_BEAT_RECEIVED";
101 counters->npu_evt_counters[3].unit = unit_beats;
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100102#else /* ETHOSU_PMU_NCOUNTERS >= 4 */
Kshitij Sisodiade54e162022-12-20 16:09:15 +0000103#error "NPU PMU expects a minimum of 4 available event triggered counters!"
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100104#endif /* ETHOSU_PMU_NCOUNTERS >= 4 */
105
106#if ETHOSU_DERIVED_NCOUNTERS >= 1
Kshitij Sisodiade54e162022-12-20 16:09:15 +0000107 counters->npu_derived_counters[0].name = "NPU IDLE";
Kshitij Sisodia4cc40212022-04-08 09:54:53 +0100108 counters->npu_derived_counters[0].unit = unit_cycles;
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100109#endif /* ETHOSU_DERIVED_NCOUNTERS >= 1 */
110
111 for (i = 0; i < ETHOSU_PMU_NCOUNTERS; ++i) {
112 ETHOSU_PMU_Set_EVTYPER(&ethosu_drv, i, counters->npu_evt_counters[i].event_type);
113 evt_mask |= counters->npu_evt_counters[i].event_mask;
114 }
115
Kshitij Sisodiade54e162022-12-20 16:09:15 +0000116 set_event_mask(evt_mask);
117
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100118 /* Reset overflow status. */
Kshitij Sisodiade54e162022-12-20 16:09:15 +0000119 ETHOSU_PMU_Set_CNTR_OVS(&ethosu_drv, get_event_mask());
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100120
121 /* Enable PMU. */
122 ETHOSU_PMU_Enable(&ethosu_drv);
123
124 /* Enable counters for cycle and event counters. */
Kshitij Sisodiade54e162022-12-20 16:09:15 +0000125 ETHOSU_PMU_CNTR_Disable(&ethosu_drv, get_event_mask());
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100126 ethosu_pmu_reset_counters();
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100127}
128
129/**
130 * @brief Resets the Arm Ethos-U NPU PMU counters.
131 */
132void ethosu_pmu_reset_counters(void)
133{
134 /* Reset all cycle and event counters. */
135 ETHOSU_PMU_CYCCNT_Reset(&ethosu_drv);
136 ETHOSU_PMU_EVCNTR_ALL_Reset(&ethosu_drv);
137}
138
139/**
140 * @brief Get the Arm Ethos-U NPU PMU counters
141 * @return ethosu_pmu_counters
142 */
143ethosu_pmu_counters ethosu_get_pmu_counters(void)
144{
145 ethosu_pmu_counters* counters = get_counter_instance();
Kshitij Sisodiade54e162022-12-20 16:09:15 +0000146 uint32_t i = 0;
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100147
148 /* Event counters */
149 for (i = 0; i < ETHOSU_PMU_NCOUNTERS; ++i) {
150 if (counter_overflow(counters->npu_evt_counters[i].event_mask)) {
151 warn("Counter overflow detected for %s.\n", counters->npu_evt_counters[i].name);
152 }
Kshitij Sisodiade54e162022-12-20 16:09:15 +0000153 counters->npu_evt_counters[i].counter_value = ETHOSU_PMU_Get_EVCNTR(&ethosu_drv, i);
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100154 }
155
156 /* Total cycle count */
157 counters->npu_total_ccnt = ETHOSU_PMU_Get_CCNTR(&ethosu_drv);
158
159 /* Derived counters */
160#if ETHOSU_DERIVED_NCOUNTERS >= 1
Kshitij Sisodiade54e162022-12-20 16:09:15 +0000161 if (counters->npu_evt_counters[0].event_type == ETHOSU_PMU_NPU_ACTIVE) {
162
163 /* Compute the idle count */
Kshitij Sisodiada2ec062022-04-01 14:43:53 +0100164 counters->npu_derived_counters[0].counter_value =
165 counters->npu_total_ccnt - counters->npu_evt_counters[0].counter_value;
166 }
167#endif /* ETHOSU_DERIVED_NCOUNTERS >= 1 */
168
169 return *counters;
170}
Kshitij Sisodiade54e162022-12-20 16:09:15 +0000171
172void ethosu_inference_begin(struct ethosu_driver* drv, void* userArg)
173{
174 UNUSED(userArg);
175 ethosu_clear_cache_states();
176 ETHOSU_PMU_CNTR_Disable(drv, get_event_mask());
177 ETHOSU_PMU_CNTR_Enable(drv, get_event_mask());
178}
179
180void ethosu_inference_end(struct ethosu_driver* drv, void* userArg)
181{
182 UNUSED(userArg);
183 ETHOSU_PMU_CNTR_Disable(drv, get_event_mask());
184}