blob: 48dce40dd18470ab29cd39d6e1e7c6923465f933 [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
Jim Flynnc454ac92022-03-16 18:43:18 +00006#include <common/include/CommonProfilingUtils.hpp>
Keith Davise394bd92019-12-02 15:12:19 +00007
Jim Flynnc454ac92022-03-16 18:43:18 +00008#include <server/include/timelineDecoder/DirectoryCaptureCommandHandler.hpp>
Finn Williams15db7452019-10-15 14:22:13 +01009
Finn Williamse63a0262019-10-22 10:30:49 +010010#include <atomic>
Keith Davis3201eea2019-10-24 17:30:41 +010011#include <iostream>
Finn Williams15db7452019-10-15 14:22:13 +010012
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000013namespace arm
Finn Williams15db7452019-10-15 14:22:13 +010014{
15
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000016namespace pipe
Finn Williams15db7452019-10-15 14:22:13 +010017{
18
19// Utils
20uint32_t uint16_t_size = sizeof(uint16_t);
21uint32_t uint32_t_size = sizeof(uint32_t);
22
Jim Flynnbbfe6032020-07-20 16:57:44 +010023void DirectoryCaptureCommandHandler::ParseData(const arm::pipe::Packet& packet)
Finn Williams15db7452019-10-15 14:22:13 +010024{
25 uint16_t categoryRecordCount;
26 uint16_t counterSetRecordCount;
27 uint16_t deviceRecordCount;
28
29 uint32_t offset = 0;
30
31 if (packet.GetLength() < 8)
32 {
33 std::cout << "Counter directory packet received." << std::endl;
34 return;
35 }
36
Keith Davis3201eea2019-10-24 17:30:41 +010037 const unsigned char* data = packet.GetData();
Finn Williams15db7452019-10-15 14:22:13 +010038 // Body header word 0:
39 // 0:15 [16] reserved: all zeros
40 offset += uint16_t_size;
41 // 16:31 [16] device_records_count: number of entries in the device_records_pointer_table
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000042 deviceRecordCount = ReadUint16(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010043 offset += uint16_t_size;
44
45 // Body header word 1:
46 // 0:31 [32] device_records_pointer_table_offset: offset to the device_records_pointer_table
47 // 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 +000048 const uint32_t deviceRecordsPointerTableOffset = ReadUint32(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010049 offset += uint32_t_size;
50
51 // Body header word 2:
52 // 0:15 [16] reserved: all zeros
53 offset += uint16_t_size;
54 // 16:31 [16] counter_set_count: number of entries in the counter_set_pointer_table
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000055 counterSetRecordCount = ReadUint16(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010056 offset += uint16_t_size;
57
58 // Body header word 3:
59 // 0:31 [32] counter_set_pointer_table_offset: offset to the counter_set_pointer_table
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000060 const uint32_t counterPointerTableSetOffset = ReadUint32(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010061 offset += uint32_t_size;
62
63 // Body header word 4:
64 // 0:15 [16] reserved: all zeros
65 offset += uint16_t_size;
66 // 16:31 [16] categories_count: number of entries in the categories_pointer_table
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000067 categoryRecordCount = ReadUint16(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010068 offset += uint16_t_size;
69
70 // Body header word 5:
71 // 0:31 [32] categories_pointer_table_offset: offset to the categories_pointer_table
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000072 const uint32_t categoriesPointerTableOffset = ReadUint32(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010073 offset += uint32_t_size;
74
75 std::vector<uint32_t> deviceRecordOffsets(deviceRecordCount);
76 std::vector<uint32_t> counterSetOffsets(counterSetRecordCount);
77 std::vector<uint32_t> categoryOffsets(categoryRecordCount);
78
Finn Williamsd44815f2020-05-01 13:25:55 +010079 offset = deviceRecordsPointerTableOffset;
Finn Williams15db7452019-10-15 14:22:13 +010080 for (uint32_t i = 0; i < deviceRecordCount; ++i)
81 {
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000082 deviceRecordOffsets[i] = ReadUint32(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010083 offset += uint32_t_size;
84 }
85
Finn Williamsd44815f2020-05-01 13:25:55 +010086 offset = counterPointerTableSetOffset;
Finn Williams15db7452019-10-15 14:22:13 +010087 for (uint32_t i = 0; i < counterSetRecordCount; ++i)
88 {
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000089 counterSetOffsets[i] = ReadUint32(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010090 offset += uint32_t_size;
91 }
92
Finn Williamsd44815f2020-05-01 13:25:55 +010093 offset = categoriesPointerTableOffset;
Finn Williams15db7452019-10-15 14:22:13 +010094 for (uint32_t i = 0; i < categoryRecordCount; ++i)
95 {
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000096 categoryOffsets[i] = ReadUint32(data, offset);
Finn Williams15db7452019-10-15 14:22:13 +010097 offset += uint32_t_size;
98 }
99
Finn Williamsd44815f2020-05-01 13:25:55 +0100100 offset = deviceRecordsPointerTableOffset;
Keith Davis3201eea2019-10-24 17:30:41 +0100101 for (uint32_t deviceIndex = 0; deviceIndex < deviceRecordCount; ++deviceIndex)
Finn Williams15db7452019-10-15 14:22:13 +0100102 {
103 uint32_t deviceRecordOffset = offset + deviceRecordOffsets[deviceIndex];
104 // Device record word 0:
105 // 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 +0000106 uint16_t deviceCores = ReadUint16(data, deviceRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100107 // 16:31 [16] deviceUid: the unique identifier for the device
108 deviceRecordOffset += uint16_t_size;
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000109 uint16_t deviceUid = ReadUint16(data, deviceRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100110 deviceRecordOffset += uint16_t_size;
111
112 // Device record word 1:
113 // Offset from the beginning of the device record pool to the name field.
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000114 uint32_t nameOffset = ReadUint32(data, deviceRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100115
Finn Williamsd44815f2020-05-01 13:25:55 +0100116 deviceRecordOffset = deviceRecordsPointerTableOffset + nameOffset;
Finn Williams15db7452019-10-15 14:22:13 +0100117
Keith Davis3201eea2019-10-24 17:30:41 +0100118 const std::string& deviceName = GetStringNameFromBuffer(data, deviceRecordOffset);
119 const Device* registeredDevice = m_CounterDirectory.RegisterDevice(deviceName, deviceCores);
120 m_UidTranslation[registeredDevice->m_Uid] = deviceUid;
Finn Williams15db7452019-10-15 14:22:13 +0100121 }
122
Finn Williamsd44815f2020-05-01 13:25:55 +0100123 offset = counterPointerTableSetOffset;
Finn Williams15db7452019-10-15 14:22:13 +0100124 for (uint32_t counterSetIndex = 0; counterSetIndex < counterSetRecordCount; ++counterSetIndex)
125 {
126 uint32_t counterSetOffset = offset + counterSetOffsets[counterSetIndex];
127
128 // Counter set record word 0:
129 // 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 +0000130 uint16_t counterSetCount = ReadUint16(data, counterSetOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100131 counterSetOffset += uint16_t_size;
132
133 // 16:31 [16] deviceUid: the unique identifier for the counter_set
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000134 uint16_t counterSetUid = ReadUint16(data, counterSetOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100135 counterSetOffset += uint16_t_size;
136
137 // Counter set record word 1:
138 // 0:31 [32] name_offset: offset from the beginning of the counter set pool to the name field
139 // The offset is always zero here, as the name field is always the first (and only) item in the pool
140 counterSetOffset += uint32_t_size;
141 counterSetOffset += uint32_t_size;
142
Keith Davis3201eea2019-10-24 17:30:41 +0100143 auto counterSet =
144 m_CounterDirectory.RegisterCounterSet(GetStringNameFromBuffer(data, counterSetOffset), counterSetCount);
145 m_UidTranslation[counterSet->m_Uid] = counterSetUid;
Finn Williams15db7452019-10-15 14:22:13 +0100146 }
Finn Williamsd44815f2020-05-01 13:25:55 +0100147 ReadCategoryRecords(data, categoriesPointerTableOffset, categoryOffsets);
Finn Williams15db7452019-10-15 14:22:13 +0100148}
149
Keith Davis3201eea2019-10-24 17:30:41 +0100150void DirectoryCaptureCommandHandler::ReadCategoryRecords(const unsigned char* const data,
151 uint32_t offset,
152 std::vector<uint32_t> categoryOffsets)
Finn Williams15db7452019-10-15 14:22:13 +0100153{
Keith Davis3201eea2019-10-24 17:30:41 +0100154 uint32_t categoryRecordCount = static_cast<uint32_t>(categoryOffsets.size());
Finn Williams15db7452019-10-15 14:22:13 +0100155
156 for (uint32_t categoryIndex = 0; categoryIndex < categoryRecordCount; ++categoryIndex)
157 {
158 uint32_t categoryRecordOffset = offset + categoryOffsets[categoryIndex];
159
Finn Williams15db7452019-10-15 14:22:13 +0100160 // Category record word 1:
161 // 0:15 Reserved, value 0x0000.
162 categoryRecordOffset += uint16_t_size;
163 // 16:31 Number of events belonging to this category.
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000164 uint32_t eventCount = ReadUint16(data, categoryRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100165 categoryRecordOffset += uint16_t_size;
166
167 // Category record word 2
168 // 0:31 Offset from the beginning of the category data pool to the event_pointer_table
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000169 uint32_t eventPointerTableOffset = ReadUint32(data, categoryRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100170 categoryRecordOffset += uint32_t_size;
171
172 // Category record word 3
173 // 0:31 Offset from the beginning of the category data pool to the name field.
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000174 uint32_t nameOffset = ReadUint32(data, categoryRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100175 categoryRecordOffset += uint32_t_size;
176
Finn Williams15db7452019-10-15 14:22:13 +0100177 std::vector<uint32_t> eventRecordsOffsets(eventCount);
178
Finn Williamsd44815f2020-05-01 13:25:55 +0100179 eventPointerTableOffset += offset + categoryOffsets[categoryIndex];
Finn Williams15db7452019-10-15 14:22:13 +0100180
181 for (uint32_t eventIndex = 0; eventIndex < eventCount; ++eventIndex)
182 {
183 eventRecordsOffsets[eventIndex] =
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000184 ReadUint32(data, eventPointerTableOffset + uint32_t_size * eventIndex);
Finn Williams15db7452019-10-15 14:22:13 +0100185 }
186
Keith Davis3201eea2019-10-24 17:30:41 +0100187 const std::vector<CounterDirectoryEventRecord>& eventRecords =
Finn Williamsd44815f2020-05-01 13:25:55 +0100188 ReadEventRecords(data, eventPointerTableOffset, eventRecordsOffsets);
Finn Williams15db7452019-10-15 14:22:13 +0100189
Keith Davis3201eea2019-10-24 17:30:41 +0100190 const Category* category = m_CounterDirectory.RegisterCategory(
Finn Williamsd44815f2020-05-01 13:25:55 +0100191 GetStringNameFromBuffer(data, offset + categoryOffsets[categoryIndex] + nameOffset + uint32_t_size));
Keith Davis3201eea2019-10-24 17:30:41 +0100192 for (auto& counter : eventRecords)
193 {
Jim Flynn4a962112022-03-13 20:18:58 +0000194 const Counter* registeredCounter = m_CounterDirectory.RegisterCounter(m_ApplicationName,
Keith Davise394bd92019-12-02 15:12:19 +0000195 counter.m_CounterUid,
196 category->m_Name,
197 counter.m_CounterClass,
198 counter.m_CounterInterpolation,
199 counter.m_CounterMultiplier,
200 counter.m_CounterName,
201 counter.m_CounterDescription,
202 counter.m_CounterUnits);
Keith Davis3201eea2019-10-24 17:30:41 +0100203 m_UidTranslation[registeredCounter->m_Uid] = counter.m_CounterUid;
204 }
Finn Williams15db7452019-10-15 14:22:13 +0100205 }
Finn Williams15db7452019-10-15 14:22:13 +0100206}
207
Keith Davis3201eea2019-10-24 17:30:41 +0100208std::vector<CounterDirectoryEventRecord> DirectoryCaptureCommandHandler::ReadEventRecords(
209 const unsigned char* data, uint32_t offset, std::vector<uint32_t> eventRecordsOffsets)
Finn Williams15db7452019-10-15 14:22:13 +0100210{
211 uint32_t eventCount = static_cast<uint32_t>(eventRecordsOffsets.size());
212
Keith Davis3201eea2019-10-24 17:30:41 +0100213 std::vector<CounterDirectoryEventRecord> eventRecords(eventCount);
Finn Williams15db7452019-10-15 14:22:13 +0100214 for (unsigned long i = 0; i < eventCount; ++i)
215 {
216 uint32_t eventRecordOffset = eventRecordsOffsets[i] + offset;
217
218 // Event record word 0:
219 // 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 +0000220 eventRecords[i].m_CounterUid = ReadUint16(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100221 eventRecordOffset += uint16_t_size;
222 // 16:31 [16] max_counter_uid: if the device this event is associated with has more than one core and there
223 // is one of these counters per core this value will be set to
224 // (counter_uid + cores (from device_record)) - 1.
225 // If there is only a single core then this value will be the same as
226 // the counter_uid value
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000227 eventRecords[i].m_MaxCounterUid = ReadUint16(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100228 eventRecordOffset += uint16_t_size;
229
230 // Event record word 1:
231 // 0:15 [16] counter_set: UID of the counter_set this event is associated with. Set to zero if the event
232 // is NOT associated with a counter_set
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000233 eventRecords[i].m_CounterSetUid = ReadUint16(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100234 eventRecordOffset += uint16_t_size;
235
236 // 16:31 [16] device: UID of the device this event is associated with. Set to zero if the event is NOT
237 // associated with a device
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000238 eventRecords[i].m_DeviceUid = ReadUint16(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100239 eventRecordOffset += uint16_t_size;
240
241 // Event record word 2:
242 // 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 +0000243 eventRecords[i].m_CounterInterpolation = ReadUint16(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100244 eventRecordOffset += uint16_t_size;
245
246 // 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 +0000247 eventRecords[i].m_CounterClass = ReadUint16(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100248 eventRecordOffset += uint16_t_size;
249
250 // Event record word 3-4:
251 // 0:63 [64] multiplier: internal data stream is represented as integer values, this allows scaling of
252 // those values as if they are fixed point numbers. Zero is not a valid value
253 uint32_t multiplier[2] = { 0u, 0u };
254
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000255 multiplier[0] = ReadUint32(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100256 eventRecordOffset += uint32_t_size;
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000257 multiplier[1] = ReadUint32(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100258 eventRecordOffset += uint32_t_size;
259
260 std::memcpy(&eventRecords[i].m_CounterMultiplier, &multiplier, sizeof(multiplier));
261
262 // Event record word 5:
263 // 0:31 [32] name_eventRecordOffset: eventRecordOffset from the
264 // beginning of the event record pool to the name field
265 // 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 +0000266 uint32_t nameOffset = ReadUint32(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100267 eventRecordOffset += uint32_t_size;
268
269 // Event record word 6:
270 // 0:31 [32] description_eventRecordOffset: eventRecordOffset from the
271 // beginning of the event record pool to the description field
272 // The size of the name buffer in bytes
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000273 uint32_t descriptionOffset = ReadUint32(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100274 eventRecordOffset += uint32_t_size;
275
276 // Event record word 7:
277 // 0:31 [32] units_eventRecordOffset: (optional) eventRecordOffset from the
278 // beginning of the event record pool to the units field.
279 // An eventRecordOffset value of zero indicates this field is not provided
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000280 uint32_t unitsOffset = ReadUint32(data, eventRecordOffset);
Finn Williams15db7452019-10-15 14:22:13 +0100281
Finn Williamsd44815f2020-05-01 13:25:55 +0100282 eventRecords[i].m_CounterName = GetStringNameFromBuffer(data, offset +
283 eventRecordsOffsets[i] +
284 nameOffset +
285 uint32_t_size);
Finn Williams15db7452019-10-15 14:22:13 +0100286
Finn Williamsd44815f2020-05-01 13:25:55 +0100287 eventRecords[i].m_CounterDescription = GetStringNameFromBuffer(data, offset +
288 eventRecordsOffsets[i] +
289 descriptionOffset +
290 uint32_t_size);
Finn Williams15db7452019-10-15 14:22:13 +0100291
Jim Flynndecd08b2022-03-13 22:35:46 +0000292 eventRecords[i].m_CounterUnits = unitsOffset == 0 ? arm::pipe::Optional<std::string>() :
Finn Williamsd44815f2020-05-01 13:25:55 +0100293 GetStringNameFromBuffer(data, eventRecordsOffsets[i] + offset + unitsOffset + uint32_t_size);
Finn Williams15db7452019-10-15 14:22:13 +0100294 }
295
296 return eventRecords;
297}
298
Jim Flynnbbfe6032020-07-20 16:57:44 +0100299void DirectoryCaptureCommandHandler::operator()(const arm::pipe::Packet& packet)
Finn Williams15db7452019-10-15 14:22:13 +0100300{
Keith Davis3201eea2019-10-24 17:30:41 +0100301 if (!m_QuietOperation) // Are we supposed to print to stdout?
Finn Williams15db7452019-10-15 14:22:13 +0100302 {
303 std::cout << "Counter directory packet received." << std::endl;
304 }
305
Keith Davis3201eea2019-10-24 17:30:41 +0100306 // The ArmNN counter directory is static per ArmNN instance. Ensure we don't parse it a second time.
307 if (!ParsedCounterDirectory())
308 {
309 ParseData(packet);
310 m_AlreadyParsed = true;
311 }
Finn Williams15db7452019-10-15 14:22:13 +0100312
313 if (!m_QuietOperation)
314 {
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000315 PrintCounterDirectory(m_CounterDirectory);
Finn Williams15db7452019-10-15 14:22:13 +0100316 }
317}
318
Keith Davis3201eea2019-10-24 17:30:41 +0100319const ICounterDirectory& DirectoryCaptureCommandHandler::GetCounterDirectory() const
Finn Williams15db7452019-10-15 14:22:13 +0100320{
321 return m_CounterDirectory;
322}
323
Keith Davis3201eea2019-10-24 17:30:41 +0100324std::string DirectoryCaptureCommandHandler::GetStringNameFromBuffer(const unsigned char* const data, uint32_t offset)
Finn Williams15db7452019-10-15 14:22:13 +0100325{
Keith Davis3201eea2019-10-24 17:30:41 +0100326 std::string deviceName;
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000327 uint8_t nextChar = ReadUint8(data, offset);
Keith Davis3201eea2019-10-24 17:30:41 +0100328
329 while (isprint(nextChar))
330 {
331 deviceName += static_cast<char>(nextChar);
332 offset++;
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000333 nextChar = ReadUint8(data, offset);
Keith Davis3201eea2019-10-24 17:30:41 +0100334 }
335
336 return deviceName;
Finn Williams15db7452019-10-15 14:22:13 +0100337}
338
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000339} // namespace pipe
Finn Williams15db7452019-10-15 14:22:13 +0100340
Jim Flynn4a962112022-03-13 20:18:58 +0000341} // namespace arm