From 102cdbd76edcd033a2f1c35f4d6853f881bcc1b4 Mon Sep 17 00:00:00 2001 From: Matteo Martincigh Date: Mon, 28 Oct 2019 11:42:50 +0000 Subject: IVGCVSW-4033 Provide a utility method to send the 'well known' labels and event classes * Added utility method SendWellKnownLabelsAndEventClasses * Added unit tests Signed-off-by: Matteo Martincigh Change-Id: Id8ec0d0eb6861feb8b61731e656d1571effc904a --- src/profiling/SendTimelinePacket.cpp | 2 +- src/profiling/TimelineUtilityMethods.cpp | 22 +++ src/profiling/TimelineUtilityMethods.hpp | 2 + src/profiling/test/TimelineUtilityMethodsTests.cpp | 168 ++++++++++++++++++++- 4 files changed, 192 insertions(+), 2 deletions(-) diff --git a/src/profiling/SendTimelinePacket.cpp b/src/profiling/SendTimelinePacket.cpp index e6e5ee7d5b..a0fbf5c01f 100644 --- a/src/profiling/SendTimelinePacket.cpp +++ b/src/profiling/SendTimelinePacket.cpp @@ -35,7 +35,7 @@ void SendTimelinePacket::ReserveBuffer() // 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()); + throw BufferExhaustion("No space left on buffer", CHECK_LOCATION()); } m_BufferSize = reserved; } diff --git a/src/profiling/TimelineUtilityMethods.cpp b/src/profiling/TimelineUtilityMethods.cpp index 5ae0cf6ee1..aa9f5a5635 100644 --- a/src/profiling/TimelineUtilityMethods.cpp +++ b/src/profiling/TimelineUtilityMethods.cpp @@ -5,6 +5,7 @@ #include "TimelineUtilityMethods.hpp" #include "ProfilingService.hpp" +#include "LabelsAndEventClasses.hpp" namespace armnn { @@ -12,6 +13,27 @@ namespace armnn namespace profiling { +void TimelineUtilityMethods::SendWellKnownLabelsAndEventClasses() +{ + // Send the "name" label, this call throws in case of error + m_SendTimelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::NAME_GUID, + LabelsAndEventClasses::NAME_LABEL); + + // Send the "type" label, this call throws in case of error + m_SendTimelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::TYPE_GUID, + LabelsAndEventClasses::TYPE_LABEL); + + // Send the "index" label, this call throws in case of error + m_SendTimelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::INDEX_GUID, + LabelsAndEventClasses::INDEX_LABEL); + + // Send the "start of life" event class, this call throws in case of error + m_SendTimelinePacket.SendTimelineEventClassBinaryPacket(LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS); + + // Send the "end of life" event class, this call throws in case of error + m_SendTimelinePacket.SendTimelineEventClassBinaryPacket(LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS); +} + ProfilingStaticGuid TimelineUtilityMethods::DeclareLabel(const std::string& labelName) { // Check that the label name is valid diff --git a/src/profiling/TimelineUtilityMethods.hpp b/src/profiling/TimelineUtilityMethods.hpp index 22727c8b9a..f3e925e3dc 100644 --- a/src/profiling/TimelineUtilityMethods.hpp +++ b/src/profiling/TimelineUtilityMethods.hpp @@ -22,6 +22,8 @@ public: {} ~TimelineUtilityMethods() = default; + void SendWellKnownLabelsAndEventClasses(); + ProfilingStaticGuid DeclareLabel(const std::string& labelName); private: diff --git a/src/profiling/test/TimelineUtilityMethodsTests.cpp b/src/profiling/test/TimelineUtilityMethodsTests.cpp index c205712d62..6d0fa2e105 100644 --- a/src/profiling/test/TimelineUtilityMethodsTests.cpp +++ b/src/profiling/test/TimelineUtilityMethodsTests.cpp @@ -7,15 +7,181 @@ #include #include +#include #include using namespace armnn; using namespace armnn::profiling; +namespace +{ + +inline unsigned int OffsetToNextWord(unsigned int numberOfBytes) +{ + unsigned int uint32_t_size = sizeof(uint32_t); + + unsigned int remainder = numberOfBytes % uint32_t_size; + if (remainder == 0) + { + return numberOfBytes; + } + + return numberOfBytes + uint32_t_size - remainder; +} + +void VerifyTimelineLabelBinaryPacket(ProfilingGuid guid, + const std::string& label, + const unsigned char* readableData, + unsigned int& offset) +{ + BOOST_ASSERT(readableData); + + // Utils + unsigned int uint32_t_size = sizeof(uint32_t); + unsigned int uint64_t_size = sizeof(uint64_t); + unsigned int label_size = boost::numeric_cast(label.size()); + + // Check the TimelineLabelBinaryPacket header + uint32_t entityBinaryPacketHeaderWord0 = ReadUint32(readableData, 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(readableData, offset); + uint32_t eventBinaryPacketSequenceNumber = (entityBinaryPacketHeaderWord1 >> 24) & 0x00000001; + uint32_t eventBinaryPacketDataLength = (entityBinaryPacketHeaderWord1 >> 0) & 0x00FFFFFF; + BOOST_CHECK(eventBinaryPacketSequenceNumber == 0); + BOOST_CHECK(eventBinaryPacketDataLength == 16 + OffsetToNextWord(label_size + 1)); + + // Check the decl id + offset += uint32_t_size; + uint32_t eventClassDeclId = ReadUint32(readableData, offset); + BOOST_CHECK(eventClassDeclId == 0); + + // Check the profiling GUID + offset += uint32_t_size; + uint64_t readProfilingGuid = ReadUint64(readableData, offset); + BOOST_CHECK(readProfilingGuid == guid); + + // Check the SWTrace label + offset += uint64_t_size; + uint32_t swTraceLabelLength = ReadUint32(readableData, offset); + BOOST_CHECK(swTraceLabelLength == label_size + 1); // Label length including the null-terminator + offset += uint32_t_size; + BOOST_CHECK(std::memcmp(readableData + offset, // Offset to the label in the buffer + label.data(), // The original label + swTraceLabelLength - 1) == 0); // The length of the label + BOOST_CHECK(readableData[offset + swTraceLabelLength] == '\0'); // The null-terminator + + // SWTrace strings are written in blocks of words, so the offset has to be updated to the next whole word + offset += OffsetToNextWord(swTraceLabelLength); +} + +void VerifyTimelineEventClassBinaryPacket(ProfilingGuid guid, + const unsigned char* readableData, + unsigned int& offset) +{ + BOOST_ASSERT(readableData); + + // Utils + unsigned int uint32_t_size = sizeof(uint32_t); + unsigned int uint64_t_size = sizeof(uint64_t); + + // Check the TimelineEventClassBinaryPacket header + uint32_t entityBinaryPacketHeaderWord0 = ReadUint32(readableData, 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(readableData, offset); + uint32_t eventBinaryPacketSequenceNumber = (entityBinaryPacketHeaderWord1 >> 24) & 0x00000001; + uint32_t eventBinaryPacketDataLength = (entityBinaryPacketHeaderWord1 >> 0) & 0x00FFFFFF; + BOOST_CHECK(eventBinaryPacketSequenceNumber == 0); + BOOST_CHECK(eventBinaryPacketDataLength == 12); + + // Check the decl id + offset += uint32_t_size; + uint32_t eventClassDeclId = ReadUint32(readableData, offset); + BOOST_CHECK(eventClassDeclId == 2); + + // Check the profiling GUID + offset += uint32_t_size; + uint64_t readProfilingGuid = ReadUint64(readableData, offset); + BOOST_CHECK(readProfilingGuid == guid); + + offset += uint64_t_size; +} + +} // Anonymous namespace + BOOST_AUTO_TEST_SUITE(TimelineUtilityMethodsTests) -BOOST_AUTO_TEST_CASE(DeclareLabelTest1) +BOOST_AUTO_TEST_CASE(SendWellKnownLabelsAndEventClassesTest) +{ + MockBufferManager mockBufferManager(1024); + SendTimelinePacket sendTimelinePacket(mockBufferManager); + TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket); + + BOOST_CHECK_NO_THROW(timelineUtilityMethods.SendWellKnownLabelsAndEventClasses()); + + // Commit all packets at once + sendTimelinePacket.Commit(); + + // Get the readable buffer + auto readableBuffer = mockBufferManager.GetReadableBuffer(); + BOOST_CHECK(readableBuffer != nullptr); + unsigned int size = readableBuffer->GetSize(); + BOOST_CHECK(size == 136); + const unsigned char* readableData = readableBuffer->GetReadableData(); + BOOST_CHECK(readableData != nullptr); + + // Utils + unsigned int offset = 0; + + // First "well-known" label: NAME + VerifyTimelineLabelBinaryPacket(LabelsAndEventClasses::NAME_GUID, + LabelsAndEventClasses::NAME_LABEL, + readableData, + offset); + + // Second "well-known" label: TYPE + VerifyTimelineLabelBinaryPacket(LabelsAndEventClasses::TYPE_GUID, + LabelsAndEventClasses::TYPE_LABEL, + readableData, + offset); + + // Third "well-known" label: INDEX + VerifyTimelineLabelBinaryPacket(LabelsAndEventClasses::INDEX_GUID, + LabelsAndEventClasses::INDEX_LABEL, + readableData, + offset); + + // First "well-known" event class: START OF LIFE + VerifyTimelineEventClassBinaryPacket(LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS, + readableData, + offset); + + // First "well-known" event class: END OF LIFE + VerifyTimelineEventClassBinaryPacket(LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS, + readableData, + offset); + + // Mark the buffer as read + mockBufferManager.MarkRead(readableBuffer); +} + +BOOST_AUTO_TEST_CASE(DeclareLabelTest) { MockBufferManager mockBufferManager(1024); SendTimelinePacket sendTimelinePacket(mockBufferManager); -- cgit v1.2.1