From 47d0fe98ca6ab3ba1d21b0971d3009a287974442 Mon Sep 17 00:00:00 2001 From: Ferran Balaguer Date: Wed, 4 Sep 2019 16:47:34 +0100 Subject: [PATCH] IVGCVSW-3690 Implement SendCounterPacket.SendStreamMetaDataPacket() function Signed-off-by: Ferran Balaguer Change-Id: I9e034b0caaff5371fadfdba20fdbe3171d4cd2e6 --- src/profiling/ProfilingUtils.cpp | 29 ++++++ src/profiling/ProfilingUtils.hpp | 11 +- src/profiling/SendCounterPacket.cpp | 143 +++++++++++++++++++++++++- src/profiling/SendCounterPacket.hpp | 3 + src/profiling/test/SendCounterPacketTests.cpp | 117 ++++++++++++++++++++- 5 files changed, 300 insertions(+), 3 deletions(-) diff --git a/src/profiling/ProfilingUtils.cpp b/src/profiling/ProfilingUtils.cpp index b948026..86abef1 100644 --- a/src/profiling/ProfilingUtils.cpp +++ b/src/profiling/ProfilingUtils.cpp @@ -5,8 +5,12 @@ #include "ProfilingUtils.hpp" +#include + #include +#include + namespace armnn { @@ -84,6 +88,31 @@ uint16_t ReadUint16(const unsigned char* buffer, unsigned int offset) return static_cast(value); } +std::string GetSoftwareInfo() +{ + return std::string("ArmNN"); +} + +std::string GetHardwareVersion() +{ + return std::string(); +} + +std::string GetSoftwareVersion() +{ + std::string armnnVersion(ARMNN_VERSION); + std::string result = "Armnn " + armnnVersion.substr(2,2) + "." + armnnVersion.substr(4,2); + return result; +} + +std::string GetProcessName() +{ + std::ifstream comm("/proc/self/comm"); + std::string name; + getline(comm, name); + return name; +} + } // namespace profiling } // namespace armnn \ No newline at end of file diff --git a/src/profiling/ProfilingUtils.hpp b/src/profiling/ProfilingUtils.hpp index fe58ee1..410198a 100644 --- a/src/profiling/ProfilingUtils.hpp +++ b/src/profiling/ProfilingUtils.hpp @@ -7,6 +7,7 @@ #include +#include #include namespace armnn @@ -27,6 +28,14 @@ uint32_t ReadUint32(const unsigned char* buffer, unsigned int offset); uint16_t ReadUint16(const unsigned char* buffer, unsigned int offset); +std::string GetSoftwareInfo(); + +std::string GetSoftwareVersion(); + +std::string GetHardwareVersion(); + +std::string GetProcessName(); + class BufferExhaustion : public armnn::Exception { using Exception::Exception; @@ -34,4 +43,4 @@ class BufferExhaustion : public armnn::Exception } // namespace profiling -} // namespace armnn \ No newline at end of file +} // namespace armnn diff --git a/src/profiling/SendCounterPacket.cpp b/src/profiling/SendCounterPacket.cpp index 645b791..61d32da 100644 --- a/src/profiling/SendCounterPacket.cpp +++ b/src/profiling/SendCounterPacket.cpp @@ -11,8 +11,11 @@ #include #include +#include +#include #include +#include namespace armnn { @@ -22,9 +25,147 @@ namespace profiling using boost::numeric_cast; +const unsigned int SendCounterPacket::PIPE_MAGIC; +const unsigned int SendCounterPacket::MAX_METADATA_PACKET_LENGTH; + void SendCounterPacket::SendStreamMetaDataPacket() { - throw armnn::UnimplementedException(); + 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) + uint32_t packetVersionEntries = 5; + + 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) + { + // Cancel the operation. + m_Buffer.Commit(0); + throw RuntimeException(boost::str(boost::format("No space left in buffer. Unable to reserve (%1%) bytes.") + % totalSize)); + } + + if (writeBuffer == nullptr) + { + // Cancel the operation. + m_Buffer.Commit(0); + throw RuntimeException("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; ++i) { + WriteUint32(writeBuffer, offset, ((packetFamily & 0x3F) << 26) | ((packetId++ & 0x3FF) << 16)); + offset += sizeUint32; + WriteUint32(writeBuffer, offset, EncodeVersion(1, 0, 0)); + offset += sizeUint32; + } + } + } + catch(...) + { + // Cancel the operation. + m_Buffer.Commit(0); + throw RuntimeException("Error processing packet."); + } + + m_Buffer.Commit(totalSize); } void SendCounterPacket::SendCounterDirectoryPacket(const Category& category, const std::vector& counters) diff --git a/src/profiling/SendCounterPacket.hpp b/src/profiling/SendCounterPacket.hpp index 453c001..0fc3055 100644 --- a/src/profiling/SendCounterPacket.hpp +++ b/src/profiling/SendCounterPacket.hpp @@ -33,6 +33,9 @@ public: void SetReadyToRead() override; + static const unsigned int PIPE_MAGIC = 0x45495434; + static const unsigned int MAX_METADATA_PACKET_LENGTH = 4096; + private: IBufferWrapper& m_Buffer; bool m_ReadyToRead; diff --git a/src/profiling/test/SendCounterPacketTests.cpp b/src/profiling/test/SendCounterPacketTests.cpp index 89c05d1..5309560 100644 --- a/src/profiling/test/SendCounterPacketTests.cpp +++ b/src/profiling/test/SendCounterPacketTests.cpp @@ -5,10 +5,12 @@ #include "../SendCounterPacket.hpp" #include "../ProfilingUtils.hpp" +#include "../EncodeVersion.hpp" #include #include +#include #include #include @@ -142,7 +144,7 @@ BOOST_AUTO_TEST_CASE(SendPeriodicCounterSelectionPacketTest) uint32_t capturePeriod = 1000; std::vector selectedCounterIds; BOOST_CHECK_THROW(sendPacket1.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds), - armnn::Exception); + armnn::RuntimeException); // Packet without any counters MockBuffer mockBuffer2(512); @@ -273,4 +275,117 @@ BOOST_AUTO_TEST_CASE(SendPeriodicCounterCapturePacketTest) } +BOOST_AUTO_TEST_CASE(SendStreamMetaDataPacketTest) +{ + using boost::numeric_cast; + + uint32_t sizeUint32 = numeric_cast(sizeof(uint32_t)); + + // Error no space left in buffer + MockBuffer mockBuffer1(10); + SendCounterPacket sendPacket1(mockBuffer1); + BOOST_CHECK_THROW(sendPacket1.SendStreamMetaDataPacket(), armnn::RuntimeException); + + // Full metadata packet + + std::string processName = GetProcessName().substr(0, 60); + + uint32_t infoSize = numeric_cast(GetSoftwareInfo().size()) > 0 ? + numeric_cast(GetSoftwareInfo().size()) + 1 : 0; + uint32_t hardwareVersionSize = numeric_cast(GetHardwareVersion().size()) > 0 ? + numeric_cast(GetHardwareVersion().size()) + 1 : 0; + uint32_t softwareVersionSize = numeric_cast(GetSoftwareVersion().size()) > 0 ? + numeric_cast(GetSoftwareVersion().size()) + 1 : 0; + uint32_t processNameSize = numeric_cast(processName.size()) > 0 ? + numeric_cast(processName.size()) + 1 : 0; + + uint32_t packetEntries = 5; + + MockBuffer mockBuffer2(512); + SendCounterPacket sendPacket2(mockBuffer2); + sendPacket2.SendStreamMetaDataPacket(); + unsigned int sizeRead = 0; + const unsigned char* readBuffer2 = mockBuffer2.GetReadBuffer(sizeRead); + + uint32_t headerWord0 = ReadUint32(readBuffer2, 0); + uint32_t headerWord1 = ReadUint32(readBuffer2, sizeUint32); + + BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family + BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 0); // packet id + + uint32_t totalLength = numeric_cast(2 * sizeUint32 + 10 * sizeUint32 + infoSize + hardwareVersionSize + + softwareVersionSize + processNameSize + sizeUint32 + + 2 * packetEntries * sizeUint32); + + BOOST_TEST(headerWord1 == totalLength - (2 * sizeUint32)); // data length + + uint32_t offset = sizeUint32 * 2; + BOOST_TEST(ReadUint32(readBuffer2, offset) == SendCounterPacket::PIPE_MAGIC); // pipe_magic + offset += sizeUint32; + BOOST_TEST(ReadUint32(readBuffer2, offset) == EncodeVersion(1, 0, 0)); // stream_metadata_version + offset += sizeUint32; + BOOST_TEST(ReadUint32(readBuffer2, offset) == SendCounterPacket::MAX_METADATA_PACKET_LENGTH); // max_data_len + offset += sizeUint32; + BOOST_TEST(ReadUint32(readBuffer2, offset) == numeric_cast(getpid())); // pid + offset += sizeUint32; + uint32_t poolOffset = 10 * sizeUint32; + BOOST_TEST(ReadUint32(readBuffer2, offset) == (infoSize ? poolOffset : 0)); // offset_info + offset += sizeUint32; + poolOffset += infoSize; + BOOST_TEST(ReadUint32(readBuffer2, offset) == (hardwareVersionSize ? poolOffset : 0)); // offset_hw_version + offset += sizeUint32; + poolOffset += hardwareVersionSize; + BOOST_TEST(ReadUint32(readBuffer2, offset) == (softwareVersionSize ? poolOffset : 0)); // offset_sw_version + offset += sizeUint32; + poolOffset += softwareVersionSize; + BOOST_TEST(ReadUint32(readBuffer2, offset) == (processNameSize ? poolOffset : 0)); // offset_process_name + offset += sizeUint32; + poolOffset += processNameSize; + BOOST_TEST(ReadUint32(readBuffer2, offset) == (packetEntries ? poolOffset : 0)); // offset_packet_version_table + offset += sizeUint32; + BOOST_TEST(ReadUint32(readBuffer2, offset) == 0); // reserved + + offset += sizeUint32; + if (infoSize) + { + BOOST_TEST(strcmp(reinterpret_cast(&readBuffer2[offset]), GetSoftwareInfo().c_str()) == 0); + offset += infoSize; + } + + if (hardwareVersionSize) + { + BOOST_TEST(strcmp(reinterpret_cast(&readBuffer2[offset]), GetHardwareVersion().c_str()) == 0); + offset += hardwareVersionSize; + } + + if (softwareVersionSize) + { + BOOST_TEST(strcmp(reinterpret_cast(&readBuffer2[offset]), GetSoftwareVersion().c_str()) == 0); + offset += softwareVersionSize; + } + + if (processNameSize) + { + BOOST_TEST(strcmp(reinterpret_cast(&readBuffer2[offset]), GetProcessName().c_str()) == 0); + offset += processNameSize; + } + + if (packetEntries) + { + BOOST_TEST((ReadUint32(readBuffer2, offset) >> 16) == packetEntries); + offset += sizeUint32; + for (uint32_t i = 0; i < packetEntries; ++i) + { + BOOST_TEST(((ReadUint32(readBuffer2, offset) >> 26) & 0x3F) == 0); + BOOST_TEST(((ReadUint32(readBuffer2, offset) >> 16) & 0x3FF) == i); + offset += sizeUint32; + BOOST_TEST(ReadUint32(readBuffer2, offset) == EncodeVersion(1, 0, 0)); + offset += sizeUint32; + } + } + + BOOST_TEST(offset == totalLength); +} + + BOOST_AUTO_TEST_SUITE_END() -- 2.7.4