IVGCVSW-3930 Create the Timeline Relationship Binary Packet
authorNarumol Prangnawarat <narumol.prangnawarat@arm.com>
Wed, 16 Oct 2019 11:16:26 +0000 (12:16 +0100)
committerNarumol Prangnawarat <narumol.prangnawarat@arm.com>
Wed, 16 Oct 2019 13:42:50 +0000 (14:42 +0100)
Signed-off-by: Narumol Prangnawarat <narumol.prangnawarat@arm.com>
Change-Id: Ia3f93a25cd26c6d9116c2112d1e8d07be438bf39

src/profiling/ProfilingUtils.cpp
src/profiling/ProfilingUtils.hpp
src/profiling/test/TimelinePacketTests.cpp

index b7def29..f4d4f8f 100644 (file)
@@ -435,6 +435,93 @@ TimelinePacketStatus WriteTimelineEntityBinaryPacket(uint64_t profilingGuid,
     return TimelinePacketStatus::Ok;
 }
 
+TimelinePacketStatus WriteTimelineRelationshipBinaryPacket(ProfilingRelationshipType relationshipType,
+                                                           uint64_t relationshipGuid,
+                                                           uint64_t headGuid,
+                                                           uint64_t tailGuid,
+                                                           unsigned char* buffer,
+                                                           unsigned int bufferSize,
+                                                           unsigned int& numberOfBytesWritten)
+{
+    // Initialize the output value
+    numberOfBytesWritten = 0;
+
+    // Check that the given buffer is valid
+    if (buffer == nullptr || bufferSize == 0)
+    {
+        return TimelinePacketStatus::BufferExhaustion;
+    }
+
+    // Utils
+    unsigned int uint32_t_size = sizeof(uint32_t);
+    unsigned int uint64_t_size = sizeof(uint64_t);
+
+    // Calculate the length of the data (in bytes)
+    unsigned int timelineRelationshipPacketDataLength = uint32_t_size * 2 + // decl_id + Relationship Type
+                                                        uint64_t_size * 3; // Relationship GUID + Head GUID + tail GUID
+
+    // Calculate the timeline binary packet size (in bytes)
+    unsigned int timelineRelationshipPacketSize = 2 * uint32_t_size + // Header (2 words)
+                                                  timelineRelationshipPacketDataLength;
+
+    // Check whether the timeline binary packet fits in the given buffer
+    if (timelineRelationshipPacketSize > bufferSize)
+    {
+        return TimelinePacketStatus::BufferExhaustion;
+    }
+
+    // Create packet header
+    uint32_t dataLength = boost::numeric_cast<uint32_t>(timelineRelationshipPacketDataLength);
+    std::pair<uint32_t, uint32_t> packetHeader = CreateTimelineMessagePacketHeader(dataLength);
+
+    // Initialize the offset for writing in the buffer
+    unsigned int offset = 0;
+
+    // Write the timeline binary packet header to the buffer
+    WriteUint32(buffer, offset, packetHeader.first);
+    offset += uint32_t_size;
+    WriteUint32(buffer, offset, packetHeader.second);
+    offset += uint32_t_size;
+
+    uint32_t relationshipTypeUint = 0;
+
+    switch (relationshipType)
+    {
+        case ProfilingRelationshipType::RetentionLink:
+            relationshipTypeUint = 0;
+            break;
+        case ProfilingRelationshipType::ExecutionLink:
+            relationshipTypeUint = 1;
+            break;
+        case ProfilingRelationshipType::DataLink:
+            relationshipTypeUint = 2;
+            break;
+        case ProfilingRelationshipType::LabelLink:
+            relationshipTypeUint = 3;
+            break;
+        default:
+            throw InvalidArgumentException("Unknown relationship type given.");
+    }
+
+    // Write the timeline binary packet payload to the buffer
+    // decl_id of the timeline message
+    uint32_t declId = 3;
+    WriteUint32(buffer, offset, declId); // decl_id
+    offset += uint32_t_size;
+    WriteUint32(buffer, offset, relationshipTypeUint); // Relationship Type
+    offset += uint32_t_size;
+    WriteUint64(buffer, offset, relationshipGuid); // GUID of this relationship
+    offset += uint64_t_size;
+    WriteUint64(buffer, offset, headGuid); // head of relationship GUID
+    offset += uint64_t_size;
+    WriteUint64(buffer, offset, tailGuid); // tail of relationship GUID
+
+    // Update the number of bytes written
+    numberOfBytesWritten = timelineRelationshipPacketSize;
+
+    return TimelinePacketStatus::Ok;
+}
+
 TimelinePacketStatus WriteTimelineMessageDirectoryPackage(unsigned char* buffer,
                                                           unsigned int bufferSize,
                                                           unsigned int& numberOfBytesWritten)
