blob: 2963a9862184ccabd21dcb9dd9fd3f9a43d3ef6d [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 Flynn6730fe92022-03-10 22:57:47 +00008#include <common/include/Assert.hpp>
Jim Flynnbbfe6032020-07-20 16:57:44 +01009#include <common/include/CommonProfilingUtils.hpp>
Jim Flynn9c85b412022-03-16 00:27:43 +000010#include <common/include/NumericCast.hpp>
Jim Flynnbbfe6032020-07-20 16:57:44 +010011#include <common/include/ProfilingException.hpp>
12#include <common/include/SwTrace.hpp>
Jim Flynn4e755a52020-03-29 17:48:26 +010013
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010014#include <armnn/Version.hpp>
15
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010016#include <fstream>
Keith Davis3201eea2019-10-24 17:30:41 +010017#include <iostream>
Matteo Martincighab173e92019-09-05 12:02:04 +010018#include <limits>
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010019
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000020namespace arm
Ferran Balaguer73882172019-09-02 16:39:42 +010021{
22
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000023namespace pipe
Ferran Balaguer73882172019-09-02 16:39:42 +010024{
25
Matteo Martincigh378bbfc2019-11-04 14:05:28 +000026void WriteBytes(const IPacketBufferPtr& packetBuffer, unsigned int offset, const void* value, unsigned int valueSize)
27{
Jim Flynn6730fe92022-03-10 22:57:47 +000028 ARM_PIPE_ASSERT(packetBuffer);
Matteo Martincigh378bbfc2019-11-04 14:05:28 +000029
30 WriteBytes(packetBuffer->GetWritableData(), offset, value, valueSize);
31}
32
Keith Davis3201eea2019-10-24 17:30:41 +010033uint32_t ConstructHeader(uint32_t packetFamily,
34 uint32_t packetId)
35{
Keith Davis33ed2212020-03-30 10:43:41 +010036 return (( packetFamily & 0x0000003F ) << 26 )|
Jim Flynn83d08a92020-07-09 13:48:16 +010037 (( packetId & 0x000003FF ) << 16 );
38}
39
40uint32_t ConstructHeader(uint32_t packetFamily, uint32_t packetClass, uint32_t packetType)
41{
42 return ((packetFamily & 0x0000003F) << 26) |
43 ((packetClass & 0x0000007F) << 19) |
44 ((packetType & 0x00000007) << 16);
Keith Davis3201eea2019-10-24 17:30:41 +010045}
46
47void WriteUint64(const std::unique_ptr<IPacketBuffer>& packetBuffer, unsigned int offset, uint64_t value)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010048{
Jim Flynn6730fe92022-03-10 22:57:47 +000049 ARM_PIPE_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010050
51 WriteUint64(packetBuffer->GetWritableData(), offset, value);
52}
53
Matteo Martincigh2ffcc412019-11-05 11:47:40 +000054void WriteUint32(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint32_t value)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010055{
Jim Flynn6730fe92022-03-10 22:57:47 +000056 ARM_PIPE_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010057
58 WriteUint32(packetBuffer->GetWritableData(), offset, value);
59}
60
Matteo Martincigh2ffcc412019-11-05 11:47:40 +000061void WriteUint16(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint16_t value)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010062{
Jim Flynn6730fe92022-03-10 22:57:47 +000063 ARM_PIPE_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010064
65 WriteUint16(packetBuffer->GetWritableData(), offset, value);
66}
67
Matteo Martincigh34a407d2019-11-06 15:30:54 +000068void WriteUint8(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint8_t value)
69{
Jim Flynn6730fe92022-03-10 22:57:47 +000070 ARM_PIPE_ASSERT(packetBuffer);
Matteo Martincigh34a407d2019-11-06 15:30:54 +000071
72 WriteUint8(packetBuffer->GetWritableData(), offset, value);
73}
74
Matteo Martincigh378bbfc2019-11-04 14:05:28 +000075void ReadBytes(const IPacketBufferPtr& packetBuffer, unsigned int offset, unsigned int valueSize, uint8_t outValue[])
76{
Jim Flynn6730fe92022-03-10 22:57:47 +000077 ARM_PIPE_ASSERT(packetBuffer);
Matteo Martincigh378bbfc2019-11-04 14:05:28 +000078
79 ReadBytes(packetBuffer->GetReadableData(), offset, valueSize, outValue);
80}
81
Matteo Martincigh2ffcc412019-11-05 11:47:40 +000082uint64_t ReadUint64(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010083{
Jim Flynn6730fe92022-03-10 22:57:47 +000084 ARM_PIPE_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010085
86 return ReadUint64(packetBuffer->GetReadableData(), offset);
87}
88
Matteo Martincigh2ffcc412019-11-05 11:47:40 +000089uint32_t ReadUint32(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010090{
Jim Flynn6730fe92022-03-10 22:57:47 +000091 ARM_PIPE_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010092
93 return ReadUint32(packetBuffer->GetReadableData(), offset);
94}
95
Matteo Martincigh2ffcc412019-11-05 11:47:40 +000096uint16_t ReadUint16(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010097{
Jim Flynn6730fe92022-03-10 22:57:47 +000098 ARM_PIPE_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010099
100 return ReadUint16(packetBuffer->GetReadableData(), offset);
101}
102
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000103uint8_t ReadUint8(const IPacketBufferPtr& packetBuffer, unsigned int offset)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100104{
Jim Flynn6730fe92022-03-10 22:57:47 +0000105 ARM_PIPE_ASSERT(packetBuffer);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100106
107 return ReadUint8(packetBuffer->GetReadableData(), offset);
108}
109
Ferran Balaguer47d0fe92019-09-04 16:47:34 +0100110std::string GetProcessName()
111{
112 std::ifstream comm("/proc/self/comm");
113 std::string name;
114 getline(comm, name);
115 return name;
116}
117
Jan Eilers92fa15b2019-10-15 15:23:25 +0100118/// Creates a timeline packet header
119///
120/// \params
121/// packetFamiliy Timeline Packet Family
122/// packetClass Timeline Packet Class
123/// packetType Timeline Packet Type
124/// streamId Stream identifier
125/// seqeunceNumbered When non-zero the 4 bytes following the header is a u32 sequence number
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100126/// dataLength Unsigned 24-bit integer. Length of data, in bytes. Zero is permitted
Jan Eilers92fa15b2019-10-15 15:23:25 +0100127///
128/// \returns
129/// Pair of uint32_t containing word0 and word1 of the header
130std::pair<uint32_t, uint32_t> CreateTimelinePacketHeader(uint32_t packetFamily,
131 uint32_t packetClass,
132 uint32_t packetType,
133 uint32_t streamId,
134 uint32_t sequenceNumbered,
135 uint32_t dataLength)
136{
137 // Packet header word 0:
138 // 26:31 [6] packet_family: timeline Packet Family, value 0b000001
139 // 19:25 [7] packet_class: packet class
140 // 16:18 [3] packet_type: packet type
141 // 8:15 [8] reserved: all zeros
142 // 0:7 [8] stream_id: stream identifier
143 uint32_t packetHeaderWord0 = ((packetFamily & 0x0000003F) << 26) |
144 ((packetClass & 0x0000007F) << 19) |
145 ((packetType & 0x00000007) << 16) |
146 ((streamId & 0x00000007) << 0);
147
148 // Packet header word 1:
149 // 25:31 [7] reserved: all zeros
150 // 24 [1] sequence_numbered: when non-zero the 4 bytes following the header is a u32 sequence number
151 // 0:23 [24] data_length: unsigned 24-bit integer. Length of data, in bytes. Zero is permitted
152 uint32_t packetHeaderWord1 = ((sequenceNumbered & 0x00000001) << 24) |
153 ((dataLength & 0x00FFFFFF) << 0);
154
155 return std::make_pair(packetHeaderWord0, packetHeaderWord1);
156}
157
158/// Creates a packet header for the timeline messages:
159/// * declareLabel
160/// * declareEntity
161/// * declareEventClass
162/// * declareRelationship
163/// * declareEvent
164///
165/// \param
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100166/// dataLength The length of the message body in bytes
Jan Eilers92fa15b2019-10-15 15:23:25 +0100167///
168/// \returns
169/// Pair of uint32_t containing word0 and word1 of the header
170std::pair<uint32_t, uint32_t> CreateTimelineMessagePacketHeader(unsigned int dataLength)
171{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100172 return CreateTimelinePacketHeader(1, // Packet family
173 0, // Packet class
174 1, // Packet type
175 0, // Stream id
176 0, // Sequence number
177 dataLength); // Data length
Jan Eilers92fa15b2019-10-15 15:23:25 +0100178}
179
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100180TimelinePacketStatus WriteTimelineLabelBinaryPacket(uint64_t profilingGuid,
181 const std::string& label,
182 unsigned char* buffer,
Keith Davis97da5e22020-03-05 16:25:28 +0000183 unsigned int remainingBufferSize,
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100184 unsigned int& numberOfBytesWritten)
185{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100186 // Initialize the output value
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100187 numberOfBytesWritten = 0;
188
189 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000190 if (buffer == nullptr || remainingBufferSize == 0)
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100191 {
192 return TimelinePacketStatus::BufferExhaustion;
193 }
194
195 // Utils
196 unsigned int uint32_t_size = sizeof(uint32_t);
197 unsigned int uint64_t_size = sizeof(uint64_t);
198
199 // Convert the label into a SWTrace string
200 std::vector<uint32_t> swTraceLabel;
Jim Flynnbbfe6032020-07-20 16:57:44 +0100201 bool result = arm::pipe::StringToSwTraceString<arm::pipe::SwTraceCharPolicy>(label, swTraceLabel);
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100202 if (!result)
203 {
204 return TimelinePacketStatus::Error;
205 }
206
207 // Calculate the size of the SWTrace string label (in bytes)
Jim Flynn75c14f42022-03-10 22:05:42 +0000208 unsigned int swTraceLabelSize = arm::pipe::numeric_cast<unsigned int>(swTraceLabel.size()) * uint32_t_size;
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100209
210 // Calculate the length of the data (in bytes)
Jan Eilersb884ea42019-10-16 09:54:15 +0100211 unsigned int timelineLabelPacketDataLength = uint32_t_size + // decl_Id
212 uint64_t_size + // Profiling GUID
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100213 swTraceLabelSize; // Label
214
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100215 // Check whether the timeline binary packet fits in the given buffer
Keith Davis97da5e22020-03-05 16:25:28 +0000216 if (timelineLabelPacketDataLength > remainingBufferSize)
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100217 {
218 return TimelinePacketStatus::BufferExhaustion;
219 }
220
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100221 // Initialize the offset for writing in the buffer
222 unsigned int offset = 0;
223
Jan Eilersb884ea42019-10-16 09:54:15 +0100224 // Write decl_Id to the buffer
225 WriteUint32(buffer, offset, 0u);
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100226 offset += uint32_t_size;
227
228 // Write the timeline binary packet payload to the buffer
229 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
230 offset += uint64_t_size;
231 for (uint32_t swTraceLabelWord : swTraceLabel)
232 {
233 WriteUint32(buffer, offset, swTraceLabelWord); // Label
234 offset += uint32_t_size;
235 }
236
237 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000238 numberOfBytesWritten = timelineLabelPacketDataLength;
Matteo Martincigh0aed4f92019-10-01 14:25:34 +0100239
240 return TimelinePacketStatus::Ok;
241}
242
Keith Davis97da5e22020-03-05 16:25:28 +0000243TimelinePacketStatus WriteTimelineEntityBinary(uint64_t profilingGuid,
244 unsigned char* buffer,
245 unsigned int remainingBufferSize,
246 unsigned int& numberOfBytesWritten)
David Monahanf21f6062019-10-07 15:11:15 +0100247{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100248 // Initialize the output value
David Monahanf21f6062019-10-07 15:11:15 +0100249 numberOfBytesWritten = 0;
250
251 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000252 if (buffer == nullptr || remainingBufferSize == 0)
David Monahanf21f6062019-10-07 15:11:15 +0100253 {
254 return TimelinePacketStatus::BufferExhaustion;
255 }
256
257 // Utils
258 unsigned int uint32_t_size = sizeof(uint32_t);
259 unsigned int uint64_t_size = sizeof(uint64_t);
260
261 // Calculate the length of the data (in bytes)
Keith Davis97da5e22020-03-05 16:25:28 +0000262 unsigned int timelineEntityDataLength = uint32_t_size + uint64_t_size; // decl_id + Profiling GUID
David Monahanf21f6062019-10-07 15:11:15 +0100263
264 // Check whether the timeline binary packet fits in the given buffer
Keith Davis97da5e22020-03-05 16:25:28 +0000265 if (timelineEntityDataLength > remainingBufferSize)
David Monahanf21f6062019-10-07 15:11:15 +0100266 {
267 return TimelinePacketStatus::BufferExhaustion;
268 }
269
David Monahanf21f6062019-10-07 15:11:15 +0100270 // Initialize the offset for writing in the buffer
271 unsigned int offset = 0;
272
Jan Eilersb884ea42019-10-16 09:54:15 +0100273 // Write the decl_Id to the buffer
274 WriteUint32(buffer, offset, 1u);
David Monahanf21f6062019-10-07 15:11:15 +0100275 offset += uint32_t_size;
276
277 // Write the timeline binary packet payload to the buffer
278 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
279
280 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000281 numberOfBytesWritten = timelineEntityDataLength;
David Monahanf21f6062019-10-07 15:11:15 +0100282
283 return TimelinePacketStatus::Ok;
284}
285
Keith Davis97da5e22020-03-05 16:25:28 +0000286TimelinePacketStatus WriteTimelineRelationshipBinary(ProfilingRelationshipType relationshipType,
287 uint64_t relationshipGuid,
288 uint64_t headGuid,
289 uint64_t tailGuid,
Finn Williams0a336dc2020-05-11 15:39:58 +0100290 uint64_t attributeGuid,
Keith Davis97da5e22020-03-05 16:25:28 +0000291 unsigned char* buffer,
292 unsigned int remainingBufferSize,
293 unsigned int& numberOfBytesWritten)
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100294{
295 // Initialize the output value
296 numberOfBytesWritten = 0;
297
298 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000299 if (buffer == nullptr || remainingBufferSize == 0)
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100300 {
301 return TimelinePacketStatus::BufferExhaustion;
302 }
303
304 // Utils
305 unsigned int uint32_t_size = sizeof(uint32_t);
306 unsigned int uint64_t_size = sizeof(uint64_t);
307
308 // Calculate the length of the data (in bytes)
Keith Davis97da5e22020-03-05 16:25:28 +0000309 unsigned int timelineRelationshipDataLength = uint32_t_size * 2 + // decl_id + Relationship Type
Finn Williams0a336dc2020-05-11 15:39:58 +0100310 uint64_t_size * 4; // Relationship GUID + Head GUID +
311 // tail GUID + attributeGuid
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100312
Keith Davis97da5e22020-03-05 16:25:28 +0000313 // Check whether the timeline binary fits in the given buffer
314 if (timelineRelationshipDataLength > remainingBufferSize)
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100315 {
316 return TimelinePacketStatus::BufferExhaustion;
317 }
318
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100319 // Initialize the offset for writing in the buffer
320 unsigned int offset = 0;
321
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100322 uint32_t relationshipTypeUint = 0;
323
324 switch (relationshipType)
325 {
326 case ProfilingRelationshipType::RetentionLink:
327 relationshipTypeUint = 0;
328 break;
329 case ProfilingRelationshipType::ExecutionLink:
330 relationshipTypeUint = 1;
331 break;
332 case ProfilingRelationshipType::DataLink:
333 relationshipTypeUint = 2;
334 break;
335 case ProfilingRelationshipType::LabelLink:
336 relationshipTypeUint = 3;
337 break;
338 default:
Jim Flynnf9db3ef2022-03-08 21:23:44 +0000339 throw arm::pipe::InvalidArgumentException("Unknown relationship type given.");
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100340 }
341
Keith Davis97da5e22020-03-05 16:25:28 +0000342 // Write the timeline binary payload to the buffer
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100343 // decl_id of the timeline message
344 uint32_t declId = 3;
345 WriteUint32(buffer, offset, declId); // decl_id
346 offset += uint32_t_size;
347 WriteUint32(buffer, offset, relationshipTypeUint); // Relationship Type
348 offset += uint32_t_size;
349 WriteUint64(buffer, offset, relationshipGuid); // GUID of this relationship
350 offset += uint64_t_size;
351 WriteUint64(buffer, offset, headGuid); // head of relationship GUID
352 offset += uint64_t_size;
353 WriteUint64(buffer, offset, tailGuid); // tail of relationship GUID
Finn Williams0a336dc2020-05-11 15:39:58 +0100354 offset += uint64_t_size;
355 WriteUint64(buffer, offset, attributeGuid); // attribute of relationship GUID
356
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100357
358 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000359 numberOfBytesWritten = timelineRelationshipDataLength;
Narumol Prangnawarat7e5eec72019-10-16 12:16:26 +0100360
361 return TimelinePacketStatus::Ok;
362}
363
Sadik Armagan784db772019-10-08 15:05:38 +0100364TimelinePacketStatus WriteTimelineMessageDirectoryPackage(unsigned char* buffer,
Keith Davis97da5e22020-03-05 16:25:28 +0000365 unsigned int remainingBufferSize,
Sadik Armagan784db772019-10-08 15:05:38 +0100366 unsigned int& numberOfBytesWritten)
367{
368 // Initialize the output value
369 numberOfBytesWritten = 0;
370
371 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000372 if (buffer == nullptr || remainingBufferSize == 0)
Sadik Armagan784db772019-10-08 15:05:38 +0100373 {
374 return TimelinePacketStatus::BufferExhaustion;
375 }
376
377 // Utils
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000378 unsigned int uint8_t_size = sizeof(uint8_t);
Sadik Armagan784db772019-10-08 15:05:38 +0100379 unsigned int uint32_t_size = sizeof(uint32_t);
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000380 unsigned int uint64_t_size = sizeof(uint64_t);
Sadik Armagan784db772019-10-08 15:05:38 +0100381
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100382 // The payload/data of the packet consists of swtrace event definitions encoded according
Sadik Armagan784db772019-10-08 15:05:38 +0100383 // to the swtrace directory specification. The messages being the five defined below:
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000384 //
385 // | decl_id | decl_name | ui_name | arg_types | arg_names |
Sadik Armagan784db772019-10-08 15:05:38 +0100386 // |-----------|---------------------|-----------------------|-------------|-------------------------------------|
387 // | 0 | declareLabel | declare label | ps | guid,value |
388 // | 1 | declareEntity | declare entity | p | guid |
Jim Flynn6398a982020-05-27 17:05:21 +0100389 // | 2 | declareEventClass | declare event class | pp | guid,nameGuid |
390 // | 3 | declareRelationship | declare relationship | Ipppp | relationshipType,relationshipGuid, |
391 // | | | | | headGuid,tailGuid,attributeGuid |
Sadik Armagan784db772019-10-08 15:05:38 +0100392 // | 4 | declareEvent | declare event | @tp | timestamp,threadId,eventGuid |
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100393 std::vector<std::vector<std::string>> timelineDirectoryMessages
394 {
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000395 { "0", "declareLabel", "declare label", "ps", "guid,value" },
396 { "1", "declareEntity", "declare entity", "p", "guid" },
Jim Flynn6398a982020-05-27 17:05:21 +0100397 { "2", "declareEventClass", "declare event class", "pp", "guid,nameGuid" },
398 { "3", "declareRelationship", "declare relationship", "Ipppp",
399 "relationshipType,relationshipGuid,headGuid,tailGuid,attributeGuid" },
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000400 { "4", "declareEvent", "declare event", "@tp", "timestamp,threadId,eventGuid" }
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100401 };
Sadik Armagan784db772019-10-08 15:05:38 +0100402
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000403 // Build the message declarations
404 std::vector<uint32_t> swTraceBuffer;
405 for (const auto& directoryComponent : timelineDirectoryMessages)
Sadik Armagan784db772019-10-08 15:05:38 +0100406 {
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000407 // decl_id
408 uint32_t declId = 0;
409 try
Sadik Armagan784db772019-10-08 15:05:38 +0100410 {
Jim Flynn75c14f42022-03-10 22:05:42 +0000411 declId = arm::pipe::numeric_cast<uint32_t>(std::stoul(directoryComponent[0]));
Sadik Armagan784db772019-10-08 15:05:38 +0100412 }
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000413 catch (const std::exception&)
414 {
415 return TimelinePacketStatus::Error;
416 }
417 swTraceBuffer.push_back(declId);
418
419 bool result = true;
Jim Flynnbbfe6032020-07-20 16:57:44 +0100420 result &= arm::pipe::ConvertDirectoryComponent<arm::pipe::SwTraceNameCharPolicy>(
421 directoryComponent[1], swTraceBuffer); // decl_name
422 result &= arm::pipe::ConvertDirectoryComponent<arm::pipe::SwTraceCharPolicy> (
423 directoryComponent[2], swTraceBuffer); // ui_name
424 result &= arm::pipe::ConvertDirectoryComponent<arm::pipe::SwTraceTypeCharPolicy>(
425 directoryComponent[3], swTraceBuffer); // arg_types
426 result &= arm::pipe::ConvertDirectoryComponent<arm::pipe::SwTraceCharPolicy> (
427 directoryComponent[4], swTraceBuffer); // arg_names
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000428 if (!result)
429 {
430 return TimelinePacketStatus::Error;
431 }
Sadik Armagan784db772019-10-08 15:05:38 +0100432 }
433
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000434 unsigned int dataLength = 3 * uint8_t_size + // Stream header (3 bytes)
Jim Flynn75c14f42022-03-10 22:05:42 +0000435 arm::pipe::numeric_cast<unsigned int>(swTraceBuffer.size()) *
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000436 uint32_t_size; // Trace directory (5 messages)
437
Sadik Armagan784db772019-10-08 15:05:38 +0100438 // Calculate the timeline directory binary packet size (in bytes)
439 unsigned int timelineDirectoryPacketSize = 2 * uint32_t_size + // Header (2 words)
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000440 dataLength; // Payload
Sadik Armagan784db772019-10-08 15:05:38 +0100441
442 // Check whether the timeline directory binary packet fits in the given buffer
Keith Davis97da5e22020-03-05 16:25:28 +0000443 if (timelineDirectoryPacketSize > remainingBufferSize)
Sadik Armagan784db772019-10-08 15:05:38 +0100444 {
445 return TimelinePacketStatus::BufferExhaustion;
446 }
447
Jan Eilersb884ea42019-10-16 09:54:15 +0100448 // Create packet header
Jim Flynn75c14f42022-03-10 22:05:42 +0000449 auto packetHeader = CreateTimelinePacketHeader(1, 0, 0, 0, 0, arm::pipe::numeric_cast<uint32_t>(dataLength));
Sadik Armagan784db772019-10-08 15:05:38 +0100450
451 // Initialize the offset for writing in the buffer
452 unsigned int offset = 0;
453
454 // Write the timeline binary packet header to the buffer
Jan Eilersb884ea42019-10-16 09:54:15 +0100455 WriteUint32(buffer, offset, packetHeader.first);
Sadik Armagan784db772019-10-08 15:05:38 +0100456 offset += uint32_t_size;
Jan Eilersb884ea42019-10-16 09:54:15 +0100457 WriteUint32(buffer, offset, packetHeader.second);
Sadik Armagan784db772019-10-08 15:05:38 +0100458 offset += uint32_t_size;
459
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000460 // Write the stream header
461 uint8_t streamVersion = 4;
Jim Flynn75c14f42022-03-10 22:05:42 +0000462 uint8_t pointerBytes = arm::pipe::numeric_cast<uint8_t>(uint64_t_size); // All GUIDs are uint64_t
463 uint8_t threadIdBytes = arm::pipe::numeric_cast<uint8_t>(ThreadIdSize);
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000464 switch (threadIdBytes)
Sadik Armagan784db772019-10-08 15:05:38 +0100465 {
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000466 case 4: // Typically Windows and Android
467 case 8: // Typically Linux
468 break; // Valid values
469 default:
470 return TimelinePacketStatus::Error; // Invalid value
471 }
472 WriteUint8(buffer, offset, streamVersion);
473 offset += uint8_t_size;
474 WriteUint8(buffer, offset, pointerBytes);
475 offset += uint8_t_size;
476 WriteUint8(buffer, offset, threadIdBytes);
477 offset += uint8_t_size;
Sadik Armagan784db772019-10-08 15:05:38 +0100478
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000479 // Write the SWTrace directory
Jim Flynn75c14f42022-03-10 22:05:42 +0000480 uint32_t numberOfDeclarations = arm::pipe::numeric_cast<uint32_t>(timelineDirectoryMessages.size());
Matteo Martincigh34a407d2019-11-06 15:30:54 +0000481 WriteUint32(buffer, offset, numberOfDeclarations); // Number of declarations
482 offset += uint32_t_size;
483 for (uint32_t i : swTraceBuffer)
484 {
485 WriteUint32(buffer, offset, i); // Message declarations
486 offset += uint32_t_size;
Sadik Armagan784db772019-10-08 15:05:38 +0100487 }
488
489 // Update the number of bytes written
490 numberOfBytesWritten = timelineDirectoryPacketSize;
491
492 return TimelinePacketStatus::Ok;
493}
494
Keith Davis97da5e22020-03-05 16:25:28 +0000495TimelinePacketStatus WriteTimelineEventClassBinary(uint64_t profilingGuid,
Jim Flynn1892d212020-05-26 21:10:49 +0100496 uint64_t nameGuid,
Keith Davis97da5e22020-03-05 16:25:28 +0000497 unsigned char* buffer,
498 unsigned int remainingBufferSize,
499 unsigned int& numberOfBytesWritten)
Jan Eilers92fa15b2019-10-15 15:23:25 +0100500{
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100501 // Initialize the output value
Jan Eilers92fa15b2019-10-15 15:23:25 +0100502 numberOfBytesWritten = 0;
503
504 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000505 if (buffer == nullptr || remainingBufferSize == 0)
Jan Eilers92fa15b2019-10-15 15:23:25 +0100506 {
507 return TimelinePacketStatus::BufferExhaustion;
508 }
509
510 // Utils
511 unsigned int uint32_t_size = sizeof(uint32_t);
512 unsigned int uint64_t_size = sizeof(uint64_t);
513
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100514 // decl_id of the timeline message
515 uint32_t declId = 2;
Jan Eilers92fa15b2019-10-15 15:23:25 +0100516
517 // Calculate the length of the data (in bytes)
Jim Flynn1892d212020-05-26 21:10:49 +0100518 unsigned int dataSize = uint32_t_size + (uint64_t_size * 2); // decl_id + Profiling GUID + Name GUID
Jan Eilers92fa15b2019-10-15 15:23:25 +0100519
Keith Davis97da5e22020-03-05 16:25:28 +0000520 // Check whether the timeline binary fits in the given buffer
521 if (dataSize > remainingBufferSize)
Jan Eilers92fa15b2019-10-15 15:23:25 +0100522 {
523 return TimelinePacketStatus::BufferExhaustion;
524 }
525
Jan Eilers92fa15b2019-10-15 15:23:25 +0100526 // Initialize the offset for writing in the buffer
527 unsigned int offset = 0;
528
Keith Davis97da5e22020-03-05 16:25:28 +0000529 // Write the timeline binary payload to the buffer
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100530 WriteUint32(buffer, offset, declId); // decl_id
Jan Eilers92fa15b2019-10-15 15:23:25 +0100531 offset += uint32_t_size;
532 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
Jim Flynn1892d212020-05-26 21:10:49 +0100533 offset += uint64_t_size;
534 WriteUint64(buffer, offset, nameGuid); // Name GUID
Jan Eilers92fa15b2019-10-15 15:23:25 +0100535
536 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000537 numberOfBytesWritten = dataSize;
Jan Eilers92fa15b2019-10-15 15:23:25 +0100538
539 return TimelinePacketStatus::Ok;
540}
541
Keith Davis97da5e22020-03-05 16:25:28 +0000542TimelinePacketStatus WriteTimelineEventBinary(uint64_t timestamp,
Jim Flynn1fdeb992020-07-09 07:28:37 +0100543 int threadId,
Keith Davis97da5e22020-03-05 16:25:28 +0000544 uint64_t profilingGuid,
545 unsigned char* buffer,
546 unsigned int remainingBufferSize,
547 unsigned int& numberOfBytesWritten)
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100548{
549 // Initialize the output value
550 numberOfBytesWritten = 0;
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100551 // Check that the given buffer is valid
Keith Davis97da5e22020-03-05 16:25:28 +0000552 if (buffer == nullptr || remainingBufferSize == 0)
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100553 {
554 return TimelinePacketStatus::BufferExhaustion;
555 }
556
557 // Utils
558 unsigned int uint32_t_size = sizeof(uint32_t);
559 unsigned int uint64_t_size = sizeof(uint64_t);
560
561 // decl_id of the timeline message
562 uint32_t declId = 4;
563
564 // Calculate the length of the data (in bytes)
Keith Davis97da5e22020-03-05 16:25:28 +0000565 unsigned int timelineEventDataLength = uint32_t_size + // decl_id
566 uint64_t_size + // Timestamp
Colm Donelan5bb3d8a2020-05-12 16:36:46 +0100567 ThreadIdSize + // Thread id
Keith Davis97da5e22020-03-05 16:25:28 +0000568 uint64_t_size; // Profiling GUID
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100569
570 // Check whether the timeline binary packet fits in the given buffer
Keith Davis97da5e22020-03-05 16:25:28 +0000571 if (timelineEventDataLength > remainingBufferSize)
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100572 {
573 return TimelinePacketStatus::BufferExhaustion;
574 }
575
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100576 // Initialize the offset for writing in the buffer
577 unsigned int offset = 0;
578
Keith Davis97da5e22020-03-05 16:25:28 +0000579 // Write the timeline binary payload to the buffer
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100580 WriteUint32(buffer, offset, declId); // decl_id
581 offset += uint32_t_size;
582 WriteUint64(buffer, offset, timestamp); // Timestamp
583 offset += uint64_t_size;
Colm Donelan5bb3d8a2020-05-12 16:36:46 +0100584 WriteBytes(buffer, offset, &threadId, ThreadIdSize); // Thread id
585 offset += ThreadIdSize;
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100586 WriteUint64(buffer, offset, profilingGuid); // Profiling GUID
587 offset += uint64_t_size;
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100588 // Update the number of bytes written
Keith Davis97da5e22020-03-05 16:25:28 +0000589 numberOfBytesWritten = timelineEventDataLength;
Matteo Martincigh8844c2f2019-10-16 10:29:17 +0100590
591 return TimelinePacketStatus::Ok;
592}
593
Matteo Martincigh5dc816e2019-11-04 14:05:28 +0000594uint64_t GetTimestamp()
595{
596#if USE_CLOCK_MONOTONIC_RAW
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000597 using clock = armnn::MonotonicClockRaw;
Matteo Martincigh5dc816e2019-11-04 14:05:28 +0000598#else
599 using clock = std::chrono::steady_clock;
600#endif
601
602 // Take a timestamp
Finn Williamsd9ba1a72020-04-16 15:32:28 +0100603 auto timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(clock::now().time_since_epoch());
Matteo Martincigh5dc816e2019-11-04 14:05:28 +0000604
Finn Williamsd9ba1a72020-04-16 15:32:28 +0100605 return static_cast<uint64_t>(timestamp.count());
Matteo Martincigh5dc816e2019-11-04 14:05:28 +0000606}
Keith Davis3201eea2019-10-24 17:30:41 +0100607
Jim Flynnbbfe6032020-07-20 16:57:44 +0100608arm::pipe::Packet ReceivePacket(const unsigned char* buffer, uint32_t length)
Jim Flynn4e755a52020-03-29 17:48:26 +0100609{
610 if (buffer == nullptr)
611 {
Jim Flynnbbfe6032020-07-20 16:57:44 +0100612 throw arm::pipe::ProfilingException("data buffer is nullptr");
Jim Flynn4e755a52020-03-29 17:48:26 +0100613 }
614 if (length < 8)
615 {
Jim Flynnbbfe6032020-07-20 16:57:44 +0100616 throw arm::pipe::ProfilingException("length of data buffer is less than 8");
Jim Flynn4e755a52020-03-29 17:48:26 +0100617 }
618
619 uint32_t metadataIdentifier = 0;
620 std::memcpy(&metadataIdentifier, buffer, sizeof(metadataIdentifier));
621
622 uint32_t dataLength = 0;
623 std::memcpy(&dataLength, buffer + 4u, sizeof(dataLength));
624
625 std::unique_ptr<unsigned char[]> packetData;
626 if (dataLength > 0)
627 {
628 packetData = std::make_unique<unsigned char[]>(dataLength);
629 std::memcpy(packetData.get(), buffer + 8u, dataLength);
630 }
631
Jim Flynnbbfe6032020-07-20 16:57:44 +0100632 return arm::pipe::Packet(metadataIdentifier, dataLength, packetData);
Jim Flynn4e755a52020-03-29 17:48:26 +0100633}
634
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000635} // namespace pipe
Ferran Balaguer73882172019-09-02 16:39:42 +0100636
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000637} // namespace arm
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000638
639namespace std
640{
641
Jim Flynn1fdeb992020-07-09 07:28:37 +0100642bool operator==(const std::vector<uint8_t>& left, int right)
Matteo Martincigh378bbfc2019-11-04 14:05:28 +0000643{
644 return std::memcmp(left.data(), &right, left.size()) == 0;
645}
646
647} // namespace std