IVGCVSW-4033 Provide a utility method to send the 'well known'
authorMatteo Martincigh <matteo.martincigh@arm.com>
Mon, 28 Oct 2019 11:42:50 +0000 (11:42 +0000)
committerMatteo Martincigh <matteo.martincigh@arm.com>
Mon, 28 Oct 2019 16:29:54 +0000 (16:29 +0000)
labels and event classes

 * Added utility method SendWellKnownLabelsAndEventClasses
 * Added unit tests

Signed-off-by: Matteo Martincigh <matteo.martincigh@arm.com>
Change-Id: Id8ec0d0eb6861feb8b61731e656d1571effc904a

src/profiling/SendTimelinePacket.cpp
src/profiling/TimelineUtilityMethods.cpp
src/profiling/TimelineUtilityMethods.hpp
src/profiling/test/TimelineUtilityMethodsTests.cpp

index e6e5ee7..a0fbf5c 100644 (file)
@@ -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;
     }
index 5ae0cf6..aa9f5a5 100644 (file)
@@ -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
index 22727c8..f3e925e 100644 (file)
@@ -22,6 +22,8 @@ public:
     {}
     ~TimelineUtilityMethods() = default;
 
+    void SendWellKnownLabelsAndEventClasses();
+
     ProfilingStaticGuid DeclareLabel(const std::string& labelName);
 
 private:
index c205712..6d0fa2e 100644 (file)
 
 #include <SendTimelinePacket.hpp>
 #include <TimelineUtilityMethods.hpp>
+#include <LabelsAndEventClasses.hpp>
 
 #include <boost/test/unit_test.hpp>
 
 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<unsigned int>(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);