2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
6 #include "SendCounterPacket.hpp"
7 #include "EncodeVersion.hpp"
8 #include "ProfilingUtils.hpp"
10 #include <armnn/Exceptions.hpp>
12 #include <boost/format.hpp>
13 #include <boost/numeric/conversion/cast.hpp>
14 #include <boost/core/ignore_unused.hpp>
26 using boost::numeric_cast;
28 const unsigned int SendCounterPacket::PIPE_MAGIC;
29 const unsigned int SendCounterPacket::MAX_METADATA_PACKET_LENGTH;
31 void SendCounterPacket::SendStreamMetaDataPacket()
33 std::string info(GetSoftwareInfo());
34 std::string hardwareVersion(GetHardwareVersion());
35 std::string softwareVersion(GetSoftwareVersion());
36 std::string processName = GetProcessName().substr(0, 60);
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;
46 uint32_t sizeUint32 = numeric_cast<uint32_t>(sizeof(uint32_t));
48 uint32_t headerSize = 2 * sizeUint32;
49 uint32_t bodySize = 10 * sizeUint32;
50 uint32_t packetVersionCountSize = sizeUint32;
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;
60 uint32_t payloadSize = numeric_cast<uint32_t>(infoSize + hardwareVersionSize + softwareVersionSize +
61 processNameSize + packetVersionCountSize +
62 (packetVersionEntries * 2 * sizeUint32));
64 uint32_t totalSize = headerSize + bodySize + payloadSize;
66 uint32_t reserved = 0;
68 unsigned char *writeBuffer = m_Buffer.Reserve(totalSize, reserved);
70 if (reserved < totalSize)
72 // Cancel the operation.
74 throw RuntimeException(boost::str(boost::format("No space left in buffer. Unable to reserve (%1%) bytes.")
78 if (writeBuffer == nullptr)
80 // Cancel the operation.
82 throw RuntimeException("Error reserving buffer memory.");
89 WriteUint32(writeBuffer, offset, 0);
91 WriteUint32(writeBuffer, offset, totalSize - headerSize);
96 WriteUint32(writeBuffer, offset, PIPE_MAGIC); // pipe_magic
98 WriteUint32(writeBuffer, offset, EncodeVersion(1, 0, 0)); // stream_metadata_version
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;
125 memcpy(&writeBuffer[offset], info.c_str(), infoSize);
129 if (hardwareVersionSize) {
130 memcpy(&writeBuffer[offset], hardwareVersion.c_str(), hardwareVersionSize);
131 offset += hardwareVersionSize;
134 if (softwareVersionSize) {
135 memcpy(&writeBuffer[offset], softwareVersion.c_str(), softwareVersionSize);
136 offset += softwareVersionSize;
139 if (processNameSize) {
140 memcpy(&writeBuffer[offset], processName.c_str(), processNameSize);
141 offset += processNameSize;
144 if (packetVersionEntries) {
145 // Packet Version Count
146 WriteUint32(writeBuffer, offset, packetVersionEntries << 16);
148 // Packet Version Entries
149 uint32_t packetFamily = 0;
150 uint32_t packetId = 0;
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;
163 // Cancel the operation.
165 throw RuntimeException("Error processing packet.");
168 m_Buffer.Commit(totalSize);
171 void SendCounterPacket::SendCounterDirectoryPacket(const Category& category, const std::vector<Counter>& counters)
173 throw armnn::UnimplementedException();
176 void SendCounterPacket::SendPeriodicCounterCapturePacket(uint64_t timestamp, const IndexValuePairsVector& values)
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;
186 uint32_t reserved = 0;
188 unsigned char* writeBuffer = m_Buffer.Reserve(totalSize, reserved);
190 if (reserved < totalSize)
192 // Cancel the operation.
194 throw profiling::BufferExhaustion(
195 boost::str(boost::format("No space left in buffer. Unable to reserve (%1%) bytes.") % totalSize));
198 if (writeBuffer == nullptr)
200 // Cancel the operation.
202 throw RuntimeException("Error reserving buffer memory.");
206 WriteUint32(writeBuffer,
208 ((packetFamily & 0x3F) << 26) | ((packetClass & 0x3FF) << 19) | ((packetType & 0x3FFF) << 16));
209 offset += numeric_cast<uint32_t>(sizeof(uint32_t));
210 WriteUint32(writeBuffer, offset, bodySize);
212 // Copy captured Timestamp.
213 offset += numeric_cast<uint32_t>(sizeof(uint32_t));
214 WriteUint64(writeBuffer, offset, timestamp);
216 // Copy selectedCounterIds.
217 offset += numeric_cast<uint32_t>(sizeof(uint64_t));
218 for (const auto& pair: values)
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));
226 m_Buffer.Commit(totalSize);
229 void SendCounterPacket::SendPeriodicCounterSelectionPacket(uint32_t capturePeriod,
230 const std::vector<uint16_t>& selectedCounterIds)
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;
239 uint32_t reserved = 0;
241 unsigned char* writeBuffer = m_Buffer.Reserve(totalSize, reserved);
243 if (reserved < totalSize)
245 // Cancel the operation.
247 throw RuntimeException(boost::str(boost::format("No space left in buffer. Unable to reserve (%1%) bytes.")
251 if (writeBuffer == nullptr)
253 // Cancel the operation.
255 throw RuntimeException("Error reserving buffer memory.");
259 WriteUint32(writeBuffer, offset, ((packetFamily & 0x3F) << 26) | ((packetId & 0x3FF) << 16));
260 offset += numeric_cast<uint32_t>(sizeof(uint32_t));
261 WriteUint32(writeBuffer, offset, bodySize);
263 // Copy capturePeriod.
264 offset += numeric_cast<uint32_t>(sizeof(uint32_t));
265 WriteUint32(writeBuffer, offset, capturePeriod);
267 // Copy selectedCounterIds.
268 offset += numeric_cast<uint32_t>(sizeof(uint32_t));
269 for(const uint16_t& id: selectedCounterIds)
271 WriteUint16(writeBuffer, offset, id);
272 offset += numeric_cast<uint32_t>(sizeof(uint16_t));
275 m_Buffer.Commit(totalSize);
278 void SendCounterPacket::SetReadyToRead()
280 m_ReadyToRead = true;
283 } // namespace profiling