index c8a5c7f..582f7c4 100644 (file)
@@ -126,6 +126,14 @@ enum class TimelinePacketStatus
     BufferExhaustion
 };
 
+enum class ProfilingRelationshipType
+{
+    RetentionLink, /// Head retains(parents) Tail
+    ExecutionLink, /// Head execution start depends on Tail execution completion
+    DataLink,      /// Head uses data of Tail
+    LabelLink      /// Head uses label Tail (Tail MUST be a guid of a label).
+};
+
 TimelinePacketStatus WriteTimelineLabelBinaryPacket(uint64_t profilingGuid,
                                                     const std::string& label,
                                                     unsigned char* buffer,
@@ -137,6 +145,14 @@ TimelinePacketStatus WriteTimelineEntityBinaryPacket(uint64_t profilingGuid,
                                                      unsigned int bufferSize,
                                                      unsigned int& numberOfBytesWritten);
 
+TimelinePacketStatus WriteTimelineRelationshipBinaryPacket(ProfilingRelationshipType relationshipType,
+                                                           uint64_t relationshipGuid,
+                                                           uint64_t headGuid,
+                                                           uint64_t tailGuid,
+                                                           unsigned char* buffer,
+                                                           unsigned int bufferSize,
+                                                           unsigned int& numberOfBytesWritten);
+
 TimelinePacketStatus WriteTimelineMessageDirectoryPackage(unsigned char* buffer,
                                                           unsigned int bufferSize,
                                                           unsigned int& numberOfBytesWritten);
index 558af04..a9ba516 100644 (file)
@@ -135,6 +135,360 @@ BOOST_AUTO_TEST_CASE(TimelineLabelPacketTest5)
     BOOST_CHECK(buffer[offset] == '\0'); // The null-terminator at the end of the SWTrace label
 }
 
