Ferran Balaguer | 7388217 | 2019-09-02 16:39:42 +0100 | [diff] [blame] | 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> |
Ferran Balaguer | 47d0fe9 | 2019-09-04 16:47:34 +0100 | [diff] [blame] | 14 | #include <boost/core/ignore_unused.hpp> |
Ferran Balaguer | 7388217 | 2019-09-02 16:39:42 +0100 | [diff] [blame] | 15 | |
Matteo Martincigh | 149528e | 2019-09-05 12:02:04 +0100 | [diff] [blame] | 16 | #include <cstring> |
Ferran Balaguer | 7388217 | 2019-09-02 16:39:42 +0100 | [diff] [blame] | 17 | |
| 18 | namespace armnn |
| 19 | { |
| 20 | |
| 21 | namespace profiling |
| 22 | { |
| 23 | |
| 24 | using boost::numeric_cast; |
| 25 | |
Ferran Balaguer | 47d0fe9 | 2019-09-04 16:47:34 +0100 | [diff] [blame] | 26 | const unsigned int SendCounterPacket::PIPE_MAGIC; |
| 27 | const unsigned int SendCounterPacket::MAX_METADATA_PACKET_LENGTH; |
| 28 | |
Ferran Balaguer | 7388217 | 2019-09-02 16:39:42 +0100 | [diff] [blame] | 29 | void SendCounterPacket::SendStreamMetaDataPacket() |
| 30 | { |
Ferran Balaguer | 47d0fe9 | 2019-09-04 16:47:34 +0100 | [diff] [blame] | 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) |
Ferran Balaguer | 5bf1d32 | 2019-09-13 13:31:40 +0100 | [diff] [blame] | 56 | // Periodic Counter Capture packet (packet family=1, packet class=0, type=0) |
| 57 | uint32_t packetVersionEntries = 6; |
Ferran Balaguer | 47d0fe9 | 2019-09-04 16:47:34 +0100 | [diff] [blame] | 58 | |
| 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 Martincigh | 149528e | 2019-09-05 12:02:04 +0100 | [diff] [blame] | 71 | CancelOperationAndThrow<BufferExhaustion>( |
| 72 | boost::str(boost::format("No space left in buffer. Unable to reserve (%1%) bytes.") |
| 73 | % totalSize)); |
Ferran Balaguer | 47d0fe9 | 2019-09-04 16:47:34 +0100 | [diff] [blame] | 74 | } |
| 75 | |
| 76 | if (writeBuffer == nullptr) |
| 77 | { |
Matteo Martincigh | 149528e | 2019-09-05 12:02:04 +0100 | [diff] [blame] | 78 | CancelOperationAndThrow<RuntimeException>("Error reserving buffer memory."); |
Ferran Balaguer | 47d0fe9 | 2019-09-04 16:47:34 +0100 | [diff] [blame] | 79 | } |
| 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 Martincigh | 149528e | 2019-09-05 12:02:04 +0100 | [diff] [blame] | 120 | if (infoSize) |
| 121 | { |
Ferran Balaguer | 47d0fe9 | 2019-09-04 16:47:34 +0100 | [diff] [blame] | 122 | memcpy(&writeBuffer[offset], info.c_str(), infoSize); |
| 123 | offset += infoSize; |
| 124 | } |
| 125 | |
Matteo Martincigh | 149528e | 2019-09-05 12:02:04 +0100 | [diff] [blame] | 126 | if (hardwareVersionSize) |
| 127 | { |
Ferran Balaguer | 47d0fe9 | 2019-09-04 16:47:34 +0100 | [diff] [blame] | 128 | memcpy(&writeBuffer[offset], hardwareVersion.c_str(), hardwareVersionSize); |
| 129 | offset += hardwareVersionSize; |
| 130 | } |
| 131 | |
Matteo Martincigh | 149528e | 2019-09-05 12:02:04 +0100 | [diff] [blame] | 132 | if (softwareVersionSize) |
| 133 | { |
Ferran Balaguer | 47d0fe9 | 2019-09-04 16:47:34 +0100 | [diff] [blame] | 134 | memcpy(&writeBuffer[offset], softwareVersion.c_str(), softwareVersionSize); |
| 135 | offset += softwareVersionSize; |
| 136 | } |
| 137 | |
Matteo Martincigh | 149528e | 2019-09-05 12:02:04 +0100 | [diff] [blame] | 138 | if (processNameSize) |
| 139 | { |
Ferran Balaguer | 47d0fe9 | 2019-09-04 16:47:34 +0100 | [diff] [blame] | 140 | memcpy(&writeBuffer[offset], processName.c_str(), processNameSize); |
| 141 | offset += processNameSize; |
| 142 | } |
| 143 | |
Matteo Martincigh | 149528e | 2019-09-05 12:02:04 +0100 | [diff] [blame] | 144 | if (packetVersionEntries) |
| 145 | { |
Ferran Balaguer | 47d0fe9 | 2019-09-04 16:47:34 +0100 | [diff] [blame] | 146 | // 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 Balaguer | 5bf1d32 | 2019-09-13 13:31:40 +0100 | [diff] [blame] | 154 | for (uint32_t i = 0; i < packetVersionEntries - 1; ++i) |
| 155 | { |
Ferran Balaguer | 47d0fe9 | 2019-09-04 16:47:34 +0100 | [diff] [blame] | 156 | 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 Balaguer | 5bf1d32 | 2019-09-13 13:31:40 +0100 | [diff] [blame] | 161 | |
| 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 Balaguer | 47d0fe9 | 2019-09-04 16:47:34 +0100 | [diff] [blame] | 168 | } |
| 169 | } |
| 170 | catch(...) |
| 171 | { |
Matteo Martincigh | 149528e | 2019-09-05 12:02:04 +0100 | [diff] [blame] | 172 | CancelOperationAndThrow<RuntimeException>("Error processing packet."); |
Ferran Balaguer | 47d0fe9 | 2019-09-04 16:47:34 +0100 | [diff] [blame] | 173 | } |
| 174 | |
| 175 | m_Buffer.Commit(totalSize); |
Ferran Balaguer | 7388217 | 2019-09-02 16:39:42 +0100 | [diff] [blame] | 176 | } |
| 177 | |
Matteo Martincigh | 149528e | 2019-09-05 12:02:04 +0100 | [diff] [blame] | 178 | void SendCounterPacket::SendCounterDirectoryPacket(const CounterDirectory& counterDirectory) |
Ferran Balaguer | 7388217 | 2019-09-02 16:39:42 +0100 | [diff] [blame] | 179 | { |
| 180 | throw armnn::UnimplementedException(); |
| 181 | } |
| 182 | |
Francis Murtagh | 3a16198 | 2019-09-04 15:25:02 +0100 | [diff] [blame] | 183 | void SendCounterPacket::SendPeriodicCounterCapturePacket(uint64_t timestamp, const IndexValuePairsVector& values) |
Ferran Balaguer | 7388217 | 2019-09-02 16:39:42 +0100 | [diff] [blame] | 184 | { |
Francis Murtagh | 3a16198 | 2019-09-04 15:25:02 +0100 | [diff] [blame] | 185 | 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 Martincigh | 149528e | 2019-09-05 12:02:04 +0100 | [diff] [blame] | 199 | CancelOperationAndThrow<BufferExhaustion>( |
| 200 | boost::str(boost::format("No space left in buffer. Unable to reserve (%1%) bytes.") |
| 201 | % totalSize)); |
Francis Murtagh | 3a16198 | 2019-09-04 15:25:02 +0100 | [diff] [blame] | 202 | } |
| 203 | |
| 204 | if (writeBuffer == nullptr) |
| 205 | { |
Matteo Martincigh | 149528e | 2019-09-05 12:02:04 +0100 | [diff] [blame] | 206 | CancelOperationAndThrow<RuntimeException>("Error reserving buffer memory."); |
Francis Murtagh | 3a16198 | 2019-09-04 15:25:02 +0100 | [diff] [blame] | 207 | } |
| 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 Balaguer | 7388217 | 2019-09-02 16:39:42 +0100 | [diff] [blame] | 231 | } |
| 232 | |
| 233 | void 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 Murtagh | 3a16198 | 2019-09-04 15:25:02 +0100 | [diff] [blame] | 239 | uint32_t bodySize = numeric_cast<uint32_t>((1 * sizeof(uint32_t)) + |
| 240 | (selectedCounterIds.size() * sizeof(uint16_t))); |
Ferran Balaguer | 7388217 | 2019-09-02 16:39:42 +0100 | [diff] [blame] | 241 | 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 Martincigh | 149528e | 2019-09-05 12:02:04 +0100 | [diff] [blame] | 249 | CancelOperationAndThrow<BufferExhaustion>( |
| 250 | boost::str(boost::format("No space left in buffer. Unable to reserve (%1%) bytes.") |
Ferran Balaguer | 7388217 | 2019-09-02 16:39:42 +0100 | [diff] [blame] | 251 | % totalSize)); |
| 252 | } |
| 253 | |
| 254 | if (writeBuffer == nullptr) |
| 255 | { |
Matteo Martincigh | 149528e | 2019-09-05 12:02:04 +0100 | [diff] [blame] | 256 | CancelOperationAndThrow<RuntimeException>("Error reserving buffer memory."); |
Ferran Balaguer | 7388217 | 2019-09-02 16:39:42 +0100 | [diff] [blame] | 257 | } |
| 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 | |
| 279 | void SendCounterPacket::SetReadyToRead() |
| 280 | { |
| 281 | m_ReadyToRead = true; |
| 282 | } |
| 283 | |
| 284 | } // namespace profiling |
| 285 | |
Matteo Martincigh | 149528e | 2019-09-05 12:02:04 +0100 | [diff] [blame] | 286 | } // namespace armnn |