blob: f00f15667baaf8d4dd64ab8949cfbb794de741f2 [file] [log] [blame]
Ferran Balaguer73882172019-09-02 16:39:42 +01001//
Jim Flynn6398a982020-05-27 17:05:21 +01002// Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
Ferran Balaguer73882172019-09-02 16:39:42 +01003// SPDX-License-Identifier: MIT
4//
5
6#include "ProfilingUtils.hpp"
7
Jim Flynnbbfe6032020-07-20 16:57:44 +01008#include <common/include/CommonProfilingUtils.hpp>
9#include <common/include/ProfilingException.hpp>
10#include <common/include/SwTrace.hpp>
Jim Flynn4e755a52020-03-29 17:48:26 +010011
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010012#include <armnn/Version.hpp>
13
Matteo Martincigh5dc816e2019-11-04 14:05:28 +000014#include <WallClockTimer.hpp>
15
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +010016#include <armnn/utility/Assert.hpp>
Ferran Balaguer73882172019-09-02 16:39:42 +010017
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010018#include <fstream>
Keith Davis3201eea2019-10-24 17:30:41 +010019#include <iostream>
Matteo Martincighab173e92019-09-05 12:02:04 +010020#include <limits>
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010021
Ferran Balaguer73882172019-09-02 16:39:42 +010022namespace armnn
23{
24
25namespace profiling
26{
27
Matteo Martincigh6db5f202019-09-05 12:02:04 +010028namespace
Matteo Martincighab173e92019-09-05 12:02:04 +010029{
Matteo Martincighab173e92019-09-05 12:02:04 +010030
Matteo Martincigh6db5f202019-09-05 12:02:04 +010031void ThrowIfCantGenerateNextUid(uint16_t uid, uint16_t cores = 0)
32{
Matteo Martincighab173e92019-09-05 12:02:04 +010033 // Check that it is possible to generate the next UID without causing an overflow
Matteo Martincigh6db5f202019-09-05 12:02:04 +010034 switch (cores)
Matteo Martincighab173e92019-09-05 12:02:04 +010035 {
Matteo Martincigh6db5f202019-09-05 12:02:04 +010036 case 0:
37 case 1:
38 // Number of cores not specified or set to 1 (a value of zero indicates the device is not capable of
39 // running multiple parallel workloads and will not provide multiple streams of data for each event)
40 if (uid == std::numeric_limits<uint16_t>::max())
41 {
42 throw RuntimeException("Generating the next UID for profiling would result in an overflow");
43 }
44 break;
45 default: // cores > 1
46 // Multiple cores available, as max_counter_uid has to be set to: counter_uid + cores - 1, the maximum
47 // allowed value for a counter UID is consequently: uint16_t_max - cores + 1
48 if (uid >= std::numeric_limits<uint16_t>::max() - cores + 1)
49 {
50 throw RuntimeException("Generating the next UID for profiling would result in an overflow");
51 }
52 break;
Matteo Martincighab173e92019-09-05 12:02:04 +010053 }
Matteo Martincigh6db5f202019-09-05 12:02:04 +010054}
Matteo Martincighab173e92019-09-05 12:02:04 +010055
Matteo Martincigh6db5f202019-09-05 12:02:04 +010056} // Anonymous namespace
57
58uint16_t GetNextUid(bool peekOnly)
59{
60 // The UID used for profiling objects and events. The first valid UID is 1, as 0 is a reserved value
61 static uint16_t uid = 1;
62
63 // Check that it is possible to generate the next UID without causing an overflow (throws in case of error)
64 ThrowIfCantGenerateNextUid(uid);
65
66 if (peekOnly)
67 {
68 // Peek only
69 return uid;
70 }
71 else
72 {
73 // Get the next UID
74 return uid++;
75 }
76}
77
Keith Davise394bd92019-12-02 15:12:19 +000078std::vector<uint16_t> GetNextCounterUids(uint16_t firstUid, uint16_t cores)
Matteo Martincigh6db5f202019-09-05 12:02:04 +010079{
Matteo Martincigh6db5f202019-09-05 12:02:04 +010080 // 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 +000081 ThrowIfCantGenerateNextUid(firstUid, cores);
Matteo Martincigh6db5f202019-09-05 12:02:04 +010082
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 {
Keith Davise394bd92019-12-02 15:12:19 +000088 counterUids[i] = firstUid++;
Matteo Martincigh6db5f202019-09-05 12:02:04 +010089 }
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{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +010095 ARMNN_ASSERT(packetBuffer);
Matteo Martincigh378bbfc2019-11-04 14:05:28 +000096
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{
Keith Davis33ed2212020-03-30 10:43:41 +0100103 return (( packetFamily & 0x0000003F ) << 26 )|
Jim Flynn83d08a92020-07-09 13:48:16 +0100104 (( packetId & 0x000003FF ) << 16 );
105}
106
107uint32_t ConstructHeader(uint32_t packetFamily, uint32_t packetClass, uint32_t packetType)
108{
109 return ((packetFamily & 0x0000003F) << 26) |
110 ((packetClass & 0x0000007F) << 19) |
111 ((packetType & 0x00000007) << 16);
Keith Davis3201eea2019-10-24 17:30:41 +0100112}
113
114void WriteUint64(const std::unique_ptr<IPacketBuffer>& packetBuffer, unsigned int offset, uint64_t value)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100115{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100116 ARMNN_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100117
118 WriteUint64(packetBuffer->GetWritableData(), offset, value);
119}
120
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000121void WriteUint32(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint32_t value)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100122{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100123 ARMNN_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100124
125 WriteUint32(packetBuffer->GetWritableData(), offset, value);
126}
127
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000128void WriteUint16(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint16_t value)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100129{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100130 ARMNN_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100131
132 WriteUint16(packetBuffer->GetWritableData(), offset, value);
133}
134
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000135void WriteUint8(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint8_t value)
136{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100137 ARMNN_ASSERT(packetBuffer);
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000138
139 WriteUint8(packetBuffer->GetWritableData(), offset, value);
140}
141
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000142void WriteBytes(unsigned char* buffer, unsigned int offset, const void* value, unsigned int valueSize)
143{
Jim Flynnbbfe6032020-07-20 16:57:44 +0100144 arm::pipe::WriteBytes(buffer, offset, value, valueSize);
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000145}
146
Francis Murtagh3a161982019-09-04 15:25:02 +0100147void WriteUint64(unsigned char* buffer, unsigned int offset, uint64_t value)
148{
Jim Flynnbbfe6032020-07-20 16:57:44 +0100149 arm::pipe::WriteUint64(buffer, offset, value);
Francis Murtagh3a161982019-09-04 15:25:02 +0100150}
151
Ferran Balaguer73882172019-09-02 16:39:42 +0100152void WriteUint32(unsigned char* buffer, unsigned int offset, uint32_t value)
153{
Jim Flynnbbfe6032020-07-20 16:57:44 +0100154 arm::pipe::WriteUint32(buffer, offset, value);
Ferran Balaguer73882172019-09-02 16:39:42 +0100155}
156
157void WriteUint16(unsigned char* buffer, unsigned int offset, uint16_t value)
158{
Jim Flynnbbfe6032020-07-20 16:57:44 +0100159 arm::pipe::WriteUint16(buffer, offset, value);
Ferran Balaguer73882172019-09-02 16:39:42 +0100160}
161
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000162void WriteUint8(unsigned char* buffer, unsigned int offset, uint8_t value)
163{
Jim Flynnbbfe6032020-07-20 16:57:44 +0100164 arm::pipe::WriteUint8(buffer, offset, value);
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000165}
166
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000167void ReadBytes(const IPacketBufferPtr& packetBuffer, unsigned int offset, unsigned int valueSize, uint8_t outValue[])
168{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100169 ARMNN_ASSERT(packetBuffer);
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000170
171 ReadBytes(packetBuffer->GetReadableData(), offset, valueSize, outValue);
172}
173
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000174uint64_t ReadUint64(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100175{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100176 ARMNN_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100177
178 return ReadUint64(packetBuffer->GetReadableData(), offset);
179}
180
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000181uint32_t ReadUint32(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100182{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100183 ARMNN_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100184
185 return ReadUint32(packetBuffer->GetReadableData(), offset);
186}
187
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000188uint16_t ReadUint16(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100189{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100190 ARMNN_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100191
192 return ReadUint16(packetBuffer->GetReadableData(), offset);
193}
194
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000195uint8_t ReadUint8(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100196{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100197 ARMNN_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100198
199 return ReadUint8(packetBuffer->GetReadableData(), offset);
200}
201
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000202void ReadBytes(const unsigned char* buffer, unsigned int offset, unsigned int valueSize, uint8_t outValue[])
203{
Jim Flynnbbfe6032020-07-20 16:57:44 +0100204 arm::pipe::ReadBytes(buffer, offset, valueSize, outValue);
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000205}
206
Francis Murtagh3a161982019-09-04 15:25:02 +0100207uint64_t ReadUint64(const unsigned char* buffer, unsigned int offset)
208{
Jim Flynnbbfe6032020-07-20 16:57:44 +0100209 return arm::pipe::ReadUint64(buffer, offset);
Francis Murtagh3a161982019-09-04 15:25:02 +0100210}
211
Ferran Balaguer73882172019-09-02 16:39:42 +0100212uint32_t ReadUint32(const unsigned char* buffer, unsigned int offset)
213{
Jim Flynnbbfe6032020-07-20 16:57:44 +0100214 return arm::pipe::ReadUint32(buffer, offset);
Ferran Balaguer73882172019-09-02 16:39:42 +0100215}
216
217uint16_t ReadUint16(const unsigned char* buffer, unsigned int offset)
218{
Jim Flynnbbfe6032020-07-20 16:57:44 +0100219 return arm::pipe::ReadUint16(buffer, offset);
Ferran Balaguer73882172019-09-02 16:39:42 +0100220}
221
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100222uint8_t ReadUint8(const unsigned char* buffer, unsigned int offset)
223{
Jim Flynnbbfe6032020-07-20 16:57:44 +0100224 return arm::pipe::ReadUint8(buffer, offset);
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100225}
226
Ferran Balaguer47d0fe92019-09-04 16:47:34 +0100227std::string GetSoftwareInfo()
228{
229 return std::string("ArmNN");
230}
231
232std::string GetHardwareVersion()
233{
234 return std::string();
235}
236
237std::string GetSoftwareVersion()
238{
Francis Murtaghd36c5282020-05-22 12:49:25 +0100239 std::string result = "Armnn " + std::to_string(ARMNN_MAJOR_VERSION) + "." + std::to_string(ARMNN_MINOR_VERSION);
Ferran Balaguer47d0fe92019-09-04 16:47:34 +0100240 return result;
241}
242
243std::string GetProcessName()
244{
245 std::ifstream comm("/proc/self/comm");
246 std::string name;
247 getline(comm, name);
248 return name;
249}
250
Jan Eilers92fa15b2019-10-15 15:23:25 +0100251/// Creates a timeline packet header
252///
253/// \params
254/// packetFamiliy Timeline Packet Family
255/// packetClass Timeline Packet Class
256/// packetType Timeline Packet Type
257/// streamId Stream identifier
258/// seqeunceNumbered When non-zero the 4 bytes following the header is a u32 sequence number
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100259/// dataLength Unsigned 24-bit integer. Length of data, in bytes. Zero is permitted
Jan Eilers92fa15b2019-10-15 15:23:25 +0100260///
261/// \returns
262/// Pair of uint32_t containing word0 and word1 of the header
263std::pair<uint32_t, uint32_t> CreateTimelinePacketHeader(uint32_t packetFamily,
264 uint32_t packetClass,
265 uint32_t packetType,
266 uint32_t streamId,
267 uint32_t sequenceNumbered,
268 uint32_t dataLength)
269{
270 // Packet header word 0:
271 // 26:31 [6] packet_family: timeline Packet Family, value 0b000001
272 // 19:25 [7] packet_class: packet class
273 // 16:18 [3] packet_type: packet type
274 // 8:15 [8] reserved: all zeros
275 // 0:7 [8] stream_id: stream identifier
276 uint32_t packetHeaderWord0 = ((packetFamily & 0x0000003F) << 26) |
277 ((packetClass & 0x0000007F) << 19) |
278 ((packetType & 0x00000007) << 16) |
279 ((streamId & 0x00000007) << 0);
280
281 // Packet header word 1:
282 // 25:31 [7] reserved: all zeros
283 // 24 [1] sequence_numbered: when non-zero the 4 bytes following the header is a u32 sequence number
284 // 0:23 [24] data_length: unsigned 24-bit integer. Length of data, in bytes. Zero is permitted
285 uint32_t packetHeaderWord1 = ((sequenceNumbered & 0x00000001) << 24) |
286 ((dataLength & 0x00FFFFFF) << 0);
287
288 return std::make_pair(packetHeaderWord0, packetHeaderWord1);
289}
290
291/// Creates a packet header for the timeline messages:
292/// * declareLabel
293/// * declareEntity
294/// * declareEventClass
295/// * declareRelationship
296/// * declareEvent
297///
298/// \param
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100299/// dataLength The length of the message body in bytes
Jan Eilers92fa15b2019-10-15 15:23:25 +0100300///
301/// \returns
302/// Pair of uint32_t containing word0 and word1 of the header
303std::pair<uint32_t, uint32_t> CreateTimelineMessagePacketHeader(unsigned int dataLength)
304{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100305 return CreateTimelinePacketHeader(1, // Packet family
306 0, // Packet class
307 1, // Packet type
308 0, // Stream id
309 0, // Sequence number
310 dataLength); // Data length
Jan Eilers92fa15b2019-10-15 15:23:25 +0100311}
312
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100313TimelinePacketStatus WriteTimelineLabelBinaryPacket(uint64_t profilingGuid,
314 const std::string& label,
315 unsigned char* buffer,
Keith Davis97da5e22020-03-05 16:25:28 +0000316 unsigned int remainingBufferSize,
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100317 unsigned int& numberOfBytesWritten)
318{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100319 // Initialize the output value
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100320 numberOfBytesWritten = 0;
321
322 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000323 if (buffer == nullptr || remainingBufferSize == 0)
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100324 {
325 return TimelinePacketStatus::BufferExhaustion;
326 }
327
328 // Utils
329 unsigned int uint32_t_size = sizeof(uint32_t);
330 unsigned int uint64_t_size = sizeof(uint64_t);
331
332 // Convert the label into a SWTrace string
333 std::vector<uint32_t> swTraceLabel;
Jim Flynnbbfe6032020-07-20 16:57:44 +0100334 bool result = arm::pipe::StringToSwTraceString<arm::pipe::SwTraceCharPolicy>(label, swTraceLabel);
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100335 if (!result)
336 {
337 return TimelinePacketStatus::Error;
338 }
339
340 // Calculate the size of the SWTrace string label (in bytes)
Matthew Sloyan371b70e2020-09-11 10:14:57 +0100341 unsigned int swTraceLabelSize = armnn::numeric_cast<unsigned int>(swTraceLabel.size()) * uint32_t_size;
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100342
343 // Calculate the length of the data (in bytes)
Jan Eilersb884ea42019-10-16 09:54:15 +0100344 unsigned int timelineLabelPacketDataLength = uint32_t_size + // decl_Id
345 uint64_t_size + // Profiling GUID
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100346 swTraceLabelSize; // Label
347
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100348 // Check whether the timeline binary packet fits in the given buffer
Keith Davis97da5e22020-03-05 16:25:28 +0000349 if (timelineLabelPacketDataLength > remainingBufferSize)
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100350 {
351 return TimelinePacketStatus::BufferExhaustion;
352 }
353
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100354 // Initialize the offset for writing in the buffer
355 unsigned int offset = 0;
356
Jan Eilersb884ea42019-10-16 09:54:15 +0100357 // Write decl_Id to the buffer
358 WriteUint32(buffer, offset, 0u);
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100359 offset += uint32_t_size;
360
361 // Write the timeline binary packet payload to the buffer
362 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
363 offset += uint64_t_size;
364 for (uint32_t swTraceLabelWord : swTraceLabel)
365 {
366 WriteUint32(buffer, offset, swTraceLabelWord); // Label
367 offset += uint32_t_size;
368 }
369
370 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000371 numberOfBytesWritten = timelineLabelPacketDataLength;
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100372
373 return TimelinePacketStatus::Ok;
374}
375
Keith Davis97da5e22020-03-05 16:25:28 +0000376TimelinePacketStatus WriteTimelineEntityBinary(uint64_t profilingGuid,
377 unsigned char* buffer,
378 unsigned int remainingBufferSize,
379 unsigned int& numberOfBytesWritten)
David Monahanf21f6062019-10-07 15:11:15 +0100380{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100381 // Initialize the output value
David Monahanf21f6062019-10-07 15:11:15 +0100382 numberOfBytesWritten = 0;
383
384 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000385 if (buffer == nullptr || remainingBufferSize == 0)
David Monahanf21f6062019-10-07 15:11:15 +0100386 {
387 return TimelinePacketStatus::BufferExhaustion;
388 }
389
390 // Utils
391 unsigned int uint32_t_size = sizeof(uint32_t);
392 unsigned int uint64_t_size = sizeof(uint64_t);
393
394 // Calculate the length of the data (in bytes)
Keith Davis97da5e22020-03-05 16:25:28 +0000395 unsigned int timelineEntityDataLength = uint32_t_size + uint64_t_size; // decl_id + Profiling GUID
David Monahanf21f6062019-10-07 15:11:15 +0100396
397 // Check whether the timeline binary packet fits in the given buffer
Keith Davis97da5e22020-03-05 16:25:28 +0000398 if (timelineEntityDataLength > remainingBufferSize)
David Monahanf21f6062019-10-07 15:11:15 +0100399 {
400 return TimelinePacketStatus::BufferExhaustion;
401 }
402
David Monahanf21f6062019-10-07 15:11:15 +0100403 // Initialize the offset for writing in the buffer
404 unsigned int offset = 0;
405
Jan Eilersb884ea42019-10-16 09:54:15 +0100406 // Write the decl_Id to the buffer
407 WriteUint32(buffer, offset, 1u);
David Monahanf21f6062019-10-07 15:11:15 +0100408 offset += uint32_t_size;
409
410 // Write the timeline binary packet payload to the buffer
411 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
412
413 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000414 numberOfBytesWritten = timelineEntityDataLength;
David Monahanf21f6062019-10-07 15:11:15 +0100415
416 return TimelinePacketStatus::Ok;
417}
418
Keith Davis97da5e22020-03-05 16:25:28 +0000419TimelinePacketStatus WriteTimelineRelationshipBinary(ProfilingRelationshipType relationshipType,
420 uint64_t relationshipGuid,
421 uint64_t headGuid,
422 uint64_t tailGuid,
Finn Williams0a336dc2020-05-11 15:39:58 +0100423 uint64_t attributeGuid,
Keith Davis97da5e22020-03-05 16:25:28 +0000424 unsigned char* buffer,
425 unsigned int remainingBufferSize,
426 unsigned int& numberOfBytesWritten)
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100427{
428 // Initialize the output value
429 numberOfBytesWritten = 0;
430
431 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000432 if (buffer == nullptr || remainingBufferSize == 0)
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100433 {
434 return TimelinePacketStatus::BufferExhaustion;
435 }
436
437 // Utils
438 unsigned int uint32_t_size = sizeof(uint32_t);
439 unsigned int uint64_t_size = sizeof(uint64_t);
440
441 // Calculate the length of the data (in bytes)
Keith Davis97da5e22020-03-05 16:25:28 +0000442 unsigned int timelineRelationshipDataLength = uint32_t_size * 2 + // decl_id + Relationship Type
Finn Williams0a336dc2020-05-11 15:39:58 +0100443 uint64_t_size * 4; // Relationship GUID + Head GUID +
444 // tail GUID + attributeGuid
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100445
Keith Davis97da5e22020-03-05 16:25:28 +0000446 // Check whether the timeline binary fits in the given buffer
447 if (timelineRelationshipDataLength > remainingBufferSize)
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100448 {
449 return TimelinePacketStatus::BufferExhaustion;
450 }
451
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100452 // Initialize the offset for writing in the buffer
453 unsigned int offset = 0;
454
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100455 uint32_t relationshipTypeUint = 0;
456
457 switch (relationshipType)
458 {
459 case ProfilingRelationshipType::RetentionLink:
460 relationshipTypeUint = 0;
461 break;
462 case ProfilingRelationshipType::ExecutionLink:
463 relationshipTypeUint = 1;
464 break;
465 case ProfilingRelationshipType::DataLink:
466 relationshipTypeUint = 2;
467 break;
468 case ProfilingRelationshipType::LabelLink:
469 relationshipTypeUint = 3;
470 break;
471 default:
472 throw InvalidArgumentException("Unknown relationship type given.");
473 }
474
Keith Davis97da5e22020-03-05 16:25:28 +0000475 // Write the timeline binary payload to the buffer
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100476 // decl_id of the timeline message
477 uint32_t declId = 3;
478 WriteUint32(buffer, offset, declId); // decl_id
479 offset += uint32_t_size;
480 WriteUint32(buffer, offset, relationshipTypeUint); // Relationship Type
481 offset += uint32_t_size;
482 WriteUint64(buffer, offset, relationshipGuid); // GUID of this relationship
483 offset += uint64_t_size;
484 WriteUint64(buffer, offset, headGuid); // head of relationship GUID
485 offset += uint64_t_size;
486 WriteUint64(buffer, offset, tailGuid); // tail of relationship GUID
Finn Williams0a336dc2020-05-11 15:39:58 +0100487 offset += uint64_t_size;
488 WriteUint64(buffer, offset, attributeGuid); // attribute of relationship GUID
489
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100490
491 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000492 numberOfBytesWritten = timelineRelationshipDataLength;
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100493
494 return TimelinePacketStatus::Ok;
495}
496
Sadik Armagan784db772019-10-08 15:05:38 +0100497TimelinePacketStatus WriteTimelineMessageDirectoryPackage(unsigned char* buffer,
Keith Davis97da5e22020-03-05 16:25:28 +0000498 unsigned int remainingBufferSize,
Sadik Armagan784db772019-10-08 15:05:38 +0100499 unsigned int& numberOfBytesWritten)
500{
501 // Initialize the output value
502 numberOfBytesWritten = 0;
503
504 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000505 if (buffer == nullptr || remainingBufferSize == 0)
Sadik Armagan784db772019-10-08 15:05:38 +0100506 {
507 return TimelinePacketStatus::BufferExhaustion;
508 }
509
510 // Utils
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000511 unsigned int uint8_t_size = sizeof(uint8_t);
Sadik Armagan784db772019-10-08 15:05:38 +0100512 unsigned int uint32_t_size = sizeof(uint32_t);
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000513 unsigned int uint64_t_size = sizeof(uint64_t);
Sadik Armagan784db772019-10-08 15:05:38 +0100514
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100515 // The payload/data of the packet consists of swtrace event definitions encoded according
Sadik Armagan784db772019-10-08 15:05:38 +0100516 // to the swtrace directory specification. The messages being the five defined below:
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000517 //
518 // | decl_id | decl_name | ui_name | arg_types | arg_names |
Sadik Armagan784db772019-10-08 15:05:38 +0100519 // |-----------|---------------------|-----------------------|-------------|-------------------------------------|
520 // | 0 | declareLabel | declare label | ps | guid,value |
521 // | 1 | declareEntity | declare entity | p | guid |
Jim Flynn6398a982020-05-27 17:05:21 +0100522 // | 2 | declareEventClass | declare event class | pp | guid,nameGuid |
523 // | 3 | declareRelationship | declare relationship | Ipppp | relationshipType,relationshipGuid, |
524 // | | | | | headGuid,tailGuid,attributeGuid |
Sadik Armagan784db772019-10-08 15:05:38 +0100525 // | 4 | declareEvent | declare event | @tp | timestamp,threadId,eventGuid |
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100526 std::vector<std::vector<std::string>> timelineDirectoryMessages
527 {
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000528 { "0", "declareLabel", "declare label", "ps", "guid,value" },
529 { "1", "declareEntity", "declare entity", "p", "guid" },
Jim Flynn6398a982020-05-27 17:05:21 +0100530 { "2", "declareEventClass", "declare event class", "pp", "guid,nameGuid" },
531 { "3", "declareRelationship", "declare relationship", "Ipppp",
532 "relationshipType,relationshipGuid,headGuid,tailGuid,attributeGuid" },
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000533 { "4", "declareEvent", "declare event", "@tp", "timestamp,threadId,eventGuid" }
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100534 };
Sadik Armagan784db772019-10-08 15:05:38 +0100535
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000536 // Build the message declarations
537 std::vector<uint32_t> swTraceBuffer;
538 for (const auto& directoryComponent : timelineDirectoryMessages)
Sadik Armagan784db772019-10-08 15:05:38 +0100539 {
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000540 // decl_id
541 uint32_t declId = 0;
542 try
Sadik Armagan784db772019-10-08 15:05:38 +0100543 {
Matthew Sloyan371b70e2020-09-11 10:14:57 +0100544 declId = armnn::numeric_cast<uint32_t>(std::stoul(directoryComponent[0]));
Sadik Armagan784db772019-10-08 15:05:38 +0100545 }
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000546 catch (const std::exception&)
547 {
548 return TimelinePacketStatus::Error;
549 }
550 swTraceBuffer.push_back(declId);
551
552 bool result = true;
Jim Flynnbbfe6032020-07-20 16:57:44 +0100553 result &= arm::pipe::ConvertDirectoryComponent<arm::pipe::SwTraceNameCharPolicy>(
554 directoryComponent[1], swTraceBuffer); // decl_name
555 result &= arm::pipe::ConvertDirectoryComponent<arm::pipe::SwTraceCharPolicy> (
556 directoryComponent[2], swTraceBuffer); // ui_name
557 result &= arm::pipe::ConvertDirectoryComponent<arm::pipe::SwTraceTypeCharPolicy>(
558 directoryComponent[3], swTraceBuffer); // arg_types
559 result &= arm::pipe::ConvertDirectoryComponent<arm::pipe::SwTraceCharPolicy> (
560 directoryComponent[4], swTraceBuffer); // arg_names
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000561 if (!result)
562 {
563 return TimelinePacketStatus::Error;
564 }
Sadik Armagan784db772019-10-08 15:05:38 +0100565 }
566
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000567 unsigned int dataLength = 3 * uint8_t_size + // Stream header (3 bytes)
Matthew Sloyan371b70e2020-09-11 10:14:57 +0100568 armnn::numeric_cast<unsigned int>(swTraceBuffer.size()) *
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000569 uint32_t_size; // Trace directory (5 messages)
570
Sadik Armagan784db772019-10-08 15:05:38 +0100571 // Calculate the timeline directory binary packet size (in bytes)
572 unsigned int timelineDirectoryPacketSize = 2 * uint32_t_size + // Header (2 words)
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000573 dataLength; // Payload
Sadik Armagan784db772019-10-08 15:05:38 +0100574
575 // Check whether the timeline directory binary packet fits in the given buffer
Keith Davis97da5e22020-03-05 16:25:28 +0000576 if (timelineDirectoryPacketSize > remainingBufferSize)
Sadik Armagan784db772019-10-08 15:05:38 +0100577 {
578 return TimelinePacketStatus::BufferExhaustion;
579 }
580
Jan Eilersb884ea42019-10-16 09:54:15 +0100581 // Create packet header
Matthew Sloyan371b70e2020-09-11 10:14:57 +0100582 auto packetHeader = CreateTimelinePacketHeader(1, 0, 0, 0, 0, armnn::numeric_cast<uint32_t>(dataLength));
Sadik Armagan784db772019-10-08 15:05:38 +0100583
584 // Initialize the offset for writing in the buffer
585 unsigned int offset = 0;
586
587 // Write the timeline binary packet header to the buffer
Jan Eilersb884ea42019-10-16 09:54:15 +0100588 WriteUint32(buffer, offset, packetHeader.first);
Sadik Armagan784db772019-10-08 15:05:38 +0100589 offset += uint32_t_size;
Jan Eilersb884ea42019-10-16 09:54:15 +0100590 WriteUint32(buffer, offset, packetHeader.second);
Sadik Armagan784db772019-10-08 15:05:38 +0100591 offset += uint32_t_size;
592
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000593 // Write the stream header
594 uint8_t streamVersion = 4;
Matthew Sloyan371b70e2020-09-11 10:14:57 +0100595 uint8_t pointerBytes = armnn::numeric_cast<uint8_t>(uint64_t_size); // All GUIDs are uint64_t
596 uint8_t threadIdBytes = armnn::numeric_cast<uint8_t>(ThreadIdSize);
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000597 switch (threadIdBytes)
Sadik Armagan784db772019-10-08 15:05:38 +0100598 {
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000599 case 4: // Typically Windows and Android
600 case 8: // Typically Linux
601 break; // Valid values
602 default:
603 return TimelinePacketStatus::Error; // Invalid value
604 }
605 WriteUint8(buffer, offset, streamVersion);
606 offset += uint8_t_size;
607 WriteUint8(buffer, offset, pointerBytes);
608 offset += uint8_t_size;
609 WriteUint8(buffer, offset, threadIdBytes);
610 offset += uint8_t_size;
Sadik Armagan784db772019-10-08 15:05:38 +0100611
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000612 // Write the SWTrace directory
Matthew Sloyan371b70e2020-09-11 10:14:57 +0100613 uint32_t numberOfDeclarations = armnn::numeric_cast<uint32_t>(timelineDirectoryMessages.size());
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000614 WriteUint32(buffer, offset, numberOfDeclarations); // Number of declarations
615 offset += uint32_t_size;
616 for (uint32_t i : swTraceBuffer)
617 {
618 WriteUint32(buffer, offset, i); // Message declarations
619 offset += uint32_t_size;
Sadik Armagan784db772019-10-08 15:05:38 +0100620 }
621
622 // Update the number of bytes written
623 numberOfBytesWritten = timelineDirectoryPacketSize;
624
625 return TimelinePacketStatus::Ok;
626}
627
Keith Davis97da5e22020-03-05 16:25:28 +0000628TimelinePacketStatus WriteTimelineEventClassBinary(uint64_t profilingGuid,
Jim Flynn1892d212020-05-26 21:10:49 +0100629 uint64_t nameGuid,
Keith Davis97da5e22020-03-05 16:25:28 +0000630 unsigned char* buffer,
631 unsigned int remainingBufferSize,
632 unsigned int& numberOfBytesWritten)
Jan Eilers92fa15b2019-10-15 15:23:25 +0100633{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100634 // Initialize the output value
Jan Eilers92fa15b2019-10-15 15:23:25 +0100635 numberOfBytesWritten = 0;
636
637 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000638 if (buffer == nullptr || remainingBufferSize == 0)
Jan Eilers92fa15b2019-10-15 15:23:25 +0100639 {
640 return TimelinePacketStatus::BufferExhaustion;
641 }
642
643 // Utils
644 unsigned int uint32_t_size = sizeof(uint32_t);
645 unsigned int uint64_t_size = sizeof(uint64_t);
646
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100647 // decl_id of the timeline message
648 uint32_t declId = 2;
Jan Eilers92fa15b2019-10-15 15:23:25 +0100649
650 // Calculate the length of the data (in bytes)
Jim Flynn1892d212020-05-26 21:10:49 +0100651 unsigned int dataSize = uint32_t_size + (uint64_t_size * 2); // decl_id + Profiling GUID + Name GUID
Jan Eilers92fa15b2019-10-15 15:23:25 +0100652
Keith Davis97da5e22020-03-05 16:25:28 +0000653 // Check whether the timeline binary fits in the given buffer
654 if (dataSize > remainingBufferSize)
Jan Eilers92fa15b2019-10-15 15:23:25 +0100655 {
656 return TimelinePacketStatus::BufferExhaustion;
657 }
658
Jan Eilers92fa15b2019-10-15 15:23:25 +0100659 // Initialize the offset for writing in the buffer
660 unsigned int offset = 0;
661
Keith Davis97da5e22020-03-05 16:25:28 +0000662 // Write the timeline binary payload to the buffer
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100663 WriteUint32(buffer, offset, declId); // decl_id
Jan Eilers92fa15b2019-10-15 15:23:25 +0100664 offset += uint32_t_size;
665 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
Jim Flynn1892d212020-05-26 21:10:49 +0100666 offset += uint64_t_size;
667 WriteUint64(buffer, offset, nameGuid); // Name GUID
Jan Eilers92fa15b2019-10-15 15:23:25 +0100668
669 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000670 numberOfBytesWritten = dataSize;
Jan Eilers92fa15b2019-10-15 15:23:25 +0100671
672 return TimelinePacketStatus::Ok;
673}
674
Keith Davis97da5e22020-03-05 16:25:28 +0000675TimelinePacketStatus WriteTimelineEventBinary(uint64_t timestamp,
Jim Flynn1fdeb992020-07-09 07:28:37 +0100676 int threadId,
Keith Davis97da5e22020-03-05 16:25:28 +0000677 uint64_t profilingGuid,
678 unsigned char* buffer,
679 unsigned int remainingBufferSize,
680 unsigned int& numberOfBytesWritten)
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100681{
682 // Initialize the output value
683 numberOfBytesWritten = 0;
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100684 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000685 if (buffer == nullptr || remainingBufferSize == 0)
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100686 {
687 return TimelinePacketStatus::BufferExhaustion;
688 }
689
690 // Utils
691 unsigned int uint32_t_size = sizeof(uint32_t);
692 unsigned int uint64_t_size = sizeof(uint64_t);
693
694 // decl_id of the timeline message
695 uint32_t declId = 4;
696
697 // Calculate the length of the data (in bytes)
Keith Davis97da5e22020-03-05 16:25:28 +0000698 unsigned int timelineEventDataLength = uint32_t_size + // decl_id
699 uint64_t_size + // Timestamp
Colm Donelan5bb3d8a2020-05-12 16:36:46 +0100700 ThreadIdSize + // Thread id
Keith Davis97da5e22020-03-05 16:25:28 +0000701 uint64_t_size; // Profiling GUID
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100702
703 // Check whether the timeline binary packet fits in the given buffer
Keith Davis97da5e22020-03-05 16:25:28 +0000704 if (timelineEventDataLength > remainingBufferSize)
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100705 {
706 return TimelinePacketStatus::BufferExhaustion;
707 }
708
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100709 // Initialize the offset for writing in the buffer
710 unsigned int offset = 0;
711
Keith Davis97da5e22020-03-05 16:25:28 +0000712 // Write the timeline binary payload to the buffer
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100713 WriteUint32(buffer, offset, declId); // decl_id
714 offset += uint32_t_size;
715 WriteUint64(buffer, offset, timestamp); // Timestamp
716 offset += uint64_t_size;
Colm Donelan5bb3d8a2020-05-12 16:36:46 +0100717 WriteBytes(buffer, offset, &threadId, ThreadIdSize); // Thread id
718 offset += ThreadIdSize;
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100719 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
720 offset += uint64_t_size;
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100721 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000722 numberOfBytesWritten = timelineEventDataLength;
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100723
724 return TimelinePacketStatus::Ok;
725}
726
Keith Davis3201eea2019-10-24 17:30:41 +0100727std::string CentreAlignFormatting(const std::string& stringToPass, const int spacingWidth)
728{
Jim Flynnbbfe6032020-07-20 16:57:44 +0100729 return arm::pipe::CentreAlignFormatting(stringToPass, spacingWidth);
Keith Davis3201eea2019-10-24 17:30:41 +0100730}
731
732void PrintDeviceDetails(const std::pair<const unsigned short, std::unique_ptr<Device>>& devicePair)
733{
734 std::string body;
735
736 body.append(CentreAlignFormatting(devicePair.second->m_Name, 20));
737 body.append(" | ");
738 body.append(CentreAlignFormatting(std::to_string(devicePair.first), 13));
739 body.append(" | ");
740 body.append(CentreAlignFormatting(std::to_string(devicePair.second->m_Cores), 10));
741 body.append("\n");
742
743 std::cout << std::string(body.size(), '-') << "\n";
744 std::cout<< body;
745}
746
747void PrintCounterSetDetails(const std::pair<const unsigned short, std::unique_ptr<CounterSet>>& counterSetPair)
748{
749 std::string body;
750
751 body.append(CentreAlignFormatting(counterSetPair.second->m_Name, 20));
752 body.append(" | ");
753 body.append(CentreAlignFormatting(std::to_string(counterSetPair.first), 13));
754 body.append(" | ");
755 body.append(CentreAlignFormatting(std::to_string(counterSetPair.second->m_Count), 10));
756 body.append("\n");
757
758 std::cout << std::string(body.size(), '-') << "\n";
759
760 std::cout<< body;
761}
762
763void PrintCounterDetails(std::shared_ptr<Counter>& counter)
764{
765 std::string body;
766
767 body.append(CentreAlignFormatting(counter->m_Name, 20));
768 body.append(" | ");
769 body.append(CentreAlignFormatting(counter->m_Description, 50));
770 body.append(" | ");
771 body.append(CentreAlignFormatting(counter->m_Units, 14));
772 body.append(" | ");
773 body.append(CentreAlignFormatting(std::to_string(counter->m_Uid), 6));
774 body.append(" | ");
775 body.append(CentreAlignFormatting(std::to_string(counter->m_MaxCounterUid), 10));
776 body.append(" | ");
777 body.append(CentreAlignFormatting(std::to_string(counter->m_Class), 8));
778 body.append(" | ");
779 body.append(CentreAlignFormatting(std::to_string(counter->m_Interpolation), 14));
780 body.append(" | ");
781 body.append(CentreAlignFormatting(std::to_string(counter->m_Multiplier), 20));
782 body.append(" | ");
783 body.append(CentreAlignFormatting(std::to_string(counter->m_CounterSetUid), 16));
784 body.append(" | ");
785 body.append(CentreAlignFormatting(std::to_string(counter->m_DeviceUid), 14));
786
787 body.append("\n");
788
789 std::cout << std::string(body.size(), '-') << "\n";
790
791 std::cout << body;
792}
793
794void PrintCategoryDetails(const std::unique_ptr<Category>& category,
795 std::unordered_map<unsigned short, std::shared_ptr<Counter>> counterMap)
796{
797 std::string categoryBody;
798 std::string categoryHeader;
799
800 categoryHeader.append(CentreAlignFormatting("Name", 20));
801 categoryHeader.append(" | ");
Keith Davis3201eea2019-10-24 17:30:41 +0100802 categoryHeader.append(CentreAlignFormatting("Event Count", 14));
803 categoryHeader.append("\n");
804
805 categoryBody.append(CentreAlignFormatting(category->m_Name, 20));
806 categoryBody.append(" | ");
Keith Davis3201eea2019-10-24 17:30:41 +0100807 categoryBody.append(CentreAlignFormatting(std::to_string(category->m_Counters.size()), 14));
808
809 std::cout << "\n" << "\n";
810 std::cout << CentreAlignFormatting("CATEGORY", static_cast<int>(categoryHeader.size()));
811 std::cout << "\n";
812 std::cout << std::string(categoryHeader.size(), '=') << "\n";
813
814 std::cout << categoryHeader;
815
816 std::cout << std::string(categoryBody.size(), '-') << "\n";
817
818 std::cout << categoryBody;
819
820 std::string counterHeader;
821
822 counterHeader.append(CentreAlignFormatting("Counter Name", 20));
823 counterHeader.append(" | ");
824 counterHeader.append(CentreAlignFormatting("Description", 50));
825 counterHeader.append(" | ");
826 counterHeader.append(CentreAlignFormatting("Units", 14));
827 counterHeader.append(" | ");
828 counterHeader.append(CentreAlignFormatting("UID", 6));
829 counterHeader.append(" | ");
830 counterHeader.append(CentreAlignFormatting("Max UID", 10));
831 counterHeader.append(" | ");
832 counterHeader.append(CentreAlignFormatting("Class", 8));
833 counterHeader.append(" | ");
834 counterHeader.append(CentreAlignFormatting("Interpolation", 14));
835 counterHeader.append(" | ");
836 counterHeader.append(CentreAlignFormatting("Multiplier", 20));
837 counterHeader.append(" | ");
838 counterHeader.append(CentreAlignFormatting("Counter set UID", 16));
839 counterHeader.append(" | ");
840 counterHeader.append(CentreAlignFormatting("Device UID", 14));
841 counterHeader.append("\n");
842
843 std::cout << "\n" << "\n";
844 std::cout << CentreAlignFormatting("EVENTS IN CATEGORY: " + category->m_Name,
845 static_cast<int>(counterHeader.size()));
846 std::cout << "\n";
847 std::cout << std::string(counterHeader.size(), '=') << "\n";
848 std::cout << counterHeader;
849 for (auto& it: category->m_Counters) {
850 auto search = counterMap.find(it);
851 if(search != counterMap.end()) {
852 PrintCounterDetails(search->second);
853 }
854 }
855}
856
857void PrintCounterDirectory(ICounterDirectory& counterDirectory)
858{
859 std::string devicesHeader;
860
861 devicesHeader.append(CentreAlignFormatting("Device name", 20));
862 devicesHeader.append(" | ");
863 devicesHeader.append(CentreAlignFormatting("UID", 13));
864 devicesHeader.append(" | ");
865 devicesHeader.append(CentreAlignFormatting("Cores", 10));
866 devicesHeader.append("\n");
867
868 std::cout << "\n" << "\n";
869 std::cout << CentreAlignFormatting("DEVICES", static_cast<int>(devicesHeader.size()));
870 std::cout << "\n";
871 std::cout << std::string(devicesHeader.size(), '=') << "\n";
872 std::cout << devicesHeader;
873 for (auto& it: counterDirectory.GetDevices()) {
874 PrintDeviceDetails(it);
875 }
876
877 std::string counterSetHeader;
878
879 counterSetHeader.append(CentreAlignFormatting("Counter set name", 20));
880 counterSetHeader.append(" | ");
881 counterSetHeader.append(CentreAlignFormatting("UID", 13));
882 counterSetHeader.append(" | ");
883 counterSetHeader.append(CentreAlignFormatting("Count", 10));
884 counterSetHeader.append("\n");
885
886 std::cout << "\n" << "\n";
887 std::cout << CentreAlignFormatting("COUNTER SETS", static_cast<int>(counterSetHeader.size()));
888 std::cout << "\n";
889 std::cout << std::string(counterSetHeader.size(), '=') << "\n";
890
891 std::cout << counterSetHeader;
892
893 for (auto& it: counterDirectory.GetCounterSets()) {
894 PrintCounterSetDetails(it);
895 }
896
897 auto counters = counterDirectory.GetCounters();
898 for (auto& it: counterDirectory.GetCategories()) {
899 PrintCategoryDetails(it, counters);
900 }
901 std::cout << "\n";
902}
903
Matteo Martincigh5dc816e2019-11-04 14:05:28 +0000904uint64_t GetTimestamp()
905{
906#if USE_CLOCK_MONOTONIC_RAW
907 using clock = MonotonicClockRaw;
908#else
909 using clock = std::chrono::steady_clock;
910#endif
911
912 // Take a timestamp
Finn Williamsd9ba1a72020-04-16 15:32:28 +0100913 auto timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(clock::now().time_since_epoch());
Matteo Martincigh5dc816e2019-11-04 14:05:28 +0000914
Finn Williamsd9ba1a72020-04-16 15:32:28 +0100915 return static_cast<uint64_t>(timestamp.count());
Matteo Martincigh5dc816e2019-11-04 14:05:28 +0000916}
Keith Davis3201eea2019-10-24 17:30:41 +0100917
Jim Flynnbbfe6032020-07-20 16:57:44 +0100918arm::pipe::Packet ReceivePacket(const unsigned char* buffer, uint32_t length)
Jim Flynn4e755a52020-03-29 17:48:26 +0100919{
920 if (buffer == nullptr)
921 {
Jim Flynnbbfe6032020-07-20 16:57:44 +0100922 throw arm::pipe::ProfilingException("data buffer is nullptr");
Jim Flynn4e755a52020-03-29 17:48:26 +0100923 }
924 if (length < 8)
925 {
Jim Flynnbbfe6032020-07-20 16:57:44 +0100926 throw arm::pipe::ProfilingException("length of data buffer is less than 8");
Jim Flynn4e755a52020-03-29 17:48:26 +0100927 }
928
929 uint32_t metadataIdentifier = 0;
930 std::memcpy(&metadataIdentifier, buffer, sizeof(metadataIdentifier));
931
932 uint32_t dataLength = 0;
933 std::memcpy(&dataLength, buffer + 4u, sizeof(dataLength));
934
935 std::unique_ptr<unsigned char[]> packetData;
936 if (dataLength > 0)
937 {
938 packetData = std::make_unique<unsigned char[]>(dataLength);
939 std::memcpy(packetData.get(), buffer + 8u, dataLength);
940 }
941
Jim Flynnbbfe6032020-07-20 16:57:44 +0100942 return arm::pipe::Packet(metadataIdentifier, dataLength, packetData);
Jim Flynn4e755a52020-03-29 17:48:26 +0100943}
944
Ferran Balaguer73882172019-09-02 16:39:42 +0100945} // namespace profiling
946
Matteo Martincigh149528e2019-09-05 12:02:04 +0100947} // namespace armnn
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000948
949namespace std
950{
951
Jim Flynn1fdeb992020-07-09 07:28:37 +0100952bool operator==(const std::vector<uint8_t>& left, int right)
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000953{
954 return std::memcmp(left.data(), &right, left.size()) == 0;
955}
956
957} // namespace std