blob: 36578684ca01938a59a7599fbb83e743832516c5 [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
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000022namespace arm
Ferran Balaguer73882172019-09-02 16:39:42 +010023{
24
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000025namespace pipe
Ferran Balaguer73882172019-09-02 16:39:42 +010026{
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 {
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000042 throw armnn::RuntimeException("Generating the next UID for profiling would result in an overflow");
Matteo Martincigh6db5f202019-09-05 12:02:04 +010043 }
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 {
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000050 throw armnn::RuntimeException("Generating the next UID for profiling would result in an overflow");
Matteo Martincigh6db5f202019-09-05 12:02:04 +010051 }
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 ReadBytes(const IPacketBufferPtr& packetBuffer, unsigned int offset, unsigned int valueSize, uint8_t outValue[])
143{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100144 ARMNN_ASSERT(packetBuffer);
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000145
146 ReadBytes(packetBuffer->GetReadableData(), offset, valueSize, outValue);
147}
148
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000149uint64_t ReadUint64(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100150{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100151 ARMNN_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100152
153 return ReadUint64(packetBuffer->GetReadableData(), offset);
154}
155
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000156uint32_t ReadUint32(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100157{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100158 ARMNN_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100159
160 return ReadUint32(packetBuffer->GetReadableData(), offset);
161}
162
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000163uint16_t ReadUint16(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100164{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100165 ARMNN_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100166
167 return ReadUint16(packetBuffer->GetReadableData(), offset);
168}
169
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000170uint8_t ReadUint8(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100171{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100172 ARMNN_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100173
174 return ReadUint8(packetBuffer->GetReadableData(), offset);
175}
176
Ferran Balaguer47d0fe92019-09-04 16:47:34 +0100177std::string GetSoftwareInfo()
178{
179 return std::string("ArmNN");
180}
181
182std::string GetHardwareVersion()
183{
184 return std::string();
185}
186
187std::string GetSoftwareVersion()
188{
Francis Murtaghd36c5282020-05-22 12:49:25 +0100189 std::string result = "Armnn " + std::to_string(ARMNN_MAJOR_VERSION) + "." + std::to_string(ARMNN_MINOR_VERSION);
Ferran Balaguer47d0fe92019-09-04 16:47:34 +0100190 return result;
191}
192
193std::string GetProcessName()
194{
195 std::ifstream comm("/proc/self/comm");
196 std::string name;
197 getline(comm, name);
198 return name;
199}
200
Jan Eilers92fa15b2019-10-15 15:23:25 +0100201/// Creates a timeline packet header
202///
203/// \params
204/// packetFamiliy Timeline Packet Family
205/// packetClass Timeline Packet Class
206/// packetType Timeline Packet Type
207/// streamId Stream identifier
208/// seqeunceNumbered When non-zero the 4 bytes following the header is a u32 sequence number
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100209/// dataLength Unsigned 24-bit integer. Length of data, in bytes. Zero is permitted
Jan Eilers92fa15b2019-10-15 15:23:25 +0100210///
211/// \returns
212/// Pair of uint32_t containing word0 and word1 of the header
213std::pair<uint32_t, uint32_t> CreateTimelinePacketHeader(uint32_t packetFamily,
214 uint32_t packetClass,
215 uint32_t packetType,
216 uint32_t streamId,
217 uint32_t sequenceNumbered,
218 uint32_t dataLength)
219{
220 // Packet header word 0:
221 // 26:31 [6] packet_family: timeline Packet Family, value 0b000001
222 // 19:25 [7] packet_class: packet class
223 // 16:18 [3] packet_type: packet type
224 // 8:15 [8] reserved: all zeros
225 // 0:7 [8] stream_id: stream identifier
226 uint32_t packetHeaderWord0 = ((packetFamily & 0x0000003F) << 26) |
227 ((packetClass & 0x0000007F) << 19) |
228 ((packetType & 0x00000007) << 16) |
229 ((streamId & 0x00000007) << 0);
230
231 // Packet header word 1:
232 // 25:31 [7] reserved: all zeros
233 // 24 [1] sequence_numbered: when non-zero the 4 bytes following the header is a u32 sequence number
234 // 0:23 [24] data_length: unsigned 24-bit integer. Length of data, in bytes. Zero is permitted
235 uint32_t packetHeaderWord1 = ((sequenceNumbered & 0x00000001) << 24) |
236 ((dataLength & 0x00FFFFFF) << 0);
237
238 return std::make_pair(packetHeaderWord0, packetHeaderWord1);
239}
240
241/// Creates a packet header for the timeline messages:
242/// * declareLabel
243/// * declareEntity
244/// * declareEventClass
245/// * declareRelationship
246/// * declareEvent
247///
248/// \param
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100249/// dataLength The length of the message body in bytes
Jan Eilers92fa15b2019-10-15 15:23:25 +0100250///
251/// \returns
252/// Pair of uint32_t containing word0 and word1 of the header
253std::pair<uint32_t, uint32_t> CreateTimelineMessagePacketHeader(unsigned int dataLength)
254{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100255 return CreateTimelinePacketHeader(1, // Packet family
256 0, // Packet class
257 1, // Packet type
258 0, // Stream id
259 0, // Sequence number
260 dataLength); // Data length
Jan Eilers92fa15b2019-10-15 15:23:25 +0100261}
262
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100263TimelinePacketStatus WriteTimelineLabelBinaryPacket(uint64_t profilingGuid,
264 const std::string& label,
265 unsigned char* buffer,
Keith Davis97da5e22020-03-05 16:25:28 +0000266 unsigned int remainingBufferSize,
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100267 unsigned int& numberOfBytesWritten)
268{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100269 // Initialize the output value
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100270 numberOfBytesWritten = 0;
271
272 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000273 if (buffer == nullptr || remainingBufferSize == 0)
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100274 {
275 return TimelinePacketStatus::BufferExhaustion;
276 }
277
278 // Utils
279 unsigned int uint32_t_size = sizeof(uint32_t);
280 unsigned int uint64_t_size = sizeof(uint64_t);
281
282 // Convert the label into a SWTrace string
283 std::vector<uint32_t> swTraceLabel;
Jim Flynnbbfe6032020-07-20 16:57:44 +0100284 bool result = arm::pipe::StringToSwTraceString<arm::pipe::SwTraceCharPolicy>(label, swTraceLabel);
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100285 if (!result)
286 {
287 return TimelinePacketStatus::Error;
288 }
289
290 // Calculate the size of the SWTrace string label (in bytes)
Matthew Sloyan371b70e2020-09-11 10:14:57 +0100291 unsigned int swTraceLabelSize = armnn::numeric_cast<unsigned int>(swTraceLabel.size()) * uint32_t_size;
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100292
293 // Calculate the length of the data (in bytes)
Jan Eilersb884ea42019-10-16 09:54:15 +0100294 unsigned int timelineLabelPacketDataLength = uint32_t_size + // decl_Id
295 uint64_t_size + // Profiling GUID
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100296 swTraceLabelSize; // Label
297
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100298 // Check whether the timeline binary packet fits in the given buffer
Keith Davis97da5e22020-03-05 16:25:28 +0000299 if (timelineLabelPacketDataLength > remainingBufferSize)
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100300 {
301 return TimelinePacketStatus::BufferExhaustion;
302 }
303
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100304 // Initialize the offset for writing in the buffer
305 unsigned int offset = 0;
306
Jan Eilersb884ea42019-10-16 09:54:15 +0100307 // Write decl_Id to the buffer
308 WriteUint32(buffer, offset, 0u);
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100309 offset += uint32_t_size;
310
311 // Write the timeline binary packet payload to the buffer
312 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
313 offset += uint64_t_size;
314 for (uint32_t swTraceLabelWord : swTraceLabel)
315 {
316 WriteUint32(buffer, offset, swTraceLabelWord); // Label
317 offset += uint32_t_size;
318 }
319
320 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000321 numberOfBytesWritten = timelineLabelPacketDataLength;
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100322
323 return TimelinePacketStatus::Ok;
324}
325
Keith Davis97da5e22020-03-05 16:25:28 +0000326TimelinePacketStatus WriteTimelineEntityBinary(uint64_t profilingGuid,
327 unsigned char* buffer,
328 unsigned int remainingBufferSize,
329 unsigned int& numberOfBytesWritten)
David Monahanf21f6062019-10-07 15:11:15 +0100330{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100331 // Initialize the output value
David Monahanf21f6062019-10-07 15:11:15 +0100332 numberOfBytesWritten = 0;
333
334 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000335 if (buffer == nullptr || remainingBufferSize == 0)
David Monahanf21f6062019-10-07 15:11:15 +0100336 {
337 return TimelinePacketStatus::BufferExhaustion;
338 }
339
340 // Utils
341 unsigned int uint32_t_size = sizeof(uint32_t);
342 unsigned int uint64_t_size = sizeof(uint64_t);
343
344 // Calculate the length of the data (in bytes)
Keith Davis97da5e22020-03-05 16:25:28 +0000345 unsigned int timelineEntityDataLength = uint32_t_size + uint64_t_size; // decl_id + Profiling GUID
David Monahanf21f6062019-10-07 15:11:15 +0100346
347 // Check whether the timeline binary packet fits in the given buffer
Keith Davis97da5e22020-03-05 16:25:28 +0000348 if (timelineEntityDataLength > remainingBufferSize)
David Monahanf21f6062019-10-07 15:11:15 +0100349 {
350 return TimelinePacketStatus::BufferExhaustion;
351 }
352
David Monahanf21f6062019-10-07 15:11:15 +0100353 // Initialize the offset for writing in the buffer
354 unsigned int offset = 0;
355
Jan Eilersb884ea42019-10-16 09:54:15 +0100356 // Write the decl_Id to the buffer
357 WriteUint32(buffer, offset, 1u);
David Monahanf21f6062019-10-07 15:11:15 +0100358 offset += uint32_t_size;
359
360 // Write the timeline binary packet payload to the buffer
361 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
362
363 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000364 numberOfBytesWritten = timelineEntityDataLength;
David Monahanf21f6062019-10-07 15:11:15 +0100365
366 return TimelinePacketStatus::Ok;
367}
368
Keith Davis97da5e22020-03-05 16:25:28 +0000369TimelinePacketStatus WriteTimelineRelationshipBinary(ProfilingRelationshipType relationshipType,
370 uint64_t relationshipGuid,
371 uint64_t headGuid,
372 uint64_t tailGuid,
Finn Williams0a336dc2020-05-11 15:39:58 +0100373 uint64_t attributeGuid,
Keith Davis97da5e22020-03-05 16:25:28 +0000374 unsigned char* buffer,
375 unsigned int remainingBufferSize,
376 unsigned int& numberOfBytesWritten)
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100377{
378 // Initialize the output value
379 numberOfBytesWritten = 0;
380
381 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000382 if (buffer == nullptr || remainingBufferSize == 0)
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100383 {
384 return TimelinePacketStatus::BufferExhaustion;
385 }
386
387 // Utils
388 unsigned int uint32_t_size = sizeof(uint32_t);
389 unsigned int uint64_t_size = sizeof(uint64_t);
390
391 // Calculate the length of the data (in bytes)
Keith Davis97da5e22020-03-05 16:25:28 +0000392 unsigned int timelineRelationshipDataLength = uint32_t_size * 2 + // decl_id + Relationship Type
Finn Williams0a336dc2020-05-11 15:39:58 +0100393 uint64_t_size * 4; // Relationship GUID + Head GUID +
394 // tail GUID + attributeGuid
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100395
Keith Davis97da5e22020-03-05 16:25:28 +0000396 // Check whether the timeline binary fits in the given buffer
397 if (timelineRelationshipDataLength > remainingBufferSize)
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100398 {
399 return TimelinePacketStatus::BufferExhaustion;
400 }
401
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100402 // Initialize the offset for writing in the buffer
403 unsigned int offset = 0;
404
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100405 uint32_t relationshipTypeUint = 0;
406
407 switch (relationshipType)
408 {
409 case ProfilingRelationshipType::RetentionLink:
410 relationshipTypeUint = 0;
411 break;
412 case ProfilingRelationshipType::ExecutionLink:
413 relationshipTypeUint = 1;
414 break;
415 case ProfilingRelationshipType::DataLink:
416 relationshipTypeUint = 2;
417 break;
418 case ProfilingRelationshipType::LabelLink:
419 relationshipTypeUint = 3;
420 break;
421 default:
422 throw InvalidArgumentException("Unknown relationship type given.");
423 }
424
Keith Davis97da5e22020-03-05 16:25:28 +0000425 // Write the timeline binary payload to the buffer
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100426 // decl_id of the timeline message
427 uint32_t declId = 3;
428 WriteUint32(buffer, offset, declId); // decl_id
429 offset += uint32_t_size;
430 WriteUint32(buffer, offset, relationshipTypeUint); // Relationship Type
431 offset += uint32_t_size;
432 WriteUint64(buffer, offset, relationshipGuid); // GUID of this relationship
433 offset += uint64_t_size;
434 WriteUint64(buffer, offset, headGuid); // head of relationship GUID
435 offset += uint64_t_size;
436 WriteUint64(buffer, offset, tailGuid); // tail of relationship GUID
Finn Williams0a336dc2020-05-11 15:39:58 +0100437 offset += uint64_t_size;
438 WriteUint64(buffer, offset, attributeGuid); // attribute of relationship GUID
439
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100440
441 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000442 numberOfBytesWritten = timelineRelationshipDataLength;
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100443
444 return TimelinePacketStatus::Ok;
445}
446
Sadik Armagan784db772019-10-08 15:05:38 +0100447TimelinePacketStatus WriteTimelineMessageDirectoryPackage(unsigned char* buffer,
Keith Davis97da5e22020-03-05 16:25:28 +0000448 unsigned int remainingBufferSize,
Sadik Armagan784db772019-10-08 15:05:38 +0100449 unsigned int& numberOfBytesWritten)
450{
451 // Initialize the output value
452 numberOfBytesWritten = 0;
453
454 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000455 if (buffer == nullptr || remainingBufferSize == 0)
Sadik Armagan784db772019-10-08 15:05:38 +0100456 {
457 return TimelinePacketStatus::BufferExhaustion;
458 }
459
460 // Utils
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000461 unsigned int uint8_t_size = sizeof(uint8_t);
Sadik Armagan784db772019-10-08 15:05:38 +0100462 unsigned int uint32_t_size = sizeof(uint32_t);
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000463 unsigned int uint64_t_size = sizeof(uint64_t);
Sadik Armagan784db772019-10-08 15:05:38 +0100464
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100465 // The payload/data of the packet consists of swtrace event definitions encoded according
Sadik Armagan784db772019-10-08 15:05:38 +0100466 // to the swtrace directory specification. The messages being the five defined below:
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000467 //
468 // | decl_id | decl_name | ui_name | arg_types | arg_names |
Sadik Armagan784db772019-10-08 15:05:38 +0100469 // |-----------|---------------------|-----------------------|-------------|-------------------------------------|
470 // | 0 | declareLabel | declare label | ps | guid,value |
471 // | 1 | declareEntity | declare entity | p | guid |
Jim Flynn6398a982020-05-27 17:05:21 +0100472 // | 2 | declareEventClass | declare event class | pp | guid,nameGuid |
473 // | 3 | declareRelationship | declare relationship | Ipppp | relationshipType,relationshipGuid, |
474 // | | | | | headGuid,tailGuid,attributeGuid |
Sadik Armagan784db772019-10-08 15:05:38 +0100475 // | 4 | declareEvent | declare event | @tp | timestamp,threadId,eventGuid |
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100476 std::vector<std::vector<std::string>> timelineDirectoryMessages
477 {
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000478 { "0", "declareLabel", "declare label", "ps", "guid,value" },
479 { "1", "declareEntity", "declare entity", "p", "guid" },
Jim Flynn6398a982020-05-27 17:05:21 +0100480 { "2", "declareEventClass", "declare event class", "pp", "guid,nameGuid" },
481 { "3", "declareRelationship", "declare relationship", "Ipppp",
482 "relationshipType,relationshipGuid,headGuid,tailGuid,attributeGuid" },
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000483 { "4", "declareEvent", "declare event", "@tp", "timestamp,threadId,eventGuid" }
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100484 };
Sadik Armagan784db772019-10-08 15:05:38 +0100485
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000486 // Build the message declarations
487 std::vector<uint32_t> swTraceBuffer;
488 for (const auto& directoryComponent : timelineDirectoryMessages)
Sadik Armagan784db772019-10-08 15:05:38 +0100489 {
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000490 // decl_id
491 uint32_t declId = 0;
492 try
Sadik Armagan784db772019-10-08 15:05:38 +0100493 {
Matthew Sloyan371b70e2020-09-11 10:14:57 +0100494 declId = armnn::numeric_cast<uint32_t>(std::stoul(directoryComponent[0]));
Sadik Armagan784db772019-10-08 15:05:38 +0100495 }
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000496 catch (const std::exception&)
497 {
498 return TimelinePacketStatus::Error;
499 }
500 swTraceBuffer.push_back(declId);
501
502 bool result = true;
Jim Flynnbbfe6032020-07-20 16:57:44 +0100503 result &= arm::pipe::ConvertDirectoryComponent<arm::pipe::SwTraceNameCharPolicy>(
504 directoryComponent[1], swTraceBuffer); // decl_name
505 result &= arm::pipe::ConvertDirectoryComponent<arm::pipe::SwTraceCharPolicy> (
506 directoryComponent[2], swTraceBuffer); // ui_name
507 result &= arm::pipe::ConvertDirectoryComponent<arm::pipe::SwTraceTypeCharPolicy>(
508 directoryComponent[3], swTraceBuffer); // arg_types
509 result &= arm::pipe::ConvertDirectoryComponent<arm::pipe::SwTraceCharPolicy> (
510 directoryComponent[4], swTraceBuffer); // arg_names
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000511 if (!result)
512 {
513 return TimelinePacketStatus::Error;
514 }
Sadik Armagan784db772019-10-08 15:05:38 +0100515 }
516
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000517 unsigned int dataLength = 3 * uint8_t_size + // Stream header (3 bytes)
Matthew Sloyan371b70e2020-09-11 10:14:57 +0100518 armnn::numeric_cast<unsigned int>(swTraceBuffer.size()) *
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000519 uint32_t_size; // Trace directory (5 messages)
520
Sadik Armagan784db772019-10-08 15:05:38 +0100521 // Calculate the timeline directory binary packet size (in bytes)
522 unsigned int timelineDirectoryPacketSize = 2 * uint32_t_size + // Header (2 words)
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000523 dataLength; // Payload
Sadik Armagan784db772019-10-08 15:05:38 +0100524
525 // Check whether the timeline directory binary packet fits in the given buffer
Keith Davis97da5e22020-03-05 16:25:28 +0000526 if (timelineDirectoryPacketSize > remainingBufferSize)
Sadik Armagan784db772019-10-08 15:05:38 +0100527 {
528 return TimelinePacketStatus::BufferExhaustion;
529 }
530
Jan Eilersb884ea42019-10-16 09:54:15 +0100531 // Create packet header
Matthew Sloyan371b70e2020-09-11 10:14:57 +0100532 auto packetHeader = CreateTimelinePacketHeader(1, 0, 0, 0, 0, armnn::numeric_cast<uint32_t>(dataLength));
Sadik Armagan784db772019-10-08 15:05:38 +0100533
534 // Initialize the offset for writing in the buffer
535 unsigned int offset = 0;
536
537 // Write the timeline binary packet header to the buffer
Jan Eilersb884ea42019-10-16 09:54:15 +0100538 WriteUint32(buffer, offset, packetHeader.first);
Sadik Armagan784db772019-10-08 15:05:38 +0100539 offset += uint32_t_size;
Jan Eilersb884ea42019-10-16 09:54:15 +0100540 WriteUint32(buffer, offset, packetHeader.second);
Sadik Armagan784db772019-10-08 15:05:38 +0100541 offset += uint32_t_size;
542
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000543 // Write the stream header
544 uint8_t streamVersion = 4;
Matthew Sloyan371b70e2020-09-11 10:14:57 +0100545 uint8_t pointerBytes = armnn::numeric_cast<uint8_t>(uint64_t_size); // All GUIDs are uint64_t
546 uint8_t threadIdBytes = armnn::numeric_cast<uint8_t>(ThreadIdSize);
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000547 switch (threadIdBytes)
Sadik Armagan784db772019-10-08 15:05:38 +0100548 {
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000549 case 4: // Typically Windows and Android
550 case 8: // Typically Linux
551 break; // Valid values
552 default:
553 return TimelinePacketStatus::Error; // Invalid value
554 }
555 WriteUint8(buffer, offset, streamVersion);
556 offset += uint8_t_size;
557 WriteUint8(buffer, offset, pointerBytes);
558 offset += uint8_t_size;
559 WriteUint8(buffer, offset, threadIdBytes);
560 offset += uint8_t_size;
Sadik Armagan784db772019-10-08 15:05:38 +0100561
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000562 // Write the SWTrace directory
Matthew Sloyan371b70e2020-09-11 10:14:57 +0100563 uint32_t numberOfDeclarations = armnn::numeric_cast<uint32_t>(timelineDirectoryMessages.size());
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000564 WriteUint32(buffer, offset, numberOfDeclarations); // Number of declarations
565 offset += uint32_t_size;
566 for (uint32_t i : swTraceBuffer)
567 {
568 WriteUint32(buffer, offset, i); // Message declarations
569 offset += uint32_t_size;
Sadik Armagan784db772019-10-08 15:05:38 +0100570 }
571
572 // Update the number of bytes written
573 numberOfBytesWritten = timelineDirectoryPacketSize;
574
575 return TimelinePacketStatus::Ok;
576}
577
Keith Davis97da5e22020-03-05 16:25:28 +0000578TimelinePacketStatus WriteTimelineEventClassBinary(uint64_t profilingGuid,
Jim Flynn1892d212020-05-26 21:10:49 +0100579 uint64_t nameGuid,
Keith Davis97da5e22020-03-05 16:25:28 +0000580 unsigned char* buffer,
581 unsigned int remainingBufferSize,
582 unsigned int& numberOfBytesWritten)
Jan Eilers92fa15b2019-10-15 15:23:25 +0100583{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100584 // Initialize the output value
Jan Eilers92fa15b2019-10-15 15:23:25 +0100585 numberOfBytesWritten = 0;
586
587 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000588 if (buffer == nullptr || remainingBufferSize == 0)
Jan Eilers92fa15b2019-10-15 15:23:25 +0100589 {
590 return TimelinePacketStatus::BufferExhaustion;
591 }
592
593 // Utils
594 unsigned int uint32_t_size = sizeof(uint32_t);
595 unsigned int uint64_t_size = sizeof(uint64_t);
596
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100597 // decl_id of the timeline message
598 uint32_t declId = 2;
Jan Eilers92fa15b2019-10-15 15:23:25 +0100599
600 // Calculate the length of the data (in bytes)
Jim Flynn1892d212020-05-26 21:10:49 +0100601 unsigned int dataSize = uint32_t_size + (uint64_t_size * 2); // decl_id + Profiling GUID + Name GUID
Jan Eilers92fa15b2019-10-15 15:23:25 +0100602
Keith Davis97da5e22020-03-05 16:25:28 +0000603 // Check whether the timeline binary fits in the given buffer
604 if (dataSize > remainingBufferSize)
Jan Eilers92fa15b2019-10-15 15:23:25 +0100605 {
606 return TimelinePacketStatus::BufferExhaustion;
607 }
608
Jan Eilers92fa15b2019-10-15 15:23:25 +0100609 // Initialize the offset for writing in the buffer
610 unsigned int offset = 0;
611
Keith Davis97da5e22020-03-05 16:25:28 +0000612 // Write the timeline binary payload to the buffer
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100613 WriteUint32(buffer, offset, declId); // decl_id
Jan Eilers92fa15b2019-10-15 15:23:25 +0100614 offset += uint32_t_size;
615 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
Jim Flynn1892d212020-05-26 21:10:49 +0100616 offset += uint64_t_size;
617 WriteUint64(buffer, offset, nameGuid); // Name GUID
Jan Eilers92fa15b2019-10-15 15:23:25 +0100618
619 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000620 numberOfBytesWritten = dataSize;
Jan Eilers92fa15b2019-10-15 15:23:25 +0100621
622 return TimelinePacketStatus::Ok;
623}
624
Keith Davis97da5e22020-03-05 16:25:28 +0000625TimelinePacketStatus WriteTimelineEventBinary(uint64_t timestamp,
Jim Flynn1fdeb992020-07-09 07:28:37 +0100626 int threadId,
Keith Davis97da5e22020-03-05 16:25:28 +0000627 uint64_t profilingGuid,
628 unsigned char* buffer,
629 unsigned int remainingBufferSize,
630 unsigned int& numberOfBytesWritten)
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100631{
632 // Initialize the output value
633 numberOfBytesWritten = 0;
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100634 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000635 if (buffer == nullptr || remainingBufferSize == 0)
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100636 {
637 return TimelinePacketStatus::BufferExhaustion;
638 }
639
640 // Utils
641 unsigned int uint32_t_size = sizeof(uint32_t);
642 unsigned int uint64_t_size = sizeof(uint64_t);
643
644 // decl_id of the timeline message
645 uint32_t declId = 4;
646
647 // Calculate the length of the data (in bytes)
Keith Davis97da5e22020-03-05 16:25:28 +0000648 unsigned int timelineEventDataLength = uint32_t_size + // decl_id
649 uint64_t_size + // Timestamp
Colm Donelan5bb3d8a2020-05-12 16:36:46 +0100650 ThreadIdSize + // Thread id
Keith Davis97da5e22020-03-05 16:25:28 +0000651 uint64_t_size; // Profiling GUID
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100652
653 // Check whether the timeline binary packet fits in the given buffer
Keith Davis97da5e22020-03-05 16:25:28 +0000654 if (timelineEventDataLength > remainingBufferSize)
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100655 {
656 return TimelinePacketStatus::BufferExhaustion;
657 }
658
Matteo Martincigh8844c2f2019-10-16 10:29:17 +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
664 offset += uint32_t_size;
665 WriteUint64(buffer, offset, timestamp); // Timestamp
666 offset += uint64_t_size;
Colm Donelan5bb3d8a2020-05-12 16:36:46 +0100667 WriteBytes(buffer, offset, &threadId, ThreadIdSize); // Thread id
668 offset += ThreadIdSize;
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100669 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
670 offset += uint64_t_size;
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100671 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000672 numberOfBytesWritten = timelineEventDataLength;
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100673
674 return TimelinePacketStatus::Ok;
675}
676
Keith Davis3201eea2019-10-24 17:30:41 +0100677void PrintDeviceDetails(const std::pair<const unsigned short, std::unique_ptr<Device>>& devicePair)
678{
679 std::string body;
680
681 body.append(CentreAlignFormatting(devicePair.second->m_Name, 20));
682 body.append(" | ");
683 body.append(CentreAlignFormatting(std::to_string(devicePair.first), 13));
684 body.append(" | ");
685 body.append(CentreAlignFormatting(std::to_string(devicePair.second->m_Cores), 10));
686 body.append("\n");
687
688 std::cout << std::string(body.size(), '-') << "\n";
689 std::cout<< body;
690}
691
692void PrintCounterSetDetails(const std::pair<const unsigned short, std::unique_ptr<CounterSet>>& counterSetPair)
693{
694 std::string body;
695
696 body.append(CentreAlignFormatting(counterSetPair.second->m_Name, 20));
697 body.append(" | ");
698 body.append(CentreAlignFormatting(std::to_string(counterSetPair.first), 13));
699 body.append(" | ");
700 body.append(CentreAlignFormatting(std::to_string(counterSetPair.second->m_Count), 10));
701 body.append("\n");
702
703 std::cout << std::string(body.size(), '-') << "\n";
704
705 std::cout<< body;
706}
707
708void PrintCounterDetails(std::shared_ptr<Counter>& counter)
709{
710 std::string body;
711
712 body.append(CentreAlignFormatting(counter->m_Name, 20));
713 body.append(" | ");
714 body.append(CentreAlignFormatting(counter->m_Description, 50));
715 body.append(" | ");
716 body.append(CentreAlignFormatting(counter->m_Units, 14));
717 body.append(" | ");
718 body.append(CentreAlignFormatting(std::to_string(counter->m_Uid), 6));
719 body.append(" | ");
720 body.append(CentreAlignFormatting(std::to_string(counter->m_MaxCounterUid), 10));
721 body.append(" | ");
722 body.append(CentreAlignFormatting(std::to_string(counter->m_Class), 8));
723 body.append(" | ");
724 body.append(CentreAlignFormatting(std::to_string(counter->m_Interpolation), 14));
725 body.append(" | ");
726 body.append(CentreAlignFormatting(std::to_string(counter->m_Multiplier), 20));
727 body.append(" | ");
728 body.append(CentreAlignFormatting(std::to_string(counter->m_CounterSetUid), 16));
729 body.append(" | ");
730 body.append(CentreAlignFormatting(std::to_string(counter->m_DeviceUid), 14));
731
732 body.append("\n");
733
734 std::cout << std::string(body.size(), '-') << "\n";
735
736 std::cout << body;
737}
738
739void PrintCategoryDetails(const std::unique_ptr<Category>& category,
740 std::unordered_map<unsigned short, std::shared_ptr<Counter>> counterMap)
741{
742 std::string categoryBody;
743 std::string categoryHeader;
744
745 categoryHeader.append(CentreAlignFormatting("Name", 20));
746 categoryHeader.append(" | ");
Keith Davis3201eea2019-10-24 17:30:41 +0100747 categoryHeader.append(CentreAlignFormatting("Event Count", 14));
748 categoryHeader.append("\n");
749
750 categoryBody.append(CentreAlignFormatting(category->m_Name, 20));
751 categoryBody.append(" | ");
Keith Davis3201eea2019-10-24 17:30:41 +0100752 categoryBody.append(CentreAlignFormatting(std::to_string(category->m_Counters.size()), 14));
753
754 std::cout << "\n" << "\n";
755 std::cout << CentreAlignFormatting("CATEGORY", static_cast<int>(categoryHeader.size()));
756 std::cout << "\n";
757 std::cout << std::string(categoryHeader.size(), '=') << "\n";
758
759 std::cout << categoryHeader;
760
761 std::cout << std::string(categoryBody.size(), '-') << "\n";
762
763 std::cout << categoryBody;
764
765 std::string counterHeader;
766
767 counterHeader.append(CentreAlignFormatting("Counter Name", 20));
768 counterHeader.append(" | ");
769 counterHeader.append(CentreAlignFormatting("Description", 50));
770 counterHeader.append(" | ");
771 counterHeader.append(CentreAlignFormatting("Units", 14));
772 counterHeader.append(" | ");
773 counterHeader.append(CentreAlignFormatting("UID", 6));
774 counterHeader.append(" | ");
775 counterHeader.append(CentreAlignFormatting("Max UID", 10));
776 counterHeader.append(" | ");
777 counterHeader.append(CentreAlignFormatting("Class", 8));
778 counterHeader.append(" | ");
779 counterHeader.append(CentreAlignFormatting("Interpolation", 14));
780 counterHeader.append(" | ");
781 counterHeader.append(CentreAlignFormatting("Multiplier", 20));
782 counterHeader.append(" | ");
783 counterHeader.append(CentreAlignFormatting("Counter set UID", 16));
784 counterHeader.append(" | ");
785 counterHeader.append(CentreAlignFormatting("Device UID", 14));
786 counterHeader.append("\n");
787
788 std::cout << "\n" << "\n";
789 std::cout << CentreAlignFormatting("EVENTS IN CATEGORY: " + category->m_Name,
790 static_cast<int>(counterHeader.size()));
791 std::cout << "\n";
792 std::cout << std::string(counterHeader.size(), '=') << "\n";
793 std::cout << counterHeader;
794 for (auto& it: category->m_Counters) {
795 auto search = counterMap.find(it);
796 if(search != counterMap.end()) {
797 PrintCounterDetails(search->second);
798 }
799 }
800}
801
802void PrintCounterDirectory(ICounterDirectory& counterDirectory)
803{
804 std::string devicesHeader;
805
806 devicesHeader.append(CentreAlignFormatting("Device name", 20));
807 devicesHeader.append(" | ");
808 devicesHeader.append(CentreAlignFormatting("UID", 13));
809 devicesHeader.append(" | ");
810 devicesHeader.append(CentreAlignFormatting("Cores", 10));
811 devicesHeader.append("\n");
812
813 std::cout << "\n" << "\n";
814 std::cout << CentreAlignFormatting("DEVICES", static_cast<int>(devicesHeader.size()));
815 std::cout << "\n";
816 std::cout << std::string(devicesHeader.size(), '=') << "\n";
817 std::cout << devicesHeader;
818 for (auto& it: counterDirectory.GetDevices()) {
819 PrintDeviceDetails(it);
820 }
821
822 std::string counterSetHeader;
823
824 counterSetHeader.append(CentreAlignFormatting("Counter set name", 20));
825 counterSetHeader.append(" | ");
826 counterSetHeader.append(CentreAlignFormatting("UID", 13));
827 counterSetHeader.append(" | ");
828 counterSetHeader.append(CentreAlignFormatting("Count", 10));
829 counterSetHeader.append("\n");
830
831 std::cout << "\n" << "\n";
832 std::cout << CentreAlignFormatting("COUNTER SETS", static_cast<int>(counterSetHeader.size()));
833 std::cout << "\n";
834 std::cout << std::string(counterSetHeader.size(), '=') << "\n";
835
836 std::cout << counterSetHeader;
837
838 for (auto& it: counterDirectory.GetCounterSets()) {
839 PrintCounterSetDetails(it);
840 }
841
842 auto counters = counterDirectory.GetCounters();
843 for (auto& it: counterDirectory.GetCategories()) {
844 PrintCategoryDetails(it, counters);
845 }
846 std::cout << "\n";
847}
848
Matteo Martincigh5dc816e2019-11-04 14:05:28 +0000849uint64_t GetTimestamp()
850{
851#if USE_CLOCK_MONOTONIC_RAW
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000852 using clock = armnn::MonotonicClockRaw;
Matteo Martincigh5dc816e2019-11-04 14:05:28 +0000853#else
854 using clock = std::chrono::steady_clock;
855#endif
856
857 // Take a timestamp
Finn Williamsd9ba1a72020-04-16 15:32:28 +0100858 auto timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(clock::now().time_since_epoch());
Matteo Martincigh5dc816e2019-11-04 14:05:28 +0000859
Finn Williamsd9ba1a72020-04-16 15:32:28 +0100860 return static_cast<uint64_t>(timestamp.count());
Matteo Martincigh5dc816e2019-11-04 14:05:28 +0000861}
Keith Davis3201eea2019-10-24 17:30:41 +0100862
Jim Flynnbbfe6032020-07-20 16:57:44 +0100863arm::pipe::Packet ReceivePacket(const unsigned char* buffer, uint32_t length)
Jim Flynn4e755a52020-03-29 17:48:26 +0100864{
865 if (buffer == nullptr)
866 {
Jim Flynnbbfe6032020-07-20 16:57:44 +0100867 throw arm::pipe::ProfilingException("data buffer is nullptr");
Jim Flynn4e755a52020-03-29 17:48:26 +0100868 }
869 if (length < 8)
870 {
Jim Flynnbbfe6032020-07-20 16:57:44 +0100871 throw arm::pipe::ProfilingException("length of data buffer is less than 8");
Jim Flynn4e755a52020-03-29 17:48:26 +0100872 }
873
874 uint32_t metadataIdentifier = 0;
875 std::memcpy(&metadataIdentifier, buffer, sizeof(metadataIdentifier));
876
877 uint32_t dataLength = 0;
878 std::memcpy(&dataLength, buffer + 4u, sizeof(dataLength));
879
880 std::unique_ptr<unsigned char[]> packetData;
881 if (dataLength > 0)
882 {
883 packetData = std::make_unique<unsigned char[]>(dataLength);
884 std::memcpy(packetData.get(), buffer + 8u, dataLength);
885 }
886
Jim Flynnbbfe6032020-07-20 16:57:44 +0100887 return arm::pipe::Packet(metadataIdentifier, dataLength, packetData);
Jim Flynn4e755a52020-03-29 17:48:26 +0100888}
889
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000890} // namespace pipe
Ferran Balaguer73882172019-09-02 16:39:42 +0100891
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000892} // namespace arm
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000893
894namespace std
895{
896
Jim Flynn1fdeb992020-07-09 07:28:37 +0100897bool operator==(const std::vector<uint8_t>& left, int right)
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000898{
899 return std::memcmp(left.data(), &right, left.size()) == 0;
900}
901
902} // namespace std