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