blob: 5d50b099c2cd882bef36410c53b8d1260ef00da4 [file] [log] [blame]
Kshitij Sisodiada2ec062022-04-01 14:43:53 +01001/*
2 * Copyright (c) 2022 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
18#include "ethosu_profiler.h"
19#include "log_macros.h"
20
21#include <string.h>
22
23extern struct ethosu_driver ethosu_drv; /* Default Arm Ethos-U NPU device driver object */
24static ethosu_pmu_counters npu_counters; /* NPU counter local instance */
Kshitij Sisodia4cc40212022-04-08 09:54:53 +010025static const char* unit_beats = "beats";
26static const char* unit_cycles = "cycles";
Kshitij Sisodiada2ec062022-04-01 14:43:53 +010027
28/**
29 * @brief Gets the npu counter instance to be used.
30 * @return Pointer to the npu counter instance.
31 */
32static ethosu_pmu_counters* get_counter_instance(void)
33{
34 return &npu_counters;
35}
36
37/**
38 * @brief Checks if the counter has overflown.
39 * @param pmu_counter_mask Mask for the event counter.
40 * @return true if overflow is detected, false otherwise.
41 */
42static bool counter_overflow(uint32_t pmu_counter_mask)
43{
44 /* Check for overflow: The idle counter is 32 bit while the
45 total cycle count is 64 bit. */
46 const uint32_t overflow_status = ETHOSU_PMU_Get_CNTR_OVS(&ethosu_drv);
47 return pmu_counter_mask & overflow_status ? true : false;
48}
49
50void ethosu_pmu_init(void)
51{
52 uint32_t i = 0;
53 uint32_t evt_mask = ETHOSU_PMU_CCNT_Msk;
54 ethosu_pmu_counters* counters = get_counter_instance();
55 memset(counters, 0, sizeof(*counters));
56
57 /* Total counters = event counters + derived counters + total cycle count */
58 counters->num_total_counters = ETHOSU_PROFILER_NUM_COUNTERS;
59
60#if ETHOSU_PMU_NCOUNTERS >= 4
61 counters->npu_evt_counters[0].event_type = ETHOSU_PMU_NPU_IDLE;
62 counters->npu_evt_counters[0].event_mask = ETHOSU_PMU_CNT1_Msk;
63 counters->npu_evt_counters[0].name = "NPU IDLE";
Kshitij Sisodia4cc40212022-04-08 09:54:53 +010064 counters->npu_evt_counters[0].unit = unit_cycles;
Kshitij Sisodiada2ec062022-04-01 14:43:53 +010065
66 counters->npu_evt_counters[1].event_type = ETHOSU_PMU_AXI0_RD_DATA_BEAT_RECEIVED;
67 counters->npu_evt_counters[1].event_mask = ETHOSU_PMU_CNT2_Msk;
68 counters->npu_evt_counters[1].name = "NPU AXI0_RD_DATA_BEAT_RECEIVED";
Kshitij Sisodia4cc40212022-04-08 09:54:53 +010069 counters->npu_evt_counters[1].unit = unit_beats;
Kshitij Sisodiada2ec062022-04-01 14:43:53 +010070
71 counters->npu_evt_counters[2].event_type = ETHOSU_PMU_AXI0_WR_DATA_BEAT_WRITTEN;
72 counters->npu_evt_counters[2].event_mask = ETHOSU_PMU_CNT3_Msk;
73 counters->npu_evt_counters[2].name = "NPU AXI0_WR_DATA_BEAT_WRITTEN";
Kshitij Sisodia4cc40212022-04-08 09:54:53 +010074 counters->npu_evt_counters[2].unit = unit_beats;
Kshitij Sisodiada2ec062022-04-01 14:43:53 +010075
76 counters->npu_evt_counters[3].event_type = ETHOSU_PMU_AXI1_RD_DATA_BEAT_RECEIVED;
77 counters->npu_evt_counters[3].event_mask = ETHOSU_PMU_CNT4_Msk;
78 counters->npu_evt_counters[3].name = "NPU AXI1_RD_DATA_BEAT_RECEIVED";
Kshitij Sisodia4cc40212022-04-08 09:54:53 +010079 counters->npu_evt_counters[3].unit = unit_beats;
Kshitij Sisodiada2ec062022-04-01 14:43:53 +010080#else /* ETHOSU_PMU_NCOUNTERS >= 4 */
81 #error "NPU PMU expects a minimum of 4 available event triggered counters!"
82#endif /* ETHOSU_PMU_NCOUNTERS >= 4 */
83
84#if ETHOSU_DERIVED_NCOUNTERS >= 1
85 counters->npu_derived_counters[0].name = "NPU ACTIVE";
Kshitij Sisodia4cc40212022-04-08 09:54:53 +010086 counters->npu_derived_counters[0].unit = unit_cycles;
Kshitij Sisodiada2ec062022-04-01 14:43:53 +010087#endif /* ETHOSU_DERIVED_NCOUNTERS >= 1 */
88
89 for (i = 0; i < ETHOSU_PMU_NCOUNTERS; ++i) {
90 ETHOSU_PMU_Set_EVTYPER(&ethosu_drv, i, counters->npu_evt_counters[i].event_type);
91 evt_mask |= counters->npu_evt_counters[i].event_mask;
92 }
93
94 /* Reset overflow status. */
95 ETHOSU_PMU_Set_CNTR_OVS(&ethosu_drv, evt_mask);
96
97 /* Enable PMU. */
98 ETHOSU_PMU_Enable(&ethosu_drv);
99
100 /* Enable counters for cycle and event counters. */
101 ETHOSU_PMU_CNTR_Disable(&ethosu_drv, evt_mask);
102 ethosu_pmu_reset_counters();
103 ETHOSU_PMU_CNTR_Enable(&ethosu_drv, evt_mask);
104}
105
106/**
107 * @brief Resets the Arm Ethos-U NPU PMU counters.
108 */
109void ethosu_pmu_reset_counters(void)
110{
111 /* Reset all cycle and event counters. */
112 ETHOSU_PMU_CYCCNT_Reset(&ethosu_drv);
113 ETHOSU_PMU_EVCNTR_ALL_Reset(&ethosu_drv);
114}
115
116/**
117 * @brief Get the Arm Ethos-U NPU PMU counters
118 * @return ethosu_pmu_counters
119 */
120ethosu_pmu_counters ethosu_get_pmu_counters(void)
121{
122 ethosu_pmu_counters* counters = get_counter_instance();
123 uint32_t i = 0;
124
125 /* Event counters */
126 for (i = 0; i < ETHOSU_PMU_NCOUNTERS; ++i) {
127 if (counter_overflow(counters->npu_evt_counters[i].event_mask)) {
128 warn("Counter overflow detected for %s.\n", counters->npu_evt_counters[i].name);
129 }
130 counters->npu_evt_counters[i].counter_value =
131 ETHOSU_PMU_Get_EVCNTR(&ethosu_drv, i);
132 }
133
134 /* Total cycle count */
135 counters->npu_total_ccnt = ETHOSU_PMU_Get_CCNTR(&ethosu_drv);
136
137 /* Derived counters */
138#if ETHOSU_DERIVED_NCOUNTERS >= 1
139 if (counters->npu_evt_counters[0].event_type == ETHOSU_PMU_NPU_IDLE) {
140 counters->npu_derived_counters[0].counter_value =
141 counters->npu_total_ccnt - counters->npu_evt_counters[0].counter_value;
142 }
143#endif /* ETHOSU_DERIVED_NCOUNTERS >= 1 */
144
145 return *counters;
146}