// // Copyright © 2017 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // #include "SendCounterPacket.hpp" #include "EncodeVersion.hpp" #include "ProfilingUtils.hpp" #include #include #include #include #include namespace armnn { namespace profiling { using boost::numeric_cast; const unsigned int SendCounterPacket::PIPE_MAGIC; const unsigned int SendCounterPacket::MAX_METADATA_PACKET_LENGTH; void SendCounterPacket::SendStreamMetaDataPacket() { std::string info(GetSoftwareInfo()); std::string hardwareVersion(GetHardwareVersion()); std::string softwareVersion(GetSoftwareVersion()); std::string processName = GetProcessName().substr(0, 60); uint32_t infoSize = numeric_cast(info.size()) > 0 ? numeric_cast(info.size()) + 1 : 0; uint32_t hardwareVersionSize = numeric_cast(hardwareVersion.size()) > 0 ? numeric_cast(hardwareVersion.size()) + 1 : 0; uint32_t softwareVersionSize = numeric_cast(softwareVersion.size()) > 0 ? numeric_cast(softwareVersion.size()) + 1 : 0; uint32_t processNameSize = numeric_cast(processName.size()) > 0 ? numeric_cast(processName.size()) + 1 : 0; uint32_t sizeUint32 = numeric_cast(sizeof(uint32_t)); uint32_t headerSize = 2 * sizeUint32; uint32_t bodySize = 10 * sizeUint32; uint32_t packetVersionCountSize = sizeUint32; // Supported Packets // Stream metadata packet (packet family=0; packet id=0) // Connection Acknowledged packet (packet family=0, packet id=1) // Counter Directory packet (packet family=0; packet id=2) // Request Counter Directory packet (packet family=0, packet id=3) // Periodic Counter Selection packet (packet family=0, packet id=4) // Periodic Counter Capture packet (packet family=1, packet class=0, type=0) uint32_t packetVersionEntries = 6; uint32_t payloadSize = numeric_cast(infoSize + hardwareVersionSize + softwareVersionSize + processNameSize + packetVersionCountSize + (packetVersionEntries * 2 * sizeUint32)); uint32_t totalSize = headerSize + bodySize + payloadSize; uint32_t offset = 0; uint32_t reserved = 0; unsigned char *writeBuffer = m_Buffer.Reserve(totalSize, reserved); if (reserved < totalSize) { CancelOperationAndThrow( boost::str(boost::format("No space left in buffer. Unable to reserve (%1%) bytes.") % totalSize)); } if (writeBuffer == nullptr) { CancelOperationAndThrow("Error reserving buffer memory."); } try { // Create header WriteUint32(writeBuffer, offset, 0); offset += sizeUint32; WriteUint32(writeBuffer, offset, totalSize - headerSize); // Packet body offset += sizeUint32; WriteUint32(writeBuffer, offset, PIPE_MAGIC); // pipe_magic offset += sizeUint32; WriteUint32(writeBuffer, offset, EncodeVersion(1, 0, 0)); // stream_metadata_version offset += sizeUint32; WriteUint32(writeBuffer, offset, MAX_METADATA_PACKET_LENGTH); // max_data_length offset += sizeUint32; WriteUint32(writeBuffer, offset, numeric_cast(getpid())); // pid offset += sizeUint32; uint32_t poolOffset = bodySize; WriteUint32(writeBuffer, offset, infoSize ? poolOffset : 0); // offset_info offset += sizeUint32; poolOffset += infoSize; WriteUint32(writeBuffer, offset, hardwareVersionSize ? poolOffset : 0); // offset_hw_version offset += sizeUint32; poolOffset += hardwareVersionSize; WriteUint32(writeBuffer, offset, softwareVersionSize ? poolOffset : 0); // offset_sw_version offset += sizeUint32; poolOffset += softwareVersionSize; WriteUint32(writeBuffer, offset, processNameSize ? poolOffset : 0); // offset_process_name offset += sizeUint32; poolOffset += processNameSize; WriteUint32(writeBuffer, offset, packetVersionEntries ? poolOffset : 0); // offset_packet_version_table offset += sizeUint32; WriteUint32(writeBuffer, offset, 0); // reserved offset += sizeUint32; // Pool if (infoSize) { memcpy(&writeBuffer[offset], info.c_str(), infoSize); offset += infoSize; } if (hardwareVersionSize) { memcpy(&writeBuffer[offset], hardwareVersion.c_str(), hardwareVersionSize); offset += hardwareVersionSize; } if (softwareVersionSize) { memcpy(&writeBuffer[offset], softwareVersion.c_str(), softwareVersionSize); offset += softwareVersionSize; } if (processNameSize) { memcpy(&writeBuffer[offset], processName.c_str(), processNameSize); offset += processNameSize; } if (packetVersionEntries) { // Packet Version Count WriteUint32(writeBuffer, offset, packetVersionEntries << 16); // Packet Version Entries uint32_t packetFamily = 0; uint32_t packetId = 0; offset += sizeUint32; for (uint32_t i = 0; i < packetVersionEntries - 1; ++i) { WriteUint32(writeBuffer, offset, ((packetFamily & 0x3F) << 26) | ((packetId++ & 0x3FF) << 16)); offset += sizeUint32; WriteUint32(writeBuffer, offset, EncodeVersion(1, 0, 0)); offset += sizeUint32; } packetFamily = 1; packetId = 0; WriteUint32(writeBuffer, offset, ((packetFamily & 0x3F) << 26) | ((packetId & 0x3FF) << 16)); offset += sizeUint32; WriteUint32(writeBuffer, offset, EncodeVersion(1, 0, 0)); } } catch(...) { CancelOperationAndThrow("Error processing packet."); } m_Buffer.Commit(totalSize); } void SendCounterPacket::SendCounterDirectoryPacket(const CounterDirectory& counterDirectory) { throw armnn::UnimplementedException(); } void SendCounterPacket::SendPeriodicCounterCapturePacket(uint64_t timestamp, const IndexValuePairsVector& values) { uint32_t packetFamily = 1; uint32_t packetClass = 0; uint32_t packetType = 0; uint32_t headerSize = numeric_cast(2 * sizeof(uint32_t)); uint32_t bodySize = numeric_cast((1 * sizeof(uint64_t)) + (values.size() * (sizeof(uint16_t) + sizeof(uint32_t)))); uint32_t totalSize = headerSize + bodySize; uint32_t offset = 0; uint32_t reserved = 0; unsigned char* writeBuffer = m_Buffer.Reserve(totalSize, reserved); if (reserved < totalSize) { CancelOperationAndThrow( boost::str(boost::format("No space left in buffer. Unable to reserve (%1%) bytes.") % totalSize)); } if (writeBuffer == nullptr) { CancelOperationAndThrow("Error reserving buffer memory."); } // Create header. WriteUint32(writeBuffer, offset, ((packetFamily & 0x3F) << 26) | ((packetClass & 0x3FF) << 19) | ((packetType & 0x3FFF) << 16)); offset += numeric_cast(sizeof(uint32_t)); WriteUint32(writeBuffer, offset, bodySize); // Copy captured Timestamp. offset += numeric_cast(sizeof(uint32_t)); WriteUint64(writeBuffer, offset, timestamp); // Copy selectedCounterIds. offset += numeric_cast(sizeof(uint64_t)); for (const auto& pair: values) { WriteUint16(writeBuffer, offset, pair.first); offset += numeric_cast(sizeof(uint16_t)); WriteUint32(writeBuffer, offset, pair.second); offset += numeric_cast(sizeof(uint32_t)); } m_Buffer.Commit(totalSize); } void SendCounterPacket::SendPeriodicCounterSelectionPacket(uint32_t capturePeriod, const std::vector& selectedCounterIds) { uint32_t packetFamily = 0; uint32_t packetId = 4; uint32_t headerSize = numeric_cast(2 * sizeof(uint32_t)); uint32_t bodySize = numeric_cast((1 * sizeof(uint32_t)) + (selectedCounterIds.size() * sizeof(uint16_t))); uint32_t totalSize = headerSize + bodySize; uint32_t offset = 0; uint32_t reserved = 0; unsigned char* writeBuffer = m_Buffer.Reserve(totalSize, reserved); if (reserved < totalSize) { CancelOperationAndThrow( boost::str(boost::format("No space left in buffer. Unable to reserve (%1%) bytes.") % totalSize)); } if (writeBuffer == nullptr) { CancelOperationAndThrow("Error reserving buffer memory."); } // Create header. WriteUint32(writeBuffer, offset, ((packetFamily & 0x3F) << 26) | ((packetId & 0x3FF) << 16)); offset += numeric_cast(sizeof(uint32_t)); WriteUint32(writeBuffer, offset, bodySize); // Copy capturePeriod. offset += numeric_cast(sizeof(uint32_t)); WriteUint32(writeBuffer, offset, capturePeriod); // Copy selectedCounterIds. offset += numeric_cast(sizeof(uint32_t)); for(const uint16_t& id: selectedCounterIds) { WriteUint16(writeBuffer, offset, id); offset += numeric_cast(sizeof(uint16_t)); } m_Buffer.Commit(totalSize); } void SendCounterPacket::SetReadyToRead() { m_ReadyToRead = true; } } // namespace profiling } // namespace armnn