blob: 60463a10c31d8a7af51731d862d9773839cb9455 [file] [log] [blame]
Finn Williams15db7452019-10-15 14:22:13 +01001//
Jim Flynnbbfe6032020-07-20 16:57:44 +01002// Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
Finn Williams15db7452019-10-15 14:22:13 +01003// SPDX-License-Identifier: MIT
4//
Jim Flynnbbfe6032020-07-20 16:57:44 +01005
Keith Davise394bd92019-12-02 15:12:19 +00006#include "DirectoryCaptureCommandHandler.hpp"
7
8#include <armnn/BackendId.hpp>
9#include "ProfilingUtils.hpp"
Finn Williams15db7452019-10-15 14:22:13 +010010
Finn Williamse63a0262019-10-22 10:30:49 +010011#include <atomic>
Keith Davis3201eea2019-10-24 17:30:41 +010012#include <iostream>
Finn Williams15db7452019-10-15 14:22:13 +010013
14namespace armnn
15{
16
Keith Davis3201eea2019-10-24 17:30:41 +010017namespace profiling
Finn Williams15db7452019-10-15 14:22:13 +010018{
19
20// Utils
21uint32_t uint16_t_size = sizeof(uint16_t);
22uint32_t uint32_t_size = sizeof(uint32_t);
23
Jim Flynnbbfe6032020-07-20 16:57:44 +010024void DirectoryCaptureCommandHandler::ParseData(const arm::pipe::Packet& packet)
Finn Williams15db7452019-10-15 14:22:13 +010025{
26 uint16_t categoryRecordCount;
27 uint16_t counterSetRecordCount;
28 uint16_t deviceRecordCount;
29
30 uint32_t offset = 0;
31
32 if (packet.GetLength() < 8)
33 {
34 std::cout << "Counter directory packet received." << std::endl;
35 return;
36 }
37
Keith Davis3201eea2019-10-24 17:30:41 +010038 const unsigned char* data = packet.GetData();
Finn Williams15db7452019-10-15 14:22:13 +010039 // Body header word 0:
40 // 0:15 [16] reserved: all zeros
41 offset += uint16_t_size;
42 // 16:31 [16] device_records_count: number of entries in the device_records_pointer_table
43 deviceRecordCount = profiling::ReadUint16(data, offset);
44 offset += uint16_t_size;
45
46 // Body header word 1:
47 // 0:31 [32] device_records_pointer_table_offset: offset to the device_records_pointer_table
48 // The offset is always zero here, as the device record pointer table field is always the first item in the pool
Finn Williamsd44815f2020-05-01 13:25:55 +010049 const uint32_t deviceRecordsPointerTableOffset = profiling::ReadUint32(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010050 offset += uint32_t_size;
51
52 // Body header word 2:
53 // 0:15 [16] reserved: all zeros
54 offset += uint16_t_size;
55 // 16:31 [16] counter_set_count: number of entries in the counter_set_pointer_table
56 counterSetRecordCount = profiling::ReadUint16(data, offset);
57 offset += uint16_t_size;
58
59 // Body header word 3:
60 // 0:31 [32] counter_set_pointer_table_offset: offset to the counter_set_pointer_table
Finn Williamsd44815f2020-05-01 13:25:55 +010061 const uint32_t counterPointerTableSetOffset = profiling::ReadUint32(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010062 offset += uint32_t_size;
63
64 // Body header word 4:
65 // 0:15 [16] reserved: all zeros
66 offset += uint16_t_size;
67 // 16:31 [16] categories_count: number of entries in the categories_pointer_table
68 categoryRecordCount = profiling::ReadUint16(data, offset);
69 offset += uint16_t_size;
70
71 // Body header word 5:
72 // 0:31 [32] categories_pointer_table_offset: offset to the categories_pointer_table
Finn Williamsd44815f2020-05-01 13:25:55 +010073 const uint32_t categoriesPointerTableOffset = profiling::ReadUint32(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010074 offset += uint32_t_size;
75
76 std::vector<uint32_t> deviceRecordOffsets(deviceRecordCount);
77 std::vector<uint32_t> counterSetOffsets(counterSetRecordCount);
78 std::vector<uint32_t> categoryOffsets(categoryRecordCount);
79
Finn Williamsd44815f2020-05-01 13:25:55 +010080 offset = deviceRecordsPointerTableOffset;
Finn Williams15db7452019-10-15 14:22:13 +010081 for (uint32_t i = 0; i < deviceRecordCount; ++i)
82 {
83 deviceRecordOffsets[i] = profiling::ReadUint32(data, offset);
84 offset += uint32_t_size;
85 }
86
Finn Williamsd44815f2020-05-01 13:25:55 +010087 offset = counterPointerTableSetOffset;
Finn Williams15db7452019-10-15 14:22:13 +010088 for (uint32_t i = 0; i < counterSetRecordCount; ++i)
89 {
90 counterSetOffsets[i] = profiling::ReadUint32(data, offset);
91 offset += uint32_t_size;
92 }
93
Finn Williamsd44815f2020-05-01 13:25:55 +010094 offset = categoriesPointerTableOffset;
Finn Williams15db7452019-10-15 14:22:13 +010095 for (uint32_t i = 0; i < categoryRecordCount; ++i)
96 {
97 categoryOffsets[i] = profiling::ReadUint32(data, offset);
98 offset += uint32_t_size;
99 }
100
Finn Williamsd44815f2020-05-01 13:25:55 +0100101 offset = deviceRecordsPointerTableOffset;
Keith Davis3201eea2019-10-24 17:30:41 +0100102 for (uint32_t deviceIndex = 0; deviceIndex < deviceRecordCount; ++deviceIndex)
Finn Williams15db7452019-10-15 14:22:13 +0100103 {
104 uint32_t deviceRecordOffset = offset + deviceRecordOffsets[deviceIndex];
105 // Device record word 0:
106 // 0:15 [16] cores: the number of individual streams of counters for one or more cores of some device
Keith Davis3201eea2019-10-24 17:30:41 +0100107 uint16_t deviceCores = profiling::ReadUint16(data, deviceRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100108 // 16:31 [16] deviceUid: the unique identifier for the device
109 deviceRecordOffset += uint16_t_size;
Keith Davis3201eea2019-10-24 17:30:41 +0100110 uint16_t deviceUid = profiling::ReadUint16(data, deviceRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100111 deviceRecordOffset += uint16_t_size;
112
113 // Device record word 1:
114 // Offset from the beginning of the device record pool to the name field.
115 uint32_t nameOffset = profiling::ReadUint32(data, deviceRecordOffset);
116
Finn Williamsd44815f2020-05-01 13:25:55 +0100117 deviceRecordOffset = deviceRecordsPointerTableOffset + nameOffset;
Finn Williams15db7452019-10-15 14:22:13 +0100118
Keith Davis3201eea2019-10-24 17:30:41 +0100119 const std::string& deviceName = GetStringNameFromBuffer(data, deviceRecordOffset);
120 const Device* registeredDevice = m_CounterDirectory.RegisterDevice(deviceName, deviceCores);
121 m_UidTranslation[registeredDevice->m_Uid] = deviceUid;
Finn Williams15db7452019-10-15 14:22:13 +0100122 }
123
Finn Williamsd44815f2020-05-01 13:25:55 +0100124 offset = counterPointerTableSetOffset;
Finn Williams15db7452019-10-15 14:22:13 +0100125 for (uint32_t counterSetIndex = 0; counterSetIndex < counterSetRecordCount; ++counterSetIndex)
126 {
127 uint32_t counterSetOffset = offset + counterSetOffsets[counterSetIndex];
128
129 // Counter set record word 0:
130 // 0:15 [16] count: the number of counters which can be active in this set at any one time
Keith Davis3201eea2019-10-24 17:30:41 +0100131 uint16_t counterSetCount = profiling::ReadUint16(data, counterSetOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100132 counterSetOffset += uint16_t_size;
133
134 // 16:31 [16] deviceUid: the unique identifier for the counter_set
Keith Davis3201eea2019-10-24 17:30:41 +0100135 uint16_t counterSetUid = profiling::ReadUint16(data, counterSetOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100136 counterSetOffset += uint16_t_size;
137
138 // Counter set record word 1:
139 // 0:31 [32] name_offset: offset from the beginning of the counter set pool to the name field
140 // The offset is always zero here, as the name field is always the first (and only) item in the pool
141 counterSetOffset += uint32_t_size;
142 counterSetOffset += uint32_t_size;
143
Keith Davis3201eea2019-10-24 17:30:41 +0100144 auto counterSet =
145 m_CounterDirectory.RegisterCounterSet(GetStringNameFromBuffer(data, counterSetOffset), counterSetCount);
146 m_UidTranslation[counterSet->m_Uid] = counterSetUid;
Finn Williams15db7452019-10-15 14:22:13 +0100147 }
Finn Williamsd44815f2020-05-01 13:25:55 +0100148 ReadCategoryRecords(data, categoriesPointerTableOffset, categoryOffsets);
Finn Williams15db7452019-10-15 14:22:13 +0100149}
150
Keith Davis3201eea2019-10-24 17:30:41 +0100151void DirectoryCaptureCommandHandler::ReadCategoryRecords(const unsigned char* const data,
152 uint32_t offset,
153 std::vector<uint32_t> categoryOffsets)
Finn Williams15db7452019-10-15 14:22:13 +0100154{
Keith Davis3201eea2019-10-24 17:30:41 +0100155 uint32_t categoryRecordCount = static_cast<uint32_t>(categoryOffsets.size());
Finn Williams15db7452019-10-15 14:22:13 +0100156
157 for (uint32_t categoryIndex = 0; categoryIndex < categoryRecordCount; ++categoryIndex)
158 {
159 uint32_t categoryRecordOffset = offset + categoryOffsets[categoryIndex];
160
Finn Williams15db7452019-10-15 14:22:13 +0100161 // Category record word 1:
162 // 0:15 Reserved, value 0x0000.
163 categoryRecordOffset += uint16_t_size;
164 // 16:31 Number of events belonging to this category.
Keith Davis3201eea2019-10-24 17:30:41 +0100165 uint32_t eventCount = profiling::ReadUint16(data, categoryRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100166 categoryRecordOffset += uint16_t_size;
167
168 // Category record word 2
169 // 0:31 Offset from the beginning of the category data pool to the event_pointer_table
170 uint32_t eventPointerTableOffset = profiling::ReadUint32(data, categoryRecordOffset);
171 categoryRecordOffset += uint32_t_size;
172
173 // Category record word 3
174 // 0:31 Offset from the beginning of the category data pool to the name field.
175 uint32_t nameOffset = profiling::ReadUint32(data, categoryRecordOffset);
176 categoryRecordOffset += uint32_t_size;
177
Finn Williams15db7452019-10-15 14:22:13 +0100178 std::vector<uint32_t> eventRecordsOffsets(eventCount);
179
Finn Williamsd44815f2020-05-01 13:25:55 +0100180 eventPointerTableOffset += offset + categoryOffsets[categoryIndex];
Finn Williams15db7452019-10-15 14:22:13 +0100181
182 for (uint32_t eventIndex = 0; eventIndex < eventCount; ++eventIndex)
183 {
184 eventRecordsOffsets[eventIndex] =
Keith Davis3201eea2019-10-24 17:30:41 +0100185 profiling::ReadUint32(data, eventPointerTableOffset + uint32_t_size * eventIndex);
Finn Williams15db7452019-10-15 14:22:13 +0100186 }
187
Keith Davis3201eea2019-10-24 17:30:41 +0100188 const std::vector<CounterDirectoryEventRecord>& eventRecords =
Finn Williamsd44815f2020-05-01 13:25:55 +0100189 ReadEventRecords(data, eventPointerTableOffset, eventRecordsOffsets);
Finn Williams15db7452019-10-15 14:22:13 +0100190
Keith Davis3201eea2019-10-24 17:30:41 +0100191 const Category* category = m_CounterDirectory.RegisterCategory(
Finn Williamsd44815f2020-05-01 13:25:55 +0100192 GetStringNameFromBuffer(data, offset + categoryOffsets[categoryIndex] + nameOffset + uint32_t_size));
Keith Davis3201eea2019-10-24 17:30:41 +0100193 for (auto& counter : eventRecords)
194 {
Keith Davise394bd92019-12-02 15:12:19 +0000195 const Counter* registeredCounter = m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
196 counter.m_CounterUid,
197 category->m_Name,
198 counter.m_CounterClass,
199 counter.m_CounterInterpolation,
200 counter.m_CounterMultiplier,
201 counter.m_CounterName,
202 counter.m_CounterDescription,
203 counter.m_CounterUnits);
Keith Davis3201eea2019-10-24 17:30:41 +0100204 m_UidTranslation[registeredCounter->m_Uid] = counter.m_CounterUid;
205 }
Finn Williams15db7452019-10-15 14:22:13 +0100206 }
Finn Williams15db7452019-10-15 14:22:13 +0100207}
208
Keith Davis3201eea2019-10-24 17:30:41 +0100209std::vector<CounterDirectoryEventRecord> DirectoryCaptureCommandHandler::ReadEventRecords(
210 const unsigned char* data, uint32_t offset, std::vector<uint32_t> eventRecordsOffsets)
Finn Williams15db7452019-10-15 14:22:13 +0100211{
212 uint32_t eventCount = static_cast<uint32_t>(eventRecordsOffsets.size());
213
Keith Davis3201eea2019-10-24 17:30:41 +0100214 std::vector<CounterDirectoryEventRecord> eventRecords(eventCount);
Finn Williams15db7452019-10-15 14:22:13 +0100215 for (unsigned long i = 0; i < eventCount; ++i)
216 {
217 uint32_t eventRecordOffset = eventRecordsOffsets[i] + offset;
218
219 // Event record word 0:
220 // 0:15 [16] count_uid: unique ID for the counter. Must be unique across all counters in all categories
221 eventRecords[i].m_CounterUid = profiling::ReadUint16(data, eventRecordOffset);
222 eventRecordOffset += uint16_t_size;
223 // 16:31 [16] max_counter_uid: if the device this event is associated with has more than one core and there
224 // is one of these counters per core this value will be set to
225 // (counter_uid + cores (from device_record)) - 1.
226 // If there is only a single core then this value will be the same as
227 // the counter_uid value
228 eventRecords[i].m_MaxCounterUid = profiling::ReadUint16(data, eventRecordOffset);
229 eventRecordOffset += uint16_t_size;
230
231 // Event record word 1:
232 // 0:15 [16] counter_set: UID of the counter_set this event is associated with. Set to zero if the event
233 // is NOT associated with a counter_set
Finn Williams78229c42020-05-08 12:24:31 +0100234 eventRecords[i].m_CounterSetUid = profiling::ReadUint16(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100235 eventRecordOffset += uint16_t_size;
236
237 // 16:31 [16] device: UID of the device this event is associated with. Set to zero if the event is NOT
238 // associated with a device
Finn Williams78229c42020-05-08 12:24:31 +0100239 eventRecords[i].m_DeviceUid = profiling::ReadUint16(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100240 eventRecordOffset += uint16_t_size;
241
242 // Event record word 2:
243 // 0:15 [16] interpolation: type describing how to interpolate each data point in a stream of data points
Finn Williams78229c42020-05-08 12:24:31 +0100244 eventRecords[i].m_CounterInterpolation = profiling::ReadUint16(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100245 eventRecordOffset += uint16_t_size;
246
247 // 16:31 [16] class: type describing how to treat each data point in a stream of data points
Finn Williams78229c42020-05-08 12:24:31 +0100248 eventRecords[i].m_CounterClass = profiling::ReadUint16(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100249 eventRecordOffset += uint16_t_size;
250
251 // Event record word 3-4:
252 // 0:63 [64] multiplier: internal data stream is represented as integer values, this allows scaling of
253 // those values as if they are fixed point numbers. Zero is not a valid value
254 uint32_t multiplier[2] = { 0u, 0u };
255
256 multiplier[0] = profiling::ReadUint32(data, eventRecordOffset);
257 eventRecordOffset += uint32_t_size;
258 multiplier[1] = profiling::ReadUint32(data, eventRecordOffset);
259 eventRecordOffset += uint32_t_size;
260
261 std::memcpy(&eventRecords[i].m_CounterMultiplier, &multiplier, sizeof(multiplier));
262
263 // Event record word 5:
264 // 0:31 [32] name_eventRecordOffset: eventRecordOffset from the
265 // beginning of the event record pool to the name field
266 // The eventRecordOffset is always zero here, as the name field is always the first item in the pool
Finn Williamsd44815f2020-05-01 13:25:55 +0100267 uint32_t nameOffset = profiling::ReadUint32(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100268 eventRecordOffset += uint32_t_size;
269
270 // Event record word 6:
271 // 0:31 [32] description_eventRecordOffset: eventRecordOffset from the
272 // beginning of the event record pool to the description field
273 // The size of the name buffer in bytes
274 uint32_t descriptionOffset = profiling::ReadUint32(data, eventRecordOffset);
275 eventRecordOffset += uint32_t_size;
276
277 // Event record word 7:
278 // 0:31 [32] units_eventRecordOffset: (optional) eventRecordOffset from the
279 // beginning of the event record pool to the units field.
280 // An eventRecordOffset value of zero indicates this field is not provided
281 uint32_t unitsOffset = profiling::ReadUint32(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100282
Finn Williamsd44815f2020-05-01 13:25:55 +0100283 eventRecords[i].m_CounterName = GetStringNameFromBuffer(data, offset +
284 eventRecordsOffsets[i] +
285 nameOffset +
286 uint32_t_size);
Finn Williams15db7452019-10-15 14:22:13 +0100287
Finn Williamsd44815f2020-05-01 13:25:55 +0100288 eventRecords[i].m_CounterDescription = GetStringNameFromBuffer(data, offset +
289 eventRecordsOffsets[i] +
290 descriptionOffset +
291 uint32_t_size);
Finn Williams15db7452019-10-15 14:22:13 +0100292
Keith Davis33ed2212020-03-30 10:43:41 +0100293 eventRecords[i].m_CounterUnits = unitsOffset == 0 ? Optional<std::string>() :
Finn Williamsd44815f2020-05-01 13:25:55 +0100294 GetStringNameFromBuffer(data, eventRecordsOffsets[i] + offset + unitsOffset + uint32_t_size);
Finn Williams15db7452019-10-15 14:22:13 +0100295 }
296
297 return eventRecords;
298}
299
Jim Flynnbbfe6032020-07-20 16:57:44 +0100300void DirectoryCaptureCommandHandler::operator()(const arm::pipe::Packet& packet)
Finn Williams15db7452019-10-15 14:22:13 +0100301{
Keith Davis3201eea2019-10-24 17:30:41 +0100302 if (!m_QuietOperation) // Are we supposed to print to stdout?
Finn Williams15db7452019-10-15 14:22:13 +0100303 {
304 std::cout << "Counter directory packet received." << std::endl;
305 }
306
Keith Davis3201eea2019-10-24 17:30:41 +0100307 // The ArmNN counter directory is static per ArmNN instance. Ensure we don't parse it a second time.
308 if (!ParsedCounterDirectory())
309 {
310 ParseData(packet);
311 m_AlreadyParsed = true;
312 }
Finn Williams15db7452019-10-15 14:22:13 +0100313
314 if (!m_QuietOperation)
315 {
Keith Davis3201eea2019-10-24 17:30:41 +0100316 armnn::profiling::PrintCounterDirectory(m_CounterDirectory);
Finn Williams15db7452019-10-15 14:22:13 +0100317 }
318}
319
Keith Davis3201eea2019-10-24 17:30:41 +0100320const ICounterDirectory& DirectoryCaptureCommandHandler::GetCounterDirectory() const
Finn Williams15db7452019-10-15 14:22:13 +0100321{
322 return m_CounterDirectory;
323}
324
Keith Davis3201eea2019-10-24 17:30:41 +0100325std::string DirectoryCaptureCommandHandler::GetStringNameFromBuffer(const unsigned char* const data, uint32_t offset)
Finn Williams15db7452019-10-15 14:22:13 +0100326{
Keith Davis3201eea2019-10-24 17:30:41 +0100327 std::string deviceName;
Rob Hughes270233f2019-11-13 11:53:48 +0000328 uint8_t nextChar = profiling::ReadUint8(data, offset);
Keith Davis3201eea2019-10-24 17:30:41 +0100329
330 while (isprint(nextChar))
331 {
332 deviceName += static_cast<char>(nextChar);
333 offset++;
334 nextChar = profiling::ReadUint8(data, offset);
335 }
336
337 return deviceName;
Finn Williams15db7452019-10-15 14:22:13 +0100338}
339
Keith Davis3201eea2019-10-24 17:30:41 +0100340} // namespace profiling
Finn Williams15db7452019-10-15 14:22:13 +0100341
Keith Davis3201eea2019-10-24 17:30:41 +0100342} // namespace armnn