blob: 002eeb9616c1e70188cf4525a8f2819db76f6844 [file] [log] [blame]
Ferran Balaguer73882172019-09-02 16:39:42 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "ProfilingUtils.hpp"
7
Ferran Balaguer47d0fe92019-09-04 16:47:34 +01008#include <armnn/Version.hpp>
9
Matteo Martincigh5dc816e2019-11-04 14:05:28 +000010#include <WallClockTimer.hpp>
11
Ferran Balaguer73882172019-09-02 16:39:42 +010012#include <boost/assert.hpp>
13
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010014#include <fstream>
Keith Davis3201eea2019-10-24 17:30:41 +010015#include <iostream>
Matteo Martincighab173e92019-09-05 12:02:04 +010016#include <limits>
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010017
Ferran Balaguer73882172019-09-02 16:39:42 +010018namespace armnn
19{
20
21namespace profiling
22{
23
Matteo Martincigh6db5f202019-09-05 12:02:04 +010024namespace
Matteo Martincighab173e92019-09-05 12:02:04 +010025{
Matteo Martincighab173e92019-09-05 12:02:04 +010026
Matteo Martincigh6db5f202019-09-05 12:02:04 +010027void ThrowIfCantGenerateNextUid(uint16_t uid, uint16_t cores = 0)
28{
Matteo Martincighab173e92019-09-05 12:02:04 +010029 // Check that it is possible to generate the next UID without causing an overflow
Matteo Martincigh6db5f202019-09-05 12:02:04 +010030 switch (cores)
Matteo Martincighab173e92019-09-05 12:02:04 +010031 {
Matteo Martincigh6db5f202019-09-05 12:02:04 +010032 case 0:
33 case 1:
34 // Number of cores not specified or set to 1 (a value of zero indicates the device is not capable of
35 // running multiple parallel workloads and will not provide multiple streams of data for each event)
36 if (uid == std::numeric_limits<uint16_t>::max())
37 {
38 throw RuntimeException("Generating the next UID for profiling would result in an overflow");
39 }
40 break;
41 default: // cores > 1
42 // Multiple cores available, as max_counter_uid has to be set to: counter_uid + cores - 1, the maximum
43 // allowed value for a counter UID is consequently: uint16_t_max - cores + 1
44 if (uid >= std::numeric_limits<uint16_t>::max() - cores + 1)
45 {
46 throw RuntimeException("Generating the next UID for profiling would result in an overflow");
47 }
48 break;
Matteo Martincighab173e92019-09-05 12:02:04 +010049 }
Matteo Martincigh6db5f202019-09-05 12:02:04 +010050}
Matteo Martincighab173e92019-09-05 12:02:04 +010051
Matteo Martincigh6db5f202019-09-05 12:02:04 +010052} // Anonymous namespace
53
54uint16_t GetNextUid(bool peekOnly)
55{
56 // The UID used for profiling objects and events. The first valid UID is 1, as 0 is a reserved value
57 static uint16_t uid = 1;
58
59 // Check that it is possible to generate the next UID without causing an overflow (throws in case of error)
60 ThrowIfCantGenerateNextUid(uid);
61
62 if (peekOnly)
63 {
64 // Peek only
65 return uid;
66 }
67 else
68 {
69 // Get the next UID
70 return uid++;
71 }
72}
73
Keith Davise394bd92019-12-02 15:12:19 +000074std::vector<uint16_t> GetNextCounterUids(uint16_t firstUid, uint16_t cores)
Matteo Martincigh6db5f202019-09-05 12:02:04 +010075{
Matteo Martincigh6db5f202019-09-05 12:02:04 +010076 // Check that it is possible to generate the next counter UID without causing an overflow (throws in case of error)
Keith Davise394bd92019-12-02 15:12:19 +000077 ThrowIfCantGenerateNextUid(firstUid, cores);
Matteo Martincigh6db5f202019-09-05 12:02:04 +010078
79 // Get the next counter UIDs
80 size_t counterUidsSize = cores == 0 ? 1 : cores;
81 std::vector<uint16_t> counterUids(counterUidsSize, 0);
82 for (size_t i = 0; i < counterUidsSize; i++)
83 {
Keith Davise394bd92019-12-02 15:12:19 +000084 counterUids[i] = firstUid++;
Matteo Martincigh6db5f202019-09-05 12:02:04 +010085 }
86 return counterUids;
Matteo Martincighab173e92019-09-05 12:02:04 +010087}
88
Matteo Martincigh378bbfc2019-11-04 14:05:28 +000089void WriteBytes(const IPacketBufferPtr& packetBuffer, unsigned int offset, const void* value, unsigned int valueSize)
90{
91 BOOST_ASSERT(packetBuffer);
92
93 WriteBytes(packetBuffer->GetWritableData(), offset, value, valueSize);
94}
95
Keith Davis3201eea2019-10-24 17:30:41 +010096uint32_t ConstructHeader(uint32_t packetFamily,
97 uint32_t packetId)
98{
99 return ((packetFamily & 0x3F) << 26)|
100 ((packetId & 0x3FF) << 16);
101}
102
103uint32_t ConstructHeader(uint32_t packetFamily,
104 uint32_t packetClass,
105 uint32_t packetType)
106{
107 return ((packetFamily & 0x3F) << 26)|
108 ((packetClass & 0x3FF) << 19)|
109 ((packetType & 0x3FFF) << 16);
110}
111
112void WriteUint64(const std::unique_ptr<IPacketBuffer>& packetBuffer, unsigned int offset, uint64_t value)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100113{
114 BOOST_ASSERT(packetBuffer);
115
116 WriteUint64(packetBuffer->GetWritableData(), offset, value);
117}
118
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000119void WriteUint32(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint32_t value)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100120{
121 BOOST_ASSERT(packetBuffer);
122
123 WriteUint32(packetBuffer->GetWritableData(), offset, value);
124}
125
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000126void WriteUint16(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint16_t value)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100127{
128 BOOST_ASSERT(packetBuffer);
129
130 WriteUint16(packetBuffer->GetWritableData(), offset, value);
131}
132
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000133void WriteUint8(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint8_t value)
134{
135 BOOST_ASSERT(packetBuffer);
136
137 WriteUint8(packetBuffer->GetWritableData(), offset, value);
138}
139
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000140void WriteBytes(unsigned char* buffer, unsigned int offset, const void* value, unsigned int valueSize)
141{
142 BOOST_ASSERT(buffer);
143 BOOST_ASSERT(value);
144
145 for (unsigned int i = 0; i < valueSize; i++, offset++)
146 {
147 buffer[offset] = *(reinterpret_cast<const unsigned char*>(value) + i);
148 }
149}
150
Francis Murtagh3a161982019-09-04 15:25:02 +0100151void WriteUint64(unsigned char* buffer, unsigned int offset, uint64_t value)
152{
153 BOOST_ASSERT(buffer);
154
155 buffer[offset] = static_cast<unsigned char>(value & 0xFF);
156 buffer[offset + 1] = static_cast<unsigned char>((value >> 8) & 0xFF);
157 buffer[offset + 2] = static_cast<unsigned char>((value >> 16) & 0xFF);
158 buffer[offset + 3] = static_cast<unsigned char>((value >> 24) & 0xFF);
159 buffer[offset + 4] = static_cast<unsigned char>((value >> 32) & 0xFF);
160 buffer[offset + 5] = static_cast<unsigned char>((value >> 40) & 0xFF);
161 buffer[offset + 6] = static_cast<unsigned char>((value >> 48) & 0xFF);
162 buffer[offset + 7] = static_cast<unsigned char>((value >> 56) & 0xFF);
163}
164
Ferran Balaguer73882172019-09-02 16:39:42 +0100165void WriteUint32(unsigned char* buffer, unsigned int offset, uint32_t value)
166{
167 BOOST_ASSERT(buffer);
168
Matteo Martincigh149528e2019-09-05 12:02:04 +0100169 buffer[offset] = static_cast<unsigned char>(value & 0xFF);
Ferran Balaguer73882172019-09-02 16:39:42 +0100170 buffer[offset + 1] = static_cast<unsigned char>((value >> 8) & 0xFF);
171 buffer[offset + 2] = static_cast<unsigned char>((value >> 16) & 0xFF);
172 buffer[offset + 3] = static_cast<unsigned char>((value >> 24) & 0xFF);
173}
174
175void WriteUint16(unsigned char* buffer, unsigned int offset, uint16_t value)
176{
Matteo Martincigh149528e2019-09-05 12:02:04 +0100177 BOOST_ASSERT(buffer);
Ferran Balaguer73882172019-09-02 16:39:42 +0100178
Matteo Martincigh149528e2019-09-05 12:02:04 +0100179 buffer[offset] = static_cast<unsigned char>(value & 0xFF);
Ferran Balaguer73882172019-09-02 16:39:42 +0100180 buffer[offset + 1] = static_cast<unsigned char>((value >> 8) & 0xFF);
181}
182
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000183void WriteUint8(unsigned char* buffer, unsigned int offset, uint8_t value)
184{
185 BOOST_ASSERT(buffer);
186
187 buffer[offset] = static_cast<unsigned char>(value);
188}
189
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000190void ReadBytes(const IPacketBufferPtr& packetBuffer, unsigned int offset, unsigned int valueSize, uint8_t outValue[])
191{
192 BOOST_ASSERT(packetBuffer);
193
194 ReadBytes(packetBuffer->GetReadableData(), offset, valueSize, outValue);
195}
196
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000197uint64_t ReadUint64(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100198{
199 BOOST_ASSERT(packetBuffer);
200
201 return ReadUint64(packetBuffer->GetReadableData(), offset);
202}
203
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000204uint32_t ReadUint32(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100205{
206 BOOST_ASSERT(packetBuffer);
207
208 return ReadUint32(packetBuffer->GetReadableData(), offset);
209}
210
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000211uint16_t ReadUint16(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100212{
213 BOOST_ASSERT(packetBuffer);
214
215 return ReadUint16(packetBuffer->GetReadableData(), offset);
216}
217
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000218uint8_t ReadUint8(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100219{
220 BOOST_ASSERT(packetBuffer);
221
222 return ReadUint8(packetBuffer->GetReadableData(), offset);
223}
224
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000225void ReadBytes(const unsigned char* buffer, unsigned int offset, unsigned int valueSize, uint8_t outValue[])
226{
227 BOOST_ASSERT(buffer);
228 BOOST_ASSERT(outValue);
229
230 for (unsigned int i = 0; i < valueSize; i++, offset++)
231 {
232 outValue[i] = static_cast<uint8_t>(buffer[offset]);
233 }
234}
235
Francis Murtagh3a161982019-09-04 15:25:02 +0100236uint64_t ReadUint64(const unsigned char* buffer, unsigned int offset)
237{
238 BOOST_ASSERT(buffer);
239
240 uint64_t value = 0;
Matteo Martincighab173e92019-09-05 12:02:04 +0100241 value = static_cast<uint64_t>(buffer[offset]);
Francis Murtagh3a161982019-09-04 15:25:02 +0100242 value |= static_cast<uint64_t>(buffer[offset + 1]) << 8;
243 value |= static_cast<uint64_t>(buffer[offset + 2]) << 16;
244 value |= static_cast<uint64_t>(buffer[offset + 3]) << 24;
245 value |= static_cast<uint64_t>(buffer[offset + 4]) << 32;
246 value |= static_cast<uint64_t>(buffer[offset + 5]) << 40;
247 value |= static_cast<uint64_t>(buffer[offset + 6]) << 48;
248 value |= static_cast<uint64_t>(buffer[offset + 7]) << 56;
249
250 return value;
251}
252
Ferran Balaguer73882172019-09-02 16:39:42 +0100253uint32_t ReadUint32(const unsigned char* buffer, unsigned int offset)
254{
255 BOOST_ASSERT(buffer);
256
257 uint32_t value = 0;
Matteo Martincigh149528e2019-09-05 12:02:04 +0100258 value = static_cast<uint32_t>(buffer[offset]);
Ferran Balaguer73882172019-09-02 16:39:42 +0100259 value |= static_cast<uint32_t>(buffer[offset + 1]) << 8;
260 value |= static_cast<uint32_t>(buffer[offset + 2]) << 16;
261 value |= static_cast<uint32_t>(buffer[offset + 3]) << 24;
262 return value;
263}
264
265uint16_t ReadUint16(const unsigned char* buffer, unsigned int offset)
266{
267 BOOST_ASSERT(buffer);
268
269 uint32_t value = 0;
Matteo Martincigh149528e2019-09-05 12:02:04 +0100270 value = static_cast<uint32_t>(buffer[offset]);
Ferran Balaguer73882172019-09-02 16:39:42 +0100271 value |= static_cast<uint32_t>(buffer[offset + 1]) << 8;
272 return static_cast<uint16_t>(value);
273}
274
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100275uint8_t ReadUint8(const unsigned char* buffer, unsigned int offset)
276{
277 BOOST_ASSERT(buffer);
278
279 return buffer[offset];
280}
281
Ferran Balaguer47d0fe92019-09-04 16:47:34 +0100282std::string GetSoftwareInfo()
283{
284 return std::string("ArmNN");
285}
286
287std::string GetHardwareVersion()
288{
289 return std::string();
290}
291
292std::string GetSoftwareVersion()
293{
294 std::string armnnVersion(ARMNN_VERSION);
295 std::string result = "Armnn " + armnnVersion.substr(2,2) + "." + armnnVersion.substr(4,2);
296 return result;
297}
298
299std::string GetProcessName()
300{
301 std::ifstream comm("/proc/self/comm");
302 std::string name;
303 getline(comm, name);
304 return name;
305}
306
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000307// Calculate the actual length an SwString will be including the terminating null character
308// padding to bring it to the next uint32_t boundary but minus the leading uint32_t encoding
309// the size to allow the offset to be correctly updated when decoding a binary packet.
310uint32_t CalculateSizeOfPaddedSwString(const std::string& str)
311{
312 std::vector<uint32_t> swTraceString;
313 StringToSwTraceString<SwTraceCharPolicy>(str, swTraceString);
314 unsigned int uint32_t_size = sizeof(uint32_t);
315 uint32_t size = (boost::numeric_cast<uint32_t>(swTraceString.size()) - 1) * uint32_t_size;
316 return size;
317}
318
319// Read TimelineMessageDirectoryPacket from given IPacketBuffer and offset
320SwTraceMessage ReadSwTraceMessage(const unsigned char* packetBuffer, unsigned int& offset)
321{
322 BOOST_ASSERT(packetBuffer);
323
324 unsigned int uint32_t_size = sizeof(uint32_t);
325
326 SwTraceMessage swTraceMessage;
327
328 // Read the decl_id
329 uint32_t readDeclId = ReadUint32(packetBuffer, offset);
330 swTraceMessage.m_Id = readDeclId;
331
332 // SWTrace "namestring" format
333 // length of the string (first 4 bytes) + string + null terminator
334
335 // Check the decl_name
336 offset += uint32_t_size;
337 uint32_t swTraceDeclNameLength = ReadUint32(packetBuffer, offset);
338
339 offset += uint32_t_size;
340 std::vector<unsigned char> swTraceStringBuffer(swTraceDeclNameLength - 1);
341 std::memcpy(swTraceStringBuffer.data(),
342 packetBuffer + offset, swTraceStringBuffer.size());
343
344 swTraceMessage.m_Name.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // name
345
346 // Check the ui_name
347 offset += CalculateSizeOfPaddedSwString(swTraceMessage.m_Name);
348 uint32_t swTraceUINameLength = ReadUint32(packetBuffer, offset);
349
350 offset += uint32_t_size;
351 swTraceStringBuffer.resize(swTraceUINameLength - 1);
352 std::memcpy(swTraceStringBuffer.data(),
353 packetBuffer + offset, swTraceStringBuffer.size());
354
355 swTraceMessage.m_UiName.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // ui_name
356
357 // Check arg_types
358 offset += CalculateSizeOfPaddedSwString(swTraceMessage.m_UiName);
359 uint32_t swTraceArgTypesLength = ReadUint32(packetBuffer, offset);
360
361 offset += uint32_t_size;
362 swTraceStringBuffer.resize(swTraceArgTypesLength - 1);
363 std::memcpy(swTraceStringBuffer.data(),
364 packetBuffer + offset, swTraceStringBuffer.size());
365
366 swTraceMessage.m_ArgTypes.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // arg_types
367
368 std::string swTraceString(swTraceStringBuffer.begin(), swTraceStringBuffer.end());
369
370 // Check arg_names
371 offset += CalculateSizeOfPaddedSwString(swTraceString);
372 uint32_t swTraceArgNamesLength = ReadUint32(packetBuffer, offset);
373
374 offset += uint32_t_size;
375 swTraceStringBuffer.resize(swTraceArgNamesLength - 1);
376 std::memcpy(swTraceStringBuffer.data(),
377 packetBuffer + offset, swTraceStringBuffer.size());
378
379 swTraceString.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end());
380 std::stringstream stringStream(swTraceString);
381 std::string argName;
382 while (std::getline(stringStream, argName, ','))
383 {
384 swTraceMessage.m_ArgNames.push_back(argName);
385 }
386
387 offset += CalculateSizeOfPaddedSwString(swTraceString);
388
389 return swTraceMessage;
390}
391
Jan Eilers92fa15b2019-10-15 15:23:25 +0100392/// Creates a timeline packet header
393///
394/// \params
395/// packetFamiliy Timeline Packet Family
396/// packetClass Timeline Packet Class
397/// packetType Timeline Packet Type
398/// streamId Stream identifier
399/// seqeunceNumbered When non-zero the 4 bytes following the header is a u32 sequence number
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100400/// dataLength Unsigned 24-bit integer. Length of data, in bytes. Zero is permitted
Jan Eilers92fa15b2019-10-15 15:23:25 +0100401///
402/// \returns
403/// Pair of uint32_t containing word0 and word1 of the header
404std::pair<uint32_t, uint32_t> CreateTimelinePacketHeader(uint32_t packetFamily,
405 uint32_t packetClass,
406 uint32_t packetType,
407 uint32_t streamId,
408 uint32_t sequenceNumbered,
409 uint32_t dataLength)
410{
411 // Packet header word 0:
412 // 26:31 [6] packet_family: timeline Packet Family, value 0b000001
413 // 19:25 [7] packet_class: packet class
414 // 16:18 [3] packet_type: packet type
415 // 8:15 [8] reserved: all zeros
416 // 0:7 [8] stream_id: stream identifier
417 uint32_t packetHeaderWord0 = ((packetFamily & 0x0000003F) << 26) |
418 ((packetClass & 0x0000007F) << 19) |
419 ((packetType & 0x00000007) << 16) |
420 ((streamId & 0x00000007) << 0);
421
422 // Packet header word 1:
423 // 25:31 [7] reserved: all zeros
424 // 24 [1] sequence_numbered: when non-zero the 4 bytes following the header is a u32 sequence number
425 // 0:23 [24] data_length: unsigned 24-bit integer. Length of data, in bytes. Zero is permitted
426 uint32_t packetHeaderWord1 = ((sequenceNumbered & 0x00000001) << 24) |
427 ((dataLength & 0x00FFFFFF) << 0);
428
429 return std::make_pair(packetHeaderWord0, packetHeaderWord1);
430}
431
432/// Creates a packet header for the timeline messages:
433/// * declareLabel
434/// * declareEntity
435/// * declareEventClass
436/// * declareRelationship
437/// * declareEvent
438///
439/// \param
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100440/// dataLength The length of the message body in bytes
Jan Eilers92fa15b2019-10-15 15:23:25 +0100441///
442/// \returns
443/// Pair of uint32_t containing word0 and word1 of the header
444std::pair<uint32_t, uint32_t> CreateTimelineMessagePacketHeader(unsigned int dataLength)
445{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100446 return CreateTimelinePacketHeader(1, // Packet family
447 0, // Packet class
448 1, // Packet type
449 0, // Stream id
450 0, // Sequence number
451 dataLength); // Data length
Jan Eilers92fa15b2019-10-15 15:23:25 +0100452}
453
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100454TimelinePacketStatus WriteTimelineLabelBinaryPacket(uint64_t profilingGuid,
455 const std::string& label,
456 unsigned char* buffer,
Keith Davis97da5e22020-03-05 16:25:28 +0000457 unsigned int remainingBufferSize,
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100458 unsigned int& numberOfBytesWritten)
459{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100460 // Initialize the output value
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100461 numberOfBytesWritten = 0;
462
463 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000464 if (buffer == nullptr || remainingBufferSize == 0)
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100465 {
466 return TimelinePacketStatus::BufferExhaustion;
467 }
468
469 // Utils
470 unsigned int uint32_t_size = sizeof(uint32_t);
471 unsigned int uint64_t_size = sizeof(uint64_t);
472
473 // Convert the label into a SWTrace string
474 std::vector<uint32_t> swTraceLabel;
475 bool result = StringToSwTraceString<SwTraceCharPolicy>(label, swTraceLabel);
476 if (!result)
477 {
478 return TimelinePacketStatus::Error;
479 }
480
481 // Calculate the size of the SWTrace string label (in bytes)
482 unsigned int swTraceLabelSize = boost::numeric_cast<unsigned int>(swTraceLabel.size()) * uint32_t_size;
483
484 // Calculate the length of the data (in bytes)
Jan Eilersb884ea42019-10-16 09:54:15 +0100485 unsigned int timelineLabelPacketDataLength = uint32_t_size + // decl_Id
486 uint64_t_size + // Profiling GUID
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100487 swTraceLabelSize; // Label
488
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100489 // Check whether the timeline binary packet fits in the given buffer
Keith Davis97da5e22020-03-05 16:25:28 +0000490 if (timelineLabelPacketDataLength > remainingBufferSize)
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100491 {
492 return TimelinePacketStatus::BufferExhaustion;
493 }
494
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100495 // Initialize the offset for writing in the buffer
496 unsigned int offset = 0;
497
Jan Eilersb884ea42019-10-16 09:54:15 +0100498 // Write decl_Id to the buffer
499 WriteUint32(buffer, offset, 0u);
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100500 offset += uint32_t_size;
501
502 // Write the timeline binary packet payload to the buffer
503 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
504 offset += uint64_t_size;
505 for (uint32_t swTraceLabelWord : swTraceLabel)
506 {
507 WriteUint32(buffer, offset, swTraceLabelWord); // Label
508 offset += uint32_t_size;
509 }
510
511 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000512 numberOfBytesWritten = timelineLabelPacketDataLength;
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100513
514 return TimelinePacketStatus::Ok;
515}
516
Keith Davis97da5e22020-03-05 16:25:28 +0000517TimelinePacketStatus WriteTimelineEntityBinary(uint64_t profilingGuid,
518 unsigned char* buffer,
519 unsigned int remainingBufferSize,
520 unsigned int& numberOfBytesWritten)
David Monahanf21f6062019-10-07 15:11:15 +0100521{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100522 // Initialize the output value
David Monahanf21f6062019-10-07 15:11:15 +0100523 numberOfBytesWritten = 0;
524
525 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000526 if (buffer == nullptr || remainingBufferSize == 0)
David Monahanf21f6062019-10-07 15:11:15 +0100527 {
528 return TimelinePacketStatus::BufferExhaustion;
529 }
530
531 // Utils
532 unsigned int uint32_t_size = sizeof(uint32_t);
533 unsigned int uint64_t_size = sizeof(uint64_t);
534
535 // Calculate the length of the data (in bytes)
Keith Davis97da5e22020-03-05 16:25:28 +0000536 unsigned int timelineEntityDataLength = uint32_t_size + uint64_t_size; // decl_id + Profiling GUID
David Monahanf21f6062019-10-07 15:11:15 +0100537
538 // Check whether the timeline binary packet fits in the given buffer
Keith Davis97da5e22020-03-05 16:25:28 +0000539 if (timelineEntityDataLength > remainingBufferSize)
David Monahanf21f6062019-10-07 15:11:15 +0100540 {
541 return TimelinePacketStatus::BufferExhaustion;
542 }
543
David Monahanf21f6062019-10-07 15:11:15 +0100544 // Initialize the offset for writing in the buffer
545 unsigned int offset = 0;
546
Jan Eilersb884ea42019-10-16 09:54:15 +0100547 // Write the decl_Id to the buffer
548 WriteUint32(buffer, offset, 1u);
David Monahanf21f6062019-10-07 15:11:15 +0100549 offset += uint32_t_size;
550
551 // Write the timeline binary packet payload to the buffer
552 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
553
554 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000555 numberOfBytesWritten = timelineEntityDataLength;
David Monahanf21f6062019-10-07 15:11:15 +0100556
557 return TimelinePacketStatus::Ok;
558}
559
Keith Davis97da5e22020-03-05 16:25:28 +0000560TimelinePacketStatus WriteTimelineRelationshipBinary(ProfilingRelationshipType relationshipType,
561 uint64_t relationshipGuid,
562 uint64_t headGuid,
563 uint64_t tailGuid,
564 unsigned char* buffer,
565 unsigned int remainingBufferSize,
566 unsigned int& numberOfBytesWritten)
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100567{
568 // Initialize the output value
569 numberOfBytesWritten = 0;
570
571 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000572 if (buffer == nullptr || remainingBufferSize == 0)
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100573 {
574 return TimelinePacketStatus::BufferExhaustion;
575 }
576
577 // Utils
578 unsigned int uint32_t_size = sizeof(uint32_t);
579 unsigned int uint64_t_size = sizeof(uint64_t);
580
581 // Calculate the length of the data (in bytes)
Keith Davis97da5e22020-03-05 16:25:28 +0000582 unsigned int timelineRelationshipDataLength = uint32_t_size * 2 + // decl_id + Relationship Type
583 uint64_t_size * 3; // Relationship GUID + Head GUID + tail GUID
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100584
Keith Davis97da5e22020-03-05 16:25:28 +0000585 // Check whether the timeline binary fits in the given buffer
586 if (timelineRelationshipDataLength > remainingBufferSize)
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100587 {
588 return TimelinePacketStatus::BufferExhaustion;
589 }
590
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100591 // Initialize the offset for writing in the buffer
592 unsigned int offset = 0;
593
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100594 uint32_t relationshipTypeUint = 0;
595
596 switch (relationshipType)
597 {
598 case ProfilingRelationshipType::RetentionLink:
599 relationshipTypeUint = 0;
600 break;
601 case ProfilingRelationshipType::ExecutionLink:
602 relationshipTypeUint = 1;
603 break;
604 case ProfilingRelationshipType::DataLink:
605 relationshipTypeUint = 2;
606 break;
607 case ProfilingRelationshipType::LabelLink:
608 relationshipTypeUint = 3;
609 break;
610 default:
611 throw InvalidArgumentException("Unknown relationship type given.");
612 }
613
Keith Davis97da5e22020-03-05 16:25:28 +0000614 // Write the timeline binary payload to the buffer
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100615 // decl_id of the timeline message
616 uint32_t declId = 3;
617 WriteUint32(buffer, offset, declId); // decl_id
618 offset += uint32_t_size;
619 WriteUint32(buffer, offset, relationshipTypeUint); // Relationship Type
620 offset += uint32_t_size;
621 WriteUint64(buffer, offset, relationshipGuid); // GUID of this relationship
622 offset += uint64_t_size;
623 WriteUint64(buffer, offset, headGuid); // head of relationship GUID
624 offset += uint64_t_size;
625 WriteUint64(buffer, offset, tailGuid); // tail of relationship GUID
626
627 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000628 numberOfBytesWritten = timelineRelationshipDataLength;
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100629
630 return TimelinePacketStatus::Ok;
631}
632
Sadik Armagan784db772019-10-08 15:05:38 +0100633TimelinePacketStatus WriteTimelineMessageDirectoryPackage(unsigned char* buffer,
Keith Davis97da5e22020-03-05 16:25:28 +0000634 unsigned int remainingBufferSize,
Sadik Armagan784db772019-10-08 15:05:38 +0100635 unsigned int& numberOfBytesWritten)
636{
637 // Initialize the output value
638 numberOfBytesWritten = 0;
639
640 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000641 if (buffer == nullptr || remainingBufferSize == 0)
Sadik Armagan784db772019-10-08 15:05:38 +0100642 {
643 return TimelinePacketStatus::BufferExhaustion;
644 }
645
646 // Utils
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000647 unsigned int uint8_t_size = sizeof(uint8_t);
Sadik Armagan784db772019-10-08 15:05:38 +0100648 unsigned int uint32_t_size = sizeof(uint32_t);
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000649 unsigned int uint64_t_size = sizeof(uint64_t);
650 unsigned int threadId_size = sizeof(std::thread::id);
Sadik Armagan784db772019-10-08 15:05:38 +0100651
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100652 // The payload/data of the packet consists of swtrace event definitions encoded according
Sadik Armagan784db772019-10-08 15:05:38 +0100653 // to the swtrace directory specification. The messages being the five defined below:
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000654 //
655 // | decl_id | decl_name | ui_name | arg_types | arg_names |
Sadik Armagan784db772019-10-08 15:05:38 +0100656 // |-----------|---------------------|-----------------------|-------------|-------------------------------------|
657 // | 0 | declareLabel | declare label | ps | guid,value |
658 // | 1 | declareEntity | declare entity | p | guid |
659 // | 2 | declareEventClass | declare event class | p | guid |
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100660 // | 3 | declareRelationship | declare relationship | Ippp | relationshipType,relationshipGuid, |
661 // | | | | | headGuid,tailGuid |
Sadik Armagan784db772019-10-08 15:05:38 +0100662 // | 4 | declareEvent | declare event | @tp | timestamp,threadId,eventGuid |
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100663 std::vector<std::vector<std::string>> timelineDirectoryMessages
664 {
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000665 { "0", "declareLabel", "declare label", "ps", "guid,value" },
666 { "1", "declareEntity", "declare entity", "p", "guid" },
667 { "2", "declareEventClass", "declare event class", "p", "guid" },
668 { "3", "declareRelationship", "declare relationship", "Ippp",
669 "relationshipType,relationshipGuid,headGuid,tailGuid" },
670 { "4", "declareEvent", "declare event", "@tp", "timestamp,threadId,eventGuid" }
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100671 };
Sadik Armagan784db772019-10-08 15:05:38 +0100672
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000673 // Build the message declarations
674 std::vector<uint32_t> swTraceBuffer;
675 for (const auto& directoryComponent : timelineDirectoryMessages)
Sadik Armagan784db772019-10-08 15:05:38 +0100676 {
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000677 // decl_id
678 uint32_t declId = 0;
679 try
Sadik Armagan784db772019-10-08 15:05:38 +0100680 {
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000681 declId = boost::numeric_cast<uint32_t>(std::stoul(directoryComponent[0]));
Sadik Armagan784db772019-10-08 15:05:38 +0100682 }
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000683 catch (const std::exception&)
684 {
685 return TimelinePacketStatus::Error;
686 }
687 swTraceBuffer.push_back(declId);
688
689 bool result = true;
690 result &= ConvertDirectoryComponent<SwTraceNameCharPolicy>(directoryComponent[1], swTraceBuffer); // decl_name
691 result &= ConvertDirectoryComponent<SwTraceCharPolicy> (directoryComponent[2], swTraceBuffer); // ui_name
692 result &= ConvertDirectoryComponent<SwTraceTypeCharPolicy>(directoryComponent[3], swTraceBuffer); // arg_types
693 result &= ConvertDirectoryComponent<SwTraceCharPolicy> (directoryComponent[4], swTraceBuffer); // arg_names
694 if (!result)
695 {
696 return TimelinePacketStatus::Error;
697 }
Sadik Armagan784db772019-10-08 15:05:38 +0100698 }
699
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000700 unsigned int dataLength = 3 * uint8_t_size + // Stream header (3 bytes)
701 boost::numeric_cast<unsigned int>(swTraceBuffer.size()) *
702 uint32_t_size; // Trace directory (5 messages)
703
Sadik Armagan784db772019-10-08 15:05:38 +0100704 // Calculate the timeline directory binary packet size (in bytes)
705 unsigned int timelineDirectoryPacketSize = 2 * uint32_t_size + // Header (2 words)
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000706 dataLength; // Payload
Sadik Armagan784db772019-10-08 15:05:38 +0100707
708 // Check whether the timeline directory binary packet fits in the given buffer
Keith Davis97da5e22020-03-05 16:25:28 +0000709 if (timelineDirectoryPacketSize > remainingBufferSize)
Sadik Armagan784db772019-10-08 15:05:38 +0100710 {
711 return TimelinePacketStatus::BufferExhaustion;
712 }
713
Jan Eilersb884ea42019-10-16 09:54:15 +0100714 // Create packet header
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000715 auto packetHeader = CreateTimelinePacketHeader(1, 0, 0, 0, 0, boost::numeric_cast<uint32_t>(dataLength));
Sadik Armagan784db772019-10-08 15:05:38 +0100716
717 // Initialize the offset for writing in the buffer
718 unsigned int offset = 0;
719
720 // Write the timeline binary packet header to the buffer
Jan Eilersb884ea42019-10-16 09:54:15 +0100721 WriteUint32(buffer, offset, packetHeader.first);
Sadik Armagan784db772019-10-08 15:05:38 +0100722 offset += uint32_t_size;
Jan Eilersb884ea42019-10-16 09:54:15 +0100723 WriteUint32(buffer, offset, packetHeader.second);
Sadik Armagan784db772019-10-08 15:05:38 +0100724 offset += uint32_t_size;
725
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000726 // Write the stream header
727 uint8_t streamVersion = 4;
728 uint8_t pointerBytes = boost::numeric_cast<uint8_t>(uint64_t_size); // All GUIDs are uint64_t
729 uint8_t threadIdBytes = boost::numeric_cast<uint8_t>(threadId_size);
730 switch (threadIdBytes)
Sadik Armagan784db772019-10-08 15:05:38 +0100731 {
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000732 case 4: // Typically Windows and Android
733 case 8: // Typically Linux
734 break; // Valid values
735 default:
736 return TimelinePacketStatus::Error; // Invalid value
737 }
738 WriteUint8(buffer, offset, streamVersion);
739 offset += uint8_t_size;
740 WriteUint8(buffer, offset, pointerBytes);
741 offset += uint8_t_size;
742 WriteUint8(buffer, offset, threadIdBytes);
743 offset += uint8_t_size;
Sadik Armagan784db772019-10-08 15:05:38 +0100744
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000745 // Write the SWTrace directory
746 uint32_t numberOfDeclarations = boost::numeric_cast<uint32_t>(timelineDirectoryMessages.size());
747 WriteUint32(buffer, offset, numberOfDeclarations); // Number of declarations
748 offset += uint32_t_size;
749 for (uint32_t i : swTraceBuffer)
750 {
751 WriteUint32(buffer, offset, i); // Message declarations
752 offset += uint32_t_size;
Sadik Armagan784db772019-10-08 15:05:38 +0100753 }
754
755 // Update the number of bytes written
756 numberOfBytesWritten = timelineDirectoryPacketSize;
757
758 return TimelinePacketStatus::Ok;
759}
760
Keith Davis97da5e22020-03-05 16:25:28 +0000761TimelinePacketStatus WriteTimelineEventClassBinary(uint64_t profilingGuid,
762 unsigned char* buffer,
763 unsigned int remainingBufferSize,
764 unsigned int& numberOfBytesWritten)
Jan Eilers92fa15b2019-10-15 15:23:25 +0100765{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100766 // Initialize the output value
Jan Eilers92fa15b2019-10-15 15:23:25 +0100767 numberOfBytesWritten = 0;
768
769 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000770 if (buffer == nullptr || remainingBufferSize == 0)
Jan Eilers92fa15b2019-10-15 15:23:25 +0100771 {
772 return TimelinePacketStatus::BufferExhaustion;
773 }
774
775 // Utils
776 unsigned int uint32_t_size = sizeof(uint32_t);
777 unsigned int uint64_t_size = sizeof(uint64_t);
778
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100779 // decl_id of the timeline message
780 uint32_t declId = 2;
Jan Eilers92fa15b2019-10-15 15:23:25 +0100781
782 // Calculate the length of the data (in bytes)
Keith Davis97da5e22020-03-05 16:25:28 +0000783 unsigned int dataSize = uint32_t_size + uint64_t_size; // decl_id + Profiling GUID
Jan Eilers92fa15b2019-10-15 15:23:25 +0100784
Keith Davis97da5e22020-03-05 16:25:28 +0000785 // Check whether the timeline binary fits in the given buffer
786 if (dataSize > remainingBufferSize)
Jan Eilers92fa15b2019-10-15 15:23:25 +0100787 {
788 return TimelinePacketStatus::BufferExhaustion;
789 }
790
Jan Eilers92fa15b2019-10-15 15:23:25 +0100791 // Initialize the offset for writing in the buffer
792 unsigned int offset = 0;
793
Keith Davis97da5e22020-03-05 16:25:28 +0000794 // Write the timeline binary payload to the buffer
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100795 WriteUint32(buffer, offset, declId); // decl_id
Jan Eilers92fa15b2019-10-15 15:23:25 +0100796 offset += uint32_t_size;
797 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
798
799 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000800 numberOfBytesWritten = dataSize;
Jan Eilers92fa15b2019-10-15 15:23:25 +0100801
802 return TimelinePacketStatus::Ok;
803}
804
Keith Davis97da5e22020-03-05 16:25:28 +0000805TimelinePacketStatus WriteTimelineEventBinary(uint64_t timestamp,
806 std::thread::id threadId,
807 uint64_t profilingGuid,
808 unsigned char* buffer,
809 unsigned int remainingBufferSize,
810 unsigned int& numberOfBytesWritten)
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100811{
812 // Initialize the output value
813 numberOfBytesWritten = 0;
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100814 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000815 if (buffer == nullptr || remainingBufferSize == 0)
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100816 {
817 return TimelinePacketStatus::BufferExhaustion;
818 }
819
820 // Utils
821 unsigned int uint32_t_size = sizeof(uint32_t);
822 unsigned int uint64_t_size = sizeof(uint64_t);
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000823 unsigned int threadId_size = sizeof(std::thread::id);
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100824
825 // decl_id of the timeline message
826 uint32_t declId = 4;
827
828 // Calculate the length of the data (in bytes)
Keith Davis97da5e22020-03-05 16:25:28 +0000829 unsigned int timelineEventDataLength = uint32_t_size + // decl_id
830 uint64_t_size + // Timestamp
831 threadId_size + // Thread id
832 uint64_t_size; // Profiling GUID
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100833
834 // Check whether the timeline binary packet fits in the given buffer
Keith Davis97da5e22020-03-05 16:25:28 +0000835 if (timelineEventDataLength > remainingBufferSize)
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100836 {
837 return TimelinePacketStatus::BufferExhaustion;
838 }
839
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100840 // Initialize the offset for writing in the buffer
841 unsigned int offset = 0;
842
Keith Davis97da5e22020-03-05 16:25:28 +0000843 // Write the timeline binary payload to the buffer
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100844 WriteUint32(buffer, offset, declId); // decl_id
845 offset += uint32_t_size;
846 WriteUint64(buffer, offset, timestamp); // Timestamp
847 offset += uint64_t_size;
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000848 WriteBytes(buffer, offset, &threadId, threadId_size); // Thread id
849 offset += threadId_size;
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100850 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
851 offset += uint64_t_size;
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100852 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000853 numberOfBytesWritten = timelineEventDataLength;
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100854
855 return TimelinePacketStatus::Ok;
856}
857
Keith Davis3201eea2019-10-24 17:30:41 +0100858std::string CentreAlignFormatting(const std::string& stringToPass, const int spacingWidth)
859{
860 std::stringstream outputStream, centrePadding;
861 int padding = spacingWidth - static_cast<int>(stringToPass.size());
862
863 for (int i = 0; i < padding / 2; ++i)
864 {
865 centrePadding << " ";
866 }
867
868 outputStream << centrePadding.str() << stringToPass << centrePadding.str();
869
870 if (padding > 0 && padding %2 != 0)
871 {
872 outputStream << " ";
873 }
874
875 return outputStream.str();
876}
877
878void PrintDeviceDetails(const std::pair<const unsigned short, std::unique_ptr<Device>>& devicePair)
879{
880 std::string body;
881
882 body.append(CentreAlignFormatting(devicePair.second->m_Name, 20));
883 body.append(" | ");
884 body.append(CentreAlignFormatting(std::to_string(devicePair.first), 13));
885 body.append(" | ");
886 body.append(CentreAlignFormatting(std::to_string(devicePair.second->m_Cores), 10));
887 body.append("\n");
888
889 std::cout << std::string(body.size(), '-') << "\n";
890 std::cout<< body;
891}
892
893void PrintCounterSetDetails(const std::pair<const unsigned short, std::unique_ptr<CounterSet>>& counterSetPair)
894{
895 std::string body;
896
897 body.append(CentreAlignFormatting(counterSetPair.second->m_Name, 20));
898 body.append(" | ");
899 body.append(CentreAlignFormatting(std::to_string(counterSetPair.first), 13));
900 body.append(" | ");
901 body.append(CentreAlignFormatting(std::to_string(counterSetPair.second->m_Count), 10));
902 body.append("\n");
903
904 std::cout << std::string(body.size(), '-') << "\n";
905
906 std::cout<< body;
907}
908
909void PrintCounterDetails(std::shared_ptr<Counter>& counter)
910{
911 std::string body;
912
913 body.append(CentreAlignFormatting(counter->m_Name, 20));
914 body.append(" | ");
915 body.append(CentreAlignFormatting(counter->m_Description, 50));
916 body.append(" | ");
917 body.append(CentreAlignFormatting(counter->m_Units, 14));
918 body.append(" | ");
919 body.append(CentreAlignFormatting(std::to_string(counter->m_Uid), 6));
920 body.append(" | ");
921 body.append(CentreAlignFormatting(std::to_string(counter->m_MaxCounterUid), 10));
922 body.append(" | ");
923 body.append(CentreAlignFormatting(std::to_string(counter->m_Class), 8));
924 body.append(" | ");
925 body.append(CentreAlignFormatting(std::to_string(counter->m_Interpolation), 14));
926 body.append(" | ");
927 body.append(CentreAlignFormatting(std::to_string(counter->m_Multiplier), 20));
928 body.append(" | ");
929 body.append(CentreAlignFormatting(std::to_string(counter->m_CounterSetUid), 16));
930 body.append(" | ");
931 body.append(CentreAlignFormatting(std::to_string(counter->m_DeviceUid), 14));
932
933 body.append("\n");
934
935 std::cout << std::string(body.size(), '-') << "\n";
936
937 std::cout << body;
938}
939
940void PrintCategoryDetails(const std::unique_ptr<Category>& category,
941 std::unordered_map<unsigned short, std::shared_ptr<Counter>> counterMap)
942{
943 std::string categoryBody;
944 std::string categoryHeader;
945
946 categoryHeader.append(CentreAlignFormatting("Name", 20));
947 categoryHeader.append(" | ");
Keith Davis3201eea2019-10-24 17:30:41 +0100948 categoryHeader.append(CentreAlignFormatting("Event Count", 14));
949 categoryHeader.append("\n");
950
951 categoryBody.append(CentreAlignFormatting(category->m_Name, 20));
952 categoryBody.append(" | ");
Keith Davis3201eea2019-10-24 17:30:41 +0100953 categoryBody.append(CentreAlignFormatting(std::to_string(category->m_Counters.size()), 14));
954
955 std::cout << "\n" << "\n";
956 std::cout << CentreAlignFormatting("CATEGORY", static_cast<int>(categoryHeader.size()));
957 std::cout << "\n";
958 std::cout << std::string(categoryHeader.size(), '=') << "\n";
959
960 std::cout << categoryHeader;
961
962 std::cout << std::string(categoryBody.size(), '-') << "\n";
963
964 std::cout << categoryBody;
965
966 std::string counterHeader;
967
968 counterHeader.append(CentreAlignFormatting("Counter Name", 20));
969 counterHeader.append(" | ");
970 counterHeader.append(CentreAlignFormatting("Description", 50));
971 counterHeader.append(" | ");
972 counterHeader.append(CentreAlignFormatting("Units", 14));
973 counterHeader.append(" | ");
974 counterHeader.append(CentreAlignFormatting("UID", 6));
975 counterHeader.append(" | ");
976 counterHeader.append(CentreAlignFormatting("Max UID", 10));
977 counterHeader.append(" | ");
978 counterHeader.append(CentreAlignFormatting("Class", 8));
979 counterHeader.append(" | ");
980 counterHeader.append(CentreAlignFormatting("Interpolation", 14));
981 counterHeader.append(" | ");
982 counterHeader.append(CentreAlignFormatting("Multiplier", 20));
983 counterHeader.append(" | ");
984 counterHeader.append(CentreAlignFormatting("Counter set UID", 16));
985 counterHeader.append(" | ");
986 counterHeader.append(CentreAlignFormatting("Device UID", 14));
987 counterHeader.append("\n");
988
989 std::cout << "\n" << "\n";
990 std::cout << CentreAlignFormatting("EVENTS IN CATEGORY: " + category->m_Name,
991 static_cast<int>(counterHeader.size()));
992 std::cout << "\n";
993 std::cout << std::string(counterHeader.size(), '=') << "\n";
994 std::cout << counterHeader;
995 for (auto& it: category->m_Counters) {
996 auto search = counterMap.find(it);
997 if(search != counterMap.end()) {
998 PrintCounterDetails(search->second);
999 }
1000 }
1001}
1002
1003void PrintCounterDirectory(ICounterDirectory& counterDirectory)
1004{
1005 std::string devicesHeader;
1006
1007 devicesHeader.append(CentreAlignFormatting("Device name", 20));
1008 devicesHeader.append(" | ");
1009 devicesHeader.append(CentreAlignFormatting("UID", 13));
1010 devicesHeader.append(" | ");
1011 devicesHeader.append(CentreAlignFormatting("Cores", 10));
1012 devicesHeader.append("\n");
1013
1014 std::cout << "\n" << "\n";
1015 std::cout << CentreAlignFormatting("DEVICES", static_cast<int>(devicesHeader.size()));
1016 std::cout << "\n";
1017 std::cout << std::string(devicesHeader.size(), '=') << "\n";
1018 std::cout << devicesHeader;
1019 for (auto& it: counterDirectory.GetDevices()) {
1020 PrintDeviceDetails(it);
1021 }
1022
1023 std::string counterSetHeader;
1024
1025 counterSetHeader.append(CentreAlignFormatting("Counter set name", 20));
1026 counterSetHeader.append(" | ");
1027 counterSetHeader.append(CentreAlignFormatting("UID", 13));
1028 counterSetHeader.append(" | ");
1029 counterSetHeader.append(CentreAlignFormatting("Count", 10));
1030 counterSetHeader.append("\n");
1031
1032 std::cout << "\n" << "\n";
1033 std::cout << CentreAlignFormatting("COUNTER SETS", static_cast<int>(counterSetHeader.size()));
1034 std::cout << "\n";
1035 std::cout << std::string(counterSetHeader.size(), '=') << "\n";
1036
1037 std::cout << counterSetHeader;
1038
1039 for (auto& it: counterDirectory.GetCounterSets()) {
1040 PrintCounterSetDetails(it);
1041 }
1042
1043 auto counters = counterDirectory.GetCounters();
1044 for (auto& it: counterDirectory.GetCategories()) {
1045 PrintCategoryDetails(it, counters);
1046 }
1047 std::cout << "\n";
1048}
1049
Matteo Martincigh5dc816e2019-11-04 14:05:28 +00001050uint64_t GetTimestamp()
1051{
1052#if USE_CLOCK_MONOTONIC_RAW
1053 using clock = MonotonicClockRaw;
1054#else
1055 using clock = std::chrono::steady_clock;
1056#endif
1057
1058 // Take a timestamp
1059 auto timestamp = clock::now();
1060
1061 return static_cast<uint64_t>(timestamp.time_since_epoch().count());
1062}
Keith Davis3201eea2019-10-24 17:30:41 +01001063
Ferran Balaguer73882172019-09-02 16:39:42 +01001064} // namespace profiling
1065
Matteo Martincigh149528e2019-09-05 12:02:04 +01001066} // namespace armnn
Matteo Martincigh378bbfc2019-11-04 14:05:28 +00001067
1068namespace std
1069{
1070
1071bool operator==(const std::vector<uint8_t>& left, std::thread::id right)
1072{
1073 return std::memcmp(left.data(), &right, left.size()) == 0;
1074}
1075
1076} // namespace std