blob: c2b8f2a4ac9bbd6c5a8264fde20733472674f6dc [file] [log] [blame]
alexander3c798932021-03-26 21:42:19 +00001/*
Isabella Gottardic64f5062022-01-21 15:27:13 +00002 * Copyright (c) 2022 Arm Limited. All rights reserved.
alexander3c798932021-03-26 21:42:19 +00003 * 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 "Profiler.hpp"
18
19#include <cstring>
Isabella Gottardi8df12f32021-04-07 17:15:31 +010020#include <iomanip>
alexander3c798932021-03-26 21:42:19 +000021
22namespace arm {
23namespace app {
alexander3c798932021-03-26 21:42:19 +000024 Profiler::Profiler(hal_platform* platform, const char* name = "Unknown")
Isabella Gottardi56ee6202021-05-12 08:27:15 +010025 : m_name(name)
alexander3c798932021-03-26 21:42:19 +000026 {
27 if (platform && platform->inited) {
Isabella Gottardi56ee6202021-05-12 08:27:15 +010028 this->m_pPlatform = platform;
alexander3c798932021-03-26 21:42:19 +000029 this->Reset();
30 } else {
31 printf_err("Profiler %s initialised with invalid platform\n",
Isabella Gottardi56ee6202021-05-12 08:27:15 +010032 this->m_name.c_str());
alexander3c798932021-03-26 21:42:19 +000033 }
34 }
35
36 bool Profiler::StartProfiling(const char* name)
37 {
38 if (name) {
39 this->SetName(name);
40 }
Isabella Gottardi56ee6202021-05-12 08:27:15 +010041 if (this->m_pPlatform && !this->m_started) {
42 this->m_pPlatform->timer->reset();
43 this->m_tstampSt = this->m_pPlatform->timer->start_profiling();
44 this->m_started = true;
alexander3c798932021-03-26 21:42:19 +000045 return true;
46 }
Isabella Gottardi56ee6202021-05-12 08:27:15 +010047 printf_err("Failed to start profiler %s\n", this->m_name.c_str());
alexander3c798932021-03-26 21:42:19 +000048 return false;
49 }
50
51 bool Profiler::StopProfiling()
52 {
Isabella Gottardi56ee6202021-05-12 08:27:15 +010053 if (this->m_pPlatform && this->m_started) {
54 this->m_tstampEnd = this->m_pPlatform->timer->stop_profiling();
55 this->m_started = false;
alexander3c798932021-03-26 21:42:19 +000056
Isabella Gottardi56ee6202021-05-12 08:27:15 +010057 this->AddProfilingUnit(this->m_tstampSt, this->m_tstampEnd, this->m_name);
alexander3c798932021-03-26 21:42:19 +000058
59 return true;
60 }
Isabella Gottardi56ee6202021-05-12 08:27:15 +010061 printf_err("Failed to stop profiler %s\n", this->m_name.c_str());
alexander3c798932021-03-26 21:42:19 +000062 return false;
63 }
64
65 bool Profiler::StopProfilingAndReset()
66 {
67 if (this->StopProfiling()) {
68 this->Reset();
69 return true;
70 }
Isabella Gottardi56ee6202021-05-12 08:27:15 +010071 printf_err("Failed to stop profiler %s\n", this->m_name.c_str());
alexander3c798932021-03-26 21:42:19 +000072 return false;
73 }
74
75 void Profiler::Reset()
76 {
Isabella Gottardi56ee6202021-05-12 08:27:15 +010077 this->m_started = false;
78 this->m_series.clear();
79 memset(&this->m_tstampSt, 0, sizeof(this->m_tstampSt));
80 memset(&this->m_tstampEnd, 0, sizeof(this->m_tstampEnd));
alexander3c798932021-03-26 21:42:19 +000081 }
82
Isabella Gottardi8df12f32021-04-07 17:15:31 +010083 void calcProfilingStat(uint64_t currentValue,
84 Statistics& data,
85 uint32_t samples)
alexander3c798932021-03-26 21:42:19 +000086 {
Isabella Gottardi8df12f32021-04-07 17:15:31 +010087 data.total += currentValue;
88 data.min = std::min(data.min, currentValue);
89 data.max = std::max(data.max, currentValue);
90 data.avrg = ((double)data.total / samples);
91 }
alexander3c798932021-03-26 21:42:19 +000092
Isabella Gottardi8df12f32021-04-07 17:15:31 +010093 void Profiler::GetAllResultsAndReset(std::vector<ProfileResult>& results)
94 {
Isabella Gottardi56ee6202021-05-12 08:27:15 +010095 for (const auto& item: this->m_series) {
alexander3c798932021-03-26 21:42:19 +000096 auto name = item.first;
97 ProfilingSeries series = item.second;
Isabella Gottardi8df12f32021-04-07 17:15:31 +010098 ProfileResult result{};
99 result.name = item.first;
100 result.samplesNum = series.size();
alexander3c798932021-03-26 21:42:19 +0000101
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100102 Statistics AXI0_RD {
103 .name = "NPU AXI0_RD_DATA_BEAT_RECEIVED",
alexanderdc8f3c82021-04-14 16:19:07 +0100104 .unit = "beats",
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100105 .total = 0,
106 .avrg = 0.0,
107 .min = series[0].axi0writes,
108 .max = 0
109 };
110 Statistics AXI0_WR {
111 .name = "NPU AXI0_WR_DATA_BEAT_WRITTEN",
alexanderdc8f3c82021-04-14 16:19:07 +0100112 .unit = "beats",
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100113 .total = 0,
114 .avrg = 0.0,
115 .min = series[0].axi0reads,
116 .max = 0
117 };
118 Statistics AXI1_RD {
119 .name = "NPU AXI1_RD_DATA_BEAT_RECEIVED",
alexanderdc8f3c82021-04-14 16:19:07 +0100120 .unit = "beats",
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100121 .total = 0,
122 .avrg = 0.0,
123 .min = series[0].axi1reads,
124 .max = 0
125 };
126 Statistics NPU_ACTIVE {
127 .name = "NPU ACTIVE",
128 .unit = "cycles",
129 .total = 0,
130 .avrg = 0.0,
131 .min = series[0].activeNpuCycles,
132 .max = 0
133 };
134 Statistics NPU_IDLE {
135 .name = "NPU IDLE",
136 .unit = "cycles",
137 .total = 0,
138 .avrg = 0.0,
139 .min = series[0].idleNpuCycles,
140 .max = 0
141 };
142 Statistics NPU_Total {
Isabella Gottardi6fded052021-07-20 12:39:02 +0100143 .name = "NPU TOTAL",
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100144 .unit = "cycles",
145 .total = 0,
146 .avrg = 0.0,
147 .min = series[0].npuCycles,
148 .max = 0,
149 };
150#if defined(CPU_PROFILE_ENABLED)
151 Statistics CPU_ACTIVE {
152 .name = "CPU ACTIVE",
153 .unit = "cycles (approx)",
154 .total = 0,
155 .avrg = 0.0,
156 .min = series[0].cpuCycles - NPU_ACTIVE.min,
157 .max = 0
158 };
159 Statistics TIME {
160 .name = "Time",
161 .unit = "ms",
162 .total = 0,
163 .avrg = 0.0,
164 .min = static_cast<uint64_t>(series[0].time),
165 .max = 0
166 };
167#endif
alexander3c798932021-03-26 21:42:19 +0000168 for(ProfilingUnit& unit: series){
alexander3c798932021-03-26 21:42:19 +0000169
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100170 calcProfilingStat(unit.npuCycles,
171 NPU_Total, result.samplesNum);
alexander3c798932021-03-26 21:42:19 +0000172
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100173 calcProfilingStat(unit.activeNpuCycles,
174 NPU_ACTIVE, result.samplesNum);
alexander3c798932021-03-26 21:42:19 +0000175
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100176 calcProfilingStat(unit.idleNpuCycles,
177 NPU_IDLE, result.samplesNum);
alexander3c798932021-03-26 21:42:19 +0000178
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100179 calcProfilingStat(unit.axi0writes,
180 AXI0_WR, result.samplesNum);
alexander3c798932021-03-26 21:42:19 +0000181
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100182 calcProfilingStat(unit.axi0reads,
183 AXI0_RD, result.samplesNum);
alexander3c798932021-03-26 21:42:19 +0000184
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100185 calcProfilingStat(unit.axi1reads,
186 AXI1_RD, result.samplesNum);
alexander3c798932021-03-26 21:42:19 +0000187#if defined(CPU_PROFILE_ENABLED)
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100188 calcProfilingStat(static_cast<uint64_t>(unit.time),
189 TIME, result.samplesNum);
alexander3c798932021-03-26 21:42:19 +0000190
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100191 calcProfilingStat(unit.cpuCycles - unit.activeNpuCycles,
192 CPU_ACTIVE, result.samplesNum);
alexander3c798932021-03-26 21:42:19 +0000193#endif
194 }
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100195 result.data.emplace_back(AXI0_RD);
196 result.data.emplace_back(AXI0_WR);
197 result.data.emplace_back(AXI1_RD);
198 result.data.emplace_back(NPU_ACTIVE);
199 result.data.emplace_back(NPU_IDLE);
200 result.data.emplace_back(NPU_Total);
201#if defined(CPU_PROFILE_ENABLED)
202 result.data.emplace_back(CPU_ACTIVE);
203 result.data.emplace_back(TIME);
204#endif
205 results.emplace_back(result);
alexander3c798932021-03-26 21:42:19 +0000206 }
207 this->Reset();
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100208 }
209
210 void printStatisticsHeader(uint32_t samplesNum) {
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100211 info("Number of samples: %" PRIu32 "\n", samplesNum);
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100212 info("%s\n", "Total / Avg./ Min / Max");
213 }
214
215 void Profiler::PrintProfilingResult(bool printFullStat) {
216 std::vector<ProfileResult> results{};
217 GetAllResultsAndReset(results);
218 for(ProfileResult& result: results) {
219 info("Profile for %s:\n", result.name.c_str());
220
221 if (printFullStat) {
222 printStatisticsHeader(result.samplesNum);
223 }
224
225 for (Statistics &stat: result.data) {
226 if (printFullStat) {
Kshitij Sisodiaf9c19ea2021-05-07 16:08:14 +0100227 info("%s %s: %" PRIu64 "/ %.0f / %" PRIu64 " / %" PRIu64 " \n",
228 stat.name.c_str(), stat.unit.c_str(),
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100229 stat.total, stat.avrg, stat.min, stat.max);
230 } else {
231 info("%s %s: %.0f\n", stat.name.c_str(), stat.unit.c_str(), stat.avrg);
232 }
233 }
234 }
alexander3c798932021-03-26 21:42:19 +0000235 }
236
237 void Profiler::SetName(const char* str)
238 {
Isabella Gottardi56ee6202021-05-12 08:27:15 +0100239 this->m_name = std::string(str);
alexander3c798932021-03-26 21:42:19 +0000240 }
241
alexanderc350cdc2021-04-29 20:36:09 +0100242 void Profiler::AddProfilingUnit(time_counter start, time_counter end,
243 const std::string& name)
alexander3c798932021-03-26 21:42:19 +0000244 {
Kshitij Sisodia14ab8d42021-10-22 17:35:01 +0100245 if (!this->m_pPlatform) {
246 printf_err("Invalid platform\n");
247 return;
248 }
249
Isabella Gottardi56ee6202021-05-12 08:27:15 +0100250 platform_timer * timer = this->m_pPlatform->timer;
alexander3c798932021-03-26 21:42:19 +0000251
252 struct ProfilingUnit unit;
253
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100254 if (timer->cap.npu_cycles && timer->get_npu_cycles_diff)
alexander3c798932021-03-26 21:42:19 +0000255 {
Isabella Gottardi8df12f32021-04-07 17:15:31 +0100256 const size_t size = 6;
257 uint64_t pmuCounters[size] = {0};
258 /* 6 values: total cc, active cc, idle cc, axi0 read, axi0 write, axi1 read*/
259 if (0 == timer->get_npu_cycles_diff(&start, &end, pmuCounters, size)) {
260 unit.npuCycles = pmuCounters[0];
261 unit.activeNpuCycles = pmuCounters[1];
262 unit.idleNpuCycles = pmuCounters[2];
263 unit.axi0reads = pmuCounters[3];
264 unit.axi0writes = pmuCounters[4];
265 unit.axi1reads = pmuCounters[5];
266 }
alexander3c798932021-03-26 21:42:19 +0000267 }
268
269 if (timer->cap.cpu_cycles && timer->get_cpu_cycle_diff) {
270 unit.cpuCycles = timer->get_cpu_cycle_diff(&start, &end);
271 }
272
273 if (timer->cap.duration_ms && timer->get_duration_ms) {
274 unit.time = timer->get_duration_ms(&start, &end);
275 }
276
Isabella Gottardi56ee6202021-05-12 08:27:15 +0100277 this->m_series[name].emplace_back(unit);
alexander3c798932021-03-26 21:42:19 +0000278 }
279
280} /* namespace app */
Kshitij Sisodia14ab8d42021-10-22 17:35:01 +0100281} /* namespace arm */