From 994b5349180b41849ee616fa4f0d3b94a928f48f Mon Sep 17 00:00:00 2001 From: Matteo Martincigh Date: Fri, 11 Oct 2019 17:19:56 +0100 Subject: IVGCVSW-3971 Implement the Per-Job Counter Selection command handler * Added new PerJobCounterSelectionCommandHandler class * The new handler drops the incoming packet without altering the state of the profiling service * Added unit test Signed-off-by: Matteo Martincigh Change-Id: I2b1bb803318a9e6c438391a0985893eb412e7787 --- .../PerJobCounterSelectionCommandHandler.cpp | 48 +++++++++++++++ .../PerJobCounterSelectionCommandHandler.hpp | 38 ++++++++++++ src/profiling/ProfilingService.hpp | 8 +++ src/profiling/test/ProfilingTests.cpp | 70 ++++++++++++++++++++++ 4 files changed, 164 insertions(+) create mode 100644 src/profiling/PerJobCounterSelectionCommandHandler.cpp create mode 100644 src/profiling/PerJobCounterSelectionCommandHandler.hpp (limited to 'src') diff --git a/src/profiling/PerJobCounterSelectionCommandHandler.cpp b/src/profiling/PerJobCounterSelectionCommandHandler.cpp new file mode 100644 index 0000000000..8892e1457d --- /dev/null +++ b/src/profiling/PerJobCounterSelectionCommandHandler.cpp @@ -0,0 +1,48 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "PerJobCounterSelectionCommandHandler.hpp" + +#include + +namespace armnn +{ + +namespace profiling +{ + +void PerJobCounterSelectionCommandHandler::operator()(const Packet& packet) +{ + ProfilingState currentState = m_StateMachine.GetCurrentState(); + switch (currentState) + { + case ProfilingState::Uninitialised: + case ProfilingState::NotConnected: + case ProfilingState::WaitingForAck: + throw RuntimeException(boost::str(boost::format("Per-Job Counter Selection Command Handler invoked while in " + "an wrong state: %1%") + % GetProfilingStateName(currentState))); + case ProfilingState::Active: + // Process the packet + if (!(packet.GetPacketFamily() == 0u && packet.GetPacketId() == 5u)) + { + throw armnn::InvalidArgumentException(boost::str(boost::format("Expected Packet family = 0, id = 5 but " + "received family = %1%, id = %2%") + % packet.GetPacketFamily() + % packet.GetPacketId())); + } + + // Silently drop the packet + + break; + default: + throw RuntimeException(boost::str(boost::format("Unknown profiling service state: %1%") + % static_cast(currentState))); + } +} + +} // namespace profiling + +} // namespace armnn diff --git a/src/profiling/PerJobCounterSelectionCommandHandler.hpp b/src/profiling/PerJobCounterSelectionCommandHandler.hpp new file mode 100644 index 0000000000..6caa08d68e --- /dev/null +++ b/src/profiling/PerJobCounterSelectionCommandHandler.hpp @@ -0,0 +1,38 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "Packet.hpp" +#include "CommandHandlerFunctor.hpp" +#include "ProfilingStateMachine.hpp" + +namespace armnn +{ + +namespace profiling +{ + +class PerJobCounterSelectionCommandHandler : public CommandHandlerFunctor +{ + +public: + PerJobCounterSelectionCommandHandler(uint32_t packetId, + uint32_t version, + const ProfilingStateMachine& profilingStateMachine) + : CommandHandlerFunctor(packetId, version) + , m_StateMachine(profilingStateMachine) + {} + + void operator()(const Packet& packet) override; + +private: + const ProfilingStateMachine& m_StateMachine; +}; + +} // namespace profiling + +} // namespace armnn + diff --git a/src/profiling/ProfilingService.hpp b/src/profiling/ProfilingService.hpp index d4fa85604c..1afcb1ca97 100644 --- a/src/profiling/ProfilingService.hpp +++ b/src/profiling/ProfilingService.hpp @@ -16,6 +16,7 @@ #include "ConnectionAcknowledgedCommandHandler.hpp" #include "RequestCounterDirectoryCommandHandler.hpp" #include "PeriodicCounterSelectionCommandHandler.hpp" +#include "PerJobCounterSelectionCommandHandler.hpp" namespace armnn { @@ -96,6 +97,7 @@ private: ConnectionAcknowledgedCommandHandler m_ConnectionAcknowledgedCommandHandler; RequestCounterDirectoryCommandHandler m_RequestCounterDirectoryCommandHandler; PeriodicCounterSelectionCommandHandler m_PeriodicCounterSelectionCommandHandler; + PerJobCounterSelectionCommandHandler m_PerJobCounterSelectionCommandHandler; protected: // Default constructor/destructor kept protected for testing @@ -131,6 +133,9 @@ protected: *this, m_SendCounterPacket, m_StateMachine) + , m_PerJobCounterSelectionCommandHandler(5, + m_PacketVersionResolver.ResolvePacketVersion(4).GetEncodedValue(), + m_StateMachine) { // Register the "Connection Acknowledged" command handler m_CommandHandlerRegistry.RegisterFunctor(&m_ConnectionAcknowledgedCommandHandler); @@ -140,6 +145,9 @@ protected: // Register the "Periodic Counter Selection" command handler m_CommandHandlerRegistry.RegisterFunctor(&m_PeriodicCounterSelectionCommandHandler); + + // Register the "Per-Job Counter Selection" command handler + m_CommandHandlerRegistry.RegisterFunctor(&m_PerJobCounterSelectionCommandHandler); } ~ProfilingService() = default; diff --git a/src/profiling/test/ProfilingTests.cpp b/src/profiling/test/ProfilingTests.cpp index 446c6096ed..6437521635 100644 --- a/src/profiling/test/ProfilingTests.cpp +++ b/src/profiling/test/ProfilingTests.cpp @@ -3072,4 +3072,74 @@ BOOST_AUTO_TEST_CASE(CheckProfilingServiceDisconnect) profilingService.ResetExternalProfilingOptions(options, true); } +BOOST_AUTO_TEST_CASE(CheckProfilingServiceGoodPerJobCounterSelectionPacket) +{ + // Swap the profiling connection factory in the profiling service instance with our mock one + SwapProfilingConnectionFactoryHelper helper; + + // Reset the profiling service to the uninitialized state + armnn::Runtime::CreationOptions::ExternalProfilingOptions options; + options.m_EnableProfiling = true; + ProfilingService& profilingService = ProfilingService::Instance(); + profilingService.ResetExternalProfilingOptions(options, true); + + // Bring the profiling service to the "Active" state + BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised); + profilingService.Update(); // Initialize the counter directory + BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected); + profilingService.Update(); // Create the profiling connection + BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck); + profilingService.Update(); // Start the command handler and the send thread + + // Wait for the Stream Metadata packet the be sent + // (we are not testing the connection acknowledgement here so it will be ignored by this test) + helper.WaitForProfilingPacketsSent(); + + // Force the profiling service to the "Active" state + helper.ForceTransitionToState(ProfilingState::Active); + BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active); + + // Get the mock profiling connection + MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection(); + BOOST_CHECK(mockProfilingConnection); + + // Remove the packets received so far + mockProfilingConnection->Clear(); + + // Write a "Per-Job Counter Selection" packet into the mock profiling connection, to simulate an input from an + // external profiling service + + // Per-Job Counter Selection packet header: + // 26:31 [6] packet_family: Control Packet Family, value 0b000000 + // 16:25 [10] packet_id: Packet identifier, value 0b0000000100 + // 8:15 [8] reserved: Reserved, value 0b00000000 + // 0:7 [8] reserved: Reserved, value 0b00000000 + uint32_t packetFamily = 0; + uint32_t packetId = 5; + uint32_t header = ((packetFamily & 0x0000003F) << 26) | + ((packetId & 0x000003FF) << 16); + + // Create the Per-Job Counter Selection packet + Packet periodicCounterSelectionPacket(header); // Length == 0, this will disable the collection of counters + + // Write the packet to the mock profiling connection + mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket)); + + // Wait for a bit (must at least be the delay value of the mock profiling connection) to make sure that + // the Per-Job Counter Selection packet gets processed by the profiling service + std::this_thread::sleep_for(std::chrono::seconds(2)); + + // The Per-Job Counter Selection packets are dropped silently, so there should be no reply coming + // from the profiling service + const std::vector writtenData = mockProfilingConnection->GetWrittenData(); + BOOST_TEST(writtenData.empty()); + + // The Per-Job Counter Selection Command Handler should not have updated the profiling state + BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active); + + // Reset the profiling service to stop any running thread + options.m_EnableProfiling = false; + profilingService.ResetExternalProfilingOptions(options, true); +} + BOOST_AUTO_TEST_SUITE_END() -- cgit v1.2.1