aboutsummaryrefslogtreecommitdiff
path: root/src/profiling/ProfilingUtils.hpp
blob: 9bbe421817bae708cd9572fb36809782afb4a06d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#pragma once

#include <armnn/Exceptions.hpp>

#include "ICounterDirectory.hpp"
#include "IPacketBuffer.hpp"

#include <boost/numeric/conversion/cast.hpp>

#include <algorithm>
#include <cstring>
#include <memory>
#include <string>
#include <vector>
#include <thread>

namespace armnn
{

namespace profiling
{

struct SwTraceHeader
{
    uint8_t m_StreamVersion;
    uint8_t m_PointerBytes;
    uint8_t m_ThreadIdBytes;
};

struct SwTraceMessage
{
    uint32_t m_Id;
    std::string m_Name;
    std::string m_UiName;
    std::vector<char> m_ArgTypes;
    std::vector<std::string> m_ArgNames;
};

struct SwTraceCharPolicy
{
    static bool IsValidChar(unsigned char c)
    {
        // Check that the given character has ASCII 7-bit encoding
        return c < 128;
    }
};

struct SwTraceNameCharPolicy
{
    static bool IsValidChar(unsigned char c)
    {
        // Check that the given character has ASCII 7-bit encoding, alpha-numeric and underscore only
        return c < 128 && (std::isalnum(c) || c == '_');
    }
};

struct SwTraceTypeCharPolicy
{
    static bool IsValidChar(unsigned char c)
    {
        // Check that the given character is among the allowed ones
        switch (c)
        {
        case '@':
        case 't':
        case 'i':
        case 'I':
        case 'l':
        case 'L':
        case 'F':
        case 'p':
        case 's':
            return true; // Valid char
        default:
            return false; // Invalid char
        }
    }
};

template <typename SwTracePolicy>
bool IsValidSwTraceString(const std::string& s)
{
    // Check that all the characters in the given string conform to the given policy
    return std::all_of(s.begin(), s.end(), [](unsigned char c) { return SwTracePolicy::IsValidChar(c); });
}

template <typename SwTracePolicy>
bool StringToSwTraceString(const std::string& s, std::vector<uint32_t>& outputBuffer)
{
    // Converts the given string to an SWTrace "string" (i.e. a string of "chars"), and writes it into
    // the given buffer including the null-terminator. It also pads it to the next uint32_t if necessary

    // Clear the output buffer
    outputBuffer.clear();

    // Check that the given string is a valid SWTrace "string" (i.e. a string of "chars")
    if (!IsValidSwTraceString<SwTracePolicy>(s))
    {
        return false;
    }

    // Prepare the output buffer
    size_t s_size        = s.size() + 1;    // The size of the string (in chars) plus the null-terminator
    size_t uint32_t_size = sizeof(uint32_t);
    size_t outBufferSize = 1 + s_size / uint32_t_size + (s_size % uint32_t_size != 0 ? 1 : 0);
    outputBuffer.resize(outBufferSize, '\0');

    // Write the SWTrace string to the output buffer
    outputBuffer[0] = boost::numeric_cast<uint32_t>(s_size);
    std::memcpy(outputBuffer.data() + 1, s.data(), s_size);

    return true;
}

template <typename SwTracePolicy,
          typename SwTraceBuffer = std::vector<uint32_t>>
bool ConvertDirectoryComponent(const std::string& directoryComponent, SwTraceBuffer& swTraceBuffer)
{
    // Convert the directory component using the given policy
    SwTraceBuffer tempSwTraceBuffer;
    bool result = StringToSwTraceString<SwTracePolicy>(directoryComponent, tempSwTraceBuffer);
    if (!result)
    {
        return false;
    }

    swTraceBuffer.insert(swTraceBuffer.end(), tempSwTraceBuffer.begin(), tempSwTraceBuffer.end());

    return true;
}

uint16_t GetNextUid(bool peekOnly = false);

std::vector<uint16_t> GetNextCounterUids(uint16_t firstUid, uint16_t cores);

void WriteBytes(const IPacketBuffer& packetBuffer, unsigned int offset, const void* value, unsigned int valueSize);

uint32_t ConstructHeader(uint32_t packetFamily, uint32_t packetId);

uint32_t ConstructHeader(uint32_t packetFamily, uint32_t packetClass, uint32_t packetType);

void WriteUint64(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint64_t value);

void WriteUint32(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint32_t value);

void WriteUint16(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint16_t value);

void WriteUint8(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint8_t value);

void WriteBytes(unsigned char* buffer, unsigned int offset, const void* value, unsigned int valueSize);

void WriteUint64(unsigned char* buffer, unsigned int offset, uint64_t value);

void WriteUint32(unsigned char* buffer, unsigned int offset, uint32_t value);

void WriteUint16(unsigned char* buffer, unsigned int offset, uint16_t value);

void WriteUint8(unsigned char* buffer, unsigned int offset, uint8_t value);

void ReadBytes(const IPacketBufferPtr& packetBuffer, unsigned int offset, unsigned int valueSize, uint8_t outValue[]);

uint64_t ReadUint64(const IPacketBufferPtr& packetBuffer, unsigned int offset);

uint32_t ReadUint32(const IPacketBufferPtr& packetBuffer, unsigned int offset);

uint16_t ReadUint16(const IPacketBufferPtr& packetBuffer, unsigned int offset);

uint8_t ReadUint8(const IPacketBufferPtr& packetBuffer, unsigned int offset);

void ReadBytes(const unsigned char* buffer, unsigned int offset, unsigned int valueSize, uint8_t outValue[]);

uint64_t ReadUint64(unsigned const char* buffer, unsigned int offset);

uint32_t ReadUint32(unsigned const char* buffer, unsigned int offset);

uint16_t ReadUint16(unsigned const char* buffer, unsigned int offset);

uint8_t ReadUint8(unsigned const char* buffer, unsigned int offset);

std::string GetSoftwareInfo();

std::string GetSoftwareVersion();

std::string GetHardwareVersion();

std::string GetProcessName();

enum class TimelinePacketStatus
{
    Ok,
    Error,
    BufferExhaustion
};

enum class ProfilingRelationshipType
{
    RetentionLink,    /// Head retains(parents) Tail
    ExecutionLink,    /// Head execution start depends on Tail execution completion
    DataLink,         /// Head uses data of Tail
    LabelLink         /// Head uses label Tail (Tail MUST be a guid of a label).
};

uint32_t CalculateSizeOfPaddedSwString(const std::string& str);

SwTraceMessage ReadSwTraceMessage(const unsigned char*, unsigned int& offset);

TimelinePacketStatus WriteTimelineLabelBinaryPacket(uint64_t profilingGuid,
                                                    const std::string& label,
                                                    unsigned char* buffer,
                                                    unsigned int bufferSize,
                                                    unsigned int& numberOfBytesWritten);

TimelinePacketStatus WriteTimelineEntityBinaryPacket(uint64_t profilingGuid,
                                                     unsigned char* buffer,
                                                     unsigned int bufferSize,
                                                     unsigned int& numberOfBytesWritten);

TimelinePacketStatus WriteTimelineRelationshipBinaryPacket(ProfilingRelationshipType relationshipType,
                                                           uint64_t relationshipGuid,
                                                           uint64_t headGuid,
                                                           uint64_t tailGuid,
                                                           unsigned char* buffer,
                                                           unsigned int bufferSize,
                                                           unsigned int& numberOfBytesWritten);

TimelinePacketStatus WriteTimelineMessageDirectoryPackage(unsigned char* buffer,
                                                          unsigned int bufferSize,
                                                          unsigned int& numberOfBytesWritten);

TimelinePacketStatus WriteTimelineEventClassBinaryPacket(uint64_t profilingGuid,
                                                         unsigned char* buffer,
                                                         unsigned int bufferSize,
                                                         unsigned int& numberOfBytesWritten);

TimelinePacketStatus WriteTimelineEventBinaryPacket(uint64_t timestamp,
                                                    std::thread::id threadId,
                                                    uint64_t profilingGuid,
                                                    unsigned char* buffer,
                                                    unsigned int bufferSize,
                                                    unsigned int& numberOfBytesWritten);

std::string CentreAlignFormatting(const std::string& stringToPass, const int spacingWidth);

void PrintCounterDirectory(ICounterDirectory& counterDirectory);

class BufferExhaustion : public armnn::Exception
{
    using Exception::Exception;
};

uint64_t GetTimestamp();

} // namespace profiling

} // namespace armnn

namespace std
{

bool operator==(const std::vector<uint8_t>& left, std::thread::id right);

} // namespace std