aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFinn Williams <Finn.Williams@arm.com>2019-10-22 10:30:49 +0100
committerDavid Monahan <david.monahan@arm.com>2019-11-07 12:20:47 +0000
commite63a026bd987e78bdaa5b94c3e53201b62011faa (patch)
treecad6e7dcc7107b723ecc92116a96eda80100a99e
parent362e03214ceceb95ec30d530ff84e8d9efc198d7 (diff)
downloadarmnn-e63a026bd987e78bdaa5b94c3e53201b62011faa.tar.gz
IVGCVSW-3951 Create the timeline decoder
* Added ITimelineDecoder.h C interface * Added an example implementation of ITimelineDecoder.h * Added command handlers for the timeline directory and objects * Added tests for the decoder implementation * Changed ReadSwTraceMessage to take a const unsigned char* so it can be used by the directory command handler * Fixed some bugs in ProfilingUtils.cpp and related tests Change-Id: If06faf1fe0274a8f022f194a6d3527f5ce5374c6 Signed-off-by: Finn Williams <Finn.Williams@arm.com>
-rw-r--r--CMakeLists.txt8
-rw-r--r--src/profiling/DirectoryCaptureCommandHandler.cpp1
-rw-r--r--src/profiling/ProfilingUtils.cpp16
-rw-r--r--src/profiling/ProfilingUtils.hpp2
-rw-r--r--src/profiling/test/SendTimelinePacketTests.cpp18
-rw-r--r--src/profiling/test/TimelinePacketTests.cpp7
-rw-r--r--src/profiling/test/TimelineUtilityMethodsTests.cpp2
-rw-r--r--tests/profiling/timelineDecoder/ITimelineDecoder.h41
-rw-r--r--tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.cpp300
-rw-r--r--tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.hpp66
-rw-r--r--tests/profiling/timelineDecoder/TimelineDecoder.cpp166
-rw-r--r--tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.cpp106
-rw-r--r--tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.hpp47
-rw-r--r--tests/profiling/timelineDecoder/TimelineModel.h96
-rw-r--r--tests/profiling/timelineDecoder/tests/TimelineTestFunctions.hpp143
-rw-r--r--tests/profiling/timelineDecoder/tests/TimelineTests.cpp206
16 files changed, 1208 insertions, 17 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 867fb34071..5b80430d7d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -822,6 +822,7 @@ if(BUILD_UNIT_TESTS)
if(BUILD_GATORD_MOCK)
list(APPEND unittest_sources
tests/profiling/gatordmock/tests/GatordMockTests.cpp
+ tests/profiling/timelineDecoder/tests/TimelineTests.cpp
)
endif()
@@ -936,6 +937,13 @@ if(BUILD_GATORD_MOCK)
tests/profiling/gatordmock/PeriodicCounterCaptureCommandHandler.hpp
tests/profiling/gatordmock/PeriodicCounterSelectionResponseHandler.cpp
tests/profiling/gatordmock/PeriodicCounterSelectionResponseHandler.hpp
+ tests/profiling/timelineDecoder/ITimelineDecoder.h
+ tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.cpp
+ tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.hpp
+ tests/profiling/timelineDecoder/TimelineDecoder.cpp
+ tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.cpp
+ tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.hpp
+ tests/profiling/timelineDecoder/tests/TimelineTestFunctions.hpp
)
include_directories(${Boost_INCLUDE_DIRS} src/profiling)
diff --git a/src/profiling/DirectoryCaptureCommandHandler.cpp b/src/profiling/DirectoryCaptureCommandHandler.cpp
index 22d1e6d0dd..c5a2d97293 100644
--- a/src/profiling/DirectoryCaptureCommandHandler.cpp
+++ b/src/profiling/DirectoryCaptureCommandHandler.cpp
@@ -3,6 +3,7 @@
// SPDX-License-Identifier: MIT
//
+#include <atomic>
#include "DirectoryCaptureCommandHandler.hpp"
#include "SendCounterPacket.hpp"
diff --git a/src/profiling/ProfilingUtils.cpp b/src/profiling/ProfilingUtils.cpp
index b649747df1..4dde235ecc 100644
--- a/src/profiling/ProfilingUtils.cpp
+++ b/src/profiling/ProfilingUtils.cpp
@@ -347,7 +347,7 @@ uint32_t CalculateSizeOfPaddedSwString(const std::string& str)
}
// Read TimelineMessageDirectoryPacket from given IPacketBuffer and offset
-SwTraceMessage ReadSwTraceMessage(const IPacketBufferPtr& packetBuffer, unsigned int& offset)
+SwTraceMessage ReadSwTraceMessage(const unsigned char* packetBuffer, unsigned int& offset)
{
BOOST_ASSERT(packetBuffer);
@@ -369,7 +369,7 @@ SwTraceMessage ReadSwTraceMessage(const IPacketBufferPtr& packetBuffer, unsigned
offset += uint32_t_size;
std::vector<unsigned char> swTraceStringBuffer(swTraceDeclNameLength - 1);
std::memcpy(swTraceStringBuffer.data(),
- packetBuffer->GetReadableData() + offset, swTraceStringBuffer.size());
+ packetBuffer + offset, swTraceStringBuffer.size());
swTraceMessage.name.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // name
@@ -380,7 +380,7 @@ SwTraceMessage ReadSwTraceMessage(const IPacketBufferPtr& packetBuffer, unsigned
offset += uint32_t_size;
swTraceStringBuffer.resize(swTraceUINameLength - 1);
std::memcpy(swTraceStringBuffer.data(),
- packetBuffer->GetReadableData() + offset, swTraceStringBuffer.size());
+ packetBuffer + offset, swTraceStringBuffer.size());
swTraceMessage.uiName.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // ui_name
@@ -391,7 +391,7 @@ SwTraceMessage ReadSwTraceMessage(const IPacketBufferPtr& packetBuffer, unsigned
offset += uint32_t_size;
swTraceStringBuffer.resize(swTraceArgTypesLength - 1);
std::memcpy(swTraceStringBuffer.data(),
- packetBuffer->GetReadableData() + offset, swTraceStringBuffer.size());
+ packetBuffer + offset, swTraceStringBuffer.size());
swTraceMessage.argTypes.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // arg_types
@@ -404,7 +404,7 @@ SwTraceMessage ReadSwTraceMessage(const IPacketBufferPtr& packetBuffer, unsigned
offset += uint32_t_size;
swTraceStringBuffer.resize(swTraceArgNamesLength - 1);
std::memcpy(swTraceStringBuffer.data(),
- packetBuffer->GetReadableData() + offset, swTraceStringBuffer.size());
+ packetBuffer + offset, swTraceStringBuffer.size());
swTraceString.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end());
std::stringstream stringStream(swTraceString);
@@ -536,12 +536,11 @@ TimelinePacketStatus WriteTimelineEntityBinaryPacket(uint64_t profilingGuid,
unsigned int uint64_t_size = sizeof(uint64_t);
// Calculate the length of the data (in bytes)
- unsigned int timelineEntityPacketDataLength = uint64_t_size; // Profiling GUID
+ unsigned int timelineEntityPacketDataLength = uint32_t_size + uint64_t_size; // decl_id + Profiling GUID
// Calculate the timeline binary packet size (in bytes)
unsigned int timelineEntityPacketSize = 2 * uint32_t_size + // Header (2 words)
- uint32_t_size + // decl_Id
timelineEntityPacketDataLength; // Profiling GUID
// Check whether the timeline binary packet fits in the given buffer
@@ -744,6 +743,9 @@ TimelinePacketStatus WriteTimelineMessageDirectoryPackage(unsigned char* buffer,
WriteUint32(buffer, offset, packetHeader.second);
offset += uint32_t_size;
+ WriteUint32(buffer, offset, static_cast<uint32_t >(swTraceTimelineDirectoryMessages.size()));
+ offset += uint32_t_size;
+
for (unsigned int i = 0u; i < swTraceTimelineDirectoryMessages.size(); ++i)
{
// Write the timeline binary packet payload to the buffer
diff --git a/src/profiling/ProfilingUtils.hpp b/src/profiling/ProfilingUtils.hpp
index 74fc437333..f7b46be972 100644
--- a/src/profiling/ProfilingUtils.hpp
+++ b/src/profiling/ProfilingUtils.hpp
@@ -156,7 +156,7 @@ enum class ProfilingRelationshipType
uint32_t CalculateSizeOfPaddedSwString(const std::string& str);
-SwTraceMessage ReadSwTraceMessage(const IPacketBufferPtr& packetBuffer, unsigned int& offset);
+SwTraceMessage ReadSwTraceMessage(const unsigned char*, unsigned int& offset);
TimelinePacketStatus WriteTimelineLabelBinaryPacket(uint64_t profilingGuid,
const std::string& label,
diff --git a/src/profiling/test/SendTimelinePacketTests.cpp b/src/profiling/test/SendTimelinePacketTests.cpp
index 60cda9a657..7f3094918d 100644
--- a/src/profiling/test/SendTimelinePacketTests.cpp
+++ b/src/profiling/test/SendTimelinePacketTests.cpp
@@ -53,7 +53,11 @@ BOOST_AUTO_TEST_CASE(SendTimelineMessageDirectoryPackageTest)
BOOST_CHECK(dataLength == 416);
offset += uint32_t_size;
- SwTraceMessage swTraceMessage = ReadSwTraceMessage(packetBuffer, offset);
+ uint32_t DeclCount = ReadUint32(packetBuffer, offset);
+ BOOST_CHECK(DeclCount == 5);
+
+ offset += uint32_t_size;
+ SwTraceMessage swTraceMessage = ReadSwTraceMessage(packetBuffer->GetReadableData(), offset);
BOOST_CHECK(swTraceMessage.id == 0);
BOOST_CHECK(swTraceMessage.name == "declareLabel");
@@ -65,7 +69,7 @@ BOOST_AUTO_TEST_CASE(SendTimelineMessageDirectoryPackageTest)
BOOST_CHECK(swTraceMessage.argNames[0] == "guid");
BOOST_CHECK(swTraceMessage.argNames[1] == "value");
- swTraceMessage = ReadSwTraceMessage(packetBuffer, offset);
+ swTraceMessage = ReadSwTraceMessage(packetBuffer->GetReadableData(), offset);
BOOST_CHECK(swTraceMessage.id == 1);
BOOST_CHECK(swTraceMessage.name == "declareEntity");
@@ -75,7 +79,7 @@ BOOST_AUTO_TEST_CASE(SendTimelineMessageDirectoryPackageTest)
BOOST_CHECK(swTraceMessage.argNames.size() == 1);
BOOST_CHECK(swTraceMessage.argNames[0] == "guid");
- swTraceMessage = ReadSwTraceMessage(packetBuffer, offset);
+ swTraceMessage = ReadSwTraceMessage(packetBuffer->GetReadableData(), offset);
BOOST_CHECK(swTraceMessage.id == 2);
BOOST_CHECK(swTraceMessage.name == "declareEventClass");
@@ -85,7 +89,7 @@ BOOST_AUTO_TEST_CASE(SendTimelineMessageDirectoryPackageTest)
BOOST_CHECK(swTraceMessage.argNames.size() == 1);
BOOST_CHECK(swTraceMessage.argNames[0] == "guid");
- swTraceMessage = ReadSwTraceMessage(packetBuffer, offset);
+ swTraceMessage = ReadSwTraceMessage(packetBuffer->GetReadableData(), offset);
BOOST_CHECK(swTraceMessage.id == 3);
BOOST_CHECK(swTraceMessage.name == "declareRelationship");
@@ -101,7 +105,7 @@ BOOST_AUTO_TEST_CASE(SendTimelineMessageDirectoryPackageTest)
BOOST_CHECK(swTraceMessage.argNames[2] == "headGuid");
BOOST_CHECK(swTraceMessage.argNames[3] == "tailGuid");
- swTraceMessage = ReadSwTraceMessage(packetBuffer, offset);
+ swTraceMessage = ReadSwTraceMessage(packetBuffer->GetReadableData(), offset);
BOOST_CHECK(swTraceMessage.id == 4);
BOOST_CHECK(swTraceMessage.name == "declareEvent");
@@ -157,7 +161,7 @@ BOOST_AUTO_TEST_CASE(SendTimelineEntityPlusEventClassBinaryPacketTest)
uint32_t entityBinaryPacketSequenceNumbered = (entityBinaryPacketHeaderWord1 >> 24) & 0x00000001;
uint32_t entityBinaryPacketDataLength = (entityBinaryPacketHeaderWord1 >> 0) & 0x00FFFFFF;
BOOST_CHECK(entityBinaryPacketSequenceNumbered == 0);
- BOOST_CHECK(entityBinaryPacketDataLength == 8);
+ BOOST_CHECK(entityBinaryPacketDataLength == 12);
// Check the decl_id
offset += uint32_t_size;
@@ -243,7 +247,7 @@ BOOST_AUTO_TEST_CASE(SendTimelinePacketTests1)
uint32_t entityBinaryPacketSequenceNumbered = (entityBinaryPacketHeaderWord1 >> 24) & 0x00000001;
uint32_t entityBinaryPacketDataLength = (entityBinaryPacketHeaderWord1 >> 0) & 0x00FFFFFF;
BOOST_CHECK(entityBinaryPacketSequenceNumbered == 0);
- BOOST_CHECK(entityBinaryPacketDataLength == 8);
+ BOOST_CHECK(entityBinaryPacketDataLength == 12);
// Check the decl_id
offset += uint32_t_size;
diff --git a/src/profiling/test/TimelinePacketTests.cpp b/src/profiling/test/TimelinePacketTests.cpp
index 6a8aa85fc0..68cd948bdd 100644
--- a/src/profiling/test/TimelinePacketTests.cpp
+++ b/src/profiling/test/TimelinePacketTests.cpp
@@ -543,6 +543,11 @@ BOOST_AUTO_TEST_CASE(TimelineMessageDirectoryPacketTest3)
BOOST_CHECK(sequenceNumbered == 0);
BOOST_CHECK(dataLength == 416);
+ // Check the number of declarations
+ offset += uint32_t_size;
+ uint32_t declCount = ReadUint32(buffer.data(), offset);
+ BOOST_CHECK(declCount == 5);
+
// Check the decl_id
offset += uint32_t_size;
uint32_t readDeclId = ReadUint32(buffer.data(), offset);
@@ -689,7 +694,7 @@ BOOST_AUTO_TEST_CASE(TimelineEntityPacketTest4)
uint32_t sequenceNumbered = (packetHeaderWord1 >> 24) & 0x00000001;
uint32_t dataLength = (packetHeaderWord1 >> 0) & 0x00FFFFFF;
BOOST_CHECK(sequenceNumbered == 0);
- BOOST_CHECK(dataLength == 8);
+ BOOST_CHECK(dataLength == 12);
// Check decl_Id
offset += uint32_t_size;
diff --git a/src/profiling/test/TimelineUtilityMethodsTests.cpp b/src/profiling/test/TimelineUtilityMethodsTests.cpp
index 3556a12a7b..f784afc6ef 100644
--- a/src/profiling/test/TimelineUtilityMethodsTests.cpp
+++ b/src/profiling/test/TimelineUtilityMethodsTests.cpp
@@ -258,7 +258,7 @@ void VerifyTimelineEntityBinaryPacket(Optional<ProfilingGuid> guid,
uint32_t entityBinaryPacketSequenceNumbered = (entityBinaryPacketHeaderWord1 >> 24) & 0x00000001;
uint32_t entityBinaryPacketDataLength = (entityBinaryPacketHeaderWord1 >> 0) & 0x00FFFFFF;
BOOST_CHECK(entityBinaryPacketSequenceNumbered == 0);
- BOOST_CHECK(entityBinaryPacketDataLength == 8);
+ BOOST_CHECK(entityBinaryPacketDataLength == 12);
// Check the decl_id
offset += uint32_t_size;
diff --git a/tests/profiling/timelineDecoder/ITimelineDecoder.h b/tests/profiling/timelineDecoder/ITimelineDecoder.h
new file mode 100644
index 0000000000..65ec8bfa6e
--- /dev/null
+++ b/tests/profiling/timelineDecoder/ITimelineDecoder.h
@@ -0,0 +1,41 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#ifndef ARMNN_ITIMELINEDECODER_H
+#define ARMNN_ITIMELINEDECODER_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "TimelineModel.h"
+
+typedef enum ErrorCode
+{
+ ErrorCode_Success,
+ ErrorCode_Fail
+} ErrorCode;
+
+ErrorCode CreateModel(Model** model);
+ErrorCode DestroyModel(Model** model);
+
+ErrorCode SetEntityCallback(OnNewEntityCallback cb, Model* model);
+ErrorCode SetEventClassCallback(OnNewEventClassCallback cb, Model* model);
+ErrorCode SetEventCallback(OnNewEventCallback cb, Model* model);
+ErrorCode SetLabelCallback(OnNewLabelCallback cb, Model* model);
+ErrorCode SetRelationshipCallback(OnNewRelationshipCallback cb, Model* model);
+
+ErrorCode CreateEntity(const Entity entity, Model* model);
+ErrorCode CreateEventClass(const EventClass eventClass, Model* model);
+ErrorCode CreateEvent(const Event event, Model* model);
+ErrorCode CreateLabel(const Label label, Model* model);
+ErrorCode CreateRelationship(const Relationship relationship, Model* model);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //ARMNN_ITIMELINEDECODER_H \ No newline at end of file
diff --git a/tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.cpp b/tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.cpp
new file mode 100644
index 0000000000..bdceca69b0
--- /dev/null
+++ b/tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.cpp
@@ -0,0 +1,300 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "TimelineCaptureCommandHandler.hpp"
+
+#include <iostream>
+#include <string>
+
+namespace armnn
+{
+
+namespace gatordmock
+{
+
+//Array of member functions, the array index matches the decl_id
+const TimelineCaptureCommandHandler::ReadFunction TimelineCaptureCommandHandler::m_ReadFunctions[5]
+{
+ &TimelineCaptureCommandHandler::ReadLabel, // Label decl_id = 0
+ &TimelineCaptureCommandHandler::ReadEntity, // Entity decl_id = 1
+ &TimelineCaptureCommandHandler::ReadEventClass, // EventClass decl_id = 2
+ &TimelineCaptureCommandHandler::ReadRelationship, // Relationship decl_id = 3
+ &TimelineCaptureCommandHandler::ReadEvent // Event decl_id = 4
+};
+
+void TimelineCaptureCommandHandler::ParseData(const armnn::profiling::Packet& packet)
+{
+ uint32_t offset = 0;
+
+ if (packet.GetLength() < 8)
+ {
+ return;
+ }
+
+ const unsigned char* data = reinterpret_cast<const unsigned char*>(packet.GetData());
+
+ uint32_t declId = 0;
+
+ declId = profiling::ReadUint32(data, offset);
+ offset += uint32_t_size;
+
+ (this->*m_ReadFunctions[declId])(data, offset);
+}
+
+void TimelineCaptureCommandHandler::ReadLabel(const unsigned char* data, uint32_t offset)
+{
+ Label label;
+ label.m_Guid = profiling::ReadUint64(data, offset);
+ offset += uint64_t_size;
+
+ uint32_t nameLength = profiling::ReadUint32(data, offset);
+ offset += uint32_t_size;
+
+ label.m_Name = new char[nameLength];
+ for (uint32_t i = 0; i< nameLength; ++i)
+ {
+ label.m_Name[i] = static_cast<char>(profiling::ReadUint8(data, offset + i));
+ }
+
+ CreateLabel(label, m_Model);
+
+ if (!m_QuietOperation)
+ {
+ printLabels();
+ }
+}
+
+void TimelineCaptureCommandHandler::ReadEntity(const unsigned char* data, uint32_t offset)
+{
+ Entity entity;
+ entity.m_Guid = profiling::ReadUint64(data, offset);
+
+ CreateEntity(entity, m_Model);
+
+ if (!m_QuietOperation)
+ {
+ printEntities();
+ }
+}
+
+void TimelineCaptureCommandHandler::ReadEventClass(const unsigned char* data, uint32_t offset)
+{
+ EventClass eventClass;
+ eventClass.m_Guid = profiling::ReadUint64(data, offset);
+
+ CreateEventClass(eventClass, m_Model);
+
+ if (!m_QuietOperation)
+ {
+ printEventClasses();
+ }
+}
+
+void TimelineCaptureCommandHandler::ReadRelationship(const unsigned char* data, uint32_t offset)
+{
+ Relationship relationship;
+ relationship.m_RelationshipType = static_cast<RelationshipType>(profiling::ReadUint32(data, offset));
+ offset += uint32_t_size;
+
+ relationship.m_Guid = profiling::ReadUint64(data, offset);
+ offset += uint64_t_size;
+
+ relationship.m_HeadGuid = profiling::ReadUint64(data, offset);
+ offset += uint64_t_size;
+
+ relationship.m_TailGuid = profiling::ReadUint64(data, offset);
+
+ CreateRelationship(relationship, m_Model);
+
+ if (!m_QuietOperation)
+ {
+ printRelationships();
+ }
+}
+
+
+
+void TimelineCaptureCommandHandler::ReadEvent(const unsigned char* data, uint32_t offset)
+{
+ Event event;
+ event.m_TimeStamp = profiling::ReadUint64(data, offset);
+ offset += uint64_t_size;
+
+ event.m_ThreadId = new u_int8_t[threadId_size];
+ profiling::ReadBytes(data, offset, threadId_size, event.m_ThreadId);
+ offset += threadId_size;
+
+ event.m_Guid = profiling::ReadUint64(data, offset);
+
+ CreateEvent(event, m_Model);
+
+ if (!m_QuietOperation)
+ {
+ printEvents();
+ }
+}
+
+void TimelineCaptureCommandHandler::operator()(const profiling::Packet& packet)
+{
+ ParseData(packet);
+}
+
+void TimelineCaptureCommandHandler::printLabels()
+{
+ std::string header;
+
+ header.append(profiling::CentreAlignFormatting("guid", 12));
+ header.append(" | ");
+ header.append(profiling::CentreAlignFormatting("value", 30));
+ header.append("\n");
+
+ std::cout << "\n" << "\n";
+ std::cout << profiling::CentreAlignFormatting("LABELS", static_cast<int>(header.size()));
+ std::cout << "\n";
+ std::cout << std::string(header.size(), '=') << "\n";
+ std::cout << header;
+
+ for (uint32_t i = 0; i < m_Model->m_LabelCount; ++i)
+ {
+ std::string body;
+
+ body.append(profiling::CentreAlignFormatting(std::to_string(m_Model->m_Labels[i]->m_Guid), 12));
+ body.append(" | ");
+ body.append(profiling::CentreAlignFormatting(m_Model->m_Labels[i]->m_Name, 30));
+ body.append("\n");
+
+ std::cout << std::string(body.size(), '-') << "\n";
+ std::cout<< body;
+ }
+}
+
+void TimelineCaptureCommandHandler::printEntities()
+{
+ std::string header;
+ header.append(profiling::CentreAlignFormatting("guid", 12));
+ header.append("\n");
+
+ std::cout << "\n" << "\n";
+ std::cout << profiling::CentreAlignFormatting("ENTITIES", static_cast<int>(header.size()));
+ std::cout << "\n";
+ std::cout << std::string(header.size(), '=') << "\n";
+ std::cout << header;
+
+ for (uint32_t i = 0; i < m_Model->m_EntityCount; ++i)
+ {
+ std::string body;
+
+ body.append(profiling::CentreAlignFormatting(std::to_string(m_Model->m_Entities[i]->m_Guid), 12));
+ body.append("\n");
+
+ std::cout << std::string(body.size(), '-') << "\n";
+ std::cout<< body;
+ }
+}
+
+void TimelineCaptureCommandHandler::printEventClasses()
+{
+ std::string header;
+ header.append(profiling::CentreAlignFormatting("guid", 12));
+ header.append("\n");
+
+ std::cout << "\n" << "\n";
+ std::cout << profiling::CentreAlignFormatting("EVENT CLASSES", static_cast<int>(header.size()));
+ std::cout << "\n";
+ std::cout << std::string(header.size(), '=') << "\n";
+ std::cout << header;
+
+ for (uint32_t i = 0; i < m_Model->m_EventClassCount; ++i)
+ {
+ std::string body;
+
+ body.append(profiling::CentreAlignFormatting(std::to_string(m_Model->m_EventClasses[i]->m_Guid), 12));
+ body.append("\n");
+
+ std::cout << std::string(body.size(), '-') << "\n";
+ std::cout<< body;
+ }
+}
+
+void TimelineCaptureCommandHandler::printRelationships()
+{
+ std::string header;
+ header.append(profiling::CentreAlignFormatting("relationshipType", 20));
+ header.append(" | ");
+ header.append(profiling::CentreAlignFormatting("relationshipGuid", 20));
+ header.append(" | ");
+ header.append(profiling::CentreAlignFormatting("headGuid", 12));
+ header.append(" | ");
+ header.append(profiling::CentreAlignFormatting("tailGuid", 12));
+ header.append("\n");
+
+ std::cout << "\n" << "\n";
+ std::cout << profiling::CentreAlignFormatting("RELATIONSHIPS", static_cast<int>(header.size()));
+ std::cout << "\n";
+ std::cout << std::string(header.size(), '=') << "\n";
+ std::cout << header;
+
+ for (uint32_t i = 0; i < m_Model->m_RelationshipCount; ++i)
+ {
+ std::string body;
+
+ body.append(
+ profiling::CentreAlignFormatting(std::to_string(m_Model->m_Relationships[i]->m_RelationshipType), 20));
+ body.append(" | ");
+ body.append(profiling::CentreAlignFormatting(std::to_string(m_Model->m_Relationships[i]->m_Guid), 20));
+ body.append(" | ");
+ body.append(profiling::CentreAlignFormatting(std::to_string(m_Model->m_Relationships[i]->m_HeadGuid), 12));
+ body.append(" | ");
+ body.append(profiling::CentreAlignFormatting(std::to_string(m_Model->m_Relationships[i]->m_TailGuid), 12));
+ body.append(" | ");
+ body.append("\n");
+
+ std::cout << std::string(body.size(), '-') << "\n";
+ std::cout<< body;
+ }
+}
+
+void TimelineCaptureCommandHandler::printEvents()
+{
+ std::string header;
+
+ header.append(profiling::CentreAlignFormatting("timestamp", 12));
+ header.append(" | ");
+ header.append(profiling::CentreAlignFormatting("threadId", 12));
+ header.append(" | ");
+ header.append(profiling::CentreAlignFormatting("eventGuid", 12));
+ header.append("\n");
+
+ std::cout << "\n" << "\n";
+ std::cout << profiling::CentreAlignFormatting("EVENTS", static_cast<int>(header.size()));
+ std::cout << "\n";
+ std::cout << std::string(header.size(), '=') << "\n";
+ std::cout << header;
+
+ for (uint32_t i = 0; i < m_Model->m_EventCount; ++i)
+ {
+ std::string body;
+
+ body.append(profiling::CentreAlignFormatting(std::to_string(m_Model->m_Events[i]->m_TimeStamp), 12));
+ body.append(" | ");
+
+ std::string threadId;
+ for(uint32_t j =0; j< threadId_size; j++)
+ {
+ threadId += static_cast<char>(m_Model->m_Events[i]->m_ThreadId[j]);
+ }
+ body.append(profiling::CentreAlignFormatting(threadId, 12));
+ body.append(" | ");
+ body.append(profiling::CentreAlignFormatting(std::to_string(m_Model->m_Events[i]->m_Guid), 12));
+ body.append("\n");
+
+ std::cout << std::string(body.size(), '-') << "\n";
+ std::cout<< body;
+ }
+}
+
+} //namespace gatordmock
+
+} //namespace armnn
diff --git a/tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.hpp b/tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.hpp
new file mode 100644
index 0000000000..3f3240491f
--- /dev/null
+++ b/tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.hpp
@@ -0,0 +1,66 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "ITimelineDecoder.h"
+
+#include <CommandHandlerFunctor.hpp>
+#include <Packet.hpp>
+#include <ProfilingUtils.hpp>
+
+namespace armnn
+{
+
+namespace gatordmock
+{
+
+class TimelineCaptureCommandHandler : public profiling::CommandHandlerFunctor
+{
+ // Utils
+ uint32_t uint32_t_size = sizeof(uint32_t);
+ uint32_t uint64_t_size = sizeof(uint64_t);
+ uint32_t threadId_size = sizeof(std::thread::id);
+
+ using ReadFunction = void (TimelineCaptureCommandHandler::*)(const unsigned char*, uint32_t);
+
+public:
+ TimelineCaptureCommandHandler(uint32_t familyId,
+ uint32_t packetId,
+ uint32_t version,
+ Model* model,
+ bool quietOperation = false)
+ : CommandHandlerFunctor(familyId, packetId, version)
+ , m_Model(model)
+ , m_QuietOperation(quietOperation)
+ {}
+
+ void operator()(const armnn::profiling::Packet& packet) override;
+
+ void ReadLabel(const unsigned char* data, uint32_t offset);
+ void ReadEntity(const unsigned char* data, uint32_t offset);
+ void ReadEventClass(const unsigned char* data, uint32_t offset);
+ void ReadRelationship(const unsigned char* data, uint32_t offset);
+ void ReadEvent(const unsigned char* data, uint32_t offset);
+
+ void print();
+
+private:
+ void ParseData(const armnn::profiling::Packet& packet);
+
+ Model* m_Model;
+ bool m_QuietOperation;
+ static const ReadFunction m_ReadFunctions[];
+
+ void printLabels();
+ void printEntities();
+ void printEventClasses();
+ void printRelationships();
+ void printEvents();
+};
+
+} //namespace gatordmock
+
+} //namespace armnn
diff --git a/tests/profiling/timelineDecoder/TimelineDecoder.cpp b/tests/profiling/timelineDecoder/TimelineDecoder.cpp
new file mode 100644
index 0000000000..b6f051b745
--- /dev/null
+++ b/tests/profiling/timelineDecoder/TimelineDecoder.cpp
@@ -0,0 +1,166 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "ITimelineDecoder.h"
+
+ErrorCode CreateEntity(const Entity entity, Model* model)
+{
+ if (model == nullptr || model->m_EntityCb == nullptr)
+ {
+ return ErrorCode::ErrorCode_Fail;
+ }
+ model->m_EntityCb(entity, model);
+ return ErrorCode::ErrorCode_Success;
+}
+
+ErrorCode CreateEventClass(const EventClass eventClass, Model* model)
+{
+ if (model == nullptr || model->m_EventClassCb == nullptr)
+ {
+ return ErrorCode::ErrorCode_Fail;
+ }
+ model->m_EventClassCb(eventClass, model);
+ return ErrorCode::ErrorCode_Success;
+}
+
+ErrorCode CreateEvent(const Event event, Model* model)
+{
+ if (model == nullptr || model->m_EventCb == nullptr)
+ {
+ return ErrorCode::ErrorCode_Fail;
+ }
+ model->m_EventCb(event, model);
+ return ErrorCode::ErrorCode_Success;
+}
+
+ErrorCode CreateLabel(const Label label, Model* model)
+{
+ if (model == nullptr || model->m_LabelCb == nullptr)
+ {
+ return ErrorCode::ErrorCode_Fail;
+ }
+ model->m_LabelCb(label, model);
+ return ErrorCode::ErrorCode_Success;
+}
+
+ErrorCode CreateRelationship(Relationship relationship, Model* model)
+{
+ if (model == nullptr || model->m_RelationshipCb == nullptr)
+ {
+ return ErrorCode::ErrorCode_Fail;
+ }
+ model->m_RelationshipCb(relationship, model);
+ return ErrorCode::ErrorCode_Success;
+}
+
+ErrorCode SetEntityCallback(OnNewEntityCallback cb, Model* model)
+{
+ if (cb == nullptr || model == nullptr)
+ {
+ return ErrorCode::ErrorCode_Fail;
+ }
+ model->m_EntityCb = cb;
+ return ErrorCode::ErrorCode_Success;
+}
+
+ErrorCode SetEventClassCallback(OnNewEventClassCallback cb, Model* model)
+{
+ if (cb == nullptr || model == nullptr)
+ {
+ return ErrorCode::ErrorCode_Fail;
+ }
+ model->m_EventClassCb = cb;
+ return ErrorCode::ErrorCode_Success;
+}
+
+ErrorCode SetEventCallback(OnNewEventCallback cb, Model* model)
+{
+ if (cb == nullptr || model == nullptr)
+ {
+ return ErrorCode::ErrorCode_Fail;
+ }
+ model->m_EventCb = cb;
+ return ErrorCode::ErrorCode_Success;
+}
+
+ErrorCode SetLabelCallback(OnNewLabelCallback cb, Model* model)
+{
+ if (cb == nullptr || model == nullptr)
+ {
+ return ErrorCode::ErrorCode_Fail;
+ }
+ model->m_LabelCb = cb;
+ return ErrorCode::ErrorCode_Success;
+}
+
+ErrorCode SetRelationshipCallback(OnNewRelationshipCallback cb, Model* model)
+{
+ if (cb == nullptr || model == nullptr)
+ {
+ return ErrorCode::ErrorCode_Fail;
+ }
+ model->m_RelationshipCb = cb;
+ return ErrorCode::ErrorCode_Success;
+}
+
+ErrorCode CreateModel(Model** model)
+{
+ Model* modelPtr = new Model;
+
+ modelPtr->m_EntityCount = 0;
+ modelPtr->m_EventClassCount = 0;
+ modelPtr->m_EventCount = 0;
+ modelPtr->m_LabelCount = 0;
+ modelPtr->m_RelationshipCount = 0;
+
+ *model = modelPtr;
+ return ErrorCode::ErrorCode_Success;
+}
+
+ErrorCode DestroyModel(Model** model)
+{
+ if (*model == nullptr)
+ {
+ return ErrorCode::ErrorCode_Fail;
+ }
+
+ Model* modelPtr = *model;
+
+ for (uint32_t i = 0; i < modelPtr->m_EntityCount; ++i)
+ {
+ delete modelPtr->m_Entities[i];
+ }
+
+ for (uint32_t i = 0; i < modelPtr->m_EventClassCount; ++i)
+ {
+ delete modelPtr->m_EventClasses[i];
+ }
+
+ for (uint32_t i = 0; i < modelPtr->m_EventCount; ++i)
+ {
+ delete[] modelPtr->m_Events[i]->m_ThreadId;
+ delete modelPtr->m_Events[i];
+ }
+
+ for (uint32_t i = 0; i < modelPtr->m_LabelCount; ++i)
+ {
+ delete[] modelPtr->m_Labels[i]->m_Name;
+ delete modelPtr->m_Labels[i];
+ }
+
+ for (uint32_t i = 0; i < modelPtr->m_RelationshipCount; ++i)
+ {
+ delete modelPtr->m_Relationships[i];
+ }
+
+ delete[] modelPtr->m_Entities;
+ delete[] modelPtr->m_EventClasses;
+ delete[] modelPtr->m_Events;
+ delete[] modelPtr->m_Labels;
+ delete[] modelPtr->m_Relationships;
+
+ delete modelPtr;
+ return ErrorCode::ErrorCode_Success;
+} \ No newline at end of file
diff --git a/tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.cpp b/tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.cpp
new file mode 100644
index 0000000000..cb860a950b
--- /dev/null
+++ b/tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.cpp
@@ -0,0 +1,106 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "TimelineDirectoryCaptureCommandHandler.hpp"
+
+#include <iostream>
+#include <string>
+
+namespace armnn
+{
+
+namespace gatordmock
+{
+
+void TimelineDirectoryCaptureCommandHandler::ParseData(const armnn::profiling::Packet& packet)
+{
+ uint32_t offset = 0;
+
+ if (packet.GetLength() < 8)
+ {
+ return;
+ }
+
+ const unsigned char* data = packet.GetData();
+
+ uint32_t numberOfDeclarations = profiling::ReadUint32(data, offset);
+ offset += uint32_t_size;
+
+ for (uint32_t declaration = 0; declaration < numberOfDeclarations; ++declaration)
+ {
+ m_SwTraceMessages.push_back(profiling::ReadSwTraceMessage(data, offset));
+ }
+}
+
+void TimelineDirectoryCaptureCommandHandler::Print()
+{
+ std::string header;
+
+ header.append(profiling::CentreAlignFormatting("decl_id", 12));
+ header.append(" | ");
+ header.append(profiling::CentreAlignFormatting("decl_name", 20));
+ header.append(" | ");
+ header.append(profiling::CentreAlignFormatting("ui_name", 20));
+ header.append(" | ");
+ header.append(profiling::CentreAlignFormatting("arg_types", 16));
+ header.append(" | ");
+ header.append(profiling::CentreAlignFormatting("arg_names", 80));
+ header.append("\n");
+
+ std::cout << "\n" << "\n";
+ std::cout << profiling::CentreAlignFormatting("SW DIRECTORY", static_cast<int>(header.size()));
+ std::cout << "\n";
+ std::cout << std::string(header.size(), '=') << "\n";
+
+ std::cout<< header;
+
+ for (auto swTraceMessage : m_SwTraceMessages)
+ {
+ std::string body;
+
+ body.append(profiling::CentreAlignFormatting(std::to_string(swTraceMessage.id), 12));
+ body.append(" | ");
+ body.append(profiling::CentreAlignFormatting(swTraceMessage.name, 20));
+ body.append(" | ");
+ body.append(profiling::CentreAlignFormatting(swTraceMessage.uiName, 20));
+ body.append(" | ");
+
+ std::string argTypes;
+ for(auto argType: swTraceMessage.argTypes)
+ {
+ argTypes += argType;
+ argTypes += " ";
+ }
+ body.append(profiling::CentreAlignFormatting(argTypes, 16));
+ body.append(" | ");
+
+ std::string argNames;
+ for(auto argName: swTraceMessage.argNames)
+ {
+ argNames += argName + " ";
+ }
+ body.append(profiling::CentreAlignFormatting(argNames, 80));
+
+ body.append("\n");
+
+ std::cout << std::string(body.size(), '-') << "\n";
+
+ std::cout<< body;
+ }
+}
+
+void TimelineDirectoryCaptureCommandHandler::operator()(const profiling::Packet& packet)
+{
+ ParseData(packet);
+
+ if(!m_QuietOperation)
+ {
+ Print();
+ }
+}
+
+} //namespace gatordmock
+
+} //namespace armnn \ No newline at end of file
diff --git a/tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.hpp b/tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.hpp
new file mode 100644
index 0000000000..3a575d7fef
--- /dev/null
+++ b/tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.hpp
@@ -0,0 +1,47 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+
+#include <CommandHandlerFunctor.hpp>
+#include <Packet.hpp>
+#include <PacketBuffer.hpp>
+#include <ProfilingUtils.hpp>
+
+namespace armnn
+{
+
+namespace gatordmock
+{
+
+class TimelineDirectoryCaptureCommandHandler : public profiling::CommandHandlerFunctor
+{
+ // Utils
+ uint32_t uint32_t_size = sizeof(uint32_t);
+
+public:
+ TimelineDirectoryCaptureCommandHandler(uint32_t familyId,
+ uint32_t packetId,
+ uint32_t version,
+ bool quietOperation = false)
+ : CommandHandlerFunctor(familyId, packetId, version)
+ , m_QuietOperation(quietOperation)
+ {}
+
+ void operator()(const armnn::profiling::Packet& packet) override;
+
+ std::vector<profiling::SwTraceMessage> m_SwTraceMessages;
+
+private:
+ void ParseData(const armnn::profiling::Packet& packet);
+ void Print();
+
+ bool m_QuietOperation;
+};
+
+} //namespace gatordmock
+
+} //namespace armnn \ No newline at end of file
diff --git a/tests/profiling/timelineDecoder/TimelineModel.h b/tests/profiling/timelineDecoder/TimelineModel.h
new file mode 100644
index 0000000000..a4fbd0dbde
--- /dev/null
+++ b/tests/profiling/timelineDecoder/TimelineModel.h
@@ -0,0 +1,96 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#ifndef ARMNN_ITIMELINEMODEL_H
+#define ARMNN_ITIMELINEMODEL_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+struct Model;
+
+typedef enum RelationshipType
+{
+ 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).
+} RelationshipType;
+
+typedef struct Entity
+{
+ uint64_t m_Guid;
+} Entity;
+
+typedef struct EventClass
+{
+ uint64_t m_Guid;
+} EventClass;
+
+typedef struct Event
+{
+ uint64_t m_Guid;
+ uint64_t m_TimeStamp;
+ unsigned char* m_ThreadId;
+} ProfilingEvent;
+
+typedef struct Label
+{
+ uint64_t m_Guid;
+ char* m_Name;
+} Label;
+
+typedef struct Relationship
+{
+ RelationshipType m_RelationshipType;
+ uint64_t m_Guid;
+ uint64_t m_HeadGuid;
+ uint64_t m_TailGuid;
+} Relationship;
+
+typedef void (*OnNewEntityCallback)(const Entity, struct Model* model);
+typedef void (*OnNewEventClassCallback)(const EventClass, struct Model* model);
+typedef void (*OnNewEventCallback)(const Event, struct Model* model);
+typedef void (*OnNewLabelCallback)(const Label, struct Model* model);
+typedef void (*OnNewRelationshipCallback)(const Relationship, struct Model* model) ;
+
+typedef struct Model
+{
+ OnNewEntityCallback m_EntityCb;
+ OnNewEventClassCallback m_EventClassCb;
+ OnNewEventCallback m_EventCb;
+ OnNewLabelCallback m_LabelCb;
+ OnNewRelationshipCallback m_RelationshipCb;
+
+ Entity** m_Entities;
+ EventClass** m_EventClasses;
+ Event** m_Events;
+ Label** m_Labels;
+ Relationship** m_Relationships;
+
+ uint32_t m_EntityCount;
+ uint32_t m_EntityCapacity;
+
+ uint32_t m_EventClassCount;
+ uint32_t m_EventClassCapacity;
+
+ uint32_t m_EventCount;
+ uint32_t m_EventCapacity;
+
+ uint32_t m_LabelCount;
+ uint32_t m_LabelCapacity;
+
+ uint32_t m_RelationshipCount;
+ uint32_t m_RelationshipCapacity;
+} Model;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //ARMNN_ITIMELINEMODEL_H \ No newline at end of file
diff --git a/tests/profiling/timelineDecoder/tests/TimelineTestFunctions.hpp b/tests/profiling/timelineDecoder/tests/TimelineTestFunctions.hpp
new file mode 100644
index 0000000000..3fd9d04dbc
--- /dev/null
+++ b/tests/profiling/timelineDecoder/tests/TimelineTestFunctions.hpp
@@ -0,0 +1,143 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include <algorithm>
+#include "../TimelineModel.h"
+
+void PushEntity(const Entity entity, Model* model)
+{
+ if(model->m_EntityCount == 0)
+ {
+ model->m_EntityCapacity = 1;
+ model->m_Entities = new Entity*[model->m_EntityCapacity];
+ }
+ else if(model->m_EntityCount >= model->m_EntityCapacity)
+ {
+ Entity** newEntityArray = new Entity*[model->m_EntityCapacity*2];
+
+ std::copy(model->m_Entities, model->m_Entities + model->m_EntityCapacity, newEntityArray);
+ delete[] model->m_Entities;
+ model->m_Entities = newEntityArray;
+
+ model->m_EntityCapacity = model->m_EntityCapacity *2;
+ }
+
+ Entity* newEntity = new Entity;
+
+ newEntity->m_Guid = entity.m_Guid;
+
+ model->m_Entities[model->m_EntityCount] = newEntity;
+ model->m_EntityCount++;
+};
+
+void PushEventClass(const EventClass eventClass, Model* model)
+{
+ if(model->m_EventClassCount == 0)
+ {
+ model->m_EventClassCapacity = 1;
+ model->m_EventClasses = new EventClass*[model->m_EventClassCapacity];
+ }
+ else if(model->m_EventClassCount >= model->m_EventClassCapacity)
+ {
+ EventClass** newEventClassArray = new EventClass*[model->m_EventClassCapacity *2];
+
+ std::copy(model->m_EventClasses, model->m_EventClasses + model->m_EventClassCapacity, newEventClassArray);
+ delete[] model->m_EventClasses;
+ model->m_EventClasses = newEventClassArray;
+
+ model->m_EventClassCapacity = model->m_EventClassCapacity *2;
+ }
+
+ EventClass* newEventClass = new EventClass;
+
+ newEventClass->m_Guid = eventClass.m_Guid;
+
+ model->m_EventClasses[model->m_EventClassCount] = newEventClass;
+ model->m_EventClassCount++;
+};
+
+void PushEvent(const Event event, Model* model)
+{
+ if(model->m_EventCount == 0)
+ {
+ model->m_EventCapacity = 1;
+ model->m_Events = new Event*[model->m_EventCapacity];
+ }
+ else if(model->m_EventCount >= model->m_EventCapacity)
+ {
+ Event** newEventArray = new Event*[model->m_EventCapacity * 2];
+
+ std::copy(model->m_Events, model->m_Events + model->m_EventCapacity, newEventArray);
+ delete[] model->m_Events;
+ model->m_Events = newEventArray;
+
+ model->m_EventCapacity = model->m_EventCapacity *2;
+ }
+
+ Event* newEvent = new Event;
+
+ newEvent->m_TimeStamp = event.m_TimeStamp;
+ newEvent->m_ThreadId = event.m_ThreadId;
+ newEvent->m_Guid = event.m_Guid;
+
+ model->m_Events[model->m_EventCount] = newEvent;
+ model->m_EventCount++;
+};
+
+void PushLabel(const Label label, Model* model)
+{
+ if(model->m_LabelCount == 0)
+ {
+ model->m_LabelCapacity = 1;
+ model->m_Labels = new Label*[model->m_LabelCapacity];
+ }
+ else if(model->m_LabelCount >= model->m_LabelCapacity)
+ {
+ Label** newLabelArray = new Label*[model->m_LabelCapacity *2];
+
+ std::copy(model->m_Labels, model->m_Labels + model->m_LabelCapacity, newLabelArray);
+ delete[] model->m_Labels;
+ model->m_Labels = newLabelArray;
+
+ model->m_LabelCapacity = model->m_LabelCapacity *2;
+ }
+
+ Label* newLabel = new Label;
+
+ newLabel->m_Guid = label.m_Guid;
+ newLabel->m_Name = label.m_Name;
+
+ model->m_Labels[model->m_LabelCount] = newLabel;
+ model->m_LabelCount++;
+};
+
+void PushRelationship(const Relationship relationship, Model* model)
+{
+ if(model->m_RelationshipCount == 0)
+ {
+ model->m_RelationshipCapacity = 1;
+ model->m_Relationships = new Relationship*[model->m_RelationshipCapacity];
+ }
+ else if(model->m_RelationshipCount >= model->m_RelationshipCapacity)
+ {
+ Relationship** newRelationshipArray = new Relationship*[model->m_RelationshipCapacity *2];
+
+ std::copy(model->m_Relationships, model->m_Relationships + model->m_RelationshipCapacity, newRelationshipArray);
+ delete[] model->m_Relationships;
+ model->m_Relationships = newRelationshipArray;
+
+ model->m_RelationshipCapacity = model->m_RelationshipCapacity *2;
+ }
+
+ Relationship* newRelationship = new Relationship;
+
+ newRelationship->m_Guid = relationship.m_Guid;
+ newRelationship->m_RelationshipType = relationship.m_RelationshipType;
+ newRelationship->m_HeadGuid = relationship.m_HeadGuid;
+ newRelationship->m_TailGuid = relationship.m_TailGuid;
+
+ model->m_Relationships[model->m_RelationshipCount] = newRelationship;
+ model->m_RelationshipCount++;
+};
diff --git a/tests/profiling/timelineDecoder/tests/TimelineTests.cpp b/tests/profiling/timelineDecoder/tests/TimelineTests.cpp
new file mode 100644
index 0000000000..a9c352b5fa
--- /dev/null
+++ b/tests/profiling/timelineDecoder/tests/TimelineTests.cpp
@@ -0,0 +1,206 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "../TimelineCaptureCommandHandler.hpp"
+#include "../TimelineDirectoryCaptureCommandHandler.hpp"
+#include "../ITimelineDecoder.h"
+#include "../TimelineModel.h"
+#include "TimelineTestFunctions.hpp"
+
+#include <CommandHandlerFunctor.hpp>
+#include <ProfilingService.hpp>
+#include <PacketBuffer.hpp>
+#include <TimelinePacketWriterFactory.hpp>
+
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test_suite.hpp>
+
+BOOST_AUTO_TEST_SUITE(TimelineDecoderTests)
+
+using namespace armnn;
+
+void SendTimelinePacketToCommandHandler(const unsigned char* packetBuffer,
+ profiling::CommandHandlerFunctor &CommandHandler)
+{
+ uint32_t uint32_t_size = sizeof(uint32_t);
+ unsigned int offset = 0;
+
+ uint32_t header[2];
+ header[0] = profiling::ReadUint32(packetBuffer, offset);
+ offset += uint32_t_size;
+ header[1] = profiling::ReadUint32(packetBuffer, offset);
+ offset += uint32_t_size;
+
+ uint32_t PacketDataLength = header[1] & 0x00FFFFFF;
+
+ std::unique_ptr<unsigned char[]> uniquePacketData = std::make_unique<unsigned char[]>(PacketDataLength);
+
+ std::memcpy(uniquePacketData.get(), packetBuffer + offset, PacketDataLength);
+
+ armnn::profiling::Packet packet = armnn::profiling::Packet(header[0], PacketDataLength, uniquePacketData);
+
+ CommandHandler(packet);
+}
+
+BOOST_AUTO_TEST_CASE(TimelineDirecotryTest)
+{
+ uint32_t uint32_t_size = sizeof(uint32_t);
+
+ profiling::BufferManager bufferManager(5);
+ profiling::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager);
+
+ std::unique_ptr<profiling::ISendTimelinePacket> sendTimelinePacket =
+ timelinePacketWriterFactory.GetSendTimelinePacket();
+
+ profiling::PacketVersionResolver packetVersionResolver;
+
+ gatordmock::TimelineDirectoryCaptureCommandHandler timelineDirectoryCaptureCommandHandler(
+ 1, 0, packetVersionResolver.ResolvePacketVersion(1, 0).GetEncodedValue(), true);
+
+ sendTimelinePacket->SendTimelineMessageDirectoryPackage();
+ sendTimelinePacket->Commit();
+
+ std::vector<profiling::SwTraceMessage> swTraceBufferMessages;
+
+ unsigned int offset = uint32_t_size * 2;
+
+ std::unique_ptr<profiling::IPacketBuffer> packetBuffer = bufferManager.GetReadableBuffer();
+
+ uint32_t declarationSize = profiling::ReadUint32(packetBuffer, offset);
+ offset += uint32_t_size;
+ for(uint32_t i = 0; i < declarationSize; ++i)
+ {
+ swTraceBufferMessages.push_back(profiling::ReadSwTraceMessage(packetBuffer->GetReadableData(), offset));
+ }
+
+ SendTimelinePacketToCommandHandler(packetBuffer->GetReadableData(), timelineDirectoryCaptureCommandHandler);
+
+ for(uint32_t index = 0; index < declarationSize; ++index)
+ {
+ profiling::SwTraceMessage& bufferMessage = swTraceBufferMessages[index];
+ profiling::SwTraceMessage& handlerMessage = timelineDirectoryCaptureCommandHandler.m_SwTraceMessages[index];
+
+ BOOST_CHECK(bufferMessage.name == handlerMessage.name);
+ BOOST_CHECK(bufferMessage.uiName == handlerMessage.uiName);
+ BOOST_CHECK(bufferMessage.id == handlerMessage.id);
+
+ BOOST_CHECK(bufferMessage.argTypes.size() == handlerMessage.argTypes.size());
+ for(uint32_t i = 0; i < bufferMessage.argTypes.size(); ++i)
+ {
+ BOOST_CHECK(bufferMessage.argTypes[i] == handlerMessage.argTypes[i]);
+ }
+
+ BOOST_CHECK(bufferMessage.argNames.size() == handlerMessage.argNames.size());
+ for(uint32_t i = 0; i < bufferMessage.argNames.size(); ++i)
+ {
+ BOOST_CHECK(bufferMessage.argNames[i] == handlerMessage.argNames[i]);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(TimelineCaptureTest)
+{
+ uint32_t threadId_size = sizeof(std::thread::id);
+
+ profiling::BufferManager bufferManager(50);
+ profiling::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager);
+
+ std::unique_ptr<profiling::ISendTimelinePacket> sendTimelinePacket =
+ timelinePacketWriterFactory.GetSendTimelinePacket();
+
+ profiling::PacketVersionResolver packetVersionResolver;
+
+ Model* modelPtr;
+ CreateModel(&modelPtr);
+
+ gatordmock::TimelineCaptureCommandHandler timelineCaptureCommandHandler(
+ 1, 1, packetVersionResolver.ResolvePacketVersion(1, 1).GetEncodedValue(), modelPtr, true);
+
+ BOOST_CHECK(SetEntityCallback(PushEntity, modelPtr) == ErrorCode_Success);
+ BOOST_CHECK(SetEventClassCallback(PushEventClass, modelPtr) == ErrorCode_Success);
+ BOOST_CHECK(SetEventCallback(PushEvent, modelPtr) == ErrorCode_Success);
+ BOOST_CHECK(SetLabelCallback(PushLabel, modelPtr) == ErrorCode_Success);
+ BOOST_CHECK(SetRelationshipCallback(PushRelationship, modelPtr) == ErrorCode_Success);
+
+ const uint64_t entityGuid = 22222u;
+
+ const uint64_t eventClassGuid = 33333u;
+
+ const uint64_t timestamp = 111111u;
+ const uint64_t eventGuid = 55555u;
+
+ const std::thread::id threadId = std::this_thread::get_id();;
+
+ const uint64_t labelGuid = 11111u;
+ std::string labelName = "test_label";
+
+ const uint64_t relationshipGuid = 44444u;
+ const uint64_t headGuid = 111111u;
+ const uint64_t tailGuid = 222222u;
+
+ for (int i = 0; i < 10; ++i)
+ {
+ // Send entity
+ sendTimelinePacket->SendTimelineEntityBinaryPacket(entityGuid);
+ sendTimelinePacket->Commit();
+ SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(),
+ timelineCaptureCommandHandler);
+
+ // Send event class
+ sendTimelinePacket->SendTimelineEventClassBinaryPacket(eventClassGuid);
+ sendTimelinePacket->Commit();
+ SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(),
+ timelineCaptureCommandHandler);
+
+ // Send event
+ sendTimelinePacket->SendTimelineEventBinaryPacket(timestamp, threadId, eventGuid);
+ sendTimelinePacket->Commit();
+ SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(),
+ timelineCaptureCommandHandler);
+
+ // Send label
+ sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName);
+ sendTimelinePacket->Commit();
+ SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(),
+ timelineCaptureCommandHandler);
+
+ // Send relationship
+ profiling::ProfilingRelationshipType relationshipType = profiling::ProfilingRelationshipType::DataLink;
+ sendTimelinePacket->SendTimelineRelationshipBinaryPacket(relationshipType,
+ relationshipGuid,
+ headGuid,
+ tailGuid);
+ sendTimelinePacket->Commit();
+ SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(),
+ timelineCaptureCommandHandler);
+ }
+
+ for (int i = 0; i < 10; ++i)
+ {
+ BOOST_CHECK(modelPtr->m_Entities[i]->m_Guid == entityGuid);
+
+ BOOST_CHECK(modelPtr->m_EventClasses[i]->m_Guid == eventClassGuid);
+
+ BOOST_CHECK(modelPtr->m_Events[i]->m_TimeStamp == timestamp);
+
+ std::vector<uint8_t> readThreadId(threadId_size, 0);
+ profiling::ReadBytes(modelPtr->m_Events[i]->m_ThreadId, 0, threadId_size, readThreadId.data());
+ BOOST_CHECK(readThreadId == threadId);
+
+ BOOST_CHECK(modelPtr->m_Events[i]->m_Guid == eventGuid);
+
+ BOOST_CHECK(modelPtr->m_Labels[i]->m_Guid == labelGuid);
+ BOOST_CHECK(std::string(modelPtr->m_Labels[i]->m_Name) == labelName);
+
+ BOOST_CHECK(modelPtr->m_Relationships[i]->m_RelationshipType == RelationshipType::DataLink);
+ BOOST_CHECK(modelPtr->m_Relationships[i]->m_Guid == relationshipGuid);
+ BOOST_CHECK(modelPtr->m_Relationships[i]->m_HeadGuid == headGuid);
+ BOOST_CHECK(modelPtr->m_Relationships[i]->m_TailGuid == tailGuid);
+ }
+
+ DestroyModel(&modelPtr);
+}
+
+BOOST_AUTO_TEST_SUITE_END()