blob: f2172b3b7d90747985f48f562f4cb570e18d9f40 [file] [log] [blame]
Ferran Balaguer73882172019-09-02 16:39:42 +01001//
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>
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010014#include <boost/core/ignore_unused.hpp>
Ferran Balaguer73882172019-09-02 16:39:42 +010015
Matteo Martincigh149528e2019-09-05 12:02:04 +010016#include <cstring>
Ferran Balaguer73882172019-09-02 16:39:42 +010017
18namespace armnn
19{
20
21namespace profiling
22{
23
24using boost::numeric_cast;
25
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010026const unsigned int SendCounterPacket::PIPE_MAGIC;
27const unsigned int SendCounterPacket::MAX_METADATA_PACKET_LENGTH;
28
Ferran Balaguer73882172019-09-02 16:39:42 +010029void SendCounterPacket::SendStreamMetaDataPacket()
30{
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010031 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)
Ferran Balaguer5bf1d322019-09-13 13:31:40 +010056 // Periodic Counter Capture packet (packet family=1, packet class=0, type=0)
57 uint32_t packetVersionEntries = 6;
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010058
59 uint32_t payloadSize = numeric_cast<uint32_t>(infoSize + hardwareVersionSize + softwareVersionSize +
60 processNameSize + packetVersionCountSize +
61 (packetVersionEntries * 2 * sizeUint32));
62
63 uint32_t totalSize = headerSize + bodySize + payloadSize;
64 uint32_t offset = 0;
65 uint32_t reserved = 0;
66
67 unsigned char *writeBuffer = m_Buffer.Reserve(totalSize, reserved);
68
69 if (reserved < totalSize)
70 {
Matteo Martincigh149528e2019-09-05 12:02:04 +010071 CancelOperationAndThrow<BufferExhaustion>(
72 boost::str(boost::format("No space left in buffer. Unable to reserve (%1%) bytes.")
73 % totalSize));
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010074 }
75
76 if (writeBuffer == nullptr)
77 {
Matteo Martincigh149528e2019-09-05 12:02:04 +010078 CancelOperationAndThrow<RuntimeException>("Error reserving buffer memory.");
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010079 }
80
81 try
82 {
83 // Create header
84
85 WriteUint32(writeBuffer, offset, 0);
86 offset += sizeUint32;
87 WriteUint32(writeBuffer, offset, totalSize - headerSize);
88
89 // Packet body
90
91 offset += sizeUint32;
92 WriteUint32(writeBuffer, offset, PIPE_MAGIC); // pipe_magic
93 offset += sizeUint32;
94 WriteUint32(writeBuffer, offset, EncodeVersion(1, 0, 0)); // stream_metadata_version
95 offset += sizeUint32;
96 WriteUint32(writeBuffer, offset, MAX_METADATA_PACKET_LENGTH); // max_data_length
97 offset += sizeUint32;
98 WriteUint32(writeBuffer, offset, numeric_cast<uint32_t>(getpid())); // pid
99 offset += sizeUint32;
100 uint32_t poolOffset = bodySize;
101 WriteUint32(writeBuffer, offset, infoSize ? poolOffset : 0); // offset_info
102 offset += sizeUint32;
103 poolOffset += infoSize;
104 WriteUint32(writeBuffer, offset, hardwareVersionSize ? poolOffset : 0); // offset_hw_version
105 offset += sizeUint32;
106 poolOffset += hardwareVersionSize;
107 WriteUint32(writeBuffer, offset, softwareVersionSize ? poolOffset : 0); // offset_sw_version
108 offset += sizeUint32;
109 poolOffset += softwareVersionSize;
110 WriteUint32(writeBuffer, offset, processNameSize ? poolOffset : 0); // offset_process_name
111 offset += sizeUint32;
112 poolOffset += processNameSize;
113 WriteUint32(writeBuffer, offset, packetVersionEntries ? poolOffset : 0); // offset_packet_version_table
114 offset += sizeUint32;
115 WriteUint32(writeBuffer, offset, 0); // reserved
116 offset += sizeUint32;
117
118 // Pool
119
Matteo Martincigh149528e2019-09-05 12:02:04 +0100120 if (infoSize)
121 {
Ferran Balaguer47d0fe92019-09-04 16:47:34 +0100122 memcpy(&writeBuffer[offset], info.c_str(), infoSize);
123 offset += infoSize;
124 }
125
Matteo Martincigh149528e2019-09-05 12:02:04 +0100126 if (hardwareVersionSize)
127 {
Ferran Balaguer47d0fe92019-09-04 16:47:34 +0100128 memcpy(&writeBuffer[offset], hardwareVersion.c_str(), hardwareVersionSize);
129 offset += hardwareVersionSize;
130 }
131
Matteo Martincigh149528e2019-09-05 12:02:04 +0100132 if (softwareVersionSize)
133 {
Ferran Balaguer47d0fe92019-09-04 16:47:34 +0100134 memcpy(&writeBuffer[offset], softwareVersion.c_str(), softwareVersionSize);
135 offset += softwareVersionSize;
136 }
137
Matteo Martincigh149528e2019-09-05 12:02:04 +0100138 if (processNameSize)
139 {
Ferran Balaguer47d0fe92019-09-04 16:47:34 +0100140 memcpy(&writeBuffer[offset], processName.c_str(), processNameSize);
141 offset += processNameSize;
142 }
143
Matteo Martincigh149528e2019-09-05 12:02:04 +0100144 if (packetVersionEntries)
145 {
Ferran Balaguer47d0fe92019-09-04 16:47:34 +0100146 // Packet Version Count
147 WriteUint32(writeBuffer, offset, packetVersionEntries << 16);
148
149 // Packet Version Entries
150 uint32_t packetFamily = 0;
151 uint32_t packetId = 0;
152
153 offset += sizeUint32;
Ferran Balaguer5bf1d322019-09-13 13:31:40 +0100154 for (uint32_t i = 0; i < packetVersionEntries - 1; ++i)
155 {
Ferran Balaguer47d0fe92019-09-04 16:47:34 +0100156 WriteUint32(writeBuffer, offset, ((packetFamily & 0x3F) << 26) | ((packetId++ & 0x3FF) << 16));
157 offset += sizeUint32;
158 WriteUint32(writeBuffer, offset, EncodeVersion(1, 0, 0));
159 offset += sizeUint32;
160 }
Ferran Balaguer5bf1d322019-09-13 13:31:40 +0100161
162 packetFamily = 1;
163 packetId = 0;
164
165 WriteUint32(writeBuffer, offset, ((packetFamily & 0x3F) << 26) | ((packetId & 0x3FF) << 16));
166 offset += sizeUint32;
167 WriteUint32(writeBuffer, offset, EncodeVersion(1, 0, 0));
Ferran Balaguer47d0fe92019-09-04 16:47:34 +0100168 }
169 }
170 catch(...)
171 {
Matteo Martincigh149528e2019-09-05 12:02:04 +0100172 CancelOperationAndThrow<RuntimeException>("Error processing packet.");
Ferran Balaguer47d0fe92019-09-04 16:47:34 +0100173 }
174
175 m_Buffer.Commit(totalSize);
Ferran Balaguer73882172019-09-02 16:39:42 +0100176}
177
Matteo Martincigh149528e2019-09-05 12:02:04 +0100178void SendCounterPacket::SendCounterDirectoryPacket(const CounterDirectory& counterDirectory)
Ferran Balaguer73882172019-09-02 16:39:42 +0100179{
180 throw armnn::UnimplementedException();
181}
182
Francis Murtagh3a161982019-09-04 15:25:02 +0100183void SendCounterPacket::SendPeriodicCounterCapturePacket(uint64_t timestamp, const IndexValuePairsVector& values)
Ferran Balaguer73882172019-09-02 16:39:42 +0100184{
Francis Murtagh3a161982019-09-04 15:25:02 +0100185 uint32_t packetFamily = 1;
186 uint32_t packetClass = 0;
187 uint32_t packetType = 0;
188 uint32_t headerSize = numeric_cast<uint32_t>(2 * sizeof(uint32_t));
189 uint32_t bodySize = numeric_cast<uint32_t>((1 * sizeof(uint64_t)) +
190 (values.size() * (sizeof(uint16_t) + sizeof(uint32_t))));
191 uint32_t totalSize = headerSize + bodySize;
192 uint32_t offset = 0;
193 uint32_t reserved = 0;
194
195 unsigned char* writeBuffer = m_Buffer.Reserve(totalSize, reserved);
196
197 if (reserved < totalSize)
198 {
Matteo Martincigh149528e2019-09-05 12:02:04 +0100199 CancelOperationAndThrow<BufferExhaustion>(
200 boost::str(boost::format("No space left in buffer. Unable to reserve (%1%) bytes.")
201 % totalSize));
Francis Murtagh3a161982019-09-04 15:25:02 +0100202 }
203
204 if (writeBuffer == nullptr)
205 {
Matteo Martincigh149528e2019-09-05 12:02:04 +0100206 CancelOperationAndThrow<RuntimeException>("Error reserving buffer memory.");
Francis Murtagh3a161982019-09-04 15:25:02 +0100207 }
208
209 // Create header.
210 WriteUint32(writeBuffer,
211 offset,
212 ((packetFamily & 0x3F) << 26) | ((packetClass & 0x3FF) << 19) | ((packetType & 0x3FFF) << 16));
213 offset += numeric_cast<uint32_t>(sizeof(uint32_t));
214 WriteUint32(writeBuffer, offset, bodySize);
215
216 // Copy captured Timestamp.
217 offset += numeric_cast<uint32_t>(sizeof(uint32_t));
218 WriteUint64(writeBuffer, offset, timestamp);
219
220 // Copy selectedCounterIds.
221 offset += numeric_cast<uint32_t>(sizeof(uint64_t));
222 for (const auto& pair: values)
223 {
224 WriteUint16(writeBuffer, offset, pair.first);
225 offset += numeric_cast<uint32_t>(sizeof(uint16_t));
226 WriteUint32(writeBuffer, offset, pair.second);
227 offset += numeric_cast<uint32_t>(sizeof(uint32_t));
228 }
229
230 m_Buffer.Commit(totalSize);
Ferran Balaguer73882172019-09-02 16:39:42 +0100231}
232
233void SendCounterPacket::SendPeriodicCounterSelectionPacket(uint32_t capturePeriod,
234 const std::vector<uint16_t>& selectedCounterIds)
235{
236 uint32_t packetFamily = 0;
237 uint32_t packetId = 4;
238 uint32_t headerSize = numeric_cast<uint32_t>(2 * sizeof(uint32_t));
Francis Murtagh3a161982019-09-04 15:25:02 +0100239 uint32_t bodySize = numeric_cast<uint32_t>((1 * sizeof(uint32_t)) +
240 (selectedCounterIds.size() * sizeof(uint16_t)));
Ferran Balaguer73882172019-09-02 16:39:42 +0100241 uint32_t totalSize = headerSize + bodySize;
242 uint32_t offset = 0;
243 uint32_t reserved = 0;
244
245 unsigned char* writeBuffer = m_Buffer.Reserve(totalSize, reserved);
246
247 if (reserved < totalSize)
248 {
Matteo Martincigh149528e2019-09-05 12:02:04 +0100249 CancelOperationAndThrow<BufferExhaustion>(
250 boost::str(boost::format("No space left in buffer. Unable to reserve (%1%) bytes.")
Ferran Balaguer73882172019-09-02 16:39:42 +0100251 % totalSize));
252 }
253
254 if (writeBuffer == nullptr)
255 {
Matteo Martincigh149528e2019-09-05 12:02:04 +0100256 CancelOperationAndThrow<RuntimeException>("Error reserving buffer memory.");
Ferran Balaguer73882172019-09-02 16:39:42 +0100257 }
258
259 // Create header.
260 WriteUint32(writeBuffer, offset, ((packetFamily & 0x3F) << 26) | ((packetId & 0x3FF) << 16));
261 offset += numeric_cast<uint32_t>(sizeof(uint32_t));
262 WriteUint32(writeBuffer, offset, bodySize);
263
264 // Copy capturePeriod.
265 offset += numeric_cast<uint32_t>(sizeof(uint32_t));
266 WriteUint32(writeBuffer, offset, capturePeriod);
267
268 // Copy selectedCounterIds.
269 offset += numeric_cast<uint32_t>(sizeof(uint32_t));
270 for(const uint16_t& id: selectedCounterIds)
271 {
272 WriteUint16(writeBuffer, offset, id);
273 offset += numeric_cast<uint32_t>(sizeof(uint16_t));
274 }
275
276 m_Buffer.Commit(totalSize);
277}
278
279void SendCounterPacket::SetReadyToRead()
280{
281 m_ReadyToRead = true;
282}
283
284} // namespace profiling
285
Matteo Martincigh149528e2019-09-05 12:02:04 +0100286} // namespace armnn