diff options
Diffstat (limited to 'src/timelineDecoder')
-rw-r--r-- | src/timelineDecoder/CMakeLists.txt | 21 | ||||
-rw-r--r-- | src/timelineDecoder/TimelineCaptureCommandHandler.cpp | 124 | ||||
-rw-r--r-- | src/timelineDecoder/TimelineCaptureCommandHandler.hpp | 57 | ||||
-rw-r--r-- | src/timelineDecoder/TimelineDecoder.cpp | 287 | ||||
-rw-r--r-- | src/timelineDecoder/TimelineDecoder.hpp | 68 | ||||
-rw-r--r-- | src/timelineDecoder/TimelineDirectoryCaptureCommandHandler.cpp | 115 | ||||
-rw-r--r-- | src/timelineDecoder/TimelineDirectoryCaptureCommandHandler.hpp | 48 | ||||
-rw-r--r-- | src/timelineDecoder/tests/TimelineTests.cpp | 253 |
8 files changed, 973 insertions, 0 deletions
diff --git a/src/timelineDecoder/CMakeLists.txt b/src/timelineDecoder/CMakeLists.txt new file mode 100644 index 0000000000..6b8517acbc --- /dev/null +++ b/src/timelineDecoder/CMakeLists.txt @@ -0,0 +1,21 @@ +# +# Copyright © 2020 Arm Ltd. All rights reserved. +# SPDX-License-Identifier: MIT +# + +set(timelineDecoder_sources) +list(APPEND timelineDecoder_sources + ../../include/armnn/profiling/ITimelineDecoder.hpp + TimelineCaptureCommandHandler.cpp + TimelineCaptureCommandHandler.hpp + TimelineDecoder.cpp + TimelineDecoder.hpp + TimelineDirectoryCaptureCommandHandler.cpp + TimelineDirectoryCaptureCommandHandler.hpp + ) + +include_directories(../timelineDecoder ../profiling) + +add_library_ex(timelineDecoder SHARED ${timelineDecoder_sources}) + +set_target_properties(timelineDecoder PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} )
\ No newline at end of file diff --git a/src/timelineDecoder/TimelineCaptureCommandHandler.cpp b/src/timelineDecoder/TimelineCaptureCommandHandler.cpp new file mode 100644 index 0000000000..01f55bd6d9 --- /dev/null +++ b/src/timelineDecoder/TimelineCaptureCommandHandler.cpp @@ -0,0 +1,124 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "TimelineCaptureCommandHandler.hpp" + +#include <string> + +namespace armnn +{ + +namespace timelinedecoder +{ + +//Array of member functions, the array index matches the decl_id +const TimelineCaptureCommandHandler::ReadFunction TimelineCaptureCommandHandler::m_ReadFunctions[] +{ + &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) +{ + ITimelineDecoder::Label label; + label.m_Guid = profiling::ReadUint64(data, offset); + offset += uint64_t_size; + + uint32_t nameLength = profiling::ReadUint32(data, offset); + offset += uint32_t_size; + + for (uint32_t i = 0; i < nameLength-1; ++i) + { + label.m_Name += static_cast<char>(profiling::ReadUint8(data, offset + i)); + } + m_TimelineDecoder.CreateLabel(label); +} + +void TimelineCaptureCommandHandler::ReadEntity(const unsigned char* data, uint32_t offset) +{ + ITimelineDecoder::Entity entity; + entity.m_Guid = profiling::ReadUint64(data, offset); + + m_TimelineDecoder.CreateEntity(entity); +} + +void TimelineCaptureCommandHandler::ReadEventClass(const unsigned char* data, uint32_t offset) +{ + ITimelineDecoder::EventClass eventClass; + eventClass.m_Guid = profiling::ReadUint64(data, offset); + + m_TimelineDecoder.CreateEventClass(eventClass); +} + +void TimelineCaptureCommandHandler::ReadRelationship(const unsigned char* data, uint32_t offset) +{ + ITimelineDecoder::Relationship relationship; + relationship.m_RelationshipType = + static_cast<ITimelineDecoder::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); + + m_TimelineDecoder.CreateRelationship(relationship); +} + +void TimelineCaptureCommandHandler::ReadEvent(const unsigned char* data, uint32_t offset) +{ + ITimelineDecoder::Event event; + event.m_TimeStamp = profiling::ReadUint64(data, offset); + offset += uint64_t_size; + + if (m_ThreadIdSize == 4) + { + event.m_ThreadId = profiling::ReadUint32(data, offset); + } + else if (m_ThreadIdSize == 8) + { + event.m_ThreadId = profiling::ReadUint64(data, offset); + } + + offset += m_ThreadIdSize; + + event.m_Guid = profiling::ReadUint64(data, offset); + + m_TimelineDecoder.CreateEvent(event); +} + +void TimelineCaptureCommandHandler::operator()(const profiling::Packet& packet) +{ + ParseData(packet); +} + +} //namespace gatordmock + +} //namespace armnn diff --git a/src/timelineDecoder/TimelineCaptureCommandHandler.hpp b/src/timelineDecoder/TimelineCaptureCommandHandler.hpp new file mode 100644 index 0000000000..d95adc0321 --- /dev/null +++ b/src/timelineDecoder/TimelineCaptureCommandHandler.hpp @@ -0,0 +1,57 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include <CommandHandlerFunctor.hpp> +#include "armnn/profiling/ITimelineDecoder.hpp" + +#include <Packet.hpp> +#include <ProfilingUtils.hpp> + +namespace armnn +{ + +namespace timelinedecoder +{ + +class TimelineCaptureCommandHandler : public profiling::CommandHandlerFunctor +{ + // Utils + uint32_t uint32_t_size = sizeof(uint32_t); + uint32_t uint64_t_size = sizeof(uint64_t); + + using ReadFunction = void (TimelineCaptureCommandHandler::*)(const unsigned char*, uint32_t); + +public: + TimelineCaptureCommandHandler(uint32_t familyId, + uint32_t packetId, + uint32_t version, + ITimelineDecoder& timelineDecoder, + uint32_t threadId_size) + : CommandHandlerFunctor(familyId, packetId, version) + , m_TimelineDecoder(timelineDecoder) + , m_ThreadIdSize(threadId_size) + {} + + 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); + +private: + void ParseData(const armnn::profiling::Packet& packet); + + ITimelineDecoder& m_TimelineDecoder; + const uint32_t m_ThreadIdSize; + static const ReadFunction m_ReadFunctions[]; +}; + +} //namespace gatordmock + +} //namespace armnn diff --git a/src/timelineDecoder/TimelineDecoder.cpp b/src/timelineDecoder/TimelineDecoder.cpp new file mode 100644 index 0000000000..fcf40b4522 --- /dev/null +++ b/src/timelineDecoder/TimelineDecoder.cpp @@ -0,0 +1,287 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "TimelineDecoder.hpp" +#include "../profiling/ProfilingUtils.hpp" + +#include <iostream> +namespace armnn +{ +namespace timelinedecoder +{ +TimelineDecoder::ErrorCode TimelineDecoder::CreateEntity(const Entity &entity) +{ + if (m_OnNewEntityCallback == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + m_OnNewEntityCallback(m_Model, entity); + + return ErrorCode::ErrorCode_Success; +} + +TimelineDecoder::ErrorCode TimelineDecoder::CreateEventClass(const EventClass &eventClass) +{ + if (m_OnNewEventClassCallback == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + m_OnNewEventClassCallback(m_Model, eventClass); + + return ErrorCode::ErrorCode_Success; +} + +TimelineDecoder::ErrorCode TimelineDecoder::CreateEvent(const Event &event) +{ + if (m_OnNewEventCallback == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + m_OnNewEventCallback(m_Model, event); + + return ErrorCode::ErrorCode_Success; +} + +TimelineDecoder::ErrorCode TimelineDecoder::CreateLabel(const Label &label) +{ + if (m_OnNewLabelCallback == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + m_OnNewLabelCallback(m_Model, label); + + return ErrorCode::ErrorCode_Success; +} + +TimelineDecoder::ErrorCode TimelineDecoder::CreateRelationship(const Relationship &relationship) +{ + if (m_OnNewRelationshipCallback == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + m_OnNewRelationshipCallback(m_Model, relationship); + return ErrorCode::ErrorCode_Success; +} + +const TimelineDecoder::Model &TimelineDecoder::GetModel() +{ + return m_Model; +} + +TimelineDecoder::ErrorCode TimelineDecoder::SetEntityCallback(OnNewEntityCallback cb) +{ + if (cb == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + m_OnNewEntityCallback = cb; + return ErrorCode::ErrorCode_Success; +} + +TimelineDecoder::ErrorCode TimelineDecoder::SetEventClassCallback(OnNewEventClassCallback cb) +{ + if (cb == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + m_OnNewEventClassCallback = cb; + return ErrorCode::ErrorCode_Success; +} + +TimelineDecoder::ErrorCode TimelineDecoder::SetEventCallback(OnNewEventCallback cb) +{ + if (cb == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + m_OnNewEventCallback = cb; + return ErrorCode::ErrorCode_Success; +} + +TimelineDecoder::ErrorCode TimelineDecoder::SetLabelCallback(OnNewLabelCallback cb) +{ + if (cb == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + m_OnNewLabelCallback = cb; + return ErrorCode::ErrorCode_Success; +} + +TimelineDecoder::ErrorCode TimelineDecoder::SetRelationshipCallback(OnNewRelationshipCallback cb) +{ + if (cb == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + m_OnNewRelationshipCallback = cb; + return ErrorCode::ErrorCode_Success; +} + +void TimelineDecoder::print() +{ + printLabels(); + printEntities(); + printEventClasses(); + printEvents(); + printRelationships(); +} + +void TimelineDecoder::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_Labels.size(); ++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 TimelineDecoder::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_Entities.size(); ++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 TimelineDecoder::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_EventClasses.size(); ++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 TimelineDecoder::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_Events.size(); ++i) + { + std::string body; + + body.append(profiling::CentreAlignFormatting(std::to_string(m_Model.m_Events[i].m_TimeStamp), 12)); + body.append(" | "); + + std::stringstream ss; + ss << m_Model.m_Events[i].m_ThreadId; + std::string threadId = ss.str();; + + 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; + } +} + +void TimelineDecoder::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_Relationships.size(); ++i) + { + std::string body; + + body.append( + profiling::CentreAlignFormatting(std::to_string(static_cast<unsigned int> + (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; + } +} +} +}
\ No newline at end of file diff --git a/src/timelineDecoder/TimelineDecoder.hpp b/src/timelineDecoder/TimelineDecoder.hpp new file mode 100644 index 0000000000..fc14603927 --- /dev/null +++ b/src/timelineDecoder/TimelineDecoder.hpp @@ -0,0 +1,68 @@ +// +// Copyright © 2020 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// +#pragma once + +#include "armnn/profiling/ITimelineDecoder.hpp" +#include <vector> + +namespace armnn +{ +namespace timelinedecoder +{ +class TimelineDecoder : public ITimelineDecoder +{ + +public: + + struct Model + { + std::vector<Entity> m_Entities; + std::vector<EventClass> m_EventClasses; + std::vector<Event> m_Events; + std::vector<Label> m_Labels; + std::vector<Relationship> m_Relationships; + }; + + using OnNewEntityCallback = void (*)(Model &, const Entity); + using OnNewEventClassCallback = void (*)(Model &, const EventClass); + using OnNewEventCallback = void (*)(Model &, const Event); + using OnNewLabelCallback = void (*)(Model &, const Label); + using OnNewRelationshipCallback = void (*)(Model &, const Relationship); + + virtual ErrorCode CreateEntity(const Entity &) override; + virtual ErrorCode CreateEventClass(const EventClass &) override; + virtual ErrorCode CreateEvent(const Event &) override; + virtual ErrorCode CreateLabel(const Label &) override; + virtual ErrorCode CreateRelationship(const Relationship &) override; + + const Model& GetModel(); + + + ErrorCode SetEntityCallback(const OnNewEntityCallback); + ErrorCode SetEventClassCallback(const OnNewEventClassCallback); + ErrorCode SetEventCallback(const OnNewEventCallback); + ErrorCode SetLabelCallback(const OnNewLabelCallback); + ErrorCode SetRelationshipCallback(const OnNewRelationshipCallback); + + void print(); + +private: + Model m_Model; + + OnNewEntityCallback m_OnNewEntityCallback; + OnNewEventClassCallback m_OnNewEventClassCallback; + OnNewEventCallback m_OnNewEventCallback; + OnNewLabelCallback m_OnNewLabelCallback; + OnNewRelationshipCallback m_OnNewRelationshipCallback; + + void printLabels(); + void printEntities(); + void printEventClasses(); + void printRelationships(); + void printEvents(); +}; + +} +}
\ No newline at end of file diff --git a/src/timelineDecoder/TimelineDirectoryCaptureCommandHandler.cpp b/src/timelineDecoder/TimelineDirectoryCaptureCommandHandler.cpp new file mode 100644 index 0000000000..655e461b8c --- /dev/null +++ b/src/timelineDecoder/TimelineDirectoryCaptureCommandHandler.cpp @@ -0,0 +1,115 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "TimelineDirectoryCaptureCommandHandler.hpp" + +#include <iostream> +#include <string> + +using namespace armnn::profiling; + +namespace armnn +{ + +namespace timelinedecoder +{ + +void TimelineDirectoryCaptureCommandHandler::ParseData(const armnn::profiling::Packet& packet) +{ + uint32_t offset = 0; + + if (packet.GetLength() < 8) + { + return; + } + + const unsigned char* data = packet.GetData(); + + m_SwTraceHeader.m_StreamVersion = ReadUint8(data, offset); + offset += uint8_t_size; + m_SwTraceHeader.m_PointerBytes = ReadUint8(data, offset); + offset += uint8_t_size; + m_SwTraceHeader.m_ThreadIdBytes = ReadUint8(data, offset); + offset += uint8_t_size; + + 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 (const auto& swTraceMessage : m_SwTraceMessages) + { + std::string body; + + body.append(profiling::CentreAlignFormatting(std::to_string(swTraceMessage.m_Id), 12)); + body.append(" | "); + body.append(profiling::CentreAlignFormatting(swTraceMessage.m_Name, 20)); + body.append(" | "); + body.append(profiling::CentreAlignFormatting(swTraceMessage.m_UiName, 20)); + body.append(" | "); + + std::string argTypes; + for (auto argType: swTraceMessage.m_ArgTypes) + { + argTypes += argType; + argTypes += " "; + } + body.append(profiling::CentreAlignFormatting(argTypes, 16)); + body.append(" | "); + + std::string argNames; + for (auto argName: swTraceMessage.m_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 diff --git a/src/timelineDecoder/TimelineDirectoryCaptureCommandHandler.hpp b/src/timelineDecoder/TimelineDirectoryCaptureCommandHandler.hpp new file mode 100644 index 0000000000..b4e0fd2d7d --- /dev/null +++ b/src/timelineDecoder/TimelineDirectoryCaptureCommandHandler.hpp @@ -0,0 +1,48 @@ +// +// 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 timelinedecoder +{ + +class TimelineDirectoryCaptureCommandHandler : public profiling::CommandHandlerFunctor +{ + // Utils + uint32_t uint8_t_size = sizeof(uint8_t); + 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; + + profiling::SwTraceHeader m_SwTraceHeader; + std::vector<profiling::SwTraceMessage> m_SwTraceMessages; + +private: + void ParseData(const armnn::profiling::Packet& packet); + void Print(); + + bool m_QuietOperation; +}; + +} //namespace gatordmock + +} //namespace armnn diff --git a/src/timelineDecoder/tests/TimelineTests.cpp b/src/timelineDecoder/tests/TimelineTests.cpp new file mode 100644 index 0000000000..052a3f12ff --- /dev/null +++ b/src/timelineDecoder/tests/TimelineTests.cpp @@ -0,0 +1,253 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include <TimelineCaptureCommandHandler.hpp> +#include <TimelineDirectoryCaptureCommandHandler.hpp> +#include <TimelineDecoder.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; +using namespace timelinedecoder; + +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; + + auto uniquePacketData = std::make_unique<unsigned char[]>(PacketDataLength); + std::memcpy(uniquePacketData.get(), packetBuffer + offset, PacketDataLength); + + armnn::profiling::Packet packet(header[0], PacketDataLength, uniquePacketData); + + BOOST_CHECK(std::memcmp(packetBuffer + offset, packet.GetData(), packet.GetLength()) == 0); + + CommandHandler(packet); +} + +void PushEntity(TimelineDecoder::Model& model, const ITimelineDecoder::Entity entity) +{ + model.m_Entities.emplace_back(entity); +} + +void PushEventClass(TimelineDecoder::Model& model, const ITimelineDecoder::EventClass eventClass) +{ + model.m_EventClasses.emplace_back(eventClass); +} + +void PushEvent(TimelineDecoder::Model& model, const ITimelineDecoder::Event event) +{ + model.m_Events.emplace_back(event); +} + +void PushLabel(TimelineDecoder::Model& model, const ITimelineDecoder::Label label) +{ + model.m_Labels.emplace_back(label); +} + +void PushRelationship(TimelineDecoder::Model& model, const ITimelineDecoder::Relationship relationship) +{ + model.m_Relationships.emplace_back(relationship); +} + +BOOST_AUTO_TEST_CASE(TimelineDirectoryTest) +{ + uint32_t uint8_t_size = sizeof(uint8_t); + uint32_t uint32_t_size = sizeof(uint32_t); + uint32_t uint64_t_size = sizeof(uint64_t); + uint32_t threadId_size = sizeof(std::thread::id); + + profiling::BufferManager bufferManager(5); + profiling::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager); + + std::unique_ptr<profiling::ISendTimelinePacket> sendTimelinePacket = + timelinePacketWriterFactory.GetSendTimelinePacket(); + + profiling::PacketVersionResolver packetVersionResolver; + + 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(); + + uint8_t readStreamVersion = ReadUint8(packetBuffer, offset); + BOOST_CHECK(readStreamVersion == 4); + offset += uint8_t_size; + uint8_t readPointerBytes = ReadUint8(packetBuffer, offset); + BOOST_CHECK(readPointerBytes == uint64_t_size); + offset += uint8_t_size; + uint8_t readThreadIdBytes = ReadUint8(packetBuffer, offset); + BOOST_CHECK(readThreadIdBytes == threadId_size); + offset += uint8_t_size; + + 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.m_Name == handlerMessage.m_Name); + BOOST_CHECK(bufferMessage.m_UiName == handlerMessage.m_UiName); + BOOST_CHECK(bufferMessage.m_Id == handlerMessage.m_Id); + + BOOST_CHECK(bufferMessage.m_ArgTypes.size() == handlerMessage.m_ArgTypes.size()); + for(uint32_t i = 0; i < bufferMessage.m_ArgTypes.size(); ++i) + { + BOOST_CHECK(bufferMessage.m_ArgTypes[i] == handlerMessage.m_ArgTypes[i]); + } + + BOOST_CHECK(bufferMessage.m_ArgNames.size() == handlerMessage.m_ArgNames.size()); + for(uint32_t i = 0; i < bufferMessage.m_ArgNames.size(); ++i) + { + BOOST_CHECK(bufferMessage.m_ArgNames[i] == handlerMessage.m_ArgNames[i]); + } + } +} + +BOOST_AUTO_TEST_CASE(TimelineCaptureTest) +{ + unsigned int threadIdSize = sizeof(std::thread::id); + profiling::BufferManager bufferManager(50); + profiling::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager); + + std::unique_ptr<profiling::ISendTimelinePacket> sendTimelinePacket = + timelinePacketWriterFactory.GetSendTimelinePacket(); + + profiling::PacketVersionResolver packetVersionResolver; + + TimelineDecoder timelineDecoder; + const TimelineDecoder::Model& model = timelineDecoder.GetModel(); + + TimelineCaptureCommandHandler timelineCaptureCommandHandler( + 1, 1, packetVersionResolver.ResolvePacketVersion(1, 1).GetEncodedValue(), timelineDecoder, threadIdSize); + + BOOST_CHECK(timelineDecoder.SetEntityCallback(PushEntity) == ITimelineDecoder::ErrorCode::ErrorCode_Success); + BOOST_CHECK( + timelineDecoder.SetEventClassCallback(PushEventClass) == ITimelineDecoder::ErrorCode::ErrorCode_Success); + BOOST_CHECK(timelineDecoder.SetEventCallback(PushEvent) == ITimelineDecoder::ErrorCode::ErrorCode_Success); + BOOST_CHECK(timelineDecoder.SetLabelCallback(PushLabel) == ITimelineDecoder::ErrorCode::ErrorCode_Success); + BOOST_CHECK( + timelineDecoder.SetRelationshipCallback(PushRelationship) == ITimelineDecoder::ErrorCode::ErrorCode_Success); + + const uint64_t entityGuid = 111111u ; + const uint64_t eventClassGuid = 22222u; + const uint64_t timestamp = 33333u; + const uint64_t eventGuid = 44444u; + + const std::thread::id threadId = std::this_thread::get_id(); + + // need to do a bit of work here to extract the value from threadId + unsigned char* uCharThreadId = new unsigned char[threadIdSize]();; + uint64_t uint64ThreadId; + + profiling::WriteBytes(uCharThreadId, 0, &threadId, threadIdSize); + + if (threadIdSize == 4) + { + uint64ThreadId = profiling::ReadUint32(uCharThreadId, 0); + } + else if (threadIdSize == 8) + { + uint64ThreadId = profiling::ReadUint64(uCharThreadId, 0); + } + delete[] uCharThreadId; + + const uint64_t labelGuid = 66666u; + std::string labelName = "test_label"; + + const uint64_t relationshipGuid = 77777u; + const uint64_t headGuid = 888888u; + const uint64_t tailGuid = 999999u; + + 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 (unsigned long i = 0; i < 10; ++i) + { + BOOST_CHECK(model.m_Entities[i].m_Guid == entityGuid); + + BOOST_CHECK(model.m_EventClasses[i].m_Guid == eventClassGuid); + + BOOST_CHECK(model.m_Events[i].m_TimeStamp == timestamp); + BOOST_CHECK(model.m_Events[i].m_ThreadId == uint64ThreadId); + BOOST_CHECK(model.m_Events[i].m_Guid == eventGuid); + + BOOST_CHECK(model.m_Labels[i].m_Guid == labelGuid); + BOOST_CHECK(model.m_Labels[i].m_Name == labelName); + + BOOST_CHECK(model.m_Relationships[i].m_RelationshipType == ITimelineDecoder::RelationshipType::DataLink); + BOOST_CHECK(model.m_Relationships[i].m_Guid == relationshipGuid); + BOOST_CHECK(model.m_Relationships[i].m_HeadGuid == headGuid); + BOOST_CHECK(model.m_Relationships[i].m_TailGuid == tailGuid); + } +} + +BOOST_AUTO_TEST_SUITE_END() |