IVGCVSW-3691 Basic refactoring in view of upcoming work in the profiler
[platform/upstream/armnn.git] / src / profiling / SendCounterPacket.cpp
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include "SendCounterPacket.hpp"
7 #include "EncodeVersion.hpp"
8 #include "ProfilingUtils.hpp"
9
10 #include <armnn/Exceptions.hpp>
11
12 #include <boost/format.hpp>
13 #include <boost/numeric/conversion/cast.hpp>
14 #include <boost/core/ignore_unused.hpp>
15
16 #include <cstring>
17
18 namespace armnn
19 {
20
21 namespace profiling
22 {
23
24 using boost::numeric_cast;
25
26 const unsigned int SendCounterPacket::PIPE_MAGIC;
27 const unsigned int SendCounterPacket::MAX_METADATA_PACKET_LENGTH;
28
29 void SendCounterPacket::SendStreamMetaDataPacket()
30 {
31     std::string info(GetSoftwareInfo());
32     std::string hardwareVersion(GetHardwareVersion());
33     std::string softwareVersion(GetSoftwareVersion());
34     std::string processName = GetProcessName().substr(0, 60);
35
36     uint32_t infoSize = numeric_cast<uint32_t>(info.size()) > 0 ? numeric_cast<uint32_t>(info.size()) + 1 : 0;
37     uint32_t hardwareVersionSize = numeric_cast<uint32_t>(hardwareVersion.size()) > 0 ?
38                                    numeric_cast<uint32_t>(hardwareVersion.size()) + 1 : 0;
39     uint32_t softwareVersionSize = numeric_cast<uint32_t>(softwareVersion.size()) > 0 ?
40                                    numeric_cast<uint32_t>(softwareVersion.size()) + 1 : 0;
41     uint32_t processNameSize = numeric_cast<uint32_t>(processName.size()) > 0 ?
42                                numeric_cast<uint32_t>(processName.size()) + 1 : 0;
43
44     uint32_t sizeUint32 = numeric_cast<uint32_t>(sizeof(uint32_t));
45
46     uint32_t headerSize = 2 * sizeUint32;
47     uint32_t bodySize = 10 * sizeUint32;
48     uint32_t packetVersionCountSize = sizeUint32;
49
50     // Supported Packets
51     // Stream metadata packet            (packet family=0; packet id=0)
52     // Connection Acknowledged packet    (packet family=0, packet id=1)
53     // Counter Directory packet          (packet family=0; packet id=2)
54     // Request Counter Directory packet  (packet family=0, packet id=3)
55     // Periodic Counter Selection packet (packet family=0, packet id=4)
56     uint32_t packetVersionEntries = 5;
57
58     uint32_t payloadSize = numeric_cast<uint32_t>(infoSize + hardwareVersionSize + softwareVersionSize +
59                                                   processNameSize + packetVersionCountSize +
60                                                   (packetVersionEntries * 2 * sizeUint32));
61
62     uint32_t totalSize = headerSize + bodySize + payloadSize;
63     uint32_t offset = 0;
64     uint32_t reserved = 0;
65
66     unsigned char *writeBuffer = m_Buffer.Reserve(totalSize, reserved);
67
68     if (reserved < totalSize)
69     {
70         CancelOperationAndThrow<BufferExhaustion>(
71                     boost::str(boost::format("No space left in buffer. Unable to reserve (%1%) bytes.")
72                                % totalSize));
73     }
74
75     if (writeBuffer == nullptr)
76     {
77         CancelOperationAndThrow<RuntimeException>("Error reserving buffer memory.");
78     }
79
80     try
81     {
82         // Create header
83
84         WriteUint32(writeBuffer, offset, 0);
85         offset += sizeUint32;
86         WriteUint32(writeBuffer, offset, totalSize - headerSize);
87
88         // Packet body
89
90         offset += sizeUint32;
91         WriteUint32(writeBuffer, offset, PIPE_MAGIC); // pipe_magic
92         offset += sizeUint32;
93         WriteUint32(writeBuffer, offset, EncodeVersion(1, 0, 0)); // stream_metadata_version
94         offset += sizeUint32;
95         WriteUint32(writeBuffer, offset, MAX_METADATA_PACKET_LENGTH); // max_data_length
96         offset += sizeUint32;
97         WriteUint32(writeBuffer, offset, numeric_cast<uint32_t>(getpid())); // pid
98         offset += sizeUint32;
99         uint32_t poolOffset = bodySize;
100         WriteUint32(writeBuffer, offset, infoSize ? poolOffset : 0); // offset_info
101         offset += sizeUint32;
102         poolOffset += infoSize;
103         WriteUint32(writeBuffer, offset, hardwareVersionSize ? poolOffset : 0); // offset_hw_version
104         offset += sizeUint32;
105         poolOffset += hardwareVersionSize;
106         WriteUint32(writeBuffer, offset, softwareVersionSize ? poolOffset : 0); // offset_sw_version
107         offset += sizeUint32;
108         poolOffset += softwareVersionSize;
109         WriteUint32(writeBuffer, offset, processNameSize ? poolOffset : 0); // offset_process_name
110         offset += sizeUint32;
111         poolOffset += processNameSize;
112         WriteUint32(writeBuffer, offset, packetVersionEntries ? poolOffset : 0); // offset_packet_version_table
113         offset += sizeUint32;
114         WriteUint32(writeBuffer, offset, 0); // reserved
115         offset += sizeUint32;
116
117         // Pool
118
119         if (infoSize)
120         {
121             memcpy(&writeBuffer[offset], info.c_str(), infoSize);
122             offset += infoSize;
123         }
124
125         if (hardwareVersionSize)
126         {
127             memcpy(&writeBuffer[offset], hardwareVersion.c_str(), hardwareVersionSize);
128             offset += hardwareVersionSize;
129         }
130
131         if (softwareVersionSize)
132         {
133             memcpy(&writeBuffer[offset], softwareVersion.c_str(), softwareVersionSize);
134             offset += softwareVersionSize;
135         }
136
137         if (processNameSize)
138         {
139             memcpy(&writeBuffer[offset], processName.c_str(), processNameSize);
140             offset += processNameSize;
141         }
142
143         if (packetVersionEntries)
144         {
145             // Packet Version Count
146             WriteUint32(writeBuffer, offset, packetVersionEntries << 16);
147
148             // Packet Version Entries
149             uint32_t packetFamily = 0;
150             uint32_t packetId = 0;
151
152             offset += sizeUint32;
153             for (uint32_t i = 0; i < packetVersionEntries; ++i) {
154                 WriteUint32(writeBuffer, offset, ((packetFamily & 0x3F) << 26) | ((packetId++ & 0x3FF) << 16));
155                 offset += sizeUint32;
156                 WriteUint32(writeBuffer, offset, EncodeVersion(1, 0, 0));
157                 offset += sizeUint32;
158             }
159         }
160     }
161     catch(...)
162     {
163         CancelOperationAndThrow<RuntimeException>("Error processing packet.");
164     }
165
166     m_Buffer.Commit(totalSize);
167 }
168
169 void SendCounterPacket::SendCounterDirectoryPacket(const CounterDirectory& counterDirectory)
170 {
171     throw armnn::UnimplementedException();
172 }
173
174 void SendCounterPacket::SendPeriodicCounterCapturePacket(uint64_t timestamp, const IndexValuePairsVector& values)
175 {
176     uint32_t packetFamily = 1;
177     uint32_t packetClass = 0;
178     uint32_t packetType = 0;
179     uint32_t headerSize = numeric_cast<uint32_t>(2 * sizeof(uint32_t));
180     uint32_t bodySize = numeric_cast<uint32_t>((1 * sizeof(uint64_t)) +
181                                                (values.size() * (sizeof(uint16_t) + sizeof(uint32_t))));
182     uint32_t totalSize = headerSize + bodySize;
183     uint32_t offset = 0;
184     uint32_t reserved = 0;
185
186     unsigned char* writeBuffer = m_Buffer.Reserve(totalSize, reserved);
187
188     if (reserved < totalSize)
189     {
190         CancelOperationAndThrow<BufferExhaustion>(
191                     boost::str(boost::format("No space left in buffer. Unable to reserve (%1%) bytes.")
192                                % totalSize));
193     }
194
195     if (writeBuffer == nullptr)
196     {
197         CancelOperationAndThrow<RuntimeException>("Error reserving buffer memory.");
198     }
199
200     // Create header.
201     WriteUint32(writeBuffer,
202                 offset,
203                 ((packetFamily & 0x3F) << 26) | ((packetClass & 0x3FF) << 19) | ((packetType & 0x3FFF) << 16));
204     offset += numeric_cast<uint32_t>(sizeof(uint32_t));
205     WriteUint32(writeBuffer, offset, bodySize);
206
207     // Copy captured Timestamp.
208     offset += numeric_cast<uint32_t>(sizeof(uint32_t));
209     WriteUint64(writeBuffer, offset, timestamp);
210
211     // Copy selectedCounterIds.
212     offset += numeric_cast<uint32_t>(sizeof(uint64_t));
213     for (const auto& pair: values)
214     {
215         WriteUint16(writeBuffer, offset, pair.first);
216         offset += numeric_cast<uint32_t>(sizeof(uint16_t));
217         WriteUint32(writeBuffer, offset, pair.second);
218         offset += numeric_cast<uint32_t>(sizeof(uint32_t));
219     }
220
221     m_Buffer.Commit(totalSize);
222 }
223
224 void SendCounterPacket::SendPeriodicCounterSelectionPacket(uint32_t capturePeriod,
225                                                            const std::vector<uint16_t>& selectedCounterIds)
226 {
227     uint32_t packetFamily = 0;
228     uint32_t packetId = 4;
229     uint32_t headerSize = numeric_cast<uint32_t>(2 * sizeof(uint32_t));
230     uint32_t bodySize   = numeric_cast<uint32_t>((1 * sizeof(uint32_t)) +
231                                                  (selectedCounterIds.size() * sizeof(uint16_t)));
232     uint32_t totalSize = headerSize + bodySize;
233     uint32_t offset = 0;
234     uint32_t reserved = 0;
235
236     unsigned char* writeBuffer = m_Buffer.Reserve(totalSize, reserved);
237
238     if (reserved < totalSize)
239     {
240         CancelOperationAndThrow<BufferExhaustion>(
241                     boost::str(boost::format("No space left in buffer. Unable to reserve (%1%) bytes.")
242                                % totalSize));
243     }
244
245     if (writeBuffer == nullptr)
246     {
247         CancelOperationAndThrow<RuntimeException>("Error reserving buffer memory.");
248     }
249
250     // Create header.
251     WriteUint32(writeBuffer, offset, ((packetFamily & 0x3F) << 26) | ((packetId & 0x3FF) << 16));
252     offset += numeric_cast<uint32_t>(sizeof(uint32_t));
253     WriteUint32(writeBuffer, offset, bodySize);
254
255     // Copy capturePeriod.
256     offset += numeric_cast<uint32_t>(sizeof(uint32_t));
257     WriteUint32(writeBuffer, offset, capturePeriod);
258
259     // Copy selectedCounterIds.
260     offset += numeric_cast<uint32_t>(sizeof(uint32_t));
261     for(const uint16_t& id: selectedCounterIds)
262     {
263         WriteUint16(writeBuffer, offset, id);
264         offset += numeric_cast<uint32_t>(sizeof(uint16_t));
265     }
266
267     m_Buffer.Commit(totalSize);
268 }
269
270 void SendCounterPacket::SetReadyToRead()
271 {
272     m_ReadyToRead = true;
273 }
274
275 } // namespace profiling
276
277 } // namespace armnn