blob: a7557fc94c3cfb261e5589a5f12d7cc40b9fcc82 [file] [log] [blame]
Moritz Pflanzer45634b42017-08-30 12:48:18 +01001/*
Michele Di Giorgiod9eaf612020-07-08 11:12:57 +01002 * Copyright (c) 2017-2019 Arm Limited.
Moritz Pflanzer45634b42017-08-30 12:48:18 +01003 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#include "MaliCounter.h"
25
Anthony Barbier144d2ff2017-09-29 10:46:08 +010026#include "arm_compute/core/Error.h"
27
Moritz Pflanzer45634b42017-08-30 12:48:18 +010028namespace arm_compute
29{
30namespace test
31{
32namespace framework
33{
34namespace
35{
36struct MaliHWInfo
37{
38 unsigned mp_count;
39 unsigned gpu_id;
40 unsigned r_value;
41 unsigned p_value;
42 unsigned core_mask;
43};
44
45MaliHWInfo get_mali_hw_info(const char *path)
46{
47 int fd = open(path, O_RDWR); // NOLINT
48
49 if(fd < 0)
50 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +010051 ARM_COMPUTE_ERROR("Failed to get HW info.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +010052 }
53
54 {
55 mali_userspace::uku_version_check_args version_check_args; // NOLINT
56 version_check_args.header.id = mali_userspace::UKP_FUNC_ID_CHECK_VERSION; // NOLINT
57 version_check_args.major = 10;
58 version_check_args.minor = 2;
59
60 if(mali_userspace::mali_ioctl(fd, version_check_args) != 0)
61 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +010062 ARM_COMPUTE_ERROR("Failed to check version.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +010063 close(fd);
64 }
65 }
66
67 {
68 mali_userspace::kbase_uk_hwcnt_reader_set_flags flags; // NOLINT
69 memset(&flags, 0, sizeof(flags));
70 flags.header.id = mali_userspace::KBASE_FUNC_SET_FLAGS; // NOLINT
71 flags.create_flags = mali_userspace::BASE_CONTEXT_CREATE_KERNEL_FLAGS;
72
73 if(mali_userspace::mali_ioctl(fd, flags) != 0)
74 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +010075 ARM_COMPUTE_ERROR("Failed settings flags ioctl.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +010076 close(fd);
77 }
78 }
79
80 {
81 mali_userspace::kbase_uk_gpuprops props; // NOLINT
82 props.header.id = mali_userspace::KBASE_FUNC_GPU_PROPS_REG_DUMP; // NOLINT
83
84 if(mali_ioctl(fd, props) != 0)
85 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +010086 ARM_COMPUTE_ERROR("Failed settings flags ioctl.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +010087 close(fd);
88 }
89
90 MaliHWInfo hw_info; // NOLINT
91 memset(&hw_info, 0, sizeof(hw_info));
92 hw_info.gpu_id = props.props.core_props.product_id;
93 hw_info.r_value = props.props.core_props.major_revision;
94 hw_info.p_value = props.props.core_props.minor_revision;
95
96 for(unsigned int i = 0; i < props.props.coherency_info.num_core_groups; ++i)
97 {
98 hw_info.core_mask |= props.props.coherency_info.group[i].core_mask;
99 }
100
101 hw_info.mp_count = __builtin_popcountll(hw_info.core_mask);
102
103 close(fd);
104
105 return hw_info;
106 }
107}
108} // namespace
109
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000110MaliCounter::MaliCounter(ScaleFactor scale_factor)
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100111{
112 _counters =
113 {
Anthony Barbierab14c152017-11-09 10:29:59 +0000114 { "GPU_ACTIVE", Measurement(0, "cycles") },
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100115 };
116
117 _core_counters =
118 {
119 { "ARITH_WORDS", { "Arithmetic pipe", std::map<int, uint64_t>(), "instructions" } },
120 { "LS_ISSUE", { "LS pipe", std::map<int, uint64_t>(), "instructions" } },
121 { "TEX_ISSUE", { "Texture pipe", std::map<int, uint64_t>(), "instructions" } },
122 { "COMPUTE_ACTIVE", { "Compute core", std::map<int, uint64_t>(), "cycles" } },
123 { "FRAG_ACTIVE", { "Fragment core", std::map<int, uint64_t>(), "cycles" } },
124 };
125
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000126 switch(scale_factor)
127 {
128 case ScaleFactor::NONE:
129 _scale_factor = 1;
130 _unit = "";
131 break;
132 case ScaleFactor::SCALE_1K:
133 _scale_factor = 1000;
134 _unit = "K ";
135 break;
136 case ScaleFactor::SCALE_1M:
137 _scale_factor = 1000000;
138 _unit = "M ";
139 break;
140 default:
141 ARM_COMPUTE_ERROR("Invalid scale");
142 }
143
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100144 init();
145}
146
147MaliCounter::~MaliCounter()
148{
149 term();
150}
151
152void MaliCounter::init()
153{
154 term();
155
156 MaliHWInfo hw_info = get_mali_hw_info(_device);
157
158 _num_cores = hw_info.mp_count;
159
160 _fd = open(_device, O_RDWR | O_CLOEXEC | O_NONBLOCK); // NOLINT
161
162 if(_fd < 0)
163 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100164 ARM_COMPUTE_ERROR("Failed to open /dev/mali0.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100165 }
166
167 {
168 mali_userspace::kbase_uk_hwcnt_reader_version_check_args check; // NOLINT
169 memset(&check, 0, sizeof(check));
170
171 if(mali_userspace::mali_ioctl(_fd, check) != 0)
172 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100173 ARM_COMPUTE_ERROR("Failed to get ABI version.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100174 }
175 else if(check.major < 10)
176 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100177 ARM_COMPUTE_ERROR("Unsupported ABI version 10.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100178 }
179 }
180
181 {
182 mali_userspace::kbase_uk_hwcnt_reader_set_flags flags; // NOLINT
183 memset(&flags, 0, sizeof(flags));
184 flags.header.id = mali_userspace::KBASE_FUNC_SET_FLAGS; // NOLINT
185 flags.create_flags = mali_userspace::BASE_CONTEXT_CREATE_KERNEL_FLAGS;
186
187 if(mali_userspace::mali_ioctl(_fd, flags) != 0)
188 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100189 ARM_COMPUTE_ERROR("Failed settings flags ioctl.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100190 }
191 }
192
193 {
194 mali_userspace::kbase_uk_hwcnt_reader_setup setup; // NOLINT
195 memset(&setup, 0, sizeof(setup));
196 setup.header.id = mali_userspace::KBASE_FUNC_HWCNT_READER_SETUP; // NOLINT
197 setup.buffer_count = _buffer_count;
198 setup.jm_bm = -1;
199 setup.shader_bm = -1;
200 setup.tiler_bm = -1;
201 setup.mmu_l2_bm = -1;
202 setup.fd = -1;
203
204 if(mali_userspace::mali_ioctl(_fd, setup) != 0)
205 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100206 ARM_COMPUTE_ERROR("Failed setting hwcnt reader ioctl.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100207 }
208
209 _hwc_fd = setup.fd;
210 }
211
212 {
213 uint32_t api_version = ~mali_userspace::HWCNT_READER_API;
214
215 if(ioctl(_hwc_fd, mali_userspace::KBASE_HWCNT_READER_GET_API_VERSION, &api_version) != 0) // NOLINT
216 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100217 ARM_COMPUTE_ERROR("Could not determine hwcnt reader API.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100218 }
219 else if(api_version != mali_userspace::HWCNT_READER_API)
220 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100221 ARM_COMPUTE_ERROR("Invalid API version.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100222 }
223 }
224
Moritz Pflanzer29088d52017-09-21 15:06:59 +0100225 if(ioctl(_hwc_fd, static_cast<int>(mali_userspace::KBASE_HWCNT_READER_GET_BUFFER_SIZE), &_buffer_size) != 0) // NOLINT
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100226 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100227 ARM_COMPUTE_ERROR("Failed to get buffer size.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100228 }
229
Moritz Pflanzer29088d52017-09-21 15:06:59 +0100230 if(ioctl(_hwc_fd, static_cast<int>(mali_userspace::KBASE_HWCNT_READER_GET_HWVER), &_hw_ver) != 0) // NOLINT
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100231 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100232 ARM_COMPUTE_ERROR("Could not determine HW version.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100233 }
234
235 if(_hw_ver < 5)
236 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100237 ARM_COMPUTE_ERROR("Unsupported HW version.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100238 }
239
240 _sample_data = static_cast<uint8_t *>(mmap(nullptr, _buffer_count * _buffer_size, PROT_READ, MAP_PRIVATE, _hwc_fd, 0));
241
242 if(_sample_data == MAP_FAILED) // NOLINT
243 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100244 ARM_COMPUTE_ERROR("Failed to map sample data.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100245 }
246
247 auto product = std::find_if(std::begin(mali_userspace::products), std::end(mali_userspace::products), [&](const mali_userspace::CounterMapping & cm)
248 {
249 return (cm.product_mask & hw_info.gpu_id) == cm.product_id;
250 });
251
252 if(product != std::end(mali_userspace::products))
253 {
254 _names_lut = product->names_lut;
255 }
256 else
257 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100258 ARM_COMPUTE_ERROR("Could not identify GPU.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100259 }
260
261 _raw_counter_buffer.resize(_buffer_size / sizeof(uint32_t));
262
263 // Build core remap table.
264 _core_index_remap.clear();
265 _core_index_remap.reserve(hw_info.mp_count);
266
267 unsigned int mask = hw_info.core_mask;
268
269 while(mask != 0)
270 {
271 unsigned int bit = __builtin_ctz(mask);
272 _core_index_remap.push_back(bit);
273 mask &= ~(1u << bit);
274 }
275}
276
277void MaliCounter::term()
278{
279 if(_sample_data != nullptr)
280 {
281 munmap(_sample_data, _buffer_count * _buffer_size);
282 _sample_data = nullptr;
283 }
284
285 if(_hwc_fd >= 0)
286 {
287 close(_hwc_fd);
288 _hwc_fd = -1;
289 }
290
291 if(_fd >= 0)
292 {
293 close(_fd);
294 _fd = -1;
295 }
296}
297
298void MaliCounter::sample_counters()
299{
300 if(ioctl(_hwc_fd, mali_userspace::KBASE_HWCNT_READER_DUMP, 0) != 0)
301 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100302 ARM_COMPUTE_ERROR("Could not sample hardware counters.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100303 }
304}
305
306void MaliCounter::wait_next_event()
307{
308 pollfd poll_fd; // NOLINT
309 poll_fd.fd = _hwc_fd;
310 poll_fd.events = POLLIN;
311
312 const int count = poll(&poll_fd, 1, -1);
313
314 if(count < 0)
315 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100316 ARM_COMPUTE_ERROR("poll() failed.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100317 }
318
319 if((poll_fd.revents & POLLIN) != 0)
320 {
321 mali_userspace::kbase_hwcnt_reader_metadata meta; // NOLINT
322
Moritz Pflanzer29088d52017-09-21 15:06:59 +0100323 if(ioctl(_hwc_fd, static_cast<int>(mali_userspace::KBASE_HWCNT_READER_GET_BUFFER), &meta) != 0) // NOLINT
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100324 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100325 ARM_COMPUTE_ERROR("Failed READER_GET_BUFFER.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100326 }
327
328 memcpy(_raw_counter_buffer.data(), _sample_data + _buffer_size * meta.buffer_idx, _buffer_size);
329 _timestamp = meta.timestamp;
330
331 if(ioctl(_hwc_fd, mali_userspace::KBASE_HWCNT_READER_PUT_BUFFER, &meta) != 0) // NOLINT
332 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100333 ARM_COMPUTE_ERROR("Failed READER_PUT_BUFFER.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100334 }
335 }
336 else if((poll_fd.revents & POLLHUP) != 0)
337 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100338 ARM_COMPUTE_ERROR("HWC hung up.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100339 }
340}
341
342const uint32_t *MaliCounter::get_counters() const
343{
344 return _raw_counter_buffer.data();
345}
346
347const uint32_t *MaliCounter::get_counters(mali_userspace::MaliCounterBlockName block, int core) const
348{
349 switch(block)
350 {
351 case mali_userspace::MALI_NAME_BLOCK_JM:
352 return _raw_counter_buffer.data() + mali_userspace::MALI_NAME_BLOCK_SIZE * 0;
353 case mali_userspace::MALI_NAME_BLOCK_MMU:
354 return _raw_counter_buffer.data() + mali_userspace::MALI_NAME_BLOCK_SIZE * 2;
355 case mali_userspace::MALI_NAME_BLOCK_TILER:
356 return _raw_counter_buffer.data() + mali_userspace::MALI_NAME_BLOCK_SIZE * 1;
357 default:
358 if(core < 0)
359 {
Anthony Barbier144d2ff2017-09-29 10:46:08 +0100360 ARM_COMPUTE_ERROR("Invalid core number.");
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100361 }
362
363 return _raw_counter_buffer.data() + mali_userspace::MALI_NAME_BLOCK_SIZE * (3 + _core_index_remap[core]);
364 }
365}
366
367int MaliCounter::find_counter_index_by_name(mali_userspace::MaliCounterBlockName block, const char *name)
368{
369 const char *const *names = &_names_lut[mali_userspace::MALI_NAME_BLOCK_SIZE * block];
370
371 for(int i = 0; i < mali_userspace::MALI_NAME_BLOCK_SIZE; ++i)
372 {
373 if(strstr(names[i], name) != nullptr)
374 {
375 return i;
376 }
377 }
378
379 return -1;
380}
381
382void MaliCounter::start()
383{
384 sample_counters();
385 wait_next_event();
386 _start_time = _timestamp;
387}
388
389void MaliCounter::stop()
390{
391 sample_counters();
392 wait_next_event();
393
Anthony Barbierab14c152017-11-09 10:29:59 +0000394 const uint32_t *counter = get_counters(mali_userspace::MALI_NAME_BLOCK_JM);
395 _counters.at("GPU_ACTIVE") = Measurement(counter[find_counter_index_by_name(mali_userspace::MALI_NAME_BLOCK_JM, "GPU_ACTIVE")], _counters.at("GPU_ACTIVE").unit());
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100396
397 const int arith_index = find_counter_index_by_name(mali_userspace::MALI_NAME_BLOCK_SHADER, "ARITH_WORDS");
398 const int ls_index = find_counter_index_by_name(mali_userspace::MALI_NAME_BLOCK_SHADER, "LS_ISSUE");
399 const int tex_index = find_counter_index_by_name(mali_userspace::MALI_NAME_BLOCK_SHADER, "TEX_ISSUE");
400 const int compute_index = find_counter_index_by_name(mali_userspace::MALI_NAME_BLOCK_SHADER, "COMPUTE_ACTIVE");
401 const int frag_index = find_counter_index_by_name(mali_userspace::MALI_NAME_BLOCK_SHADER, "FRAG_ACTIVE");
402
403 // Shader core counters can be averaged if desired, but here we don't.
Michalis Spyroufae513c2019-10-16 17:41:33 +0100404 for(uint32_t core = 0; core < _num_cores; ++core)
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100405 {
Anthony Barbierab14c152017-11-09 10:29:59 +0000406 const uint32_t *sc_counter = get_counters(mali_userspace::MALI_NAME_BLOCK_SHADER, core);
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100407
408 _core_counters.at("ARITH_WORDS").values[core] = sc_counter[arith_index];
409 _core_counters.at("LS_ISSUE").values[core] = sc_counter[ls_index];
410 _core_counters.at("TEX_ISSUE").values[core] = sc_counter[tex_index];
411 _core_counters.at("COMPUTE_ACTIVE").values[core] = sc_counter[compute_index];
412 _core_counters.at("FRAG_ACTIVE").values[core] = sc_counter[frag_index];
413 }
414
415 _stop_time = _timestamp;
416}
417
418std::string MaliCounter::id() const
419{
420 return "Mali Counter";
421}
422
423Instrument::MeasurementsMap MaliCounter::measurements() const
424{
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000425 Measurement counters((_counters.at("GPU_ACTIVE").value() / _scale_factor).v.floating_point, _unit + _counters.at("GPU_ACTIVE").unit()); //NOLINT
426
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100427 MeasurementsMap measurements
428 {
Anthony Barbierab14c152017-11-09 10:29:59 +0000429 { "Timespan", Measurement(_stop_time - _start_time, "ns") },
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000430 { "GPU active", counters },
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100431 };
432
433 for(const auto &counter : _core_counters)
434 {
435 for(const auto &core : counter.second.values)
436 {
Giorgio Arenace58a9f2017-10-31 17:59:17 +0000437 measurements.emplace(counter.second.name + " #" + support::cpp11::to_string(core.first), Measurement(core.second / _scale_factor, _unit + counter.second.unit));
Moritz Pflanzer45634b42017-08-30 12:48:18 +0100438 }
439 }
440
441 return measurements;
442}
443} // namespace framework
444} // namespace test
445} // namespace arm_compute