+BOOST_AUTO_TEST_CASE(TimelineRelationshipPacketNullBufferTest)
+{
+    ProfilingRelationshipType relationshipType = ProfilingRelationshipType::DataLink;
+    const uint64_t relationshipGuid = 123456u;
+    const uint64_t headGuid = 234567u;
+    const uint64_t tailGuid = 345678u;
+    unsigned int numberOfBytesWritten = 789u;
+    TimelinePacketStatus result = WriteTimelineRelationshipBinaryPacket(relationshipType,
+                                                                        relationshipGuid,
+                                                                        headGuid,
+                                                                        tailGuid,
+                                                                        nullptr,
+                                                                        512u,
+                                                                        numberOfBytesWritten);
+    BOOST_CHECK(result == TimelinePacketStatus::BufferExhaustion);
+    BOOST_CHECK(numberOfBytesWritten == 0);
+}
+
+BOOST_AUTO_TEST_CASE(TimelineRelationshipPacketZeroBufferSizeTest)
+{
+    std::vector<unsigned char> buffer(512, 0);
+
+    ProfilingRelationshipType relationshipType = ProfilingRelationshipType::DataLink;
+    const uint64_t relationshipGuid = 123456u;
+    const uint64_t headGuid = 234567u;
+    const uint64_t tailGuid = 345678u;
+    unsigned int numberOfBytesWritten = 789u;
+    TimelinePacketStatus result = WriteTimelineRelationshipBinaryPacket(relationshipType,
+                                                                        relationshipGuid,
+                                                                        headGuid,
+                                                                        tailGuid,
+                                                                        buffer.data(),
+                                                                        0,
+                                                                        numberOfBytesWritten);
+    BOOST_CHECK(result == TimelinePacketStatus::BufferExhaustion);
+    BOOST_CHECK(numberOfBytesWritten == 0);
+}
+
+BOOST_AUTO_TEST_CASE(TimelineRelationshipPacketSmallBufferSizeTest)
+{
+    std::vector<unsigned char> buffer(10, 0);
+
+    ProfilingRelationshipType relationshipType = ProfilingRelationshipType::DataLink;
+    const uint64_t relationshipGuid = 123456u;
+    const uint64_t headGuid = 234567u;
+    const uint64_t tailGuid = 345678u;
+    unsigned int numberOfBytesWritten = 789u;
+    TimelinePacketStatus result =
+        WriteTimelineRelationshipBinaryPacket(relationshipType,
+                                              relationshipGuid,
+                                              headGuid,
+                                              tailGuid,
+                                              buffer.data(),
+                                              boost::numeric_cast<unsigned int>(buffer.size()),
+                                              numberOfBytesWritten);
+    BOOST_CHECK(result == TimelinePacketStatus::BufferExhaustion);
+    BOOST_CHECK(numberOfBytesWritten == 0);
+}
+
+BOOST_AUTO_TEST_CASE(TimelineRelationshipPacketInvalidRelationTest)
+{
+    std::vector<unsigned char> buffer(512, 0);
+    ProfilingRelationshipType relationshipType = static_cast<ProfilingRelationshipType>(5);
+    const uint64_t relationshipGuid = 123456u;
+    const uint64_t headGuid = 234567u;
+    const uint64_t tailGuid = 345678u;
+    unsigned int numberOfBytesWritten = 789u;
+
+    BOOST_CHECK_THROW(WriteTimelineRelationshipBinaryPacket(relationshipType,
+                                                            relationshipGuid,
+                                                            headGuid,
+                                                            tailGuid,
+                                                            buffer.data(),
+                                                            boost::numeric_cast<unsigned int>(buffer.size()),
+                                                            numberOfBytesWritten),
+                       armnn::InvalidArgumentException);
+
+    BOOST_CHECK(numberOfBytesWritten == 0);
+}
+
+BOOST_AUTO_TEST_CASE(TimelineRelationshipPacketTest)
+{
+    std::vector<unsigned char> buffer(512, 0);
+
+    ProfilingRelationshipType relationshipType = ProfilingRelationshipType::RetentionLink;
+    const uint64_t relationshipGuid = 123456u;
+    const uint64_t headGuid = 234567u;
+    const uint64_t tailGuid = 345678u;
+    unsigned int numberOfBytesWritten = 789u;
+    TimelinePacketStatus result =
+        WriteTimelineRelationshipBinaryPacket(relationshipType,
+                                              relationshipGuid,
+                                              headGuid,
+                                              tailGuid,
+                                              buffer.data(),
+                                              boost::numeric_cast<unsigned int>(buffer.size()),
+                                              numberOfBytesWritten);
+    BOOST_CHECK(result == TimelinePacketStatus::Ok);
+    BOOST_CHECK(numberOfBytesWritten == 40);
+
+    unsigned int uint32_t_size = sizeof(uint32_t);
+    unsigned int uint64_t_size = sizeof(uint64_t);
+
+    // Check the packet header
+    unsigned int offset = 0;
+    uint32_t packetHeaderWord0 = ReadUint32(buffer.data(), 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   == 1);
+    BOOST_CHECK(streamId     == 0);
+
+    offset += uint32_t_size;
+    uint32_t packetHeaderWord1 = ReadUint32(buffer.data(), offset);
+    uint32_t sequenceNumbered = (packetHeaderWord1 >> 24) & 0x00000001;
+    uint32_t dataLength       = (packetHeaderWord1 >>  0) & 0x00FFFFFF;
+    BOOST_CHECK(sequenceNumbered ==  0);
+    BOOST_CHECK(dataLength       == 32);
+
+    // Check the decl_id
+    offset += uint32_t_size;
+    uint32_t readDeclId = ReadUint32(buffer.data(), offset);
+    BOOST_CHECK(readDeclId == 3);
+
+    // Check the relationship type
+    offset += uint32_t_size;
+    uint32_t readRelationshipType = ReadUint32(buffer.data(), offset);
+    BOOST_CHECK(readRelationshipType == 0);
+
+    // Check the relationship GUID
+    offset += uint32_t_size;
+    uint64_t readRelationshipGuid = ReadUint64(buffer.data(), offset);
+    BOOST_CHECK(readRelationshipGuid == relationshipGuid);
+
+    // Check the head GUID
+    offset += uint64_t_size;
+    uint64_t readHeadGuid = ReadUint64(buffer.data(), offset);
+    BOOST_CHECK(readHeadGuid == headGuid);
+
+    // Check the tail GUID
+    offset += uint64_t_size;
+    uint64_t readTailGuid = ReadUint64(buffer.data(), offset);
+    BOOST_CHECK(readTailGuid == tailGuid);
+}
+
+BOOST_AUTO_TEST_CASE(TimelineRelationshipPacketExecutionLinkTest)
+{
+    std::vector<unsigned char> buffer(512, 0);
+
+    ProfilingRelationshipType relationshipType = ProfilingRelationshipType::ExecutionLink;
+    const uint64_t relationshipGuid = 123456u;
+    const uint64_t headGuid = 234567u;
+    const uint64_t tailGuid = 345678u;
+    unsigned int numberOfBytesWritten = 789u;
+    TimelinePacketStatus result =
+        WriteTimelineRelationshipBinaryPacket(relationshipType,
+                                              relationshipGuid,
+                                              headGuid,
+                                              tailGuid,
+                                              buffer.data(),
+                                              boost::numeric_cast<unsigned int>(buffer.size()),
+                                              numberOfBytesWritten);
+    BOOST_CHECK(result == TimelinePacketStatus::Ok);
+    BOOST_CHECK(numberOfBytesWritten == 40);
+
+    unsigned int uint32_t_size = sizeof(uint32_t);
+    unsigned int uint64_t_size = sizeof(uint64_t);
+
+    // Check the packet header
+    unsigned int offset = 0;
+    uint32_t packetHeaderWord0 = ReadUint32(buffer.data(), 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   == 1);
+    BOOST_CHECK(streamId     == 0);
+
+    offset += uint32_t_size;
+    uint32_t packetHeaderWord1 = ReadUint32(buffer.data(), offset);
+    uint32_t sequenceNumbered = (packetHeaderWord1 >> 24) & 0x00000001;
+    uint32_t dataLength       = (packetHeaderWord1 >>  0) & 0x00FFFFFF;
+    BOOST_CHECK(sequenceNumbered ==  0);
+    BOOST_CHECK(dataLength       == 32);
+
+    // Check the decl_id
+    offset += uint32_t_size;
+    uint32_t readDeclId = ReadUint32(buffer.data(), offset);
+    BOOST_CHECK(readDeclId == 3);
+
+    // Check the relationship type
+    offset += uint32_t_size;
+    uint32_t readRelationshipType = ReadUint32(buffer.data(), offset);
+    BOOST_CHECK(readRelationshipType == 1);
+
+    // Check the relationship GUID
+    offset += uint32_t_size;
+    uint64_t readRelationshipGuid = ReadUint64(buffer.data(), offset);
+    BOOST_CHECK(readRelationshipGuid == relationshipGuid);
+
+    // Check the head GUID
+    offset += uint64_t_size;
+    uint64_t readHeadGuid = ReadUint64(buffer.data(), offset);
+    BOOST_CHECK(readHeadGuid == headGuid);
+
+    // Check the tail GUID
+    offset += uint64_t_size;
+    uint64_t readTailGuid = ReadUint64(buffer.data(), offset);
+    BOOST_CHECK(readTailGuid == tailGuid);
+}
+
+
+BOOST_AUTO_TEST_CASE(TimelineRelationshipPacketDataLinkTest)
+{
+    std::vector<unsigned char> buffer(512, 0);
+
+    ProfilingRelationshipType relationshipType = ProfilingRelationshipType::DataLink;
+    const uint64_t relationshipGuid = 123456u;
+    const uint64_t headGuid = 234567u;
+    const uint64_t tailGuid = 345678u;
+    unsigned int numberOfBytesWritten = 789u;
+    TimelinePacketStatus result =
+        WriteTimelineRelationshipBinaryPacket(relationshipType,
+                                              relationshipGuid,
+                                              headGuid,
+                                              tailGuid,
+                                              buffer.data(),
+                                              boost::numeric_cast<unsigned int>(buffer.size()),
+                                              numberOfBytesWritten);
+    BOOST_CHECK(result == TimelinePacketStatus::Ok);
+    BOOST_CHECK(numberOfBytesWritten == 40);
+
+    unsigned int uint32_t_size = sizeof(uint32_t);
+    unsigned int uint64_t_size = sizeof(uint64_t);
+
+    // Check the packet header
+    unsigned int offset = 0;
+    uint32_t packetHeaderWord0 = ReadUint32(buffer.data(), 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   == 1);
+    BOOST_CHECK(streamId     == 0);
+
+    offset += uint32_t_size;
+    uint32_t packetHeaderWord1 = ReadUint32(buffer.data(), offset);
+    uint32_t sequenceNumbered = (packetHeaderWord1 >> 24) & 0x00000001;
+    uint32_t dataLength       = (packetHeaderWord1 >>  0) & 0x00FFFFFF;
+    BOOST_CHECK(sequenceNumbered ==  0);
+    BOOST_CHECK(dataLength       == 32);
+
+    // Check the decl_id
+    offset += uint32_t_size;
+    uint32_t readDeclId = ReadUint32(buffer.data(), offset);
+    BOOST_CHECK(readDeclId == 3);
+
+    // Check the relationship type
+    offset += uint32_t_size;
+    uint32_t readRelationshipType = ReadUint32(buffer.data(), offset);
+    BOOST_CHECK(readRelationshipType == 2);
+
+    // Check the relationship GUID
+    offset += uint32_t_size;
+    uint64_t readRelationshipGuid = ReadUint64(buffer.data(), offset);
+    BOOST_CHECK(readRelationshipGuid == relationshipGuid);
+
+    // Check the head GUID
+    offset += uint64_t_size;
+    uint64_t readHeadGuid = ReadUint64(buffer.data(), offset);
+    BOOST_CHECK(readHeadGuid == headGuid);
+
+    // Check the tail GUID
+    offset += uint64_t_size;
+    uint64_t readTailGuid = ReadUint64(buffer.data(), offset);
+    BOOST_CHECK(readTailGuid == tailGuid);
+}
+
+
+BOOST_AUTO_TEST_CASE(TimelineRelationshipPacketLabelLinkTest)
+{
+    std::vector<unsigned char> buffer(512, 0);
+
+    ProfilingRelationshipType relationshipType = ProfilingRelationshipType::LabelLink;
+    const uint64_t relationshipGuid = 123456u;
+    const uint64_t headGuid = 234567u;
+    const uint64_t tailGuid = 345678u;
+    unsigned int numberOfBytesWritten = 789u;
+    TimelinePacketStatus result =
+        WriteTimelineRelationshipBinaryPacket(relationshipType,
+                                              relationshipGuid,
+                                              headGuid,
+                                              tailGuid,
+                                              buffer.data(),
+                                              boost::numeric_cast<unsigned int>(buffer.size()),
+                                              numberOfBytesWritten);
+    BOOST_CHECK(result == TimelinePacketStatus::Ok);
+    BOOST_CHECK(numberOfBytesWritten == 40);
+
+    unsigned int uint32_t_size = sizeof(uint32_t);
+    unsigned int uint64_t_size = sizeof(uint64_t);
+
+    // Check the packet header
+    unsigned int offset = 0;
+    uint32_t packetHeaderWord0 = ReadUint32(buffer.data(), 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   == 1);
+    BOOST_CHECK(streamId     == 0);
+
+    offset += uint32_t_size;
+    uint32_t packetHeaderWord1 = ReadUint32(buffer.data(), offset);
+    uint32_t sequenceNumbered = (packetHeaderWord1 >> 24) & 0x00000001;
+    uint32_t dataLength       = (packetHeaderWord1 >>  0) & 0x00FFFFFF;
+    BOOST_CHECK(sequenceNumbered ==  0);
+    BOOST_CHECK(dataLength       == 32);
+
+    // Check the decl_id
+    offset += uint32_t_size;
+    uint32_t readDeclId = ReadUint32(buffer.data(), offset);
+    BOOST_CHECK(readDeclId == 3);
+
+    // Check the relationship type
+    offset += uint32_t_size;
+    uint32_t readRelationshipType = ReadUint32(buffer.data(), offset);
+    BOOST_CHECK(readRelationshipType == 3);
+
+    // Check the relationship GUID
+    offset += uint32_t_size;
+    uint64_t readRelationshipGuid = ReadUint64(buffer.data(), offset);
+    BOOST_CHECK(readRelationshipGuid == relationshipGuid);
+
+    // Check the head GUID
+    offset += uint64_t_size;
+    uint64_t readHeadGuid = ReadUint64(buffer.data(), offset);
+    BOOST_CHECK(readHeadGuid == headGuid);
+
+    // Check the tail GUID
+    offset += uint64_t_size;
+    uint64_t readTailGuid = ReadUint64(buffer.data(), offset);
+    BOOST_CHECK(readTailGuid == tailGuid);
+}
+
 BOOST_AUTO_TEST_CASE(TimelineMessageDirectoryPacketTest1)
 {
     unsigned int numberOfBytesWritten = 789u;