blob: 75e1aebeb7c719ad4c59123f20d26b8e79be4c7f [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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000014namespace arm
Finn Williams15db7452019-10-15 14:22:13 +010015{
16
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000017namespace pipe
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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000043 deviceRecordCount = ReadUint16(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010044 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000049 const uint32_t deviceRecordsPointerTableOffset = 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000056 counterSetRecordCount = ReadUint16(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010057 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000061 const uint32_t counterPointerTableSetOffset = 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000068 categoryRecordCount = ReadUint16(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010069 offset += uint16_t_size;
70
71 // Body header word 5:
72 // 0:31 [32] categories_pointer_table_offset: offset to the categories_pointer_table
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000073 const uint32_t categoriesPointerTableOffset = 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 {
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000083 deviceRecordOffsets[i] = ReadUint32(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010084 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 {
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000090 counterSetOffsets[i] = ReadUint32(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010091 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 {
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000097 categoryOffsets[i] = ReadUint32(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010098 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000107 uint16_t deviceCores = 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;
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000110 uint16_t deviceUid = 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.
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000115 uint32_t nameOffset = ReadUint32(data, deviceRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100116
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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000131 uint16_t counterSetCount = 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000135 uint16_t counterSetUid = 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.
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000165 uint32_t eventCount = 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000170 uint32_t eventPointerTableOffset = ReadUint32(data, categoryRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100171 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.
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000175 uint32_t nameOffset = ReadUint32(data, categoryRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100176 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] =
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000185 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000221 eventRecords[i].m_CounterUid = ReadUint16(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100222 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000228 eventRecords[i].m_MaxCounterUid = ReadUint16(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100229 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000234 eventRecords[i].m_CounterSetUid = 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000239 eventRecords[i].m_DeviceUid = 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000244 eventRecords[i].m_CounterInterpolation = 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000248 eventRecords[i].m_CounterClass = 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000256 multiplier[0] = ReadUint32(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100257 eventRecordOffset += uint32_t_size;
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000258 multiplier[1] = ReadUint32(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100259 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000267 uint32_t nameOffset = 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000274 uint32_t descriptionOffset = ReadUint32(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100275 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000281 uint32_t unitsOffset = 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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000293 eventRecords[i].m_CounterUnits = unitsOffset == 0 ? armnn::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 {
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000316 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;
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000328 uint8_t nextChar = ReadUint8(data, offset);
Keith Davis3201eea2019-10-24 17:30:41 +0100329
330 while (isprint(nextChar))
331 {
332 deviceName += static_cast<char>(nextChar);
333 offset++;
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000334 nextChar = ReadUint8(data, offset);
Keith Davis3201eea2019-10-24 17:30:41 +0100335 }
336
337 return deviceName;
Finn Williams15db7452019-10-15 14:22:13 +0100338}
339
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000340} // namespace pipe
Finn Williams15db7452019-10-15 14:22:13 +0100341
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000342} // namespace arm