From: Sadik Armagan Date: Thu, 24 Oct 2019 09:26:05 +0000 (+0100) Subject: IVGCVSW-3950 Create SendTimelinePacket interface and class X-Git-Tag: submit/tizen/20200316.035456~119 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7bbdf9db051f40377a284a28375816e60349376d;p=platform%2Fupstream%2Farmnn.git IVGCVSW-3950 Create SendTimelinePacket interface and class * Implemented ISendTimelinePacket interface and its implementation SendTimelinePacket * Implemented TimelinePacketWriterFactory * Implemented unit tests for SendTimelinePacket functions Signed-off-by: Sadik Armagan Change-Id: I0a47586437f99510394d4d94589dccfb397d38e5 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index d686d3f..e3b1f8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -455,6 +455,7 @@ list(APPEND armnn_sources src/profiling/ICounterDirectory.hpp src/profiling/ICounterValues.hpp src/profiling/ISendCounterPacket.hpp + src/profiling/ISendTimelinePacket.hpp src/profiling/IPacketBuffer.hpp src/profiling/IPeriodicCounterCapture.hpp src/profiling/IProfilingConnection.hpp @@ -486,8 +487,12 @@ list(APPEND armnn_sources src/profiling/RequestCounterDirectoryCommandHandler.hpp src/profiling/SendCounterPacket.cpp src/profiling/SendCounterPacket.hpp + src/profiling/SendTimelinePacket.cpp + src/profiling/SendTimelinePacket.hpp src/profiling/SocketProfilingConnection.cpp src/profiling/SocketProfilingConnection.hpp + src/profiling/TimelinePacketWriterFactory.cpp + src/profiling/TimelinePacketWriterFactory.hpp third-party/half/half.hpp ) @@ -616,6 +621,7 @@ if(BUILD_UNIT_TESTS) src/profiling/test/ProfilingTests.hpp src/profiling/test/SendCounterPacketTests.cpp src/profiling/test/SendCounterPacketTests.hpp + src/profiling/test/SendTimelinePacketTests.cpp src/profiling/test/TimelinePacketTests.cpp ) diff --git a/src/profiling/IBufferManager.hpp b/src/profiling/IBufferManager.hpp index 0acdf61..c35d9c6 100644 --- a/src/profiling/IBufferManager.hpp +++ b/src/profiling/IBufferManager.hpp @@ -9,6 +9,8 @@ #include +#define MAX_METADATA_PACKET_LENGTH 4096 + namespace armnn { diff --git a/src/profiling/ISendTimelinePacket.hpp b/src/profiling/ISendTimelinePacket.hpp new file mode 100644 index 0000000..34157b8 --- /dev/null +++ b/src/profiling/ISendTimelinePacket.hpp @@ -0,0 +1,53 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "ProfilingUtils.hpp" + +#include +#include +#include + +namespace armnn +{ + +namespace profiling +{ + +class ISendTimelinePacket +{ +public: + virtual ~ISendTimelinePacket() {} + + /// Commits the current buffer and reset the member variables + virtual void Commit() = 0; + + /// Create and write a TimelineEntityBinaryPacket from the parameters to the buffer. + virtual void SendTimelineEntityBinaryPacket(uint64_t profilingGuid) = 0; + + /// Create and write a TimelineEventBinaryPacket from the parameters to the buffer. + virtual void SendTimelineEventBinaryPacket(uint64_t timestamp, uint32_t threadId, uint64_t profilingGuid) = 0; + + /// Create and write a TimelineEventClassBinaryPacket from the parameters to the buffer. + virtual void SendTimelineEventClassBinaryPacket(uint64_t profilingGuid) = 0; + + /// Create and write a TimelineLabelBinaryPacket from the parameters to the buffer. + virtual void SendTimelineLabelBinaryPacket(uint64_t profilingGuid, const std::string& label) = 0; + + /// Create and write a TimelineMessageDirectoryPackage in the buffer + virtual void SendTimelineMessageDirectoryPackage() = 0; + + /// Create and write a TimelineRelationshipBinaryPacket from the parameters to the buffer. + virtual void SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType relationshipType, + uint64_t relationshipGuid, + uint64_t headGuid, + uint64_t tailGuid) = 0; +}; + +} // namespace profiling + +} // namespace armnn + diff --git a/src/profiling/ProfilingUtils.cpp b/src/profiling/ProfilingUtils.cpp index f4d4f8f..905ecb5 100644 --- a/src/profiling/ProfilingUtils.cpp +++ b/src/profiling/ProfilingUtils.cpp @@ -279,6 +279,91 @@ std::pair CreateTimelinePacketHeader(uint32_t packetFamily, return std::make_pair(packetHeaderWord0, packetHeaderWord1); } +// Calculate the actual length an SwString will be including the terminating null character +// padding to bring it to the next uint32_t boundary but minus the leading uint32_t encoding +// the size to allow the offset to be correctly updated when decoding a binary packet. +uint32_t CalculateSizeOfPaddedSwString(const std::string& str) +{ + std::vector swTraceString; + StringToSwTraceString(str, swTraceString); + unsigned int uint32_t_size = sizeof(uint32_t); + uint32_t size = (boost::numeric_cast(swTraceString.size()) - 1) * uint32_t_size; + return size; +} + +// Read TimelineMessageDirectoryPacket from given IPacketBuffer and offset +SwTraceMessage ReadSwTraceMessage(const std::unique_ptr& packetBuffer, unsigned int& offset) +{ + BOOST_ASSERT(packetBuffer); + + unsigned int uint32_t_size = sizeof(uint32_t); + + SwTraceMessage swTraceMessage; + + // Read the decl_id + uint32_t readDeclId = ReadUint32(packetBuffer, offset); + swTraceMessage.id = readDeclId; + + // SWTrace "namestring" format + // length of the string (first 4 bytes) + string + null terminator + + // Check the decl_name + offset += uint32_t_size; + uint32_t swTraceDeclNameLength = ReadUint32(packetBuffer, offset); + + offset += uint32_t_size; + std::vector swTraceStringBuffer(swTraceDeclNameLength - 1); + std::memcpy(swTraceStringBuffer.data(), + packetBuffer->GetReadableData() + offset, swTraceStringBuffer.size()); + + swTraceMessage.name.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // name + + // Check the ui_name + offset += CalculateSizeOfPaddedSwString(swTraceMessage.name); + uint32_t swTraceUINameLength = ReadUint32(packetBuffer, offset); + + offset += uint32_t_size; + swTraceStringBuffer.resize(swTraceUINameLength - 1); + std::memcpy(swTraceStringBuffer.data(), + packetBuffer->GetReadableData() + offset, swTraceStringBuffer.size()); + + swTraceMessage.uiName.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // ui_name + + // Check arg_types + offset += CalculateSizeOfPaddedSwString(swTraceMessage.uiName); + uint32_t swTraceArgTypesLength = ReadUint32(packetBuffer, offset); + + offset += uint32_t_size; + swTraceStringBuffer.resize(swTraceArgTypesLength - 1); + std::memcpy(swTraceStringBuffer.data(), + packetBuffer->GetReadableData() + offset, swTraceStringBuffer.size()); + + swTraceMessage.argTypes.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // arg_types + + std::string swTraceString(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); + + // Check arg_names + offset += CalculateSizeOfPaddedSwString(swTraceString); + uint32_t swTraceArgNamesLength = ReadUint32(packetBuffer, offset); + + offset += uint32_t_size; + swTraceStringBuffer.resize(swTraceArgNamesLength - 1); + std::memcpy(swTraceStringBuffer.data(), + packetBuffer->GetReadableData() + offset, swTraceStringBuffer.size()); + + swTraceString.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); + std::stringstream stringStream(swTraceString); + std::string argName; + while (std::getline(stringStream, argName, ',')) + { + swTraceMessage.argNames.push_back(argName); + } + + offset += CalculateSizeOfPaddedSwString(swTraceString); + + return swTraceMessage; +} + /// Creates a packet header for the timeline messages: /// * declareLabel /// * declareEntity diff --git a/src/profiling/ProfilingUtils.hpp b/src/profiling/ProfilingUtils.hpp index 582f7c4..777711a 100644 --- a/src/profiling/ProfilingUtils.hpp +++ b/src/profiling/ProfilingUtils.hpp @@ -23,6 +23,15 @@ namespace armnn namespace profiling { +struct SwTraceMessage +{ + uint32_t id; + std::string name; + std::string uiName; + std::vector argTypes; + std::vector argNames; +}; + struct SwTraceCharPolicy { static bool IsValidChar(unsigned char c) @@ -134,6 +143,10 @@ enum class ProfilingRelationshipType LabelLink /// Head uses label Tail (Tail MUST be a guid of a label). }; +uint32_t CalculateSizeOfPaddedSwString(const std::string& str); + +SwTraceMessage ReadSwTraceMessage(const std::unique_ptr& packetBuffer, unsigned int& offset); + TimelinePacketStatus WriteTimelineLabelBinaryPacket(uint64_t profilingGuid, const std::string& label, unsigned char* buffer, diff --git a/src/profiling/SendCounterPacket.cpp b/src/profiling/SendCounterPacket.cpp index 0ac6ecf..382f958 100644 --- a/src/profiling/SendCounterPacket.cpp +++ b/src/profiling/SendCounterPacket.cpp @@ -25,7 +25,6 @@ namespace profiling using boost::numeric_cast; const unsigned int SendCounterPacket::PIPE_MAGIC; -const unsigned int SendCounterPacket::MAX_METADATA_PACKET_LENGTH; void SendCounterPacket::SendStreamMetaDataPacket() { diff --git a/src/profiling/SendCounterPacket.hpp b/src/profiling/SendCounterPacket.hpp index e1a42aa..2aaabc8 100644 --- a/src/profiling/SendCounterPacket.hpp +++ b/src/profiling/SendCounterPacket.hpp @@ -59,7 +59,6 @@ public: void SetReadyToRead() override; static const unsigned int PIPE_MAGIC = 0x45495434; - static const unsigned int MAX_METADATA_PACKET_LENGTH = 4096; void Start(IProfilingConnection& profilingConnection); void Stop(bool rethrowSendThreadExceptions = true); diff --git a/src/profiling/SendTimelinePacket.cpp b/src/profiling/SendTimelinePacket.cpp new file mode 100644 index 0000000..e6e5ee7 --- /dev/null +++ b/src/profiling/SendTimelinePacket.cpp @@ -0,0 +1,154 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "SendTimelinePacket.hpp" + +namespace armnn +{ + +namespace profiling +{ + +void SendTimelinePacket::Commit() +{ + if (m_WriteBuffer != nullptr) + { + // Commit the message + m_BufferManager.Commit(m_WriteBuffer, m_Offset); + m_WriteBuffer.reset(nullptr); + m_Offset = 0; + m_BufferSize = 0; + } +} + +void SendTimelinePacket::ReserveBuffer() +{ + if (m_WriteBuffer == nullptr) + { + uint32_t reserved = 0; + + // Reserve the buffer + m_WriteBuffer = m_BufferManager.Reserve(MAX_METADATA_PACKET_LENGTH, reserved); + + // Check if there is enough space in the buffer + if (m_WriteBuffer == nullptr || reserved < m_Offset) + { + throw RuntimeException("No space left on buffer", CHECK_LOCATION()); + } + m_BufferSize = reserved; + } +} + +#define FORWARD_WRITE_BINARY_FUNC(func, ...) \ +try \ +{ \ + ReserveBuffer(); \ + unsigned int numberOfBytes = 0; \ + while (1) \ + { \ + TimelinePacketStatus result = func(__VA_ARGS__, numberOfBytes); \ + if (result == armnn::profiling::TimelinePacketStatus::BufferExhaustion) \ + { \ + Commit(); \ + ReserveBuffer(); \ + } \ + else if (result == armnn::profiling::TimelinePacketStatus::Error) \ + { \ + throw RuntimeException("Error processing while sending TimelineBinaryPacket.", CHECK_LOCATION()); \ + } \ + else \ + { \ + break; \ + } \ + } \ + m_Offset += numberOfBytes; \ + m_BufferSize -= numberOfBytes; \ +} \ +catch(...) \ +{ \ + throw RuntimeException("Error processing while sending TimelineBinaryPacket.", CHECK_LOCATION()); \ +} + +void SendTimelinePacket::SendTimelineEntityBinaryPacket(uint64_t profilingGuid) +{ + FORWARD_WRITE_BINARY_FUNC(WriteTimelineEntityBinaryPacket, + profilingGuid, + &m_WriteBuffer->GetWritableData()[m_Offset], + m_BufferSize); +} + +void SendTimelinePacket::SendTimelineEventBinaryPacket(uint64_t timestamp, uint32_t threadId, uint64_t profilingGuid) +{ + FORWARD_WRITE_BINARY_FUNC(WriteTimelineEventBinaryPacket, + timestamp, + threadId, + profilingGuid, + &m_WriteBuffer->GetWritableData()[m_Offset], + m_BufferSize); +} + +void SendTimelinePacket::SendTimelineEventClassBinaryPacket(uint64_t profilingGuid) +{ + FORWARD_WRITE_BINARY_FUNC(WriteTimelineEventClassBinaryPacket, + profilingGuid, + &m_WriteBuffer->GetWritableData()[m_Offset], + m_BufferSize); +} + +void SendTimelinePacket::SendTimelineLabelBinaryPacket(uint64_t profilingGuid, const std::string& label) +{ + FORWARD_WRITE_BINARY_FUNC(WriteTimelineLabelBinaryPacket, + profilingGuid, + label, + &m_WriteBuffer->GetWritableData()[m_Offset], + m_BufferSize); +} + +void SendTimelinePacket::SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType relationshipType, + uint64_t relationshipGuid, + uint64_t headGuid, + uint64_t tailGuid) +{ + FORWARD_WRITE_BINARY_FUNC(WriteTimelineRelationshipBinaryPacket, + relationshipType, + relationshipGuid, + headGuid, + tailGuid, + &m_WriteBuffer->GetWritableData()[m_Offset], + m_BufferSize); +} + +void SendTimelinePacket::SendTimelineMessageDirectoryPackage() +{ + try + { + // Reserve buffer if hasn't already reserved + ReserveBuffer(); + + unsigned int numberOfBytes = 0; + // Write to buffer + TimelinePacketStatus result = WriteTimelineMessageDirectoryPackage(&m_WriteBuffer->GetWritableData()[m_Offset], + m_BufferSize, + numberOfBytes); + + if (result != armnn::profiling::TimelinePacketStatus::Ok) + { + throw RuntimeException("Error processing TimelineMessageDirectoryPackage.", CHECK_LOCATION()); + } + + // Commit the message + m_Offset += numberOfBytes; + m_BufferSize -= numberOfBytes; + m_BufferManager.Commit(m_WriteBuffer, m_Offset); + } + catch(...) + { + throw RuntimeException("Error processing TimelineMessageDirectoryPackage.", CHECK_LOCATION()); + } +} + +} // namespace profiling + +} // namespace armnn diff --git a/src/profiling/SendTimelinePacket.hpp b/src/profiling/SendTimelinePacket.hpp new file mode 100644 index 0000000..35ec24f --- /dev/null +++ b/src/profiling/SendTimelinePacket.hpp @@ -0,0 +1,65 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "IBufferManager.hpp" +#include "ISendTimelinePacket.hpp" +#include "ProfilingUtils.hpp" + +#include + +namespace armnn +{ + +namespace profiling +{ + +class SendTimelinePacket : public ISendTimelinePacket +{ +public: + SendTimelinePacket(IBufferManager& bufferManager) + : m_BufferManager(bufferManager) + , m_WriteBuffer(nullptr) + , m_Offset(0u) + , m_BufferSize(0u) + {} + + /// Commits the current buffer and reset the member variables + void Commit() override; + + /// Create and write a TimelineEntityBinaryPacket from the parameters to the buffer. + void SendTimelineEntityBinaryPacket(uint64_t profilingGuid) override; + + /// Create and write a TimelineEventBinaryPacket from the parameters to the buffer. + void SendTimelineEventBinaryPacket(uint64_t timestamp, uint32_t threadId, uint64_t profilingGuid) override; + + /// Create and write a TimelineEventClassBinaryPacket from the parameters to the buffer. + void SendTimelineEventClassBinaryPacket(uint64_t profilingGuid) override; + + /// Create and write a TimelineLabelBinaryPacket from the parameters to the buffer. + void SendTimelineLabelBinaryPacket(uint64_t profilingGuid, const std::string& label) override; + + /// Create and write a TimelineMessageDirectoryPackage in the buffer + void SendTimelineMessageDirectoryPackage() override; + + /// Create and write a TimelineRelationshipBinaryPacket from the parameters to the buffer. + virtual void SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType relationshipType, + uint64_t relationshipGuid, + uint64_t headGuid, + uint64_t tailGuid) override; +private: + /// Reserves maximum packet size from buffer + void ReserveBuffer(); + + IBufferManager& m_BufferManager; + std::unique_ptr m_WriteBuffer; + unsigned int m_Offset; + unsigned int m_BufferSize; +}; + +} // namespace profiling + +} // namespace armnn diff --git a/src/profiling/TimelinePacketWriterFactory.cpp b/src/profiling/TimelinePacketWriterFactory.cpp new file mode 100644 index 0000000..b1de629 --- /dev/null +++ b/src/profiling/TimelinePacketWriterFactory.cpp @@ -0,0 +1,23 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "TimelinePacketWriterFactory.hpp" + +#include "SendTimelinePacket.hpp" + +namespace armnn +{ + +namespace profiling +{ + +std::unique_ptr TimelinePacketWriterFactory::GetSendTimelinePacket() const +{ + return std::make_unique(m_BufferManager); +} + +} // namespace profiling + +} // namespace armnn diff --git a/src/profiling/TimelinePacketWriterFactory.hpp b/src/profiling/TimelinePacketWriterFactory.hpp new file mode 100644 index 0000000..1bbd3fd --- /dev/null +++ b/src/profiling/TimelinePacketWriterFactory.hpp @@ -0,0 +1,32 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "IBufferManager.hpp" +#include "ISendTimelinePacket.hpp" + +#include + +namespace armnn +{ + +namespace profiling +{ + +class TimelinePacketWriterFactory +{ +public: + TimelinePacketWriterFactory(IBufferManager& bufferManager) : m_BufferManager(bufferManager) {} + + std::unique_ptr GetSendTimelinePacket() const; + +private: + IBufferManager& m_BufferManager; +}; + +} // namespace profiling + +} // namespace armnn diff --git a/src/profiling/test/SendCounterPacketTests.cpp b/src/profiling/test/SendCounterPacketTests.cpp index f0ba347..b33b62f 100644 --- a/src/profiling/test/SendCounterPacketTests.cpp +++ b/src/profiling/test/SendCounterPacketTests.cpp @@ -5,8 +5,8 @@ #include "SendCounterPacketTests.hpp" -#include #include +#include #include #include #include @@ -318,7 +318,7 @@ BOOST_AUTO_TEST_CASE(SendStreamMetaDataPacketTest) 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 + BOOST_TEST(ReadUint32(readBuffer2, offset) == MAX_METADATA_PACKET_LENGTH); // max_data_len offset += sizeUint32; BOOST_TEST(ReadUint32(readBuffer2, offset) == numeric_cast(getpid())); // pid offset += sizeUint32; diff --git a/src/profiling/test/SendTimelinePacketTests.cpp b/src/profiling/test/SendTimelinePacketTests.cpp new file mode 100644 index 0000000..6f90106 --- /dev/null +++ b/src/profiling/test/SendTimelinePacketTests.cpp @@ -0,0 +1,387 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "SendCounterPacketTests.hpp" + +#include +#include +#include +#include + +#include + +using namespace armnn::profiling; + +BOOST_AUTO_TEST_SUITE(SendTimelinePacketTests) + +BOOST_AUTO_TEST_CASE(SendTimelineMessageDirectoryPackageTest) +{ + MockBufferManager mockBuffer(512); + TimelinePacketWriterFactory timelinePacketWriterFactory(mockBuffer); + std::unique_ptr sendTimelinePacket = timelinePacketWriterFactory.GetSendTimelinePacket(); + + sendTimelinePacket->SendTimelineMessageDirectoryPackage(); + + // Get the readable buffer + auto packetBuffer = mockBuffer.GetReadableBuffer(); + + unsigned int uint32_t_size = sizeof(uint32_t); + // Check the packet header + unsigned int offset = 0; + uint32_t packetHeaderWord0 = ReadUint32(packetBuffer, offset); + uint32_t packetFamily = (packetHeaderWord0 >> 26) & 0x0000003F; + uint32_t packetClass = (packetHeaderWord0 >> 19) & 0x0000007F; + uint32_t packetType = (packetHeaderWord0 >> 16) & 0x00000007; + uint32_t streamId = (packetHeaderWord0 >> 0) & 0x00000007; + + BOOST_CHECK(packetFamily == 1); + BOOST_CHECK(packetClass == 0); + BOOST_CHECK(packetType == 0); + BOOST_CHECK(streamId == 0); + + offset += uint32_t_size; + uint32_t packetHeaderWord1 = ReadUint32(packetBuffer, offset); + uint32_t sequenceNumbered = (packetHeaderWord1 >> 24) & 0x00000001; + uint32_t dataLength = (packetHeaderWord1 >> 0) & 0x00FFFFFF; + BOOST_CHECK(sequenceNumbered == 0); + BOOST_CHECK(dataLength == 416); + + offset += uint32_t_size; + SwTraceMessage swTraceMessage = ReadSwTraceMessage(packetBuffer, offset); + + BOOST_CHECK(swTraceMessage.id == 0); + BOOST_CHECK(swTraceMessage.name == "declareLabel"); + BOOST_CHECK(swTraceMessage.uiName == "declare label"); + BOOST_CHECK(swTraceMessage.argTypes.size() == 2); + BOOST_CHECK(swTraceMessage.argTypes[0] == 'p'); + BOOST_CHECK(swTraceMessage.argTypes[1] == 's'); + BOOST_CHECK(swTraceMessage.argNames.size() == 2); + BOOST_CHECK(swTraceMessage.argNames[0] == "guid"); + BOOST_CHECK(swTraceMessage.argNames[1] == "value"); + + swTraceMessage = ReadSwTraceMessage(packetBuffer, offset); + + BOOST_CHECK(swTraceMessage.id == 1); + BOOST_CHECK(swTraceMessage.name == "declareEntity"); + BOOST_CHECK(swTraceMessage.uiName == "declare entity"); + BOOST_CHECK(swTraceMessage.argTypes.size() == 1); + BOOST_CHECK(swTraceMessage.argTypes[0] == 'p'); + BOOST_CHECK(swTraceMessage.argNames.size() == 1); + BOOST_CHECK(swTraceMessage.argNames[0] == "guid"); + + swTraceMessage = ReadSwTraceMessage(packetBuffer, offset); + + BOOST_CHECK(swTraceMessage.id == 2); + BOOST_CHECK(swTraceMessage.name == "declareEventClass"); + BOOST_CHECK(swTraceMessage.uiName == "declare event class"); + BOOST_CHECK(swTraceMessage.argTypes.size() == 1); + BOOST_CHECK(swTraceMessage.argTypes[0] == 'p'); + BOOST_CHECK(swTraceMessage.argNames.size() == 1); + BOOST_CHECK(swTraceMessage.argNames[0] == "guid"); + + swTraceMessage = ReadSwTraceMessage(packetBuffer, offset); + + BOOST_CHECK(swTraceMessage.id == 3); + BOOST_CHECK(swTraceMessage.name == "declareRelationship"); + BOOST_CHECK(swTraceMessage.uiName == "declare relationship"); + BOOST_CHECK(swTraceMessage.argTypes.size() == 4); + BOOST_CHECK(swTraceMessage.argTypes[0] == 'I'); + BOOST_CHECK(swTraceMessage.argTypes[1] == 'p'); + BOOST_CHECK(swTraceMessage.argTypes[2] == 'p'); + BOOST_CHECK(swTraceMessage.argTypes[3] == 'p'); + BOOST_CHECK(swTraceMessage.argNames.size() == 4); + BOOST_CHECK(swTraceMessage.argNames[0] == "relationshipType"); + BOOST_CHECK(swTraceMessage.argNames[1] == "relationshipGuid"); + BOOST_CHECK(swTraceMessage.argNames[2] == "headGuid"); + BOOST_CHECK(swTraceMessage.argNames[3] == "tailGuid"); + + swTraceMessage = ReadSwTraceMessage(packetBuffer, offset); + + BOOST_CHECK(swTraceMessage.id == 4); + BOOST_CHECK(swTraceMessage.name == "declareEvent"); + BOOST_CHECK(swTraceMessage.uiName == "declare event"); + BOOST_CHECK(swTraceMessage.argTypes.size() == 3); + BOOST_CHECK(swTraceMessage.argTypes[0] == '@'); + BOOST_CHECK(swTraceMessage.argTypes[1] == 't'); + BOOST_CHECK(swTraceMessage.argTypes[2] == 'p'); + BOOST_CHECK(swTraceMessage.argNames.size() == 3); + BOOST_CHECK(swTraceMessage.argNames[0] == "timestamp"); + BOOST_CHECK(swTraceMessage.argNames[1] == "threadId"); + BOOST_CHECK(swTraceMessage.argNames[2] == "eventGuid"); +} + +BOOST_AUTO_TEST_CASE(SendTimelineEntityPlusEventClassBinaryPacketTest) +{ + MockBufferManager bufferManager(40); + TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager); + std::unique_ptr sendTimelinePacket = timelinePacketWriterFactory.GetSendTimelinePacket(); + + const uint64_t entityBinaryPacketProfilingGuid = 123456u; + sendTimelinePacket->SendTimelineEntityBinaryPacket(entityBinaryPacketProfilingGuid); + + const uint64_t eventClassBinaryPacketProfilingGuid = 789123u; + sendTimelinePacket->SendTimelineEventClassBinaryPacket(eventClassBinaryPacketProfilingGuid); + + // Commit the messages + sendTimelinePacket->Commit(); + + // Get the readable buffer + auto packetBuffer = bufferManager.GetReadableBuffer(); + + unsigned int uint32_t_size = sizeof(uint32_t); + unsigned int uint64_t_size = sizeof(uint64_t); + + // Check the packet header + unsigned int offset = 0; + + // Reading TimelineEntityClassBinaryPacket + uint32_t entityBinaryPacketHeaderWord0 = ReadUint32(packetBuffer, offset); + uint32_t entityBinaryPacketFamily = (entityBinaryPacketHeaderWord0 >> 26) & 0x0000003F; + uint32_t entityBinaryPacketClass = (entityBinaryPacketHeaderWord0 >> 19) & 0x0000007F; + uint32_t entityBinaryPacketType = (entityBinaryPacketHeaderWord0 >> 16) & 0x00000007; + uint32_t entityBinaryPacketStreamId = (entityBinaryPacketHeaderWord0 >> 0) & 0x00000007; + + BOOST_CHECK(entityBinaryPacketFamily == 1); + BOOST_CHECK(entityBinaryPacketClass == 0); + BOOST_CHECK(entityBinaryPacketType == 1); + BOOST_CHECK(entityBinaryPacketStreamId == 0); + + offset += uint32_t_size; + uint32_t entityBinaryPacketHeaderWord1 = ReadUint32(packetBuffer, offset); + uint32_t entityBinaryPacketSequenceNumbered = (entityBinaryPacketHeaderWord1 >> 24) & 0x00000001; + uint32_t entityBinaryPacketDataLength = (entityBinaryPacketHeaderWord1 >> 0) & 0x00FFFFFF; + BOOST_CHECK(entityBinaryPacketSequenceNumbered == 0); + BOOST_CHECK(entityBinaryPacketDataLength == 8); + + // Check the decl_id + offset += uint32_t_size; + uint32_t entitytDecId = ReadUint32(packetBuffer, offset); + + BOOST_CHECK(entitytDecId == uint32_t(1)); + + // Check the profiling GUID + offset += uint32_t_size; + uint64_t readProfilingGuid = ReadUint64(packetBuffer, offset); + + BOOST_CHECK(readProfilingGuid == entityBinaryPacketProfilingGuid); + + // Reading TimelineEventClassBinaryPacket + offset += uint64_t_size; + uint32_t eventClassBinaryPacketHeaderWord0 = ReadUint32(packetBuffer, offset); + uint32_t eventClassBinaryPacketFamily = (eventClassBinaryPacketHeaderWord0 >> 26) & 0x0000003F; + uint32_t eventClassBinaryPacketClass = (eventClassBinaryPacketHeaderWord0 >> 19) & 0x0000007F; + uint32_t eventClassBinaryPacketType = (eventClassBinaryPacketHeaderWord0 >> 16) & 0x00000007; + uint32_t eventClassBinaryPacketStreamId = (eventClassBinaryPacketHeaderWord0 >> 0) & 0x00000007; + + BOOST_CHECK(eventClassBinaryPacketFamily == 1); + BOOST_CHECK(eventClassBinaryPacketClass == 0); + BOOST_CHECK(eventClassBinaryPacketType == 1); + BOOST_CHECK(eventClassBinaryPacketStreamId == 0); + + offset += uint32_t_size; + uint32_t eventClassBinaryPacketHeaderWord1 = ReadUint32(packetBuffer, offset); + uint32_t eventClassBinaryPacketSequenceNumbered = (eventClassBinaryPacketHeaderWord1 >> 24) & 0x00000001; + uint32_t eventClassBinaryPacketDataLength = (eventClassBinaryPacketHeaderWord1 >> 0) & 0x00FFFFFF; + BOOST_CHECK(eventClassBinaryPacketSequenceNumbered == 0); + BOOST_CHECK(eventClassBinaryPacketDataLength == 12); + + offset += uint32_t_size; + uint32_t eventClassDeclId = ReadUint32(packetBuffer, offset); + BOOST_CHECK(eventClassDeclId == uint32_t(2)); + + // Check the profiling GUID + offset += uint32_t_size; + readProfilingGuid = ReadUint64(packetBuffer, offset); + BOOST_CHECK(readProfilingGuid == eventClassBinaryPacketProfilingGuid); + + bufferManager.MarkRead(packetBuffer); +} + +BOOST_AUTO_TEST_CASE(SendTimelinePacketTests1) +{ + unsigned int uint32_t_size = sizeof(uint32_t); + unsigned int uint64_t_size = sizeof(uint64_t); + + MockBufferManager bufferManager(512); + TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager); + std::unique_ptr sendTimelinePacket = timelinePacketWriterFactory.GetSendTimelinePacket(); + + // Send TimelineEntityClassBinaryPacket + const uint64_t entityBinaryPacketProfilingGuid = 123456u; + sendTimelinePacket->SendTimelineEntityBinaryPacket(entityBinaryPacketProfilingGuid); + + // Commit the buffer + sendTimelinePacket->Commit(); + + // Get the readable buffer + auto packetBuffer = bufferManager.GetReadableBuffer(); + + // Check the packet header + unsigned int offset = 0; + + // Reading TimelineEntityClassBinaryPacket + uint32_t entityBinaryPacketHeaderWord0 = ReadUint32(packetBuffer, offset); + uint32_t entityBinaryPacketFamily = (entityBinaryPacketHeaderWord0 >> 26) & 0x0000003F; + uint32_t entityBinaryPacketClass = (entityBinaryPacketHeaderWord0 >> 19) & 0x0000007F; + uint32_t entityBinaryPacketType = (entityBinaryPacketHeaderWord0 >> 16) & 0x00000007; + uint32_t entityBinaryPacketStreamId = (entityBinaryPacketHeaderWord0 >> 0) & 0x00000007; + + BOOST_CHECK(entityBinaryPacketFamily == 1); + BOOST_CHECK(entityBinaryPacketClass == 0); + BOOST_CHECK(entityBinaryPacketType == 1); + BOOST_CHECK(entityBinaryPacketStreamId == 0); + + offset += uint32_t_size; + uint32_t entityBinaryPacketHeaderWord1 = ReadUint32(packetBuffer, offset); + uint32_t entityBinaryPacketSequenceNumbered = (entityBinaryPacketHeaderWord1 >> 24) & 0x00000001; + uint32_t entityBinaryPacketDataLength = (entityBinaryPacketHeaderWord1 >> 0) & 0x00FFFFFF; + BOOST_CHECK(entityBinaryPacketSequenceNumbered == 0); + BOOST_CHECK(entityBinaryPacketDataLength == 8); + + // Check the decl_id + offset += uint32_t_size; + uint32_t entitytDecId = ReadUint32(packetBuffer, offset); + + BOOST_CHECK(entitytDecId == uint32_t(1)); + + // Check the profiling GUID + offset += uint32_t_size; + uint64_t readProfilingGuid = ReadUint64(packetBuffer, offset); + + BOOST_CHECK(readProfilingGuid == entityBinaryPacketProfilingGuid); + + bufferManager.MarkRead(packetBuffer); + + // Send TimelineEventClassBinaryPacket + const uint64_t eventClassBinaryPacketProfilingGuid = 789123u; + sendTimelinePacket->SendTimelineEventClassBinaryPacket(eventClassBinaryPacketProfilingGuid); + + // Commit the buffer + sendTimelinePacket->Commit(); + + // Get the readable buffer + packetBuffer = bufferManager.GetReadableBuffer(); + + // Check the packet header + offset = 0; + + // Reading TimelineEventClassBinaryPacket + uint32_t eventClassBinaryPacketHeaderWord0 = ReadUint32(packetBuffer, offset); + uint32_t eventClassBinaryPacketFamily = (eventClassBinaryPacketHeaderWord0 >> 26) & 0x0000003F; + uint32_t eventClassBinaryPacketClass = (eventClassBinaryPacketHeaderWord0 >> 19) & 0x0000007F; + uint32_t eventClassBinaryPacketType = (eventClassBinaryPacketHeaderWord0 >> 16) & 0x00000007; + uint32_t eventClassBinaryPacketStreamId = (eventClassBinaryPacketHeaderWord0 >> 0) & 0x00000007; + + BOOST_CHECK(eventClassBinaryPacketFamily == 1); + BOOST_CHECK(eventClassBinaryPacketClass == 0); + BOOST_CHECK(eventClassBinaryPacketType == 1); + BOOST_CHECK(eventClassBinaryPacketStreamId == 0); + + offset += uint32_t_size; + uint32_t eventClassBinaryPacketHeaderWord1 = ReadUint32(packetBuffer, offset); + uint32_t eventClassBinaryPacketSequenceNumbered = (eventClassBinaryPacketHeaderWord1 >> 24) & 0x00000001; + uint32_t eventClassBinaryPacketDataLength = (eventClassBinaryPacketHeaderWord1 >> 0) & 0x00FFFFFF; + BOOST_CHECK(eventClassBinaryPacketSequenceNumbered == 0); + BOOST_CHECK(eventClassBinaryPacketDataLength == 12); + + offset += uint32_t_size; + uint32_t eventClassDeclId = ReadUint32(packetBuffer, offset); + BOOST_CHECK(eventClassDeclId == uint32_t(2)); + + // Check the profiling GUID + offset += uint32_t_size; + readProfilingGuid = ReadUint64(packetBuffer, offset); + BOOST_CHECK(readProfilingGuid == eventClassBinaryPacketProfilingGuid); + + bufferManager.MarkRead(packetBuffer); + + // Send TimelineEventBinaryPacket + const uint64_t timestamp = 456789u; + const uint32_t threadId = 654321u; + const uint64_t eventProfilingGuid = 123456u; + sendTimelinePacket->SendTimelineEventBinaryPacket(timestamp, threadId, eventProfilingGuid); + + // Commit the buffer + sendTimelinePacket->Commit(); + + // Get the readable buffer + packetBuffer = bufferManager.GetReadableBuffer(); + + // Check the packet header + offset = 0; + + // Reading TimelineEventBinaryPacket + uint32_t eventBinaryPacketHeaderWord0 = ReadUint32(packetBuffer, offset); + uint32_t eventBinaryPacketFamily = (eventBinaryPacketHeaderWord0 >> 26) & 0x0000003F; + uint32_t eventBinaryPacketClass = (eventBinaryPacketHeaderWord0 >> 19) & 0x0000007F; + uint32_t eventBinaryPacketType = (eventBinaryPacketHeaderWord0 >> 16) & 0x00000007; + uint32_t eventBinaryPacketStreamId = (eventBinaryPacketHeaderWord0 >> 0) & 0x00000007; + + BOOST_CHECK(eventBinaryPacketFamily == 1); + BOOST_CHECK(eventBinaryPacketClass == 0); + BOOST_CHECK(eventBinaryPacketType == 1); + BOOST_CHECK(eventBinaryPacketStreamId == 0); + + offset += uint32_t_size; + uint32_t eventBinaryPacketHeaderWord1 = ReadUint32(packetBuffer, offset); + uint32_t eventBinaryPacketSequenceNumbered = (eventBinaryPacketHeaderWord1 >> 24) & 0x00000001; + uint32_t eventBinaryPacketDataLength = (eventBinaryPacketHeaderWord1 >> 0) & 0x00FFFFFF; + BOOST_CHECK(eventBinaryPacketSequenceNumbered == 0); + BOOST_CHECK(eventBinaryPacketDataLength == 24); + + // Check the decl_id + offset += uint32_t_size; + uint32_t eventDeclId = ReadUint32(packetBuffer, offset); + BOOST_CHECK(eventDeclId == 4); + + // Check the timestamp + offset += uint32_t_size; + uint64_t eventTimestamp = ReadUint64(packetBuffer, offset); + BOOST_CHECK(eventTimestamp == timestamp); + + // Check the thread id + offset += uint64_t_size; + uint32_t readThreadId = ReadUint32(packetBuffer, offset); + BOOST_CHECK(readThreadId == threadId); + + // Check the profiling GUID + offset += uint32_t_size; + readProfilingGuid = ReadUint64(packetBuffer, offset); + BOOST_CHECK(readProfilingGuid == eventProfilingGuid); +} + +BOOST_AUTO_TEST_CASE(SendTimelinePacketTests2) +{ + MockBufferManager bufferManager(40); + TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager); + std::unique_ptr sendTimelinePacket = timelinePacketWriterFactory.GetSendTimelinePacket(); + + BOOST_CHECK_THROW(sendTimelinePacket->SendTimelineMessageDirectoryPackage(), + armnn::RuntimeException); +} + +BOOST_AUTO_TEST_CASE(SendTimelinePacketTests3) +{ + MockBufferManager bufferManager(512); + TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager); + std::unique_ptr sendTimelinePacket = timelinePacketWriterFactory.GetSendTimelinePacket(); + + // Send TimelineEntityClassBinaryPacket + const uint64_t entityBinaryPacketProfilingGuid = 123456u; + sendTimelinePacket->SendTimelineEntityBinaryPacket(entityBinaryPacketProfilingGuid); + + // Commit the buffer + sendTimelinePacket->Commit(); + + // Get the readable buffer + auto packetBuffer = bufferManager.GetReadableBuffer(); + + // Send TimelineEventClassBinaryPacket + const uint64_t eventClassBinaryPacketProfilingGuid = 789123u; + BOOST_CHECK_THROW(sendTimelinePacket->SendTimelineEventClassBinaryPacket(eventClassBinaryPacketProfilingGuid), + armnn::RuntimeException); +} + +BOOST_AUTO_TEST_SUITE_END()