blob: eb1b15791cb9d7569ab7e52255f1f6ef84f19ed6 [file] [log] [blame]
Matteo Martincighd0613b52019-10-09 16:47:04 +01001//
Jim Flynn6398a982020-05-27 17:05:21 +01002// Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
Matteo Martincighd0613b52019-10-09 16:47:04 +01003// SPDX-License-Identifier: MIT
4//
5
6#pragma once
7
Jim Flynn64063552020-02-14 10:18:08 +00008#include "ProfilingMocks.hpp"
Matteo Martincighd0613b52019-10-09 16:47:04 +01009
Jan Eilersbb446e52020-04-02 13:56:54 +010010#include <armnn/utility/PolymorphicDowncast.hpp>
Derek Lamberti08446972019-11-26 16:38:31 +000011
Jim Flynn3e9bc192022-03-23 23:01:26 +000012#include <client/src/IProfilingConnection.hpp>
13#include <client/src/ProfilingService.hpp>
Matteo Martincighd0613b52019-10-09 16:47:04 +010014
Jim Flynn9c85b412022-03-16 00:27:43 +000015#include <armnn/profiling/ArmNNProfiling.hpp>
16
Jim Flynnbbfe6032020-07-20 16:57:44 +010017#include <common/include/CommandHandlerFunctor.hpp>
Jim Flynn6c9f17d2022-03-10 23:13:01 +000018#include <common/include/Logging.hpp>
Jim Flynnbbfe6032020-07-20 16:57:44 +010019
Sadik Armagan1625efc2021-06-10 18:24:34 +010020#include <doctest/doctest.h>
Matteo Martincighd0613b52019-10-09 16:47:04 +010021
22#include <chrono>
Matteo Martincighd0613b52019-10-09 16:47:04 +010023#include <thread>
24
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000025namespace arm
Matteo Martincighd0613b52019-10-09 16:47:04 +010026{
27
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000028namespace pipe
Matteo Martincighd0613b52019-10-09 16:47:04 +010029{
30
Matteo Martincighd0613b52019-10-09 16:47:04 +010031class TestProfilingConnectionBase : public IProfilingConnection
32{
33public:
34 TestProfilingConnectionBase() = default;
35 ~TestProfilingConnectionBase() = default;
36
37 bool IsOpen() const override { return true; }
38
39 void Close() override {}
40
Derek Lamberti1dd75b32019-12-10 21:23:23 +000041 bool WritePacket(const unsigned char* buffer, uint32_t length) override
42 {
Jim Flynn9265a882022-03-10 23:35:26 +000043 arm::pipe::IgnoreUnused(buffer, length);
Derek Lamberti1dd75b32019-12-10 21:23:23 +000044
45 return false;
46 }
Matteo Martincighd0613b52019-10-09 16:47:04 +010047
Jim Flynnbbfe6032020-07-20 16:57:44 +010048 arm::pipe::Packet ReadPacket(uint32_t timeout) override
Matteo Martincighd0613b52019-10-09 16:47:04 +010049 {
Colm Donelan2ba48d22019-11-29 09:10:59 +000050 // First time we're called return a connection ack packet. After that always timeout.
51 if (m_FirstCall)
52 {
53 m_FirstCall = false;
54 // Return connection acknowledged packet
Jim Flynnbbfe6032020-07-20 16:57:44 +010055 return arm::pipe::Packet(65536);
Colm Donelan2ba48d22019-11-29 09:10:59 +000056 }
57 else
58 {
59 std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
Jim Flynnf9db3ef2022-03-08 21:23:44 +000060 throw arm::pipe::TimeoutException("Simulate a timeout error\n");
Colm Donelan2ba48d22019-11-29 09:10:59 +000061 }
Matteo Martincighd0613b52019-10-09 16:47:04 +010062 }
Colm Donelan2ba48d22019-11-29 09:10:59 +000063
64 bool m_FirstCall = true;
Matteo Martincighd0613b52019-10-09 16:47:04 +010065};
66
67class TestProfilingConnectionTimeoutError : public TestProfilingConnectionBase
68{
69public:
70 TestProfilingConnectionTimeoutError()
71 : m_ReadRequests(0)
72 {}
73
Jim Flynnbbfe6032020-07-20 16:57:44 +010074 arm::pipe::Packet ReadPacket(uint32_t timeout) override
Matteo Martincighd0613b52019-10-09 16:47:04 +010075 {
Colm Donelan2ba48d22019-11-29 09:10:59 +000076 // Return connection acknowledged packet after three timeouts
77 if (m_ReadRequests % 3 == 0)
Matteo Martincighd0613b52019-10-09 16:47:04 +010078 {
Colm Donelan2ba48d22019-11-29 09:10:59 +000079 std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
80 ++m_ReadRequests;
Jim Flynnf9db3ef2022-03-08 21:23:44 +000081 throw arm::pipe::TimeoutException("Simulate a timeout error\n");
Matteo Martincighd0613b52019-10-09 16:47:04 +010082 }
83
Jim Flynnbbfe6032020-07-20 16:57:44 +010084 return arm::pipe::Packet(65536);
Matteo Martincighd0613b52019-10-09 16:47:04 +010085 }
86
Colm Donelan2ba48d22019-11-29 09:10:59 +000087 int ReadCalledCount()
88 {
89 return m_ReadRequests.load();
90 }
91
Matteo Martincighd0613b52019-10-09 16:47:04 +010092private:
Colm Donelan2ba48d22019-11-29 09:10:59 +000093 std::atomic<int> m_ReadRequests;
Matteo Martincighd0613b52019-10-09 16:47:04 +010094};
95
96class TestProfilingConnectionArmnnError : public TestProfilingConnectionBase
97{
98public:
Colm Donelan2ba48d22019-11-29 09:10:59 +000099 TestProfilingConnectionArmnnError()
100 : m_ReadRequests(0)
101 {}
102
Jim Flynnbbfe6032020-07-20 16:57:44 +0100103 arm::pipe::Packet ReadPacket(uint32_t timeout) override
Matteo Martincighd0613b52019-10-09 16:47:04 +0100104 {
Jim Flynn9265a882022-03-10 23:35:26 +0000105 arm::pipe::IgnoreUnused(timeout);
Colm Donelan2ba48d22019-11-29 09:10:59 +0000106 ++m_ReadRequests;
Jim Flynnf9db3ef2022-03-08 21:23:44 +0000107 throw arm::pipe::ProfilingException("Simulate a non-timeout error");
Matteo Martincighd0613b52019-10-09 16:47:04 +0100108 }
Colm Donelan2ba48d22019-11-29 09:10:59 +0000109
110 int ReadCalledCount()
111 {
112 return m_ReadRequests.load();
113 }
114
115private:
116 std::atomic<int> m_ReadRequests;
Matteo Martincighd0613b52019-10-09 16:47:04 +0100117};
118
Finn Williams09ad6f92019-12-19 17:05:18 +0000119class TestProfilingConnectionBadAckPacket : public TestProfilingConnectionBase
120{
121public:
Jim Flynnbbfe6032020-07-20 16:57:44 +0100122 arm::pipe::Packet ReadPacket(uint32_t timeout) override
Finn Williams09ad6f92019-12-19 17:05:18 +0000123 {
Jim Flynn9265a882022-03-10 23:35:26 +0000124 arm::pipe::IgnoreUnused(timeout);
Finn Williams09ad6f92019-12-19 17:05:18 +0000125 // Connection Acknowledged Packet header (word 0, word 1 is always zero):
126 // 26:31 [6] packet_family: Control Packet Family, value 0b000000
127 // 16:25 [10] packet_id: Packet identifier, value 0b0000000001
128 // 8:15 [8] reserved: Reserved, value 0b00000000
129 // 0:7 [8] reserved: Reserved, value 0b00000000
130 uint32_t packetFamily = 0;
131 uint32_t packetId = 37; // Wrong packet id!!!
132 uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
133
Jim Flynnbbfe6032020-07-20 16:57:44 +0100134 return arm::pipe::Packet(header);
Finn Williams09ad6f92019-12-19 17:05:18 +0000135 }
136};
137
Jim Flynnbbfe6032020-07-20 16:57:44 +0100138class TestFunctorA : public arm::pipe::CommandHandlerFunctor
Matteo Martincighd0613b52019-10-09 16:47:04 +0100139{
140public:
141 using CommandHandlerFunctor::CommandHandlerFunctor;
142
143 int GetCount() { return m_Count; }
144
Jim Flynnbbfe6032020-07-20 16:57:44 +0100145 void operator()(const arm::pipe::Packet& packet) override
Matteo Martincighd0613b52019-10-09 16:47:04 +0100146 {
Jim Flynn9265a882022-03-10 23:35:26 +0000147 arm::pipe::IgnoreUnused(packet);
Matteo Martincighd0613b52019-10-09 16:47:04 +0100148 m_Count++;
149 }
150
151private:
152 int m_Count = 0;
153};
154
155class TestFunctorB : public TestFunctorA
156{
157 using TestFunctorA::TestFunctorA;
158};
159
160class TestFunctorC : public TestFunctorA
161{
162 using TestFunctorA::TestFunctorA;
163};
164
Matteo Martincighd0613b52019-10-09 16:47:04 +0100165class SwapProfilingConnectionFactoryHelper : public ProfilingService
166{
167public:
168 using MockProfilingConnectionFactoryPtr = std::unique_ptr<MockProfilingConnectionFactory>;
169
Jim Flynn34430252022-03-04 15:03:58 +0000170 SwapProfilingConnectionFactoryHelper(uint16_t maxGlobalCounterId,
171 IInitialiseProfilingService& initialiser,
172 ProfilingService& profilingService)
Jim Flynn9c85b412022-03-16 00:27:43 +0000173 : ProfilingService(maxGlobalCounterId,
174 initialiser,
175 arm::pipe::ARMNN_SOFTWARE_INFO,
176 arm::pipe::ARMNN_SOFTWARE_VERSION,
177 arm::pipe::ARMNN_HARDWARE_VERSION)
Sadik Armagan3184c902020-03-18 10:57:30 +0000178 , m_ProfilingService(profilingService)
Matteo Martincighd0613b52019-10-09 16:47:04 +0100179 , m_MockProfilingConnectionFactory(new MockProfilingConnectionFactory())
180 , m_BackupProfilingConnectionFactory(nullptr)
Sadik Armagan3184c902020-03-18 10:57:30 +0000181
Matteo Martincighd0613b52019-10-09 16:47:04 +0100182 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100183 CHECK(m_MockProfilingConnectionFactory);
Sadik Armagan3184c902020-03-18 10:57:30 +0000184 SwapProfilingConnectionFactory(m_ProfilingService,
Matteo Martincighd0613b52019-10-09 16:47:04 +0100185 m_MockProfilingConnectionFactory.get(),
186 m_BackupProfilingConnectionFactory);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100187 CHECK(m_BackupProfilingConnectionFactory);
Matteo Martincighd0613b52019-10-09 16:47:04 +0100188 }
189 ~SwapProfilingConnectionFactoryHelper()
190 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100191 CHECK(m_BackupProfilingConnectionFactory);
Matteo Martincighd0613b52019-10-09 16:47:04 +0100192 IProfilingConnectionFactory* temp = nullptr;
Sadik Armagan3184c902020-03-18 10:57:30 +0000193 SwapProfilingConnectionFactory(m_ProfilingService,
Matteo Martincighd0613b52019-10-09 16:47:04 +0100194 m_BackupProfilingConnectionFactory,
195 temp);
196 }
197
198 MockProfilingConnection* GetMockProfilingConnection()
199 {
Sadik Armagan3184c902020-03-18 10:57:30 +0000200 IProfilingConnection* profilingConnection = GetProfilingConnection(m_ProfilingService);
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000201 return armnn::PolymorphicDowncast<MockProfilingConnection*>(profilingConnection);
Matteo Martincighd0613b52019-10-09 16:47:04 +0100202 }
203
Matteo Martincigh8efc5002019-10-10 14:30:29 +0100204 void ForceTransitionToState(ProfilingState newState)
205 {
Sadik Armagan3184c902020-03-18 10:57:30 +0000206 TransitionToState(m_ProfilingService, newState);
Matteo Martincigh8efc5002019-10-10 14:30:29 +0100207 }
208
Finn Williams09ad6f92019-12-19 17:05:18 +0000209 long WaitForPacketsSent(MockProfilingConnection* mockProfilingConnection,
210 MockProfilingConnection::PacketType packetType,
211 uint32_t length = 0,
212 uint32_t timeout = 1000)
Matteo Martincighe8485382019-10-10 14:08:21 +0100213 {
Keith Davis33ed2212020-03-30 10:43:41 +0100214 long packetCount = mockProfilingConnection->CheckForPacket({ packetType, length });
Finn Williams09ad6f92019-12-19 17:05:18 +0000215 // The first packet we receive may not be the one we are looking for, so keep looping until till we find it,
216 // or until WaitForPacketsSent times out
217 while(packetCount == 0 && timeout != 0)
Colm Donelan2ba48d22019-11-29 09:10:59 +0000218 {
Finn Williams09ad6f92019-12-19 17:05:18 +0000219 std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
220 // Wait for a notification from the send thread
Sadik Armagan3184c902020-03-18 10:57:30 +0000221 ProfilingService::WaitForPacketSent(m_ProfilingService, timeout);
Finn Williams09ad6f92019-12-19 17:05:18 +0000222
223 std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
224
225 // We need to make sure the timeout does not reset each time we call WaitForPacketsSent
226 uint32_t elapsedTime = static_cast<uint32_t>(
227 std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count());
228
229 packetCount = mockProfilingConnection->CheckForPacket({packetType, length});
230
231 if (elapsedTime > timeout)
Colm Donelan2ba48d22019-11-29 09:10:59 +0000232 {
Finn Williams09ad6f92019-12-19 17:05:18 +0000233 break;
Colm Donelan2ba48d22019-11-29 09:10:59 +0000234 }
Finn Williams09ad6f92019-12-19 17:05:18 +0000235
236 timeout -= elapsedTime;
Colm Donelan2ba48d22019-11-29 09:10:59 +0000237 }
Finn Williams09ad6f92019-12-19 17:05:18 +0000238 return packetCount;
Matteo Martincighe8485382019-10-10 14:08:21 +0100239 }
240
Matteo Martincighd0613b52019-10-09 16:47:04 +0100241private:
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000242 ProfilingService& m_ProfilingService;
Matteo Martincighd0613b52019-10-09 16:47:04 +0100243 MockProfilingConnectionFactoryPtr m_MockProfilingConnectionFactory;
244 IProfilingConnectionFactory* m_BackupProfilingConnectionFactory;
245};
246
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000247} // namespace pipe
Matteo Martincighd0613b52019-10-09 16:47:04 +0100248
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000249} // namespace arm