#include "ProfilingUtils.hpp"
+#include <armnn/Version.hpp>
+
#include <boost/assert.hpp>
+#include <fstream>
+
namespace armnn
{
return static_cast<uint16_t>(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
#include <armnn/Exceptions.hpp>
+#include <string>
#include <stdint.h>
namespace armnn
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;
} // namespace profiling
-} // namespace armnn
\ No newline at end of file
+} // namespace armnn
#include <boost/format.hpp>
#include <boost/numeric/conversion/cast.hpp>
+#include <boost/core/ignore_unused.hpp>
+#include <iostream>
#include <unistd.h>
+#include <string.h>
namespace armnn
{
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<uint32_t>(info.size()) > 0 ? numeric_cast<uint32_t>(info.size()) + 1 : 0;
+ uint32_t hardwareVersionSize = numeric_cast<uint32_t>(hardwareVersion.size()) > 0 ?
+ numeric_cast<uint32_t>(hardwareVersion.size()) + 1 : 0;
+ uint32_t softwareVersionSize = numeric_cast<uint32_t>(softwareVersion.size()) > 0 ?
+ numeric_cast<uint32_t>(softwareVersion.size()) + 1 : 0;
+ uint32_t processNameSize = numeric_cast<uint32_t>(processName.size()) > 0 ?
+ numeric_cast<uint32_t>(processName.size()) + 1 : 0;
+
+ uint32_t sizeUint32 = numeric_cast<uint32_t>(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<uint32_t>(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<uint32_t>(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<Counter>& counters)
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;
#include "../SendCounterPacket.hpp"
#include "../ProfilingUtils.hpp"
+#include "../EncodeVersion.hpp"
#include <armnn/Exceptions.hpp>
#include <boost/test/unit_test.hpp>
+#include <boost/numeric/conversion/cast.hpp>
#include <chrono>
#include <iostream>
uint32_t capturePeriod = 1000;
std::vector<uint16_t> selectedCounterIds;
BOOST_CHECK_THROW(sendPacket1.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds),
- armnn::Exception);
+ armnn::RuntimeException);
// Packet without any counters
MockBuffer mockBuffer2(512);
}
+BOOST_AUTO_TEST_CASE(SendStreamMetaDataPacketTest)
+{
+ using boost::numeric_cast;
+
+ uint32_t sizeUint32 = numeric_cast<uint32_t>(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<uint32_t>(GetSoftwareInfo().size()) > 0 ?
+ numeric_cast<uint32_t>(GetSoftwareInfo().size()) + 1 : 0;
+ uint32_t hardwareVersionSize = numeric_cast<uint32_t>(GetHardwareVersion().size()) > 0 ?
+ numeric_cast<uint32_t>(GetHardwareVersion().size()) + 1 : 0;
+ uint32_t softwareVersionSize = numeric_cast<uint32_t>(GetSoftwareVersion().size()) > 0 ?
+ numeric_cast<uint32_t>(GetSoftwareVersion().size()) + 1 : 0;
+ uint32_t processNameSize = numeric_cast<uint32_t>(processName.size()) > 0 ?
+ numeric_cast<uint32_t>(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<uint32_t>(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<uint32_t>(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<const char *>(&readBuffer2[offset]), GetSoftwareInfo().c_str()) == 0);
+ offset += infoSize;
+ }
+
+ if (hardwareVersionSize)
+ {
+ BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readBuffer2[offset]), GetHardwareVersion().c_str()) == 0);
+ offset += hardwareVersionSize;
+ }
+
+ if (softwareVersionSize)
+ {
+ BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readBuffer2[offset]), GetSoftwareVersion().c_str()) == 0);
+ offset += softwareVersionSize;
+ }
+
+ if (processNameSize)
+ {
+ BOOST_TEST(strcmp(reinterpret_cast<const char *>(&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()