blob: 8a7d9147cc7e5638f3941391757df1b80d21987f [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>
Matteo Martincigh6db5f202019-09-05 12:02:04 +01009#include <armnn/Conversion.hpp>
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010010
Matteo Martincigh5dc816e2019-11-04 14:05:28 +000011#include <WallClockTimer.hpp>
12
Ferran Balaguer73882172019-09-02 16:39:42 +010013#include <boost/assert.hpp>
14
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010015#include <fstream>
Keith Davis3201eea2019-10-24 17:30:41 +010016#include <iostream>
Matteo Martincighab173e92019-09-05 12:02:04 +010017#include <limits>
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010018
Ferran Balaguer73882172019-09-02 16:39:42 +010019namespace armnn
20{
21
22namespace profiling
23{
24
Matteo Martincigh6db5f202019-09-05 12:02:04 +010025namespace
Matteo Martincighab173e92019-09-05 12:02:04 +010026{
Matteo Martincighab173e92019-09-05 12:02:04 +010027
Matteo Martincigh6db5f202019-09-05 12:02:04 +010028void ThrowIfCantGenerateNextUid(uint16_t uid, uint16_t cores = 0)
29{
Matteo Martincighab173e92019-09-05 12:02:04 +010030 // Check that it is possible to generate the next UID without causing an overflow
Matteo Martincigh6db5f202019-09-05 12:02:04 +010031 switch (cores)
Matteo Martincighab173e92019-09-05 12:02:04 +010032 {
Matteo Martincigh6db5f202019-09-05 12:02:04 +010033 case 0:
34 case 1:
35 // Number of cores not specified or set to 1 (a value of zero indicates the device is not capable of
36 // running multiple parallel workloads and will not provide multiple streams of data for each event)
37 if (uid == std::numeric_limits<uint16_t>::max())
38 {
39 throw RuntimeException("Generating the next UID for profiling would result in an overflow");
40 }
41 break;
42 default: // cores > 1
43 // Multiple cores available, as max_counter_uid has to be set to: counter_uid + cores - 1, the maximum
44 // allowed value for a counter UID is consequently: uint16_t_max - cores + 1
45 if (uid >= std::numeric_limits<uint16_t>::max() - cores + 1)
46 {
47 throw RuntimeException("Generating the next UID for profiling would result in an overflow");
48 }
49 break;
Matteo Martincighab173e92019-09-05 12:02:04 +010050 }
Matteo Martincigh6db5f202019-09-05 12:02:04 +010051}
Matteo Martincighab173e92019-09-05 12:02:04 +010052
Matteo Martincigh6db5f202019-09-05 12:02:04 +010053} // Anonymous namespace
54
55uint16_t GetNextUid(bool peekOnly)
56{
57 // The UID used for profiling objects and events. The first valid UID is 1, as 0 is a reserved value
58 static uint16_t uid = 1;
59
60 // Check that it is possible to generate the next UID without causing an overflow (throws in case of error)
61 ThrowIfCantGenerateNextUid(uid);
62
63 if (peekOnly)
64 {
65 // Peek only
66 return uid;
67 }
68 else
69 {
70 // Get the next UID
71 return uid++;
72 }
73}
74
75std::vector<uint16_t> GetNextCounterUids(uint16_t cores)
76{
77 // The UID used for counters only. The first valid UID is 0
78 static uint16_t counterUid = 0;
79
80 // Check that it is possible to generate the next counter UID without causing an overflow (throws in case of error)
81 ThrowIfCantGenerateNextUid(counterUid, cores);
82
83 // Get the next counter UIDs
84 size_t counterUidsSize = cores == 0 ? 1 : cores;
85 std::vector<uint16_t> counterUids(counterUidsSize, 0);
86 for (size_t i = 0; i < counterUidsSize; i++)
87 {
88 counterUids[i] = counterUid++;
89 }
90 return counterUids;
Matteo Martincighab173e92019-09-05 12:02:04 +010091}
92
Matteo Martincigh378bbfc2019-11-04 14:05:28 +000093void WriteBytes(const IPacketBufferPtr& packetBuffer, unsigned int offset, const void* value, unsigned int valueSize)
94{
95 BOOST_ASSERT(packetBuffer);
96
97 WriteBytes(packetBuffer->GetWritableData(), offset, value, valueSize);
98}
99
Keith Davis3201eea2019-10-24 17:30:41 +0100100uint32_t ConstructHeader(uint32_t packetFamily,
101 uint32_t packetId)
102{
103 return ((packetFamily & 0x3F) << 26)|
104 ((packetId & 0x3FF) << 16);
105}
106
107uint32_t ConstructHeader(uint32_t packetFamily,
108 uint32_t packetClass,
109 uint32_t packetType)
110{
111 return ((packetFamily & 0x3F) << 26)|
112 ((packetClass & 0x3FF) << 19)|
113 ((packetType & 0x3FFF) << 16);
114}
115
116void WriteUint64(const std::unique_ptr<IPacketBuffer>& packetBuffer, unsigned int offset, uint64_t value)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100117{
118 BOOST_ASSERT(packetBuffer);
119
120 WriteUint64(packetBuffer->GetWritableData(), offset, value);
121}
122
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000123void WriteUint32(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint32_t value)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100124{
125 BOOST_ASSERT(packetBuffer);
126
127 WriteUint32(packetBuffer->GetWritableData(), offset, value);
128}
129
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000130void WriteUint16(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint16_t value)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100131{
132 BOOST_ASSERT(packetBuffer);
133
134 WriteUint16(packetBuffer->GetWritableData(), offset, value);
135}
136
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000137void WriteUint8(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint8_t value)
138{
139 BOOST_ASSERT(packetBuffer);
140
141 WriteUint8(packetBuffer->GetWritableData(), offset, value);
142}
143
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000144void WriteBytes(unsigned char* buffer, unsigned int offset, const void* value, unsigned int valueSize)
145{
146 BOOST_ASSERT(buffer);
147 BOOST_ASSERT(value);
148
149 for (unsigned int i = 0; i < valueSize; i++, offset++)
150 {
151 buffer[offset] = *(reinterpret_cast<const unsigned char*>(value) + i);
152 }
153}
154
Francis Murtagh3a161982019-09-04 15:25:02 +0100155void WriteUint64(unsigned char* buffer, unsigned int offset, uint64_t value)
156{
157 BOOST_ASSERT(buffer);
158
159 buffer[offset] = static_cast<unsigned char>(value & 0xFF);
160 buffer[offset + 1] = static_cast<unsigned char>((value >> 8) & 0xFF);
161 buffer[offset + 2] = static_cast<unsigned char>((value >> 16) & 0xFF);
162 buffer[offset + 3] = static_cast<unsigned char>((value >> 24) & 0xFF);
163 buffer[offset + 4] = static_cast<unsigned char>((value >> 32) & 0xFF);
164 buffer[offset + 5] = static_cast<unsigned char>((value >> 40) & 0xFF);
165 buffer[offset + 6] = static_cast<unsigned char>((value >> 48) & 0xFF);
166 buffer[offset + 7] = static_cast<unsigned char>((value >> 56) & 0xFF);
167}
168
Ferran Balaguer73882172019-09-02 16:39:42 +0100169void WriteUint32(unsigned char* buffer, unsigned int offset, uint32_t value)
170{
171 BOOST_ASSERT(buffer);
172
Matteo Martincigh149528e2019-09-05 12:02:04 +0100173 buffer[offset] = static_cast<unsigned char>(value & 0xFF);
Ferran Balaguer73882172019-09-02 16:39:42 +0100174 buffer[offset + 1] = static_cast<unsigned char>((value >> 8) & 0xFF);
175 buffer[offset + 2] = static_cast<unsigned char>((value >> 16) & 0xFF);
176 buffer[offset + 3] = static_cast<unsigned char>((value >> 24) & 0xFF);
177}
178
179void WriteUint16(unsigned char* buffer, unsigned int offset, uint16_t value)
180{
Matteo Martincigh149528e2019-09-05 12:02:04 +0100181 BOOST_ASSERT(buffer);
Ferran Balaguer73882172019-09-02 16:39:42 +0100182
Matteo Martincigh149528e2019-09-05 12:02:04 +0100183 buffer[offset] = static_cast<unsigned char>(value & 0xFF);
Ferran Balaguer73882172019-09-02 16:39:42 +0100184 buffer[offset + 1] = static_cast<unsigned char>((value >> 8) & 0xFF);
185}
186
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000187void WriteUint8(unsigned char* buffer, unsigned int offset, uint8_t value)
188{
189 BOOST_ASSERT(buffer);
190
191 buffer[offset] = static_cast<unsigned char>(value);
192}
193
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000194void ReadBytes(const IPacketBufferPtr& packetBuffer, unsigned int offset, unsigned int valueSize, uint8_t outValue[])
195{
196 BOOST_ASSERT(packetBuffer);
197
198 ReadBytes(packetBuffer->GetReadableData(), offset, valueSize, outValue);
199}
200
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000201uint64_t ReadUint64(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100202{
203 BOOST_ASSERT(packetBuffer);
204
205 return ReadUint64(packetBuffer->GetReadableData(), offset);
206}
207
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000208uint32_t ReadUint32(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100209{
210 BOOST_ASSERT(packetBuffer);
211
212 return ReadUint32(packetBuffer->GetReadableData(), offset);
213}
214
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000215uint16_t ReadUint16(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100216{
217 BOOST_ASSERT(packetBuffer);
218
219 return ReadUint16(packetBuffer->GetReadableData(), offset);
220}
221
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000222uint8_t ReadUint8(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100223{
224 BOOST_ASSERT(packetBuffer);
225
226 return ReadUint8(packetBuffer->GetReadableData(), offset);
227}
228
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000229void ReadBytes(const unsigned char* buffer, unsigned int offset, unsigned int valueSize, uint8_t outValue[])
230{
231 BOOST_ASSERT(buffer);
232 BOOST_ASSERT(outValue);
233
234 for (unsigned int i = 0; i < valueSize; i++, offset++)
235 {
236 outValue[i] = static_cast<uint8_t>(buffer[offset]);
237 }
238}
239
Francis Murtagh3a161982019-09-04 15:25:02 +0100240uint64_t ReadUint64(const unsigned char* buffer, unsigned int offset)
241{
242 BOOST_ASSERT(buffer);
243
244 uint64_t value = 0;
Matteo Martincighab173e92019-09-05 12:02:04 +0100245 value = static_cast<uint64_t>(buffer[offset]);
Francis Murtagh3a161982019-09-04 15:25:02 +0100246 value |= static_cast<uint64_t>(buffer[offset + 1]) << 8;
247 value |= static_cast<uint64_t>(buffer[offset + 2]) << 16;
248 value |= static_cast<uint64_t>(buffer[offset + 3]) << 24;
249 value |= static_cast<uint64_t>(buffer[offset + 4]) << 32;
250 value |= static_cast<uint64_t>(buffer[offset + 5]) << 40;
251 value |= static_cast<uint64_t>(buffer[offset + 6]) << 48;
252 value |= static_cast<uint64_t>(buffer[offset + 7]) << 56;
253
254 return value;
255}
256
Ferran Balaguer73882172019-09-02 16:39:42 +0100257uint32_t ReadUint32(const unsigned char* buffer, unsigned int offset)
258{
259 BOOST_ASSERT(buffer);
260
261 uint32_t value = 0;
Matteo Martincigh149528e2019-09-05 12:02:04 +0100262 value = static_cast<uint32_t>(buffer[offset]);
Ferran Balaguer73882172019-09-02 16:39:42 +0100263 value |= static_cast<uint32_t>(buffer[offset + 1]) << 8;
264 value |= static_cast<uint32_t>(buffer[offset + 2]) << 16;
265 value |= static_cast<uint32_t>(buffer[offset + 3]) << 24;
266 return value;
267}
268
269uint16_t ReadUint16(const unsigned char* buffer, unsigned int offset)
270{
271 BOOST_ASSERT(buffer);
272
273 uint32_t value = 0;
Matteo Martincigh149528e2019-09-05 12:02:04 +0100274 value = static_cast<uint32_t>(buffer[offset]);
Ferran Balaguer73882172019-09-02 16:39:42 +0100275 value |= static_cast<uint32_t>(buffer[offset + 1]) << 8;
276 return static_cast<uint16_t>(value);
277}
278
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100279uint8_t ReadUint8(const unsigned char* buffer, unsigned int offset)
280{
281 BOOST_ASSERT(buffer);
282
283 return buffer[offset];
284}
285
Ferran Balaguer47d0fe92019-09-04 16:47:34 +0100286std::string GetSoftwareInfo()
287{
288 return std::string("ArmNN");
289}
290
291std::string GetHardwareVersion()
292{
293 return std::string();
294}
295
296std::string GetSoftwareVersion()
297{
298 std::string armnnVersion(ARMNN_VERSION);
299 std::string result = "Armnn " + armnnVersion.substr(2,2) + "." + armnnVersion.substr(4,2);
300 return result;
301}
302
303std::string GetProcessName()
304{
305 std::ifstream comm("/proc/self/comm");
306 std::string name;
307 getline(comm, name);
308 return name;
309}
310
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000311// Calculate the actual length an SwString will be including the terminating null character
312// padding to bring it to the next uint32_t boundary but minus the leading uint32_t encoding
313// the size to allow the offset to be correctly updated when decoding a binary packet.
314uint32_t CalculateSizeOfPaddedSwString(const std::string& str)
315{
316 std::vector<uint32_t> swTraceString;
317 StringToSwTraceString<SwTraceCharPolicy>(str, swTraceString);
318 unsigned int uint32_t_size = sizeof(uint32_t);
319 uint32_t size = (boost::numeric_cast<uint32_t>(swTraceString.size()) - 1) * uint32_t_size;
320 return size;
321}
322
323// Read TimelineMessageDirectoryPacket from given IPacketBuffer and offset
324SwTraceMessage ReadSwTraceMessage(const unsigned char* packetBuffer, unsigned int& offset)
325{
326 BOOST_ASSERT(packetBuffer);
327
328 unsigned int uint32_t_size = sizeof(uint32_t);
329
330 SwTraceMessage swTraceMessage;
331
332 // Read the decl_id
333 uint32_t readDeclId = ReadUint32(packetBuffer, offset);
334 swTraceMessage.m_Id = readDeclId;
335
336 // SWTrace "namestring" format
337 // length of the string (first 4 bytes) + string + null terminator
338
339 // Check the decl_name
340 offset += uint32_t_size;
341 uint32_t swTraceDeclNameLength = ReadUint32(packetBuffer, offset);
342
343 offset += uint32_t_size;
344 std::vector<unsigned char> swTraceStringBuffer(swTraceDeclNameLength - 1);
345 std::memcpy(swTraceStringBuffer.data(),
346 packetBuffer + offset, swTraceStringBuffer.size());
347
348 swTraceMessage.m_Name.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // name
349
350 // Check the ui_name
351 offset += CalculateSizeOfPaddedSwString(swTraceMessage.m_Name);
352 uint32_t swTraceUINameLength = ReadUint32(packetBuffer, offset);
353
354 offset += uint32_t_size;
355 swTraceStringBuffer.resize(swTraceUINameLength - 1);
356 std::memcpy(swTraceStringBuffer.data(),
357 packetBuffer + offset, swTraceStringBuffer.size());
358
359 swTraceMessage.m_UiName.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // ui_name
360
361 // Check arg_types
362 offset += CalculateSizeOfPaddedSwString(swTraceMessage.m_UiName);
363 uint32_t swTraceArgTypesLength = ReadUint32(packetBuffer, offset);
364
365 offset += uint32_t_size;
366 swTraceStringBuffer.resize(swTraceArgTypesLength - 1);
367 std::memcpy(swTraceStringBuffer.data(),
368 packetBuffer + offset, swTraceStringBuffer.size());
369
370 swTraceMessage.m_ArgTypes.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // arg_types
371
372 std::string swTraceString(swTraceStringBuffer.begin(), swTraceStringBuffer.end());
373
374 // Check arg_names
375 offset += CalculateSizeOfPaddedSwString(swTraceString);
376 uint32_t swTraceArgNamesLength = ReadUint32(packetBuffer, offset);
377
378 offset += uint32_t_size;
379 swTraceStringBuffer.resize(swTraceArgNamesLength - 1);
380 std::memcpy(swTraceStringBuffer.data(),
381 packetBuffer + offset, swTraceStringBuffer.size());
382
383 swTraceString.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end());
384 std::stringstream stringStream(swTraceString);
385 std::string argName;
386 while (std::getline(stringStream, argName, ','))
387 {
388 swTraceMessage.m_ArgNames.push_back(argName);
389 }
390
391 offset += CalculateSizeOfPaddedSwString(swTraceString);
392
393 return swTraceMessage;
394}
395
Jan Eilers92fa15b2019-10-15 15:23:25 +0100396/// Creates a timeline packet header
397///
398/// \params
399/// packetFamiliy Timeline Packet Family
400/// packetClass Timeline Packet Class
401/// packetType Timeline Packet Type
402/// streamId Stream identifier
403/// seqeunceNumbered When non-zero the 4 bytes following the header is a u32 sequence number
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100404/// dataLength Unsigned 24-bit integer. Length of data, in bytes. Zero is permitted
Jan Eilers92fa15b2019-10-15 15:23:25 +0100405///
406/// \returns
407/// Pair of uint32_t containing word0 and word1 of the header
408std::pair<uint32_t, uint32_t> CreateTimelinePacketHeader(uint32_t packetFamily,
409 uint32_t packetClass,
410 uint32_t packetType,
411 uint32_t streamId,
412 uint32_t sequenceNumbered,
413 uint32_t dataLength)
414{
415 // Packet header word 0:
416 // 26:31 [6] packet_family: timeline Packet Family, value 0b000001
417 // 19:25 [7] packet_class: packet class
418 // 16:18 [3] packet_type: packet type
419 // 8:15 [8] reserved: all zeros
420 // 0:7 [8] stream_id: stream identifier
421 uint32_t packetHeaderWord0 = ((packetFamily & 0x0000003F) << 26) |
422 ((packetClass & 0x0000007F) << 19) |
423 ((packetType & 0x00000007) << 16) |
424 ((streamId & 0x00000007) << 0);
425
426 // Packet header word 1:
427 // 25:31 [7] reserved: all zeros
428 // 24 [1] sequence_numbered: when non-zero the 4 bytes following the header is a u32 sequence number
429 // 0:23 [24] data_length: unsigned 24-bit integer. Length of data, in bytes. Zero is permitted
430 uint32_t packetHeaderWord1 = ((sequenceNumbered & 0x00000001) << 24) |
431 ((dataLength & 0x00FFFFFF) << 0);
432
433 return std::make_pair(packetHeaderWord0, packetHeaderWord1);
434}
435
436/// Creates a packet header for the timeline messages:
437/// * declareLabel
438/// * declareEntity
439/// * declareEventClass
440/// * declareRelationship
441/// * declareEvent
442///
443/// \param
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100444/// dataLength The length of the message body in bytes
Jan Eilers92fa15b2019-10-15 15:23:25 +0100445///
446/// \returns
447/// Pair of uint32_t containing word0 and word1 of the header
448std::pair<uint32_t, uint32_t> CreateTimelineMessagePacketHeader(unsigned int dataLength)
449{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100450 return CreateTimelinePacketHeader(1, // Packet family
451 0, // Packet class
452 1, // Packet type
453 0, // Stream id
454 0, // Sequence number
455 dataLength); // Data length
Jan Eilers92fa15b2019-10-15 15:23:25 +0100456}
457
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100458TimelinePacketStatus WriteTimelineLabelBinaryPacket(uint64_t profilingGuid,
459 const std::string& label,
460 unsigned char* buffer,
461 unsigned int bufferSize,
462 unsigned int& numberOfBytesWritten)
463{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100464 // Initialize the output value
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100465 numberOfBytesWritten = 0;
466
467 // Check that the given buffer is valid
468 if (buffer == nullptr || bufferSize == 0)
469 {
470 return TimelinePacketStatus::BufferExhaustion;
471 }
472
473 // Utils
474 unsigned int uint32_t_size = sizeof(uint32_t);
475 unsigned int uint64_t_size = sizeof(uint64_t);
476
477 // Convert the label into a SWTrace string
478 std::vector<uint32_t> swTraceLabel;
479 bool result = StringToSwTraceString<SwTraceCharPolicy>(label, swTraceLabel);
480 if (!result)
481 {
482 return TimelinePacketStatus::Error;
483 }
484
485 // Calculate the size of the SWTrace string label (in bytes)
486 unsigned int swTraceLabelSize = boost::numeric_cast<unsigned int>(swTraceLabel.size()) * uint32_t_size;
487
488 // Calculate the length of the data (in bytes)
Jan Eilersb884ea42019-10-16 09:54:15 +0100489 unsigned int timelineLabelPacketDataLength = uint32_t_size + // decl_Id
490 uint64_t_size + // Profiling GUID
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100491 swTraceLabelSize; // Label
492
493 // Calculate the timeline binary packet size (in bytes)
494 unsigned int timelineLabelPacketSize = 2 * uint32_t_size + // Header (2 words)
Jan Eilersb884ea42019-10-16 09:54:15 +0100495 timelineLabelPacketDataLength; // decl_Id + Profiling GUID + label
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100496
497 // Check whether the timeline binary packet fits in the given buffer
498 if (timelineLabelPacketSize > bufferSize)
499 {
500 return TimelinePacketStatus::BufferExhaustion;
501 }
502
Jan Eilersb884ea42019-10-16 09:54:15 +0100503 // Create packet header
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100504 std::pair<uint32_t, uint32_t> packetHeader = CreateTimelineMessagePacketHeader(timelineLabelPacketDataLength);
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100505
506 // Initialize the offset for writing in the buffer
507 unsigned int offset = 0;
508
509 // Write the timeline binary packet header to the buffer
Jan Eilersb884ea42019-10-16 09:54:15 +0100510 WriteUint32(buffer, offset, packetHeader.first);
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100511 offset += uint32_t_size;
Jan Eilersb884ea42019-10-16 09:54:15 +0100512 WriteUint32(buffer, offset, packetHeader.second);
513 offset += uint32_t_size;
514
515 // Write decl_Id to the buffer
516 WriteUint32(buffer, offset, 0u);
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100517 offset += uint32_t_size;
518
519 // Write the timeline binary packet payload to the buffer
520 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
521 offset += uint64_t_size;
522 for (uint32_t swTraceLabelWord : swTraceLabel)
523 {
524 WriteUint32(buffer, offset, swTraceLabelWord); // Label
525 offset += uint32_t_size;
526 }
527
528 // Update the number of bytes written
529 numberOfBytesWritten = timelineLabelPacketSize;
530
531 return TimelinePacketStatus::Ok;
532}
533
David Monahanf21f6062019-10-07 15:11:15 +0100534TimelinePacketStatus WriteTimelineEntityBinaryPacket(uint64_t profilingGuid,
535 unsigned char* buffer,
536 unsigned int bufferSize,
537 unsigned int& numberOfBytesWritten)
538{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100539 // Initialize the output value
David Monahanf21f6062019-10-07 15:11:15 +0100540 numberOfBytesWritten = 0;
541
542 // Check that the given buffer is valid
543 if (buffer == nullptr || bufferSize == 0)
544 {
545 return TimelinePacketStatus::BufferExhaustion;
546 }
547
548 // Utils
549 unsigned int uint32_t_size = sizeof(uint32_t);
550 unsigned int uint64_t_size = sizeof(uint64_t);
551
552 // Calculate the length of the data (in bytes)
Finn Williamse63a0262019-10-22 10:30:49 +0100553 unsigned int timelineEntityPacketDataLength = uint32_t_size + uint64_t_size; // decl_id + Profiling GUID
David Monahanf21f6062019-10-07 15:11:15 +0100554
555
556 // Calculate the timeline binary packet size (in bytes)
557 unsigned int timelineEntityPacketSize = 2 * uint32_t_size + // Header (2 words)
Jan Eilersb884ea42019-10-16 09:54:15 +0100558 timelineEntityPacketDataLength; // Profiling GUID
David Monahanf21f6062019-10-07 15:11:15 +0100559
560 // Check whether the timeline binary packet fits in the given buffer
561 if (timelineEntityPacketSize > bufferSize)
562 {
563 return TimelinePacketStatus::BufferExhaustion;
564 }
565
Jan Eilersb884ea42019-10-16 09:54:15 +0100566 // Create packet header
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100567 std::pair<uint32_t, uint32_t> packetHeader = CreateTimelineMessagePacketHeader(timelineEntityPacketDataLength);
David Monahanf21f6062019-10-07 15:11:15 +0100568
569 // Initialize the offset for writing in the buffer
570 unsigned int offset = 0;
571
572 // Write the timeline binary packet header to the buffer
Jan Eilersb884ea42019-10-16 09:54:15 +0100573 WriteUint32(buffer, offset, packetHeader.first);
David Monahanf21f6062019-10-07 15:11:15 +0100574 offset += uint32_t_size;
Jan Eilersb884ea42019-10-16 09:54:15 +0100575 WriteUint32(buffer, offset, packetHeader.second);
576 offset += uint32_t_size;
577
578 // Write the decl_Id to the buffer
579 WriteUint32(buffer, offset, 1u);
David Monahanf21f6062019-10-07 15:11:15 +0100580 offset += uint32_t_size;
581
582 // Write the timeline binary packet payload to the buffer
583 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
584
585 // Update the number of bytes written
586 numberOfBytesWritten = timelineEntityPacketSize;
587
588 return TimelinePacketStatus::Ok;
589}
590
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100591TimelinePacketStatus WriteTimelineRelationshipBinaryPacket(ProfilingRelationshipType relationshipType,
592 uint64_t relationshipGuid,
593 uint64_t headGuid,
594 uint64_t tailGuid,
595 unsigned char* buffer,
596 unsigned int bufferSize,
597 unsigned int& numberOfBytesWritten)
598{
599 // Initialize the output value
600 numberOfBytesWritten = 0;
601
602 // Check that the given buffer is valid
603 if (buffer == nullptr || bufferSize == 0)
604 {
605 return TimelinePacketStatus::BufferExhaustion;
606 }
607
608 // Utils
609 unsigned int uint32_t_size = sizeof(uint32_t);
610 unsigned int uint64_t_size = sizeof(uint64_t);
611
612 // Calculate the length of the data (in bytes)
613 unsigned int timelineRelationshipPacketDataLength = uint32_t_size * 2 + // decl_id + Relationship Type
614 uint64_t_size * 3; // Relationship GUID + Head GUID + tail GUID
615
616 // Calculate the timeline binary packet size (in bytes)
617 unsigned int timelineRelationshipPacketSize = 2 * uint32_t_size + // Header (2 words)
618 timelineRelationshipPacketDataLength;
619
620 // Check whether the timeline binary packet fits in the given buffer
621 if (timelineRelationshipPacketSize > bufferSize)
622 {
623 return TimelinePacketStatus::BufferExhaustion;
624 }
625
626 // Create packet header
627 uint32_t dataLength = boost::numeric_cast<uint32_t>(timelineRelationshipPacketDataLength);
628 std::pair<uint32_t, uint32_t> packetHeader = CreateTimelineMessagePacketHeader(dataLength);
629
630 // Initialize the offset for writing in the buffer
631 unsigned int offset = 0;
632
633 // Write the timeline binary packet header to the buffer
634 WriteUint32(buffer, offset, packetHeader.first);
635 offset += uint32_t_size;
636 WriteUint32(buffer, offset, packetHeader.second);
637 offset += uint32_t_size;
638
639 uint32_t relationshipTypeUint = 0;
640
641 switch (relationshipType)
642 {
643 case ProfilingRelationshipType::RetentionLink:
644 relationshipTypeUint = 0;
645 break;
646 case ProfilingRelationshipType::ExecutionLink:
647 relationshipTypeUint = 1;
648 break;
649 case ProfilingRelationshipType::DataLink:
650 relationshipTypeUint = 2;
651 break;
652 case ProfilingRelationshipType::LabelLink:
653 relationshipTypeUint = 3;
654 break;
655 default:
656 throw InvalidArgumentException("Unknown relationship type given.");
657 }
658
659 // Write the timeline binary packet payload to the buffer
660 // decl_id of the timeline message
661 uint32_t declId = 3;
662 WriteUint32(buffer, offset, declId); // decl_id
663 offset += uint32_t_size;
664 WriteUint32(buffer, offset, relationshipTypeUint); // Relationship Type
665 offset += uint32_t_size;
666 WriteUint64(buffer, offset, relationshipGuid); // GUID of this relationship
667 offset += uint64_t_size;
668 WriteUint64(buffer, offset, headGuid); // head of relationship GUID
669 offset += uint64_t_size;
670 WriteUint64(buffer, offset, tailGuid); // tail of relationship GUID
671
672 // Update the number of bytes written
673 numberOfBytesWritten = timelineRelationshipPacketSize;
674
675 return TimelinePacketStatus::Ok;
676}
677
Sadik Armagan784db772019-10-08 15:05:38 +0100678TimelinePacketStatus WriteTimelineMessageDirectoryPackage(unsigned char* buffer,
679 unsigned int bufferSize,
680 unsigned int& numberOfBytesWritten)
681{
682 // Initialize the output value
683 numberOfBytesWritten = 0;
684
685 // Check that the given buffer is valid
686 if (buffer == nullptr || bufferSize == 0)
687 {
688 return TimelinePacketStatus::BufferExhaustion;
689 }
690
691 // Utils
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000692 unsigned int uint8_t_size = sizeof(uint8_t);
Sadik Armagan784db772019-10-08 15:05:38 +0100693 unsigned int uint32_t_size = sizeof(uint32_t);
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000694 unsigned int uint64_t_size = sizeof(uint64_t);
695 unsigned int threadId_size = sizeof(std::thread::id);
Sadik Armagan784db772019-10-08 15:05:38 +0100696
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100697 // The payload/data of the packet consists of swtrace event definitions encoded according
Sadik Armagan784db772019-10-08 15:05:38 +0100698 // to the swtrace directory specification. The messages being the five defined below:
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000699 //
700 // | decl_id | decl_name | ui_name | arg_types | arg_names |
Sadik Armagan784db772019-10-08 15:05:38 +0100701 // |-----------|---------------------|-----------------------|-------------|-------------------------------------|
702 // | 0 | declareLabel | declare label | ps | guid,value |
703 // | 1 | declareEntity | declare entity | p | guid |
704 // | 2 | declareEventClass | declare event class | p | guid |
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100705 // | 3 | declareRelationship | declare relationship | Ippp | relationshipType,relationshipGuid, |
706 // | | | | | headGuid,tailGuid |
Sadik Armagan784db772019-10-08 15:05:38 +0100707 // | 4 | declareEvent | declare event | @tp | timestamp,threadId,eventGuid |
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100708 std::vector<std::vector<std::string>> timelineDirectoryMessages
709 {
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000710 { "0", "declareLabel", "declare label", "ps", "guid,value" },
711 { "1", "declareEntity", "declare entity", "p", "guid" },
712 { "2", "declareEventClass", "declare event class", "p", "guid" },
713 { "3", "declareRelationship", "declare relationship", "Ippp",
714 "relationshipType,relationshipGuid,headGuid,tailGuid" },
715 { "4", "declareEvent", "declare event", "@tp", "timestamp,threadId,eventGuid" }
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100716 };
Sadik Armagan784db772019-10-08 15:05:38 +0100717
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000718 // Build the message declarations
719 std::vector<uint32_t> swTraceBuffer;
720 for (const auto& directoryComponent : timelineDirectoryMessages)
Sadik Armagan784db772019-10-08 15:05:38 +0100721 {
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000722 // decl_id
723 uint32_t declId = 0;
724 try
Sadik Armagan784db772019-10-08 15:05:38 +0100725 {
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000726 declId = boost::numeric_cast<uint32_t>(std::stoul(directoryComponent[0]));
Sadik Armagan784db772019-10-08 15:05:38 +0100727 }
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000728 catch (const std::exception&)
729 {
730 return TimelinePacketStatus::Error;
731 }
732 swTraceBuffer.push_back(declId);
733
734 bool result = true;
735 result &= ConvertDirectoryComponent<SwTraceNameCharPolicy>(directoryComponent[1], swTraceBuffer); // decl_name
736 result &= ConvertDirectoryComponent<SwTraceCharPolicy> (directoryComponent[2], swTraceBuffer); // ui_name
737 result &= ConvertDirectoryComponent<SwTraceTypeCharPolicy>(directoryComponent[3], swTraceBuffer); // arg_types
738 result &= ConvertDirectoryComponent<SwTraceCharPolicy> (directoryComponent[4], swTraceBuffer); // arg_names
739 if (!result)
740 {
741 return TimelinePacketStatus::Error;
742 }
Sadik Armagan784db772019-10-08 15:05:38 +0100743 }
744
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000745 unsigned int dataLength = 3 * uint8_t_size + // Stream header (3 bytes)
746 boost::numeric_cast<unsigned int>(swTraceBuffer.size()) *
747 uint32_t_size; // Trace directory (5 messages)
748
Sadik Armagan784db772019-10-08 15:05:38 +0100749 // Calculate the timeline directory binary packet size (in bytes)
750 unsigned int timelineDirectoryPacketSize = 2 * uint32_t_size + // Header (2 words)
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000751 dataLength; // Payload
Sadik Armagan784db772019-10-08 15:05:38 +0100752
753 // Check whether the timeline directory binary packet fits in the given buffer
754 if (timelineDirectoryPacketSize > bufferSize)
755 {
756 return TimelinePacketStatus::BufferExhaustion;
757 }
758
Jan Eilersb884ea42019-10-16 09:54:15 +0100759 // Create packet header
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000760 auto packetHeader = CreateTimelinePacketHeader(1, 0, 0, 0, 0, boost::numeric_cast<uint32_t>(dataLength));
Sadik Armagan784db772019-10-08 15:05:38 +0100761
762 // Initialize the offset for writing in the buffer
763 unsigned int offset = 0;
764
765 // Write the timeline binary packet header to the buffer
Jan Eilersb884ea42019-10-16 09:54:15 +0100766 WriteUint32(buffer, offset, packetHeader.first);
Sadik Armagan784db772019-10-08 15:05:38 +0100767 offset += uint32_t_size;
Jan Eilersb884ea42019-10-16 09:54:15 +0100768 WriteUint32(buffer, offset, packetHeader.second);
Sadik Armagan784db772019-10-08 15:05:38 +0100769 offset += uint32_t_size;
770
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000771 // Write the stream header
772 uint8_t streamVersion = 4;
773 uint8_t pointerBytes = boost::numeric_cast<uint8_t>(uint64_t_size); // All GUIDs are uint64_t
774 uint8_t threadIdBytes = boost::numeric_cast<uint8_t>(threadId_size);
775 switch (threadIdBytes)
Sadik Armagan784db772019-10-08 15:05:38 +0100776 {
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000777 case 4: // Typically Windows and Android
778 case 8: // Typically Linux
779 break; // Valid values
780 default:
781 return TimelinePacketStatus::Error; // Invalid value
782 }
783 WriteUint8(buffer, offset, streamVersion);
784 offset += uint8_t_size;
785 WriteUint8(buffer, offset, pointerBytes);
786 offset += uint8_t_size;
787 WriteUint8(buffer, offset, threadIdBytes);
788 offset += uint8_t_size;
Sadik Armagan784db772019-10-08 15:05:38 +0100789
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000790 // Write the SWTrace directory
791 uint32_t numberOfDeclarations = boost::numeric_cast<uint32_t>(timelineDirectoryMessages.size());
792 WriteUint32(buffer, offset, numberOfDeclarations); // Number of declarations
793 offset += uint32_t_size;
794 for (uint32_t i : swTraceBuffer)
795 {
796 WriteUint32(buffer, offset, i); // Message declarations
797 offset += uint32_t_size;
Sadik Armagan784db772019-10-08 15:05:38 +0100798 }
799
800 // Update the number of bytes written
801 numberOfBytesWritten = timelineDirectoryPacketSize;
802
803 return TimelinePacketStatus::Ok;
804}
805
Jan Eilers92fa15b2019-10-15 15:23:25 +0100806TimelinePacketStatus WriteTimelineEventClassBinaryPacket(uint64_t profilingGuid,
807 unsigned char* buffer,
808 unsigned int bufferSize,
809 unsigned int& numberOfBytesWritten)
810{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100811 // Initialize the output value
Jan Eilers92fa15b2019-10-15 15:23:25 +0100812 numberOfBytesWritten = 0;
813
814 // Check that the given buffer is valid
815 if (buffer == nullptr || bufferSize == 0)
816 {
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);
823
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100824 // decl_id of the timeline message
825 uint32_t declId = 2;
Jan Eilers92fa15b2019-10-15 15:23:25 +0100826
827 // Calculate the length of the data (in bytes)
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100828 unsigned int packetBodySize = uint32_t_size + uint64_t_size; // decl_id + Profiling GUID
Jan Eilers92fa15b2019-10-15 15:23:25 +0100829
830 // Calculate the timeline binary packet size (in bytes)
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100831 unsigned int packetSize = 2 * uint32_t_size + // Header (2 words)
832 packetBodySize; // Body
Jan Eilers92fa15b2019-10-15 15:23:25 +0100833
834 // Check whether the timeline binary packet fits in the given buffer
835 if (packetSize > bufferSize)
836 {
837 return TimelinePacketStatus::BufferExhaustion;
838 }
839
840 // Create packet header
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100841 std::pair<uint32_t, uint32_t> packetHeader = CreateTimelineMessagePacketHeader(packetBodySize);
Jan Eilers92fa15b2019-10-15 15:23:25 +0100842
843 // Initialize the offset for writing in the buffer
844 unsigned int offset = 0;
845
846 // Write the timeline binary packet header to the buffer
847 WriteUint32(buffer, offset, packetHeader.first);
848 offset += uint32_t_size;
849 WriteUint32(buffer, offset, packetHeader.second);
850 offset += uint32_t_size;
851
852 // Write the timeline binary packet payload to the buffer
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100853 WriteUint32(buffer, offset, declId); // decl_id
Jan Eilers92fa15b2019-10-15 15:23:25 +0100854 offset += uint32_t_size;
855 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
856
857 // Update the number of bytes written
858 numberOfBytesWritten = packetSize;
859
860 return TimelinePacketStatus::Ok;
861}
862
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100863TimelinePacketStatus WriteTimelineEventBinaryPacket(uint64_t timestamp,
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000864 std::thread::id threadId,
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100865 uint64_t profilingGuid,
866 unsigned char* buffer,
867 unsigned int bufferSize,
868 unsigned int& numberOfBytesWritten)
869{
870 // Initialize the output value
871 numberOfBytesWritten = 0;
872
873 // Check that the given buffer is valid
874 if (buffer == nullptr || bufferSize == 0)
875 {
876 return TimelinePacketStatus::BufferExhaustion;
877 }
878
879 // Utils
880 unsigned int uint32_t_size = sizeof(uint32_t);
881 unsigned int uint64_t_size = sizeof(uint64_t);
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000882 unsigned int threadId_size = sizeof(std::thread::id);
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100883
884 // decl_id of the timeline message
885 uint32_t declId = 4;
886
887 // Calculate the length of the data (in bytes)
888 unsigned int timelineEventPacketDataLength = uint32_t_size + // decl_id
889 uint64_t_size + // Timestamp
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000890 threadId_size + // Thread id
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100891 uint64_t_size; // Profiling GUID
892
893 // Calculate the timeline binary packet size (in bytes)
894 unsigned int timelineEventPacketSize = 2 * uint32_t_size + // Header (2 words)
895 timelineEventPacketDataLength; // Timestamp + thread id + profiling GUID
896
897 // Check whether the timeline binary packet fits in the given buffer
898 if (timelineEventPacketSize > bufferSize)
899 {
900 return TimelinePacketStatus::BufferExhaustion;
901 }
902
903 // Create packet header
904 std::pair<uint32_t, uint32_t> packetHeader = CreateTimelineMessagePacketHeader(timelineEventPacketDataLength);
905
906 // Initialize the offset for writing in the buffer
907 unsigned int offset = 0;
908
909 // Write the timeline binary packet header to the buffer
910 WriteUint32(buffer, offset, packetHeader.first);
911 offset += uint32_t_size;
912 WriteUint32(buffer, offset, packetHeader.second);
913 offset += uint32_t_size;
914
915 // Write the timeline binary packet payload to the buffer
916 WriteUint32(buffer, offset, declId); // decl_id
917 offset += uint32_t_size;
918 WriteUint64(buffer, offset, timestamp); // Timestamp
919 offset += uint64_t_size;
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000920 WriteBytes(buffer, offset, &threadId, threadId_size); // Thread id
921 offset += threadId_size;
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100922 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
923 offset += uint64_t_size;
924
925 // Update the number of bytes written
926 numberOfBytesWritten = timelineEventPacketSize;
927
928 return TimelinePacketStatus::Ok;
929}
930
Keith Davis3201eea2019-10-24 17:30:41 +0100931std::string CentreAlignFormatting(const std::string& stringToPass, const int spacingWidth)
932{
933 std::stringstream outputStream, centrePadding;
934 int padding = spacingWidth - static_cast<int>(stringToPass.size());
935
936 for (int i = 0; i < padding / 2; ++i)
937 {
938 centrePadding << " ";
939 }
940
941 outputStream << centrePadding.str() << stringToPass << centrePadding.str();
942
943 if (padding > 0 && padding %2 != 0)
944 {
945 outputStream << " ";
946 }
947
948 return outputStream.str();
949}
950
951void PrintDeviceDetails(const std::pair<const unsigned short, std::unique_ptr<Device>>& devicePair)
952{
953 std::string body;
954
955 body.append(CentreAlignFormatting(devicePair.second->m_Name, 20));
956 body.append(" | ");
957 body.append(CentreAlignFormatting(std::to_string(devicePair.first), 13));
958 body.append(" | ");
959 body.append(CentreAlignFormatting(std::to_string(devicePair.second->m_Cores), 10));
960 body.append("\n");
961
962 std::cout << std::string(body.size(), '-') << "\n";
963 std::cout<< body;
964}
965
966void PrintCounterSetDetails(const std::pair<const unsigned short, std::unique_ptr<CounterSet>>& counterSetPair)
967{
968 std::string body;
969
970 body.append(CentreAlignFormatting(counterSetPair.second->m_Name, 20));
971 body.append(" | ");
972 body.append(CentreAlignFormatting(std::to_string(counterSetPair.first), 13));
973 body.append(" | ");
974 body.append(CentreAlignFormatting(std::to_string(counterSetPair.second->m_Count), 10));
975 body.append("\n");
976
977 std::cout << std::string(body.size(), '-') << "\n";
978
979 std::cout<< body;
980}
981
982void PrintCounterDetails(std::shared_ptr<Counter>& counter)
983{
984 std::string body;
985
986 body.append(CentreAlignFormatting(counter->m_Name, 20));
987 body.append(" | ");
988 body.append(CentreAlignFormatting(counter->m_Description, 50));
989 body.append(" | ");
990 body.append(CentreAlignFormatting(counter->m_Units, 14));
991 body.append(" | ");
992 body.append(CentreAlignFormatting(std::to_string(counter->m_Uid), 6));
993 body.append(" | ");
994 body.append(CentreAlignFormatting(std::to_string(counter->m_MaxCounterUid), 10));
995 body.append(" | ");
996 body.append(CentreAlignFormatting(std::to_string(counter->m_Class), 8));
997 body.append(" | ");
998 body.append(CentreAlignFormatting(std::to_string(counter->m_Interpolation), 14));
999 body.append(" | ");
1000 body.append(CentreAlignFormatting(std::to_string(counter->m_Multiplier), 20));
1001 body.append(" | ");
1002 body.append(CentreAlignFormatting(std::to_string(counter->m_CounterSetUid), 16));
1003 body.append(" | ");
1004 body.append(CentreAlignFormatting(std::to_string(counter->m_DeviceUid), 14));
1005
1006 body.append("\n");
1007
1008 std::cout << std::string(body.size(), '-') << "\n";
1009
1010 std::cout << body;
1011}
1012
1013void PrintCategoryDetails(const std::unique_ptr<Category>& category,
1014 std::unordered_map<unsigned short, std::shared_ptr<Counter>> counterMap)
1015{
1016 std::string categoryBody;
1017 std::string categoryHeader;
1018
1019 categoryHeader.append(CentreAlignFormatting("Name", 20));
1020 categoryHeader.append(" | ");
1021 categoryHeader.append(CentreAlignFormatting("Device", 12));
1022 categoryHeader.append(" | ");
1023 categoryHeader.append(CentreAlignFormatting("Counter set UID:", 16));
1024 categoryHeader.append(" | ");
1025 categoryHeader.append(CentreAlignFormatting("Event Count", 14));
1026 categoryHeader.append("\n");
1027
1028 categoryBody.append(CentreAlignFormatting(category->m_Name, 20));
1029 categoryBody.append(" | ");
1030 categoryBody.append(CentreAlignFormatting(std::to_string(category->m_DeviceUid), 12));
1031 categoryBody.append(" | ");
1032 categoryBody.append(CentreAlignFormatting(std::to_string(category->m_CounterSetUid), 16));
1033 categoryBody.append(" | ");
1034 categoryBody.append(CentreAlignFormatting(std::to_string(category->m_Counters.size()), 14));
1035
1036 std::cout << "\n" << "\n";
1037 std::cout << CentreAlignFormatting("CATEGORY", static_cast<int>(categoryHeader.size()));
1038 std::cout << "\n";
1039 std::cout << std::string(categoryHeader.size(), '=') << "\n";
1040
1041 std::cout << categoryHeader;
1042
1043 std::cout << std::string(categoryBody.size(), '-') << "\n";
1044
1045 std::cout << categoryBody;
1046
1047 std::string counterHeader;
1048
1049 counterHeader.append(CentreAlignFormatting("Counter Name", 20));
1050 counterHeader.append(" | ");
1051 counterHeader.append(CentreAlignFormatting("Description", 50));
1052 counterHeader.append(" | ");
1053 counterHeader.append(CentreAlignFormatting("Units", 14));
1054 counterHeader.append(" | ");
1055 counterHeader.append(CentreAlignFormatting("UID", 6));
1056 counterHeader.append(" | ");
1057 counterHeader.append(CentreAlignFormatting("Max UID", 10));
1058 counterHeader.append(" | ");
1059 counterHeader.append(CentreAlignFormatting("Class", 8));
1060 counterHeader.append(" | ");
1061 counterHeader.append(CentreAlignFormatting("Interpolation", 14));
1062 counterHeader.append(" | ");
1063 counterHeader.append(CentreAlignFormatting("Multiplier", 20));
1064 counterHeader.append(" | ");
1065 counterHeader.append(CentreAlignFormatting("Counter set UID", 16));
1066 counterHeader.append(" | ");
1067 counterHeader.append(CentreAlignFormatting("Device UID", 14));
1068 counterHeader.append("\n");
1069
1070 std::cout << "\n" << "\n";
1071 std::cout << CentreAlignFormatting("EVENTS IN CATEGORY: " + category->m_Name,
1072 static_cast<int>(counterHeader.size()));
1073 std::cout << "\n";
1074 std::cout << std::string(counterHeader.size(), '=') << "\n";
1075 std::cout << counterHeader;
1076 for (auto& it: category->m_Counters) {
1077 auto search = counterMap.find(it);
1078 if(search != counterMap.end()) {
1079 PrintCounterDetails(search->second);
1080 }
1081 }
1082}
1083
1084void PrintCounterDirectory(ICounterDirectory& counterDirectory)
1085{
1086 std::string devicesHeader;
1087
1088 devicesHeader.append(CentreAlignFormatting("Device name", 20));
1089 devicesHeader.append(" | ");
1090 devicesHeader.append(CentreAlignFormatting("UID", 13));
1091 devicesHeader.append(" | ");
1092 devicesHeader.append(CentreAlignFormatting("Cores", 10));
1093 devicesHeader.append("\n");
1094
1095 std::cout << "\n" << "\n";
1096 std::cout << CentreAlignFormatting("DEVICES", static_cast<int>(devicesHeader.size()));
1097 std::cout << "\n";
1098 std::cout << std::string(devicesHeader.size(), '=') << "\n";
1099 std::cout << devicesHeader;
1100 for (auto& it: counterDirectory.GetDevices()) {
1101 PrintDeviceDetails(it);
1102 }
1103
1104 std::string counterSetHeader;
1105
1106 counterSetHeader.append(CentreAlignFormatting("Counter set name", 20));
1107 counterSetHeader.append(" | ");
1108 counterSetHeader.append(CentreAlignFormatting("UID", 13));
1109 counterSetHeader.append(" | ");
1110 counterSetHeader.append(CentreAlignFormatting("Count", 10));
1111 counterSetHeader.append("\n");
1112
1113 std::cout << "\n" << "\n";
1114 std::cout << CentreAlignFormatting("COUNTER SETS", static_cast<int>(counterSetHeader.size()));
1115 std::cout << "\n";
1116 std::cout << std::string(counterSetHeader.size(), '=') << "\n";
1117
1118 std::cout << counterSetHeader;
1119
1120 for (auto& it: counterDirectory.GetCounterSets()) {
1121 PrintCounterSetDetails(it);
1122 }
1123
1124 auto counters = counterDirectory.GetCounters();
1125 for (auto& it: counterDirectory.GetCategories()) {
1126 PrintCategoryDetails(it, counters);
1127 }
1128 std::cout << "\n";
1129}
1130
Matteo Martincigh5dc816e2019-11-04 14:05:28 +00001131uint64_t GetTimestamp()
1132{
1133#if USE_CLOCK_MONOTONIC_RAW
1134 using clock = MonotonicClockRaw;
1135#else
1136 using clock = std::chrono::steady_clock;
1137#endif
1138
1139 // Take a timestamp
1140 auto timestamp = clock::now();
1141
1142 return static_cast<uint64_t>(timestamp.time_since_epoch().count());
1143}
Keith Davis3201eea2019-10-24 17:30:41 +01001144
Ferran Balaguer73882172019-09-02 16:39:42 +01001145} // namespace profiling
1146
Matteo Martincigh149528e2019-09-05 12:02:04 +01001147} // namespace armnn
Matteo Martincigh378bbfc2019-11-04 14:05:28 +00001148
1149namespace std
1150{
1151
1152bool operator==(const std::vector<uint8_t>& left, std::thread::id right)
1153{
1154 return std::memcmp(left.data(), &right, left.size()) == 0;
1155}
1156
1157} // namespace std