blob: a4f67d6dff63c69b42db0645eb8fa243c1da7809 [file] [log] [blame]
Jens Elofsson955288a2021-04-22 20:57:15 +02001/*
2 * Copyright (c) 2021 Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#include "tensorflow/lite/kernels/internal/compatibility.h"
20#include "tensorflow/lite/micro/micro_error_reporter.h"
21#include "tensorflow/lite/micro/micro_profiler.h"
22#include "tensorflow/lite/micro/micro_time.h"
23
24#include <string.h>
25
Anton Moberg07cf70b2021-07-07 11:08:17 +020026#include "ethosu_log.h"
Jens Elofsson701a63b2021-05-23 17:37:07 +020027#include "layer_by_layer_profiler.hpp"
Jens Elofsson955288a2021-04-22 20:57:15 +020028#include <ethosu_driver.h>
29#include <inttypes.h>
30#include <stdio.h>
31
32namespace {
33
34uint64_t GetCurrentEthosuTicks(struct ethosu_driver *drv) {
Anton Moberg596a4662021-05-24 09:16:07 +020035 return ETHOSU_PMU_Get_CCNTR(drv);
Jens Elofsson955288a2021-04-22 20:57:15 +020036}
37
Jens Elofsson955288a2021-04-22 20:57:15 +020038} // namespace
39
40namespace tflite {
41
Jonny Svärd4c11a482021-12-17 17:04:08 +010042LayerByLayerProfiler::LayerByLayerProfiler(const std::vector<uint8_t> &event_config,
Kristofer Jonssondcc1ce02021-12-21 16:25:19 +010043 bool _pmu_cycle_counter_enable,
Jonny Svärd4c11a482021-12-17 17:04:08 +010044 size_t max_events,
Kristofer Jonssondcc1ce02021-12-21 16:25:19 +010045 Backend _backend,
46 int32_t _event_id) :
Jonny Svärd4c11a482021-12-17 17:04:08 +010047 pmu_event_config(event_config),
Kristofer Jonssondcc1ce02021-12-21 16:25:19 +010048 pmu_event_count(), pmu_cycle_counter_enable(_pmu_cycle_counter_enable), pmu_cycle_counter_count(0),
49 max_events_(max_events), backend(_backend), event_id(_event_id), num_events_(0) {
Jens Elofsson701a63b2021-05-23 17:37:07 +020050
Jonny Svärd4c11a482021-12-17 17:04:08 +010051 tags_ = std::make_unique<const char *[]>(max_events);
52 start_ticks_ = std::make_unique<uint64_t[]>(max_events);
53 end_ticks_ = std::make_unique<uint64_t[]>(max_events);
Jens Elofsson955288a2021-04-22 20:57:15 +020054}
55
56// NOTE: THIS PROFILER ONLY WORKS ON SYSTEMS WITH 1 NPU
Jens Elofsson701a63b2021-05-23 17:37:07 +020057uint32_t LayerByLayerProfiler::BeginEvent(const char *tag) {
Jens Elofsson955288a2021-04-22 20:57:15 +020058 if (num_events_ == max_events_) {
59 tflite::GetMicroErrorReporter()->Report("Profiling event overflow, max: %u events", max_events_);
60 num_events_ = 0;
61 }
62
63 tags_[num_events_] = tag;
64
65 if (strcmp("ethos-u", tag) == 0) {
Jonny Svärd4c11a482021-12-17 17:04:08 +010066 struct ethosu_driver *drv = ethosu_reserve_driver();
67 size_t numEventCounters = ETHOSU_PMU_Get_NumEventCounters();
68
69 if (pmu_event_config.size() > numEventCounters) {
Kristofer Jonssondcc1ce02021-12-21 16:25:19 +010070 LOG_WARN("PMU event config list is bigger (%zu) than available PMU event counters (%zu)",
Jonny Svärd4c11a482021-12-17 17:04:08 +010071 pmu_event_config.size(),
72 numEventCounters);
73 LOG_WARN("PMU event config list will be truncated");
74 pmu_event_config.resize(numEventCounters);
75 }
76 // Enable PMU
77 ETHOSU_PMU_Enable(drv);
78
79 for (size_t i = 0; i < pmu_event_config.size(); i++) {
80 ETHOSU_PMU_Set_EVTYPER(drv, i, static_cast<ethosu_pmu_event_type>(pmu_event_config[i]));
81 }
82
83 ETHOSU_PMU_CNTR_Enable(drv, (1 << pmu_event_config.size()) - 1);
84 ETHOSU_PMU_EVCNTR_ALL_Reset(drv);
85
86 // Configure the cycle counter
87 if (pmu_cycle_counter_enable) {
88 ETHOSU_PMU_CNTR_Disable(drv, ETHOSU_PMU_CCNT_Msk);
89 ETHOSU_PMU_CYCCNT_Reset(drv);
90
91 ETHOSU_PMU_PMCCNTR_CFG_Set_Stop_Event(drv, ETHOSU_PMU_NPU_IDLE);
92 ETHOSU_PMU_PMCCNTR_CFG_Set_Start_Event(drv, ETHOSU_PMU_NPU_ACTIVE);
93
94 ETHOSU_PMU_CNTR_Enable(drv, ETHOSU_PMU_CCNT_Msk);
95 }
96 start_ticks_[num_events_] = 0; // Hardware cycle counter has been reset above, thus starts at 0
97 ethosu_release_driver(drv);
Jens Elofsson955288a2021-04-22 20:57:15 +020098 } else {
99 start_ticks_[num_events_] = GetCurrentTimeTicks();
100 }
101
Jonny Svärd4c11a482021-12-17 17:04:08 +0100102 end_ticks_[num_events_] =
103 start_ticks_[num_events_]; // NOTE: In case an EndEvent() doesn't trigger, cycles reports as 0
Jens Elofsson955288a2021-04-22 20:57:15 +0200104 return num_events_++;
105}
106
107// NOTE: THIS PROFILER ONLY WORKS ON SYSTEMS WITH 1 NPU
Jens Elofsson701a63b2021-05-23 17:37:07 +0200108void LayerByLayerProfiler::EndEvent(uint32_t event_handle) {
Jens Elofsson955288a2021-04-22 20:57:15 +0200109 TFLITE_DCHECK(event_handle < max_events_);
110
111 if (strcmp("ethos-u", tags_[event_handle]) == 0) {
Jonny Svärd4c11a482021-12-17 17:04:08 +0100112 struct ethosu_driver *drv = ethosu_reserve_driver();
113
114 end_ticks_[event_handle] = GetCurrentEthosuTicks(drv);
115 // Get the cycle count
116 if (pmu_cycle_counter_enable) {
117 pmu_cycle_counter_count = end_ticks_[event_handle];
118 }
119
120 // Save the PMU counter values
121 // NOTE: If multiple ethos-u layers, only the latest will be saved
122 pmu_event_count.resize(pmu_event_config.size());
123 for (size_t i = 0; i < pmu_event_config.size(); i++) {
124 pmu_event_count[i] = ETHOSU_PMU_Get_EVCNTR(drv, i);
125 }
126
127 // Shut down the PMU
128 ETHOSU_PMU_Disable(drv);
129
130 ethosu_release_driver(drv);
Jens Elofsson955288a2021-04-22 20:57:15 +0200131 } else {
132 end_ticks_[event_handle] = GetCurrentTimeTicks();
Jens Elofsson955288a2021-04-22 20:57:15 +0200133 }
Jens Elofssonde044c32021-05-06 16:21:29 +0200134
Jonny Svärd4c11a482021-12-17 17:04:08 +0100135 if (backend == PRINTF) {
136 if (strcmp("ethos-u", tags_[event_handle]) == 0) {
137 for (size_t i = 0; i < pmu_event_count.size(); i++) {
Kristofer Jonssondcc1ce02021-12-21 16:25:19 +0100138 LOG("ethos-u : ethosu_pmu_cntr%zu : %" PRIu32 "\n", i, pmu_event_count[i]);
Jonny Svärd4c11a482021-12-17 17:04:08 +0100139 }
140 LOG("ethos-u : cycle_cnt : %" PRIu64 " cycles\n", pmu_cycle_counter_count);
141 } else {
142 LOG("%s : cycle_cnt : %" PRIu64 " cycles\n",
143 tags_[event_handle],
144 end_ticks_[event_handle] - start_ticks_[event_handle]);
145 }
Jens Elofsson701a63b2021-05-23 17:37:07 +0200146 } else {
Jonny Svärd4c11a482021-12-17 17:04:08 +0100147 EventRecord2(event_id, (int32_t)event_handle, end_ticks_[event_handle] - start_ticks_[event_handle]);
Jens Elofsson701a63b2021-05-23 17:37:07 +0200148 }
Jens Elofsson955288a2021-04-22 20:57:15 +0200149}
150
Kristofer Jonssondcc1ce02021-12-21 16:25:19 +0100151int32_t LayerByLayerProfiler::GetTotalTicks() const {
152 int32_t ticks = 0;
Kristofer Jonsson44d6e222021-05-21 18:59:18 +0200153
154 for (size_t i = 0; i < num_events_; ++i) {
Kristofer Jonssondcc1ce02021-12-21 16:25:19 +0100155 ticks += static_cast<int32_t>(end_ticks_[i] - start_ticks_[i]);
Jens Elofsson955288a2021-04-22 20:57:15 +0200156 }
157
158 return ticks;
159}
160
Jonny Svärd4c11a482021-12-17 17:04:08 +0100161uint64_t LayerByLayerProfiler::GetPmuCycleCounterCount() const {
162 return pmu_cycle_counter_count;
163}
164
165const std::vector<uint32_t> &LayerByLayerProfiler::GetPmuEventCount() const {
166 return pmu_event_count;
167}
168
Jens Elofsson701a63b2021-05-23 17:37:07 +0200169void LayerByLayerProfiler::Log() const {
170
Jens Elofsson955288a2021-04-22 20:57:15 +0200171#if !defined(TF_LITE_STRIP_ERROR_STRINGS)
Jonny Svärd4c11a482021-12-17 17:04:08 +0100172 if (backend == PRINTF) {
Jens Elofsson701a63b2021-05-23 17:37:07 +0200173 for (size_t i = 0; i < num_events_; ++i) {
174 uint64_t ticks = end_ticks_[i] - start_ticks_[i];
Anton Moberg07cf70b2021-07-07 11:08:17 +0200175 LOG("%s took %" PRIu64 " cycles", tags_[i], ticks);
Jens Elofsson701a63b2021-05-23 17:37:07 +0200176 }
Jens Elofsson955288a2021-04-22 20:57:15 +0200177 }
178#endif
179}
180
Jens Elofsson955288a2021-04-22 20:57:15 +0200181} // namespace tflite