blob: 128e1f15d2729cb8ee19c67bd5c08c02f643a430 [file] [log] [blame]
Francis Murtagh1f7db452019-08-14 09:49:34 +01001//
Jim Flynn6398a982020-05-27 17:05:21 +01002// Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
Francis Murtagh1f7db452019-08-14 09:49:34 +01003// SPDX-License-Identifier: MIT
4//
5
Jim Flynn34430252022-03-04 15:03:58 +00006#include <ArmNNProfilingServiceInitialiser.hpp>
7
Matteo Martincighd0613b52019-10-09 16:47:04 +01008#include "ProfilingTests.hpp"
Keith Davis33ed2212020-03-30 10:43:41 +01009#include "ProfilingTestUtils.hpp"
Teresa Charlin9bab4962019-09-06 12:28:35 +010010
James Conroy2dcd3fe2020-02-06 18:34:52 +000011#include <backends/BackendProfiling.hpp>
Jim Flynnbbfe6032020-07-20 16:57:44 +010012#include <common/include/EncodeVersion.hpp>
13#include <common/include/PacketVersionResolver.hpp>
14#include <common/include/SwTrace.hpp>
Matteo Martincigh8a837172019-10-04 17:01:07 +010015#include <CommandHandler.hpp>
Sadik Armaganb5f01b22019-09-18 17:29:00 +010016#include <ConnectionAcknowledgedCommandHandler.hpp>
Matteo Martincigh6db5f202019-09-05 12:02:04 +010017#include <CounterDirectory.hpp>
David Monahande803072020-01-30 12:44:23 +000018#include <CounterIdMap.hpp>
Matteo Martincigh6db5f202019-09-05 12:02:04 +010019#include <Holder.hpp>
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010020#include <ICounterValues.hpp>
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010021#include <PeriodicCounterCapture.hpp>
Matteo Martincigh6db5f202019-09-05 12:02:04 +010022#include <PeriodicCounterSelectionCommandHandler.hpp>
Jim Flynn34430252022-03-04 15:03:58 +000023#include <armnn/profiling/ArmNNProfiling.hpp>
Jim Flynn4c9ed1d2022-01-23 23:57:20 +000024#include <armnn/profiling/ProfilingOptions.hpp>
Matteo Martincigh6db5f202019-09-05 12:02:04 +010025#include <ProfilingStateMachine.hpp>
Matteo Martincigh6db5f202019-09-05 12:02:04 +010026#include <ProfilingUtils.hpp>
James Conroy2dcd3fe2020-02-06 18:34:52 +000027#include <RegisterBackendCounters.hpp>
Narumol Prangnawarat48033692019-09-20 12:04:55 +010028#include <RequestCounterDirectoryCommandHandler.hpp>
Teresa Charlin9bab4962019-09-06 12:28:35 +010029#include <Runtime.hpp>
Matteo Martincigh6db5f202019-09-05 12:02:04 +010030#include <SocketProfilingConnection.hpp>
Matteo Martincighcdfb9412019-11-08 11:23:06 +000031#include <SendCounterPacket.hpp>
Sadik Armagan3896b472020-02-10 12:24:15 +000032#include <SendThread.hpp>
Matteo Martincighcdfb9412019-11-08 11:23:06 +000033#include <SendTimelinePacket.hpp>
Keith Davis02356de2019-08-26 18:28:17 +010034
Matteo Martincigh6db5f202019-09-05 12:02:04 +010035#include <armnn/Conversion.hpp>
Ferran Balaguer1b941722019-08-28 16:57:18 +010036
Matteo Martincigh54fb9572019-10-02 12:50:57 +010037#include <armnn/Utils.hpp>
Jan Eilers8eb25602020-03-09 12:13:48 +000038#include <armnn/utility/IgnoreUnused.hpp>
Matthew Sloyan371b70e2020-09-11 10:14:57 +010039#include <armnn/utility/NumericCast.hpp>
Matteo Martincigh54fb9572019-10-02 12:50:57 +010040
Jim Flynnbbfe6032020-07-20 16:57:44 +010041#include <common/include/CommandHandlerKey.hpp>
42#include <common/include/CommandHandlerRegistry.hpp>
43#include <common/include/SocketConnectionException.hpp>
44#include <common/include/Packet.hpp>
45
Sadik Armagan1625efc2021-06-10 18:24:34 +010046#include <doctest/doctest.h>
47
Sadik Armagan95e9efc2021-08-05 15:01:07 +010048#include <algorithm>
Nikhil Rajbc626052019-08-15 15:49:45 +010049#include <cstdint>
50#include <cstring>
Keith Davis3201eea2019-10-24 17:30:41 +010051#include <iostream>
Aron Virginas-Tare898db92019-08-22 12:56:34 +010052#include <limits>
Francis Murtagh11f99b42019-08-16 11:28:52 +010053#include <map>
Aron Virginas-Tare898db92019-08-22 12:56:34 +010054#include <random>
James Conroy2dcd3fe2020-02-06 18:34:52 +000055
Francis Murtagh1f7db452019-08-14 09:49:34 +010056
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000057using namespace arm::pipe;
Finn Williams09ad6f92019-12-19 17:05:18 +000058using PacketType = MockProfilingConnection::PacketType;
Aron Virginas-Tare898db92019-08-22 12:56:34 +010059
Sadik Armagan1625efc2021-06-10 18:24:34 +010060TEST_SUITE("ExternalProfiling")
61{
62TEST_CASE("CheckCommandHandlerKeyComparisons")
Francis Murtagh1f7db452019-08-14 09:49:34 +010063{
Jim Flynnbbfe6032020-07-20 16:57:44 +010064 arm::pipe::CommandHandlerKey testKey1_0(1, 1, 1);
65 arm::pipe::CommandHandlerKey testKey1_1(1, 1, 1);
66 arm::pipe::CommandHandlerKey testKey1_2(1, 2, 1);
Jim Flynn397043f2019-10-17 17:37:10 +010067
Jim Flynnbbfe6032020-07-20 16:57:44 +010068 arm::pipe::CommandHandlerKey testKey0(0, 1, 1);
69 arm::pipe::CommandHandlerKey testKey1(0, 1, 1);
70 arm::pipe::CommandHandlerKey testKey2(0, 1, 1);
71 arm::pipe::CommandHandlerKey testKey3(0, 0, 0);
72 arm::pipe::CommandHandlerKey testKey4(0, 2, 2);
73 arm::pipe::CommandHandlerKey testKey5(0, 0, 2);
Jim Flynn397043f2019-10-17 17:37:10 +010074
Sadik Armagan1625efc2021-06-10 18:24:34 +010075 CHECK(testKey1_0 > testKey0);
76 CHECK(testKey1_0 == testKey1_1);
77 CHECK(testKey1_0 < testKey1_2);
Francis Murtagh1f7db452019-08-14 09:49:34 +010078
Sadik Armagan1625efc2021-06-10 18:24:34 +010079 CHECK(testKey1 < testKey4);
80 CHECK(testKey1 > testKey3);
81 CHECK(testKey1 <= testKey4);
82 CHECK(testKey1 >= testKey3);
83 CHECK(testKey1 <= testKey2);
84 CHECK(testKey1 >= testKey2);
85 CHECK(testKey1 == testKey2);
86 CHECK(testKey1 == testKey1);
Francis Murtagh1f7db452019-08-14 09:49:34 +010087
Sadik Armagan1625efc2021-06-10 18:24:34 +010088 CHECK(!(testKey1 == testKey5));
89 CHECK(!(testKey1 != testKey1));
90 CHECK(testKey1 != testKey5);
Francis Murtagh1f7db452019-08-14 09:49:34 +010091
Sadik Armagan1625efc2021-06-10 18:24:34 +010092 CHECK((testKey1 == testKey2 && testKey2 == testKey1));
93 CHECK((testKey0 == testKey1 && testKey1 == testKey2 && testKey0 == testKey2));
Francis Murtagh1f7db452019-08-14 09:49:34 +010094
Sadik Armagan1625efc2021-06-10 18:24:34 +010095 CHECK(testKey1.GetPacketId() == 1);
96 CHECK(testKey1.GetVersion() == 1);
Francis Murtagh1f7db452019-08-14 09:49:34 +010097
Jim Flynnbbfe6032020-07-20 16:57:44 +010098 std::vector<arm::pipe::CommandHandlerKey> vect = {
99 arm::pipe::CommandHandlerKey(0, 0, 1), arm::pipe::CommandHandlerKey(0, 2, 0),
100 arm::pipe::CommandHandlerKey(0, 1, 0), arm::pipe::CommandHandlerKey(0, 2, 1),
101 arm::pipe::CommandHandlerKey(0, 1, 1), arm::pipe::CommandHandlerKey(0, 0, 1),
102 arm::pipe::CommandHandlerKey(0, 2, 0), arm::pipe::CommandHandlerKey(0, 0, 0) };
Francis Murtagh1f7db452019-08-14 09:49:34 +0100103
104 std::sort(vect.begin(), vect.end());
105
Jim Flynnbbfe6032020-07-20 16:57:44 +0100106 std::vector<arm::pipe::CommandHandlerKey> expectedVect = {
107 arm::pipe::CommandHandlerKey(0, 0, 0), arm::pipe::CommandHandlerKey(0, 0, 1),
108 arm::pipe::CommandHandlerKey(0, 0, 1), arm::pipe::CommandHandlerKey(0, 1, 0),
109 arm::pipe::CommandHandlerKey(0, 1, 1), arm::pipe::CommandHandlerKey(0, 2, 0),
110 arm::pipe::CommandHandlerKey(0, 2, 0), arm::pipe::CommandHandlerKey(0, 2, 1) };
Francis Murtagh1f7db452019-08-14 09:49:34 +0100111
Sadik Armagan1625efc2021-06-10 18:24:34 +0100112 CHECK(vect == expectedVect);
Francis Murtagh1f7db452019-08-14 09:49:34 +0100113}
114
Sadik Armagan1625efc2021-06-10 18:24:34 +0100115TEST_CASE("CheckPacketKeyComparisons")
Jim Flynned25e0e2019-10-18 13:21:43 +0100116{
Jim Flynnbbfe6032020-07-20 16:57:44 +0100117 arm::pipe::PacketKey key0(0, 0);
118 arm::pipe::PacketKey key1(0, 0);
119 arm::pipe::PacketKey key2(0, 1);
120 arm::pipe::PacketKey key3(0, 2);
121 arm::pipe::PacketKey key4(1, 0);
122 arm::pipe::PacketKey key5(1, 0);
123 arm::pipe::PacketKey key6(1, 1);
Jim Flynned25e0e2019-10-18 13:21:43 +0100124
Sadik Armagan1625efc2021-06-10 18:24:34 +0100125 CHECK(!(key0 < key1));
126 CHECK(!(key0 > key1));
127 CHECK(key0 <= key1);
128 CHECK(key0 >= key1);
129 CHECK(key0 == key1);
130 CHECK(key0 < key2);
131 CHECK(key2 < key3);
132 CHECK(key3 > key0);
133 CHECK(key4 == key5);
134 CHECK(key4 > key0);
135 CHECK(key5 < key6);
136 CHECK(key5 <= key6);
137 CHECK(key5 != key6);
Jim Flynned25e0e2019-10-18 13:21:43 +0100138}
139
Sadik Armagan1625efc2021-06-10 18:24:34 +0100140TEST_CASE("CheckCommandHandler")
FinnWilliamsArm4833cea2019-09-17 16:53:53 +0100141{
Jim Flynnbbfe6032020-07-20 16:57:44 +0100142 arm::pipe::PacketVersionResolver packetVersionResolver;
Matteo Martincigh8a837172019-10-04 17:01:07 +0100143 ProfilingStateMachine profilingStateMachine;
FinnWilliamsArm4833cea2019-09-17 16:53:53 +0100144
Matteo Martincigh8a837172019-10-04 17:01:07 +0100145 TestProfilingConnectionBase testProfilingConnectionBase;
146 TestProfilingConnectionTimeoutError testProfilingConnectionTimeOutError;
147 TestProfilingConnectionArmnnError testProfilingConnectionArmnnError;
Keith Davis3201eea2019-10-24 17:30:41 +0100148 CounterDirectory counterDirectory;
149 MockBufferManager mockBuffer(1024);
Sadik Armagan3896b472020-02-10 12:24:15 +0000150 SendCounterPacket sendCounterPacket(mockBuffer);
151 SendThread sendThread(profilingStateMachine, mockBuffer, sendCounterPacket);
Matteo Martincighcdfb9412019-11-08 11:23:06 +0000152 SendTimelinePacket sendTimelinePacket(mockBuffer);
Jim Flynn6398a982020-05-27 17:05:21 +0100153 MockProfilingServiceStatus mockProfilingServiceStatus;
Matteo Martincighcdfb9412019-11-08 11:23:06 +0000154
Keith Davis3201eea2019-10-24 17:30:41 +0100155 ConnectionAcknowledgedCommandHandler connectionAcknowledgedCommandHandler(0, 1, 4194304, counterDirectory,
Matteo Martincighcdfb9412019-11-08 11:23:06 +0000156 sendCounterPacket, sendTimelinePacket,
Jim Flynn6398a982020-05-27 17:05:21 +0100157 profilingStateMachine,
158 mockProfilingServiceStatus);
Jim Flynnbbfe6032020-07-20 16:57:44 +0100159 arm::pipe::CommandHandlerRegistry commandHandlerRegistry;
FinnWilliamsArm4833cea2019-09-17 16:53:53 +0100160
Matteo Martincighc2728f92019-10-07 12:35:21 +0100161 commandHandlerRegistry.RegisterFunctor(&connectionAcknowledgedCommandHandler);
FinnWilliamsArm4833cea2019-09-17 16:53:53 +0100162
Matteo Martincigh8a837172019-10-04 17:01:07 +0100163 profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
164 profilingStateMachine.TransitionToState(ProfilingState::WaitingForAck);
FinnWilliamsArm4833cea2019-09-17 16:53:53 +0100165
Keith Davis3201eea2019-10-24 17:30:41 +0100166 CommandHandler commandHandler0(1, true, commandHandlerRegistry, packetVersionResolver);
FinnWilliamsArm4833cea2019-09-17 16:53:53 +0100167
Colm Donelan2ba48d22019-11-29 09:10:59 +0000168 // This should start the command handler thread return the connection ack and put the profiling
169 // service into active state.
Matteo Martincigh8a837172019-10-04 17:01:07 +0100170 commandHandler0.Start(testProfilingConnectionBase);
Colm Donelan2ba48d22019-11-29 09:10:59 +0000171 // Try to start the send thread many times, it must only start once
Matteo Martincigh8a837172019-10-04 17:01:07 +0100172 commandHandler0.Start(testProfilingConnectionBase);
FinnWilliamsArm4833cea2019-09-17 16:53:53 +0100173
Colm Donelan2ba48d22019-11-29 09:10:59 +0000174 // This could take up to 20mSec but we'll check often.
175 for (int i = 0; i < 10; i++)
Matteo Martincigh8a837172019-10-04 17:01:07 +0100176 {
177 if (profilingStateMachine.GetCurrentState() == ProfilingState::Active)
FinnWilliamsArm4833cea2019-09-17 16:53:53 +0100178 {
Matteo Martincigh8a837172019-10-04 17:01:07 +0100179 break;
FinnWilliamsArm4833cea2019-09-17 16:53:53 +0100180 }
Colm Donelan2ba48d22019-11-29 09:10:59 +0000181 std::this_thread::sleep_for(std::chrono::milliseconds(2));
Matteo Martincigh8a837172019-10-04 17:01:07 +0100182 }
FinnWilliamsArm4833cea2019-09-17 16:53:53 +0100183
Sadik Armagan1625efc2021-06-10 18:24:34 +0100184 CHECK(profilingStateMachine.GetCurrentState() == ProfilingState::Active);
FinnWilliamsArm4833cea2019-09-17 16:53:53 +0100185
Colm Donelan2ba48d22019-11-29 09:10:59 +0000186 // Close the thread again.
187 commandHandler0.Stop();
188
189 profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
190 profilingStateMachine.TransitionToState(ProfilingState::WaitingForAck);
191
192 // In this test we'll simulate a timeout without a connection ack packet being received.
193 // Stop after timeout is set so we expect the command handler to stop almost immediately.
194 CommandHandler commandHandler1(1, true, commandHandlerRegistry, packetVersionResolver);
195
196 commandHandler1.Start(testProfilingConnectionTimeOutError);
197 // Wait until we know a timeout exception has been sent at least once.
198 for (int i = 0; i < 10; i++)
199 {
200 if (testProfilingConnectionTimeOutError.ReadCalledCount())
201 {
202 break;
203 }
204 std::this_thread::sleep_for(std::chrono::milliseconds(2));
205 }
Colm Donelan2ba48d22019-11-29 09:10:59 +0000206
207 // The command handler loop should have stopped after the timeout.
Finn Williams09ad6f92019-12-19 17:05:18 +0000208 // wait for the timeout exception to be processed and the loop to break.
209 uint32_t timeout = 50;
210 uint32_t timeSlept = 0;
211 while (commandHandler1.IsRunning())
212 {
213 if (timeSlept >= timeout)
214 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100215 FAIL("Timeout: The command handler loop did not stop after the timeout");
Finn Williams09ad6f92019-12-19 17:05:18 +0000216 }
217 std::this_thread::sleep_for(std::chrono::milliseconds(1));
218 timeSlept ++;
219 }
Colm Donelan2ba48d22019-11-29 09:10:59 +0000220
221 commandHandler1.Stop();
222 // The state machine should never have received the ack so will still be in WaitingForAck.
Sadik Armagan1625efc2021-06-10 18:24:34 +0100223 CHECK(profilingStateMachine.GetCurrentState() == ProfilingState::WaitingForAck);
Colm Donelan2ba48d22019-11-29 09:10:59 +0000224
Finn Williams09ad6f92019-12-19 17:05:18 +0000225 // Now try sending a bad connection acknowledged packet
226 TestProfilingConnectionBadAckPacket testProfilingConnectionBadAckPacket;
227 commandHandler1.Start(testProfilingConnectionBadAckPacket);
228 commandHandler1.Stop();
229 // This should also not change the state machine
Sadik Armagan1625efc2021-06-10 18:24:34 +0100230 CHECK(profilingStateMachine.GetCurrentState() == ProfilingState::WaitingForAck);
Finn Williams09ad6f92019-12-19 17:05:18 +0000231
Colm Donelan2ba48d22019-11-29 09:10:59 +0000232 // Disable stop after timeout and now commandHandler1 should persist after a timeout
233 commandHandler1.SetStopAfterTimeout(false);
234 // Restart the thread.
235 commandHandler1.Start(testProfilingConnectionTimeOutError);
236
237 // Wait for at the three timeouts and the ack to be sent.
238 for (int i = 0; i < 10; i++)
239 {
240 if (testProfilingConnectionTimeOutError.ReadCalledCount() > 3)
241 {
242 break;
243 }
244 std::this_thread::sleep_for(std::chrono::milliseconds(2));
245 }
246 commandHandler1.Stop();
247
248 // Even after the 3 exceptions the ack packet should have transitioned the command handler to active.
Sadik Armagan1625efc2021-06-10 18:24:34 +0100249 CHECK(profilingStateMachine.GetCurrentState() == ProfilingState::Active);
Colm Donelan2ba48d22019-11-29 09:10:59 +0000250
251 // A command handler that gets exceptions other than timeouts should keep going.
252 CommandHandler commandHandler2(1, false, commandHandlerRegistry, packetVersionResolver);
FinnWilliamsArm4833cea2019-09-17 16:53:53 +0100253
Matteo Martincigh8a837172019-10-04 17:01:07 +0100254 commandHandler2.Start(testProfilingConnectionArmnnError);
255
Colm Donelan2ba48d22019-11-29 09:10:59 +0000256 // Wait for two exceptions to be thrown.
257 for (int i = 0; i < 10; i++)
258 {
259 if (testProfilingConnectionTimeOutError.ReadCalledCount() >= 2)
260 {
261 break;
262 }
263 std::this_thread::sleep_for(std::chrono::milliseconds(2));
264 }
FinnWilliamsArm4833cea2019-09-17 16:53:53 +0100265
Sadik Armagan1625efc2021-06-10 18:24:34 +0100266 CHECK(commandHandler2.IsRunning());
Matteo Martincigh8a837172019-10-04 17:01:07 +0100267 commandHandler2.Stop();
FinnWilliamsArm4833cea2019-09-17 16:53:53 +0100268}
269
Sadik Armagan1625efc2021-06-10 18:24:34 +0100270TEST_CASE("CheckEncodeVersion")
Nikhil Rajd88e47c2019-08-19 10:04:23 +0100271{
Jim Flynnbbfe6032020-07-20 16:57:44 +0100272 arm::pipe::Version version1(12);
Nikhil Rajd88e47c2019-08-19 10:04:23 +0100273
Sadik Armagan1625efc2021-06-10 18:24:34 +0100274 CHECK(version1.GetMajor() == 0);
275 CHECK(version1.GetMinor() == 0);
276 CHECK(version1.GetPatch() == 12);
Nikhil Rajd88e47c2019-08-19 10:04:23 +0100277
Jim Flynnbbfe6032020-07-20 16:57:44 +0100278 arm::pipe::Version version2(4108);
Nikhil Rajd88e47c2019-08-19 10:04:23 +0100279
Sadik Armagan1625efc2021-06-10 18:24:34 +0100280 CHECK(version2.GetMajor() == 0);
281 CHECK(version2.GetMinor() == 1);
282 CHECK(version2.GetPatch() == 12);
Nikhil Rajd88e47c2019-08-19 10:04:23 +0100283
Jim Flynnbbfe6032020-07-20 16:57:44 +0100284 arm::pipe::Version version3(4198412);
Nikhil Rajd88e47c2019-08-19 10:04:23 +0100285
Sadik Armagan1625efc2021-06-10 18:24:34 +0100286 CHECK(version3.GetMajor() == 1);
287 CHECK(version3.GetMinor() == 1);
288 CHECK(version3.GetPatch() == 12);
Nikhil Rajd88e47c2019-08-19 10:04:23 +0100289
Jim Flynnbbfe6032020-07-20 16:57:44 +0100290 arm::pipe::Version version4(0);
Nikhil Rajd88e47c2019-08-19 10:04:23 +0100291
Sadik Armagan1625efc2021-06-10 18:24:34 +0100292 CHECK(version4.GetMajor() == 0);
293 CHECK(version4.GetMinor() == 0);
294 CHECK(version4.GetPatch() == 0);
Nikhil Rajd88e47c2019-08-19 10:04:23 +0100295
Jim Flynnbbfe6032020-07-20 16:57:44 +0100296 arm::pipe::Version version5(1, 0, 0);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100297 CHECK(version5.GetEncodedValue() == 4194304);
Nikhil Rajd88e47c2019-08-19 10:04:23 +0100298}
299
Sadik Armagan1625efc2021-06-10 18:24:34 +0100300TEST_CASE("CheckPacketClass")
Nikhil Rajbc626052019-08-15 15:49:45 +0100301{
Keith Davis3201eea2019-10-24 17:30:41 +0100302 uint32_t length = 4;
Matteo Martincigh67ef2a52019-10-10 13:29:02 +0100303 std::unique_ptr<unsigned char[]> packetData0 = std::make_unique<unsigned char[]>(length);
304 std::unique_ptr<unsigned char[]> packetData1 = std::make_unique<unsigned char[]>(0);
305 std::unique_ptr<unsigned char[]> nullPacketData;
Nikhil Rajbc626052019-08-15 15:49:45 +0100306
Jim Flynnbbfe6032020-07-20 16:57:44 +0100307 arm::pipe::Packet packetTest0(472580096, length, packetData0);
Nikhil Rajbc626052019-08-15 15:49:45 +0100308
Sadik Armagan1625efc2021-06-10 18:24:34 +0100309 CHECK(packetTest0.GetHeader() == 472580096);
310 CHECK(packetTest0.GetPacketFamily() == 7);
311 CHECK(packetTest0.GetPacketId() == 43);
312 CHECK(packetTest0.GetLength() == length);
313 CHECK(packetTest0.GetPacketType() == 3);
314 CHECK(packetTest0.GetPacketClass() == 5);
Nikhil Rajbc626052019-08-15 15:49:45 +0100315
Sadik Armagan1625efc2021-06-10 18:24:34 +0100316 CHECK_THROWS_AS(arm::pipe::Packet packetTest1(472580096, 0, packetData1), arm::pipe::InvalidArgumentException);
317 CHECK_NOTHROW(arm::pipe::Packet packetTest2(472580096, 0, nullPacketData));
Nikhil Rajbc626052019-08-15 15:49:45 +0100318
Jim Flynnbbfe6032020-07-20 16:57:44 +0100319 arm::pipe::Packet packetTest3(472580096, 0, nullPacketData);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100320 CHECK(packetTest3.GetLength() == 0);
321 CHECK(packetTest3.GetData() == nullptr);
FinnWilliamsArma0c78712019-09-16 12:06:47 +0100322
Matteo Martincigh67ef2a52019-10-10 13:29:02 +0100323 const unsigned char* packetTest0Data = packetTest0.GetData();
Jim Flynnbbfe6032020-07-20 16:57:44 +0100324 arm::pipe::Packet packetTest4(std::move(packetTest0));
FinnWilliamsArma0c78712019-09-16 12:06:47 +0100325
Sadik Armagan1625efc2021-06-10 18:24:34 +0100326 CHECK(packetTest0.GetData() == nullptr);
327 CHECK(packetTest4.GetData() == packetTest0Data);
FinnWilliamsArma0c78712019-09-16 12:06:47 +0100328
Sadik Armagan1625efc2021-06-10 18:24:34 +0100329 CHECK(packetTest4.GetHeader() == 472580096);
330 CHECK(packetTest4.GetPacketFamily() == 7);
331 CHECK(packetTest4.GetPacketId() == 43);
332 CHECK(packetTest4.GetLength() == length);
333 CHECK(packetTest4.GetPacketType() == 3);
334 CHECK(packetTest4.GetPacketClass() == 5);
Nikhil Rajbc626052019-08-15 15:49:45 +0100335}
336
Sadik Armagan1625efc2021-06-10 18:24:34 +0100337TEST_CASE("CheckCommandHandlerFunctor")
Francis Murtagh11f99b42019-08-16 11:28:52 +0100338{
Francis Murtagh11f99b42019-08-16 11:28:52 +0100339 // Hard code the version as it will be the same during a single profiling session
340 uint32_t version = 1;
341
Jim Flynn397043f2019-10-17 17:37:10 +0100342 TestFunctorA testFunctorA(7, 461, version);
343 TestFunctorB testFunctorB(8, 963, version);
344 TestFunctorC testFunctorC(5, 983, version);
Francis Murtagh11f99b42019-08-16 11:28:52 +0100345
Jim Flynnbbfe6032020-07-20 16:57:44 +0100346 arm::pipe::CommandHandlerKey keyA(
347 testFunctorA.GetFamilyId(), testFunctorA.GetPacketId(), testFunctorA.GetVersion());
348 arm::pipe::CommandHandlerKey keyB(
349 testFunctorB.GetFamilyId(), testFunctorB.GetPacketId(), testFunctorB.GetVersion());
350 arm::pipe::CommandHandlerKey keyC(
351 testFunctorC.GetFamilyId(), testFunctorC.GetPacketId(), testFunctorC.GetVersion());
Francis Murtagh11f99b42019-08-16 11:28:52 +0100352
353 // Create the unwrapped map to simulate the Command Handler Registry
Jim Flynnbbfe6032020-07-20 16:57:44 +0100354 std::map<arm::pipe::CommandHandlerKey, arm::pipe::CommandHandlerFunctor*> registry;
Francis Murtagh11f99b42019-08-16 11:28:52 +0100355
356 registry.insert(std::make_pair(keyB, &testFunctorB));
357 registry.insert(std::make_pair(keyA, &testFunctorA));
358 registry.insert(std::make_pair(keyC, &testFunctorC));
359
360 // Check the order of the map is correct
361 auto it = registry.begin();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100362 CHECK(it->first == keyC); // familyId == 5
Francis Murtagh11f99b42019-08-16 11:28:52 +0100363 it++;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100364 CHECK(it->first == keyA); // familyId == 7
Francis Murtagh11f99b42019-08-16 11:28:52 +0100365 it++;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100366 CHECK(it->first == keyB); // familyId == 8
Francis Murtagh11f99b42019-08-16 11:28:52 +0100367
Matteo Martincigh67ef2a52019-10-10 13:29:02 +0100368 std::unique_ptr<unsigned char[]> packetDataA;
369 std::unique_ptr<unsigned char[]> packetDataB;
370 std::unique_ptr<unsigned char[]> packetDataC;
FinnWilliamsArma0c78712019-09-16 12:06:47 +0100371
Jim Flynnbbfe6032020-07-20 16:57:44 +0100372 arm::pipe::Packet packetA(500000000, 0, packetDataA);
373 arm::pipe::Packet packetB(600000000, 0, packetDataB);
374 arm::pipe::Packet packetC(400000000, 0, packetDataC);
Francis Murtagh11f99b42019-08-16 11:28:52 +0100375
376 // Check the correct operator of derived class is called
Jim Flynnbbfe6032020-07-20 16:57:44 +0100377 registry.at(arm::pipe::CommandHandlerKey(
378 packetA.GetPacketFamily(), packetA.GetPacketId(), version))->operator()(packetA);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100379 CHECK(testFunctorA.GetCount() == 1);
380 CHECK(testFunctorB.GetCount() == 0);
381 CHECK(testFunctorC.GetCount() == 0);
Francis Murtagh11f99b42019-08-16 11:28:52 +0100382
Jim Flynnbbfe6032020-07-20 16:57:44 +0100383 registry.at(arm::pipe::CommandHandlerKey(
384 packetB.GetPacketFamily(), packetB.GetPacketId(), version))->operator()(packetB);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100385 CHECK(testFunctorA.GetCount() == 1);
386 CHECK(testFunctorB.GetCount() == 1);
387 CHECK(testFunctorC.GetCount() == 0);
Francis Murtagh11f99b42019-08-16 11:28:52 +0100388
Jim Flynnbbfe6032020-07-20 16:57:44 +0100389 registry.at(arm::pipe::CommandHandlerKey(
390 packetC.GetPacketFamily(), packetC.GetPacketId(), version))->operator()(packetC);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100391 CHECK(testFunctorA.GetCount() == 1);
392 CHECK(testFunctorB.GetCount() == 1);
393 CHECK(testFunctorC.GetCount() == 1);
Francis Murtagh11f99b42019-08-16 11:28:52 +0100394}
395
Sadik Armagan1625efc2021-06-10 18:24:34 +0100396TEST_CASE("CheckCommandHandlerRegistry")
Francis Murtagh94d79152019-08-16 17:45:07 +0100397{
398 // Hard code the version as it will be the same during a single profiling session
399 uint32_t version = 1;
400
Jim Flynn397043f2019-10-17 17:37:10 +0100401 TestFunctorA testFunctorA(7, 461, version);
402 TestFunctorB testFunctorB(8, 963, version);
403 TestFunctorC testFunctorC(5, 983, version);
Francis Murtagh94d79152019-08-16 17:45:07 +0100404
405 // Create the Command Handler Registry
Jim Flynnbbfe6032020-07-20 16:57:44 +0100406 arm::pipe::CommandHandlerRegistry registry;
Francis Murtagh94d79152019-08-16 17:45:07 +0100407
408 // Register multiple different derived classes
Matteo Martincighc2728f92019-10-07 12:35:21 +0100409 registry.RegisterFunctor(&testFunctorA);
410 registry.RegisterFunctor(&testFunctorB);
411 registry.RegisterFunctor(&testFunctorC);
Francis Murtagh94d79152019-08-16 17:45:07 +0100412
Matteo Martincigh67ef2a52019-10-10 13:29:02 +0100413 std::unique_ptr<unsigned char[]> packetDataA;
414 std::unique_ptr<unsigned char[]> packetDataB;
415 std::unique_ptr<unsigned char[]> packetDataC;
FinnWilliamsArma0c78712019-09-16 12:06:47 +0100416
Jim Flynnbbfe6032020-07-20 16:57:44 +0100417 arm::pipe::Packet packetA(500000000, 0, packetDataA);
418 arm::pipe::Packet packetB(600000000, 0, packetDataB);
419 arm::pipe::Packet packetC(400000000, 0, packetDataC);
Francis Murtagh94d79152019-08-16 17:45:07 +0100420
421 // Check the correct operator of derived class is called
Jim Flynn397043f2019-10-17 17:37:10 +0100422 registry.GetFunctor(packetA.GetPacketFamily(), packetA.GetPacketId(), version)->operator()(packetA);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100423 CHECK(testFunctorA.GetCount() == 1);
424 CHECK(testFunctorB.GetCount() == 0);
425 CHECK(testFunctorC.GetCount() == 0);
Francis Murtagh94d79152019-08-16 17:45:07 +0100426
Jim Flynn397043f2019-10-17 17:37:10 +0100427 registry.GetFunctor(packetB.GetPacketFamily(), packetB.GetPacketId(), version)->operator()(packetB);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100428 CHECK(testFunctorA.GetCount() == 1);
429 CHECK(testFunctorB.GetCount() == 1);
430 CHECK(testFunctorC.GetCount() == 0);
Francis Murtagh94d79152019-08-16 17:45:07 +0100431
Jim Flynn397043f2019-10-17 17:37:10 +0100432 registry.GetFunctor(packetC.GetPacketFamily(), packetC.GetPacketId(), version)->operator()(packetC);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100433 CHECK(testFunctorA.GetCount() == 1);
434 CHECK(testFunctorB.GetCount() == 1);
435 CHECK(testFunctorC.GetCount() == 1);
Francis Murtagh94d79152019-08-16 17:45:07 +0100436
437 // Re-register an existing key with a new function
Jim Flynn397043f2019-10-17 17:37:10 +0100438 registry.RegisterFunctor(&testFunctorC, testFunctorA.GetFamilyId(), testFunctorA.GetPacketId(), version);
439 registry.GetFunctor(packetA.GetPacketFamily(), packetA.GetPacketId(), version)->operator()(packetC);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100440 CHECK(testFunctorA.GetCount() == 1);
441 CHECK(testFunctorB.GetCount() == 1);
442 CHECK(testFunctorC.GetCount() == 2);
Francis Murtagh94d79152019-08-16 17:45:07 +0100443
444 // Check that non-existent key returns nullptr for its functor
Sadik Armagan1625efc2021-06-10 18:24:34 +0100445 CHECK_THROWS_AS(registry.GetFunctor(0, 0, 0), arm::pipe::ProfilingException);
Francis Murtagh94d79152019-08-16 17:45:07 +0100446}
447
Sadik Armagan1625efc2021-06-10 18:24:34 +0100448TEST_CASE("CheckPacketVersionResolver")
Aron Virginas-Tare898db92019-08-22 12:56:34 +0100449{
450 // Set up random number generator for generating packetId values
451 std::random_device device;
452 std::mt19937 generator(device());
453 std::uniform_int_distribution<uint32_t> distribution(std::numeric_limits<uint32_t>::min(),
454 std::numeric_limits<uint32_t>::max());
455
456 // NOTE: Expected version is always 1.0.0, regardless of packetId
Jim Flynnbbfe6032020-07-20 16:57:44 +0100457 const arm::pipe::Version expectedVersion(1, 0, 0);
Aron Virginas-Tare898db92019-08-22 12:56:34 +0100458
Jim Flynnbbfe6032020-07-20 16:57:44 +0100459 arm::pipe::PacketVersionResolver packetVersionResolver;
Aron Virginas-Tare898db92019-08-22 12:56:34 +0100460
461 constexpr unsigned int numTests = 10u;
462
463 for (unsigned int i = 0u; i < numTests; ++i)
464 {
Jim Flynned25e0e2019-10-18 13:21:43 +0100465 const uint32_t familyId = distribution(generator);
Aron Virginas-Tare898db92019-08-22 12:56:34 +0100466 const uint32_t packetId = distribution(generator);
Jim Flynnbbfe6032020-07-20 16:57:44 +0100467 arm::pipe::Version resolvedVersion = packetVersionResolver.ResolvePacketVersion(familyId, packetId);
Aron Virginas-Tare898db92019-08-22 12:56:34 +0100468
Sadik Armagan1625efc2021-06-10 18:24:34 +0100469 CHECK(resolvedVersion == expectedVersion);
Aron Virginas-Tare898db92019-08-22 12:56:34 +0100470 }
471}
Matteo Martincighd0613b52019-10-09 16:47:04 +0100472
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100473void ProfilingCurrentStateThreadImpl(ProfilingStateMachine& states)
474{
475 ProfilingState newState = ProfilingState::NotConnected;
476 states.GetCurrentState();
477 states.TransitionToState(newState);
478}
479
Sadik Armagan1625efc2021-06-10 18:24:34 +0100480TEST_CASE("CheckProfilingStateMachine")
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100481{
482 ProfilingStateMachine profilingState1(ProfilingState::Uninitialised);
483 profilingState1.TransitionToState(ProfilingState::Uninitialised);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100484 CHECK(profilingState1.GetCurrentState() == ProfilingState::Uninitialised);
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100485
486 ProfilingStateMachine profilingState2(ProfilingState::Uninitialised);
487 profilingState2.TransitionToState(ProfilingState::NotConnected);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100488 CHECK(profilingState2.GetCurrentState() == ProfilingState::NotConnected);
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100489
490 ProfilingStateMachine profilingState3(ProfilingState::NotConnected);
491 profilingState3.TransitionToState(ProfilingState::NotConnected);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100492 CHECK(profilingState3.GetCurrentState() == ProfilingState::NotConnected);
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100493
494 ProfilingStateMachine profilingState4(ProfilingState::NotConnected);
495 profilingState4.TransitionToState(ProfilingState::WaitingForAck);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100496 CHECK(profilingState4.GetCurrentState() == ProfilingState::WaitingForAck);
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100497
498 ProfilingStateMachine profilingState5(ProfilingState::WaitingForAck);
499 profilingState5.TransitionToState(ProfilingState::WaitingForAck);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100500 CHECK(profilingState5.GetCurrentState() == ProfilingState::WaitingForAck);
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100501
502 ProfilingStateMachine profilingState6(ProfilingState::WaitingForAck);
503 profilingState6.TransitionToState(ProfilingState::Active);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100504 CHECK(profilingState6.GetCurrentState() == ProfilingState::Active);
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100505
506 ProfilingStateMachine profilingState7(ProfilingState::Active);
507 profilingState7.TransitionToState(ProfilingState::NotConnected);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100508 CHECK(profilingState7.GetCurrentState() == ProfilingState::NotConnected);
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100509
510 ProfilingStateMachine profilingState8(ProfilingState::Active);
511 profilingState8.TransitionToState(ProfilingState::Active);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100512 CHECK(profilingState8.GetCurrentState() == ProfilingState::Active);
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100513
514 ProfilingStateMachine profilingState9(ProfilingState::Uninitialised);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100515 CHECK_THROWS_AS(profilingState9.TransitionToState(ProfilingState::WaitingForAck), armnn::Exception);
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100516
517 ProfilingStateMachine profilingState10(ProfilingState::Uninitialised);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100518 CHECK_THROWS_AS(profilingState10.TransitionToState(ProfilingState::Active), armnn::Exception);
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100519
520 ProfilingStateMachine profilingState11(ProfilingState::NotConnected);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100521 CHECK_THROWS_AS(profilingState11.TransitionToState(ProfilingState::Uninitialised), armnn::Exception);
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100522
523 ProfilingStateMachine profilingState12(ProfilingState::NotConnected);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100524 CHECK_THROWS_AS(profilingState12.TransitionToState(ProfilingState::Active), armnn::Exception);
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100525
526 ProfilingStateMachine profilingState13(ProfilingState::WaitingForAck);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100527 CHECK_THROWS_AS(profilingState13.TransitionToState(ProfilingState::Uninitialised), armnn::Exception);
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100528
529 ProfilingStateMachine profilingState14(ProfilingState::WaitingForAck);
Jim Flynn53e46992019-10-14 12:31:10 +0100530 profilingState14.TransitionToState(ProfilingState::NotConnected);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100531 CHECK(profilingState14.GetCurrentState() == ProfilingState::NotConnected);
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100532
533 ProfilingStateMachine profilingState15(ProfilingState::Active);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100534 CHECK_THROWS_AS(profilingState15.TransitionToState(ProfilingState::Uninitialised), armnn::Exception);
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100535
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000536 ProfilingStateMachine profilingState16(ProfilingState::Active);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100537 CHECK_THROWS_AS(profilingState16.TransitionToState(ProfilingState::WaitingForAck), armnn::Exception);
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100538
539 ProfilingStateMachine profilingState17(ProfilingState::Uninitialised);
540
Sadik Armagan95e9efc2021-08-05 15:01:07 +0100541 std::vector<std::thread> threads;
542 for (unsigned int i = 0; i < 5; ++i)
543 {
544 threads.push_back(std::thread(ProfilingCurrentStateThreadImpl, std::ref(profilingState17)));
545 }
546 std::for_each(threads.begin(), threads.end(), [](std::thread& theThread)
547 {
548 theThread.join();
549 });
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100550
Sadik Armagan1625efc2021-06-10 18:24:34 +0100551 CHECK((profilingState17.GetCurrentState() == ProfilingState::NotConnected));
Nikhil Raj3ecc5102019-09-03 15:55:33 +0100552}
Aron Virginas-Tare898db92019-08-22 12:56:34 +0100553
Jim Flynn8355ec92019-09-17 12:29:50 +0100554void CaptureDataWriteThreadImpl(Holder& holder, uint32_t capturePeriod, const std::vector<uint16_t>& counterIds)
Francis Murtagh68f78d82019-09-04 16:42:29 +0100555{
Finn Williams032bc742020-02-12 11:02:34 +0000556 holder.SetCaptureData(capturePeriod, counterIds, {});
Francis Murtagh68f78d82019-09-04 16:42:29 +0100557}
558
Francis Murtaghbd707162019-09-09 11:26:44 +0100559void CaptureDataReadThreadImpl(const Holder& holder, CaptureData& captureData)
Francis Murtagh68f78d82019-09-04 16:42:29 +0100560{
561 captureData = holder.GetCaptureData();
562}
563
Sadik Armagan1625efc2021-06-10 18:24:34 +0100564TEST_CASE("CheckCaptureDataHolder")
Francis Murtagh68f78d82019-09-04 16:42:29 +0100565{
Francis Murtaghbd707162019-09-09 11:26:44 +0100566 std::map<uint32_t, std::vector<uint16_t>> periodIdMap;
567 std::vector<uint16_t> counterIds;
Jim Flynn8355ec92019-09-17 12:29:50 +0100568 uint32_t numThreads = 10;
569 for (uint32_t i = 0; i < numThreads; ++i)
Francis Murtaghbd707162019-09-09 11:26:44 +0100570 {
571 counterIds.emplace_back(i);
572 periodIdMap.insert(std::make_pair(i, counterIds));
573 }
Francis Murtagh68f78d82019-09-04 16:42:29 +0100574
Jim Flynn8355ec92019-09-17 12:29:50 +0100575 // Verify the read and write threads set the holder correctly
576 // and retrieve the expected values
Francis Murtagh68f78d82019-09-04 16:42:29 +0100577 Holder holder;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100578 CHECK((holder.GetCaptureData()).GetCapturePeriod() == 0);
579 CHECK(((holder.GetCaptureData()).GetCounterIds()).empty());
Francis Murtagh68f78d82019-09-04 16:42:29 +0100580
581 // Check Holder functions
Francis Murtaghbd707162019-09-09 11:26:44 +0100582 std::thread thread1(CaptureDataWriteThreadImpl, std::ref(holder), 2, std::ref(periodIdMap[2]));
Francis Murtagh68f78d82019-09-04 16:42:29 +0100583 thread1.join();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100584 CHECK((holder.GetCaptureData()).GetCapturePeriod() == 2);
585 CHECK((holder.GetCaptureData()).GetCounterIds() == periodIdMap[2]);
Jim Flynn8355ec92019-09-17 12:29:50 +0100586 // NOTE: now that we have some initial values in the holder we don't have to worry
587 // in the multi-threaded section below about a read thread accessing the holder
588 // before any write thread has gotten to it so we read period = 0, counterIds empty
589 // instead of period = 0, counterIds = {0} as will the case when write thread 0
590 // has executed.
Francis Murtagh68f78d82019-09-04 16:42:29 +0100591
592 CaptureData captureData;
593 std::thread thread2(CaptureDataReadThreadImpl, std::ref(holder), std::ref(captureData));
594 thread2.join();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100595 CHECK(captureData.GetCapturePeriod() == 2);
596 CHECK(captureData.GetCounterIds() == periodIdMap[2]);
Francis Murtagh68f78d82019-09-04 16:42:29 +0100597
Jim Flynn8355ec92019-09-17 12:29:50 +0100598 std::map<uint32_t, CaptureData> captureDataIdMap;
599 for (uint32_t i = 0; i < numThreads; ++i)
600 {
601 CaptureData perThreadCaptureData;
602 captureDataIdMap.insert(std::make_pair(i, perThreadCaptureData));
603 }
604
Francis Murtaghbd707162019-09-09 11:26:44 +0100605 std::vector<std::thread> threadsVect;
Jim Flynn8355ec92019-09-17 12:29:50 +0100606 std::vector<std::thread> readThreadsVect;
607 for (uint32_t i = 0; i < numThreads; ++i)
Francis Murtaghbd707162019-09-09 11:26:44 +0100608 {
Keith Davis3201eea2019-10-24 17:30:41 +0100609 threadsVect.emplace_back(
610 std::thread(CaptureDataWriteThreadImpl, std::ref(holder), i, std::ref(periodIdMap[i])));
Francis Murtagh06965692019-09-05 16:29:01 +0100611
Jim Flynn8355ec92019-09-17 12:29:50 +0100612 // Verify that the CaptureData goes into the thread in a virgin state
Sadik Armagan1625efc2021-06-10 18:24:34 +0100613 CHECK(captureDataIdMap.at(i).GetCapturePeriod() == 0);
614 CHECK(captureDataIdMap.at(i).GetCounterIds().empty());
Keith Davis3201eea2019-10-24 17:30:41 +0100615 readThreadsVect.emplace_back(
616 std::thread(CaptureDataReadThreadImpl, std::ref(holder), std::ref(captureDataIdMap.at(i))));
Francis Murtaghbd707162019-09-09 11:26:44 +0100617 }
618
Jim Flynn8355ec92019-09-17 12:29:50 +0100619 for (uint32_t i = 0; i < numThreads; ++i)
Francis Murtaghbd707162019-09-09 11:26:44 +0100620 {
621 threadsVect[i].join();
Francis Murtaghbd707162019-09-09 11:26:44 +0100622 readThreadsVect[i].join();
623 }
Francis Murtagh68f78d82019-09-04 16:42:29 +0100624
Jim Flynn8355ec92019-09-17 12:29:50 +0100625 // Look at the CaptureData that each read thread has filled
626 // the capture period it read should match the counter ids entry
627 for (uint32_t i = 0; i < numThreads; ++i)
628 {
629 CaptureData perThreadCaptureData = captureDataIdMap.at(i);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100630 CHECK(perThreadCaptureData.GetCounterIds() == periodIdMap.at(perThreadCaptureData.GetCapturePeriod()));
Jim Flynn8355ec92019-09-17 12:29:50 +0100631 }
Matthew Bentham46d1c622019-09-13 12:45:04 +0100632}
Francis Murtagh68f78d82019-09-04 16:42:29 +0100633
Sadik Armagan1625efc2021-06-10 18:24:34 +0100634TEST_CASE("CaptureDataMethods")
Matthew Bentham46d1c622019-09-13 12:45:04 +0100635{
Jim Flynn8355ec92019-09-17 12:29:50 +0100636 // Check CaptureData setter and getter functions
Keith Davis3201eea2019-10-24 17:30:41 +0100637 std::vector<uint16_t> counterIds = { 42, 29, 13 };
Jim Flynn8355ec92019-09-17 12:29:50 +0100638 CaptureData captureData;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100639 CHECK(captureData.GetCapturePeriod() == 0);
640 CHECK((captureData.GetCounterIds()).empty());
Jim Flynn8355ec92019-09-17 12:29:50 +0100641 captureData.SetCapturePeriod(150);
642 captureData.SetCounterIds(counterIds);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100643 CHECK(captureData.GetCapturePeriod() == 150);
644 CHECK(captureData.GetCounterIds() == counterIds);
Francis Murtagh68f78d82019-09-04 16:42:29 +0100645
Jim Flynn8355ec92019-09-17 12:29:50 +0100646 // Check assignment operator
Francis Murtagh68f78d82019-09-04 16:42:29 +0100647 CaptureData secondCaptureData;
Francis Murtagh68f78d82019-09-04 16:42:29 +0100648
Jim Flynn8355ec92019-09-17 12:29:50 +0100649 secondCaptureData = captureData;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100650 CHECK(secondCaptureData.GetCapturePeriod() == 150);
651 CHECK(secondCaptureData.GetCounterIds() == counterIds);
Francis Murtagh68f78d82019-09-04 16:42:29 +0100652
653 // Check copy constructor
Jim Flynn8355ec92019-09-17 12:29:50 +0100654 CaptureData copyConstructedCaptureData(captureData);
Francis Murtagh68f78d82019-09-04 16:42:29 +0100655
Sadik Armagan1625efc2021-06-10 18:24:34 +0100656 CHECK(copyConstructedCaptureData.GetCapturePeriod() == 150);
657 CHECK(copyConstructedCaptureData.GetCounterIds() == counterIds);
Keith Davis02356de2019-08-26 18:28:17 +0100658}
Francis Murtagh68f78d82019-09-04 16:42:29 +0100659
Sadik Armagan1625efc2021-06-10 18:24:34 +0100660TEST_CASE("CheckProfilingServiceDisabled")
Keith Davis02356de2019-08-26 18:28:17 +0100661{
Jim Flynn4c9ed1d2022-01-23 23:57:20 +0000662 ProfilingOptions options;
Jim Flynn34430252022-03-04 15:03:58 +0000663 armnn::ArmNNProfilingServiceInitialiser initialiser;
664 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100665 profilingService.ResetExternalProfilingOptions(options, true);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100666 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100667 profilingService.Update();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100668 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Keith Davis02356de2019-08-26 18:28:17 +0100669}
670
Sadik Armagan1625efc2021-06-10 18:24:34 +0100671TEST_CASE("CheckProfilingServiceCounterDirectory")
FinnWilliamsArmce2d9d12019-09-18 10:28:16 +0100672{
Jim Flynn4c9ed1d2022-01-23 23:57:20 +0000673 ProfilingOptions options;
Jim Flynn34430252022-03-04 15:03:58 +0000674 armnn::ArmNNProfilingServiceInitialiser initialiser;
675 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100676 profilingService.ResetExternalProfilingOptions(options, true);
FinnWilliamsArmce2d9d12019-09-18 10:28:16 +0100677
Matteo Martincigha84edee2019-10-02 12:50:57 +0100678 const ICounterDirectory& counterDirectory0 = profilingService.GetCounterDirectory();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100679 CHECK(counterDirectory0.GetCounterCount() == 0);
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100680 profilingService.Update();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100681 CHECK(counterDirectory0.GetCounterCount() == 0);
FinnWilliamsArmce2d9d12019-09-18 10:28:16 +0100682
683 options.m_EnableProfiling = true;
Matteo Martincigha84edee2019-10-02 12:50:57 +0100684 profilingService.ResetExternalProfilingOptions(options);
FinnWilliamsArmce2d9d12019-09-18 10:28:16 +0100685
Matteo Martincigha84edee2019-10-02 12:50:57 +0100686 const ICounterDirectory& counterDirectory1 = profilingService.GetCounterDirectory();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100687 CHECK(counterDirectory1.GetCounterCount() == 0);
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100688 profilingService.Update();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100689 CHECK(counterDirectory1.GetCounterCount() != 0);
Colm Donelan2ba48d22019-11-29 09:10:59 +0000690 // Reset the profiling service to stop any running thread
691 options.m_EnableProfiling = false;
692 profilingService.ResetExternalProfilingOptions(options, true);
FinnWilliamsArmce2d9d12019-09-18 10:28:16 +0100693}
694
Sadik Armagan1625efc2021-06-10 18:24:34 +0100695TEST_CASE("CheckProfilingServiceCounterValues")
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100696{
Jim Flynn4c9ed1d2022-01-23 23:57:20 +0000697 ProfilingOptions options;
Keith Davis3201eea2019-10-24 17:30:41 +0100698 options.m_EnableProfiling = true;
Jim Flynn34430252022-03-04 15:03:58 +0000699 armnn::ArmNNProfilingServiceInitialiser initialiser;
700 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Matteo Martincigha84edee2019-10-02 12:50:57 +0100701 profilingService.ResetExternalProfilingOptions(options, true);
702
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100703 profilingService.Update();
Matteo Martincigha84edee2019-10-02 12:50:57 +0100704 const ICounterDirectory& counterDirectory = profilingService.GetCounterDirectory();
Keith Davis3201eea2019-10-24 17:30:41 +0100705 const Counters& counters = counterDirectory.GetCounters();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100706 CHECK(!counters.empty());
Matteo Martincigha84edee2019-10-02 12:50:57 +0100707
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100708 std::vector<std::thread> writers;
709
Sadik Armagan1625efc2021-06-10 18:24:34 +0100710 CHECK(!counters.empty());
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000711 uint16_t inferencesRun = INFERENCES_RUN;
Finn Williamsf3fcf322020-05-11 14:38:02 +0100712
713 // Test GetAbsoluteCounterValue
714 for (int i = 0; i < 4; ++i)
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100715 {
Finn Williamsf3fcf322020-05-11 14:38:02 +0100716 // Increment and decrement the INFERENCES_RUN counter 250 times
Sadik Armagan95e9efc2021-08-05 15:01:07 +0100717 writers.push_back(std::thread([&profilingService, inferencesRun]()
Finn Williamsf3fcf322020-05-11 14:38:02 +0100718 {
719 for (int i = 0; i < 250; ++i)
720 {
Sadik Armagan95e9efc2021-08-05 15:01:07 +0100721 profilingService.IncrementCounterValue(inferencesRun);
Finn Williamsf3fcf322020-05-11 14:38:02 +0100722 }
723 }));
724 // Add 10 to the INFERENCES_RUN counter 200 times
Sadik Armagan95e9efc2021-08-05 15:01:07 +0100725 writers.push_back(std::thread([&profilingService, inferencesRun]()
Finn Williamsf3fcf322020-05-11 14:38:02 +0100726 {
727 for (int i = 0; i < 200; ++i)
728 {
Sadik Armagan95e9efc2021-08-05 15:01:07 +0100729 profilingService.AddCounterValue(inferencesRun, 10);
Finn Williamsf3fcf322020-05-11 14:38:02 +0100730 }
731 }));
732 // Subtract 5 from the INFERENCES_RUN counter 200 times
Sadik Armagan95e9efc2021-08-05 15:01:07 +0100733 writers.push_back(std::thread([&profilingService, inferencesRun]()
Finn Williamsf3fcf322020-05-11 14:38:02 +0100734 {
735 for (int i = 0; i < 200; ++i)
736 {
Sadik Armagan95e9efc2021-08-05 15:01:07 +0100737 profilingService.SubtractCounterValue(inferencesRun, 5);
Finn Williamsf3fcf322020-05-11 14:38:02 +0100738 }
739 }));
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100740 }
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100741 std::for_each(writers.begin(), writers.end(), mem_fn(&std::thread::join));
742
Finn Williamsf3fcf322020-05-11 14:38:02 +0100743 uint32_t absoluteCounterValue = 0;
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100744
Sadik Armagan1625efc2021-06-10 18:24:34 +0100745 CHECK_NOTHROW(absoluteCounterValue = profilingService.GetAbsoluteCounterValue(INFERENCES_RUN));
746 CHECK(absoluteCounterValue == 5000);
Finn Williamsf3fcf322020-05-11 14:38:02 +0100747
748 // Test SetCounterValue
Sadik Armagan1625efc2021-06-10 18:24:34 +0100749 CHECK_NOTHROW(profilingService.SetCounterValue(INFERENCES_RUN, 0));
750 CHECK_NOTHROW(absoluteCounterValue = profilingService.GetAbsoluteCounterValue(INFERENCES_RUN));
751 CHECK(absoluteCounterValue == 0);
Finn Williamsf3fcf322020-05-11 14:38:02 +0100752
753 // Test GetDeltaCounterValue
754 writers.clear();
755 uint32_t deltaCounterValue = 0;
756 //Start a reading thread to randomly read the INFERENCES_RUN counter value
Sadik Armagan95e9efc2021-08-05 15:01:07 +0100757 std::thread reader([&profilingService, inferencesRun](uint32_t& deltaCounterValue)
Finn Williamsf3fcf322020-05-11 14:38:02 +0100758 {
759 for (int i = 0; i < 300; ++i)
760 {
Sadik Armagan95e9efc2021-08-05 15:01:07 +0100761 deltaCounterValue += profilingService.GetDeltaCounterValue(inferencesRun);
Finn Williamsf3fcf322020-05-11 14:38:02 +0100762 }
763 }, std::ref(deltaCounterValue));
764
765 for (int i = 0; i < 4; ++i)
766 {
767 // Increment and decrement the INFERENCES_RUN counter 250 times
Sadik Armagan95e9efc2021-08-05 15:01:07 +0100768 writers.push_back(std::thread([&profilingService, inferencesRun]()
Finn Williamsf3fcf322020-05-11 14:38:02 +0100769 {
770 for (int i = 0; i < 250; ++i)
771 {
Sadik Armagan95e9efc2021-08-05 15:01:07 +0100772 profilingService.IncrementCounterValue(inferencesRun);
Finn Williamsf3fcf322020-05-11 14:38:02 +0100773 }
774 }));
775 // Add 10 to the INFERENCES_RUN counter 200 times
Sadik Armagan95e9efc2021-08-05 15:01:07 +0100776 writers.push_back(std::thread([&profilingService, inferencesRun]()
Finn Williamsf3fcf322020-05-11 14:38:02 +0100777 {
778 for (int i = 0; i < 200; ++i)
779 {
Sadik Armagan95e9efc2021-08-05 15:01:07 +0100780 profilingService.AddCounterValue(inferencesRun, 10);
Finn Williamsf3fcf322020-05-11 14:38:02 +0100781 }
782 }));
783 // Subtract 5 from the INFERENCES_RUN counter 200 times
Sadik Armagan95e9efc2021-08-05 15:01:07 +0100784 writers.push_back(std::thread([&profilingService, inferencesRun]()
Finn Williamsf3fcf322020-05-11 14:38:02 +0100785 {
786 for (int i = 0; i < 200; ++i)
787 {
Sadik Armagan95e9efc2021-08-05 15:01:07 +0100788 profilingService.SubtractCounterValue(inferencesRun, 5);
Finn Williamsf3fcf322020-05-11 14:38:02 +0100789 }
790 }));
791 }
792
793 std::for_each(writers.begin(), writers.end(), mem_fn(&std::thread::join));
794 reader.join();
795
796 // Do one last read in case the reader stopped early
797 deltaCounterValue += profilingService.GetDeltaCounterValue(INFERENCES_RUN);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100798 CHECK(deltaCounterValue == 5000);
Finn Williamsf3fcf322020-05-11 14:38:02 +0100799
Colm Donelan2ba48d22019-11-29 09:10:59 +0000800 // Reset the profiling service to stop any running thread
801 options.m_EnableProfiling = false;
802 profilingService.ResetExternalProfilingOptions(options, true);
FinnWilliamsArmf6e534a2019-09-16 15:45:42 +0100803}
804
Sadik Armagan1625efc2021-06-10 18:24:34 +0100805TEST_CASE("CheckProfilingObjectUids")
Matteo Martincighab173e92019-09-05 12:02:04 +0100806{
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100807 uint16_t uid = 0;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100808 CHECK_NOTHROW(uid = GetNextUid());
809 CHECK(uid >= 1);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100810
811 uint16_t nextUid = 0;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100812 CHECK_NOTHROW(nextUid = GetNextUid());
813 CHECK(nextUid > uid);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100814
815 std::vector<uint16_t> counterUids;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100816 CHECK_NOTHROW(counterUids = GetNextCounterUids(uid,0));
817 CHECK(counterUids.size() == 1);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100818
819 std::vector<uint16_t> nextCounterUids;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100820 CHECK_NOTHROW(nextCounterUids = GetNextCounterUids(nextUid, 2));
821 CHECK(nextCounterUids.size() == 2);
822 CHECK(nextCounterUids[0] > counterUids[0]);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100823
824 std::vector<uint16_t> counterUidsMultiCore;
Francis Murtagh1e5afee2021-05-11 09:37:47 +0100825 uint16_t thirdUid = nextCounterUids[0];
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100826 uint16_t numberOfCores = 13;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100827 CHECK_NOTHROW(counterUidsMultiCore = GetNextCounterUids(thirdUid, numberOfCores));
828 CHECK(counterUidsMultiCore.size() == numberOfCores);
829 CHECK(counterUidsMultiCore.front() >= nextCounterUids[0]);
Keith Davis3201eea2019-10-24 17:30:41 +0100830 for (size_t i = 1; i < numberOfCores; i++)
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100831 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100832 CHECK(counterUidsMultiCore[i] == counterUidsMultiCore[i - 1] + 1);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100833 }
Sadik Armagan1625efc2021-06-10 18:24:34 +0100834 CHECK(counterUidsMultiCore.back() == counterUidsMultiCore.front() + numberOfCores - 1);
Matteo Martincighab173e92019-09-05 12:02:04 +0100835}
836
Sadik Armagan1625efc2021-06-10 18:24:34 +0100837TEST_CASE("CheckCounterDirectoryRegisterCategory")
Matteo Martincighab173e92019-09-05 12:02:04 +0100838{
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100839 CounterDirectory counterDirectory;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100840 CHECK(counterDirectory.GetCategoryCount() == 0);
841 CHECK(counterDirectory.GetDeviceCount() == 0);
842 CHECK(counterDirectory.GetCounterSetCount() == 0);
843 CHECK(counterDirectory.GetCounterCount() == 0);
Matteo Martincighab173e92019-09-05 12:02:04 +0100844
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100845 // Register a category with an invalid name
846 const Category* noCategory = nullptr;
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000847 CHECK_THROWS_AS(noCategory = counterDirectory.RegisterCategory(""), arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100848 CHECK(counterDirectory.GetCategoryCount() == 0);
849 CHECK(!noCategory);
Matteo Martincighab173e92019-09-05 12:02:04 +0100850
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100851 // Register a category with an invalid name
Sadik Armagan1625efc2021-06-10 18:24:34 +0100852 CHECK_THROWS_AS(noCategory = counterDirectory.RegisterCategory("invalid category"),
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000853 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100854 CHECK(counterDirectory.GetCategoryCount() == 0);
855 CHECK(!noCategory);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100856
857 // Register a new category
858 const std::string categoryName = "some_category";
Keith Davis3201eea2019-10-24 17:30:41 +0100859 const Category* category = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100860 CHECK_NOTHROW(category = counterDirectory.RegisterCategory(categoryName));
861 CHECK(counterDirectory.GetCategoryCount() == 1);
862 CHECK(category);
863 CHECK(category->m_Name == categoryName);
864 CHECK(category->m_Counters.empty());
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100865
866 // Get the registered category
867 const Category* registeredCategory = counterDirectory.GetCategory(categoryName);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100868 CHECK(counterDirectory.GetCategoryCount() == 1);
869 CHECK(registeredCategory);
870 CHECK(registeredCategory == category);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100871
872 // Try to get a category not registered
873 const Category* notRegisteredCategory = counterDirectory.GetCategory("not_registered_category");
Sadik Armagan1625efc2021-06-10 18:24:34 +0100874 CHECK(counterDirectory.GetCategoryCount() == 1);
875 CHECK(!notRegisteredCategory);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100876
877 // Register a category already registered
878 const Category* anotherCategory = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100879 CHECK_THROWS_AS(anotherCategory = counterDirectory.RegisterCategory(categoryName),
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000880 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100881 CHECK(counterDirectory.GetCategoryCount() == 1);
882 CHECK(!anotherCategory);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100883
884 // Register a device for testing
885 const std::string deviceName = "some_device";
Keith Davis3201eea2019-10-24 17:30:41 +0100886 const Device* device = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100887 CHECK_NOTHROW(device = counterDirectory.RegisterDevice(deviceName));
888 CHECK(counterDirectory.GetDeviceCount() == 1);
889 CHECK(device);
890 CHECK(device->m_Uid >= 1);
891 CHECK(device->m_Name == deviceName);
892 CHECK(device->m_Cores == 0);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100893
894 // Register a new category not associated to any device
895 const std::string categoryWoDeviceName = "some_category_without_device";
Keith Davis3201eea2019-10-24 17:30:41 +0100896 const Category* categoryWoDevice = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100897 CHECK_NOTHROW(categoryWoDevice = counterDirectory.RegisterCategory(categoryWoDeviceName));
898 CHECK(counterDirectory.GetCategoryCount() == 2);
899 CHECK(categoryWoDevice);
900 CHECK(categoryWoDevice->m_Name == categoryWoDeviceName);
901 CHECK(categoryWoDevice->m_Counters.empty());
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100902
Sadik Armagan4c998992020-02-25 12:44:44 +0000903 // Register a new category associated to an invalid device name (already exist)
904 const Category* categoryInvalidDeviceName = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100905 CHECK_THROWS_AS(categoryInvalidDeviceName =
Sadik Armagan4c998992020-02-25 12:44:44 +0000906 counterDirectory.RegisterCategory(categoryWoDeviceName),
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000907 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100908 CHECK(counterDirectory.GetCategoryCount() == 2);
909 CHECK(!categoryInvalidDeviceName);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100910
911 // Register a new category associated to a valid device
912 const std::string categoryWValidDeviceName = "some_category_with_valid_device";
Keith Davis3201eea2019-10-24 17:30:41 +0100913 const Category* categoryWValidDevice = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100914 CHECK_NOTHROW(categoryWValidDevice =
Sadik Armagan4c998992020-02-25 12:44:44 +0000915 counterDirectory.RegisterCategory(categoryWValidDeviceName));
Sadik Armagan1625efc2021-06-10 18:24:34 +0100916 CHECK(counterDirectory.GetCategoryCount() == 3);
917 CHECK(categoryWValidDevice);
918 CHECK(categoryWValidDevice != category);
919 CHECK(categoryWValidDevice->m_Name == categoryWValidDeviceName);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100920
921 // Register a counter set for testing
922 const std::string counterSetName = "some_counter_set";
Keith Davis3201eea2019-10-24 17:30:41 +0100923 const CounterSet* counterSet = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100924 CHECK_NOTHROW(counterSet = counterDirectory.RegisterCounterSet(counterSetName));
925 CHECK(counterDirectory.GetCounterSetCount() == 1);
926 CHECK(counterSet);
927 CHECK(counterSet->m_Uid >= 1);
928 CHECK(counterSet->m_Name == counterSetName);
929 CHECK(counterSet->m_Count == 0);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100930
931 // Register a new category not associated to any counter set
932 const std::string categoryWoCounterSetName = "some_category_without_counter_set";
Keith Davis3201eea2019-10-24 17:30:41 +0100933 const Category* categoryWoCounterSet = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100934 CHECK_NOTHROW(categoryWoCounterSet =
Sadik Armagan4c998992020-02-25 12:44:44 +0000935 counterDirectory.RegisterCategory(categoryWoCounterSetName));
Sadik Armagan1625efc2021-06-10 18:24:34 +0100936 CHECK(counterDirectory.GetCategoryCount() == 4);
937 CHECK(categoryWoCounterSet);
938 CHECK(categoryWoCounterSet->m_Name == categoryWoCounterSetName);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100939
940 // Register a new category associated to a valid counter set
941 const std::string categoryWValidCounterSetName = "some_category_with_valid_counter_set";
Keith Davis3201eea2019-10-24 17:30:41 +0100942 const Category* categoryWValidCounterSet = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100943 CHECK_NOTHROW(categoryWValidCounterSet = counterDirectory.RegisterCategory(categoryWValidCounterSetName));
944 CHECK(counterDirectory.GetCategoryCount() == 5);
945 CHECK(categoryWValidCounterSet);
946 CHECK(categoryWValidCounterSet != category);
947 CHECK(categoryWValidCounterSet->m_Name == categoryWValidCounterSetName);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100948
949 // Register a new category associated to a valid device and counter set
950 const std::string categoryWValidDeviceAndValidCounterSetName = "some_category_with_valid_device_and_counter_set";
Keith Davis3201eea2019-10-24 17:30:41 +0100951 const Category* categoryWValidDeviceAndValidCounterSet = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100952 CHECK_NOTHROW(categoryWValidDeviceAndValidCounterSet = counterDirectory.RegisterCategory(
Sadik Armagan4c998992020-02-25 12:44:44 +0000953 categoryWValidDeviceAndValidCounterSetName));
Sadik Armagan1625efc2021-06-10 18:24:34 +0100954 CHECK(counterDirectory.GetCategoryCount() == 6);
955 CHECK(categoryWValidDeviceAndValidCounterSet);
956 CHECK(categoryWValidDeviceAndValidCounterSet != category);
957 CHECK(categoryWValidDeviceAndValidCounterSet->m_Name == categoryWValidDeviceAndValidCounterSetName);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100958}
959
Sadik Armagan1625efc2021-06-10 18:24:34 +0100960TEST_CASE("CheckCounterDirectoryRegisterDevice")
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100961{
962 CounterDirectory counterDirectory;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100963 CHECK(counterDirectory.GetCategoryCount() == 0);
964 CHECK(counterDirectory.GetDeviceCount() == 0);
965 CHECK(counterDirectory.GetCounterSetCount() == 0);
966 CHECK(counterDirectory.GetCounterCount() == 0);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100967
968 // Register a device with an invalid name
969 const Device* noDevice = nullptr;
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000970 CHECK_THROWS_AS(noDevice = counterDirectory.RegisterDevice(""), arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100971 CHECK(counterDirectory.GetDeviceCount() == 0);
972 CHECK(!noDevice);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100973
974 // Register a device with an invalid name
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000975 CHECK_THROWS_AS(noDevice = counterDirectory.RegisterDevice("inv@lid nam€"), arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100976 CHECK(counterDirectory.GetDeviceCount() == 0);
977 CHECK(!noDevice);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100978
979 // Register a new device with no cores or parent category
980 const std::string deviceName = "some_device";
Keith Davis3201eea2019-10-24 17:30:41 +0100981 const Device* device = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100982 CHECK_NOTHROW(device = counterDirectory.RegisterDevice(deviceName));
983 CHECK(counterDirectory.GetDeviceCount() == 1);
984 CHECK(device);
985 CHECK(device->m_Name == deviceName);
986 CHECK(device->m_Uid >= 1);
987 CHECK(device->m_Cores == 0);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100988
Matteo Martincigh657ab2d2019-09-18 10:53:24 +0100989 // Try getting an unregistered device
990 const Device* unregisteredDevice = counterDirectory.GetDevice(9999);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100991 CHECK(!unregisteredDevice);
Matteo Martincigh657ab2d2019-09-18 10:53:24 +0100992
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100993 // Get the registered device
994 const Device* registeredDevice = counterDirectory.GetDevice(device->m_Uid);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100995 CHECK(counterDirectory.GetDeviceCount() == 1);
996 CHECK(registeredDevice);
997 CHECK(registeredDevice == device);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100998
Matteo Martincigh657ab2d2019-09-18 10:53:24 +0100999 // Register a device with the name of a device already registered
1000 const Device* deviceSameName = nullptr;
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001001 CHECK_THROWS_AS(deviceSameName = counterDirectory.RegisterDevice(deviceName), arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001002 CHECK(counterDirectory.GetDeviceCount() == 1);
1003 CHECK(!deviceSameName);
Matteo Martincigh657ab2d2019-09-18 10:53:24 +01001004
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001005 // Register a new device with cores and no parent category
1006 const std::string deviceWCoresName = "some_device_with_cores";
Keith Davis3201eea2019-10-24 17:30:41 +01001007 const Device* deviceWCores = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001008 CHECK_NOTHROW(deviceWCores = counterDirectory.RegisterDevice(deviceWCoresName, 2));
1009 CHECK(counterDirectory.GetDeviceCount() == 2);
1010 CHECK(deviceWCores);
1011 CHECK(deviceWCores->m_Name == deviceWCoresName);
1012 CHECK(deviceWCores->m_Uid >= 1);
1013 CHECK(deviceWCores->m_Uid > device->m_Uid);
1014 CHECK(deviceWCores->m_Cores == 2);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001015
1016 // Get the registered device
1017 const Device* registeredDeviceWCores = counterDirectory.GetDevice(deviceWCores->m_Uid);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001018 CHECK(counterDirectory.GetDeviceCount() == 2);
1019 CHECK(registeredDeviceWCores);
1020 CHECK(registeredDeviceWCores == deviceWCores);
1021 CHECK(registeredDeviceWCores != device);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001022
1023 // Register a new device with cores and invalid parent category
1024 const std::string deviceWCoresWInvalidParentCategoryName = "some_device_with_cores_with_invalid_parent_category";
Keith Davis3201eea2019-10-24 17:30:41 +01001025 const Device* deviceWCoresWInvalidParentCategory = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001026 CHECK_THROWS_AS(deviceWCoresWInvalidParentCategory =
Keith Davis3201eea2019-10-24 17:30:41 +01001027 counterDirectory.RegisterDevice(deviceWCoresWInvalidParentCategoryName, 3, std::string("")),
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001028 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001029 CHECK(counterDirectory.GetDeviceCount() == 2);
1030 CHECK(!deviceWCoresWInvalidParentCategory);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001031
1032 // Register a new device with cores and invalid parent category
1033 const std::string deviceWCoresWInvalidParentCategoryName2 = "some_device_with_cores_with_invalid_parent_category2";
Keith Davis3201eea2019-10-24 17:30:41 +01001034 const Device* deviceWCoresWInvalidParentCategory2 = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001035 CHECK_THROWS_AS(deviceWCoresWInvalidParentCategory2 = counterDirectory.RegisterDevice(
Keith Davis3201eea2019-10-24 17:30:41 +01001036 deviceWCoresWInvalidParentCategoryName2, 3, std::string("invalid_parent_category")),
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001037 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001038 CHECK(counterDirectory.GetDeviceCount() == 2);
1039 CHECK(!deviceWCoresWInvalidParentCategory2);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001040
1041 // Register a category for testing
1042 const std::string categoryName = "some_category";
Keith Davis3201eea2019-10-24 17:30:41 +01001043 const Category* category = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001044 CHECK_NOTHROW(category = counterDirectory.RegisterCategory(categoryName));
1045 CHECK(counterDirectory.GetCategoryCount() == 1);
1046 CHECK(category);
1047 CHECK(category->m_Name == categoryName);
1048 CHECK(category->m_Counters.empty());
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001049
1050 // Register a new device with cores and valid parent category
1051 const std::string deviceWCoresWValidParentCategoryName = "some_device_with_cores_with_valid_parent_category";
Keith Davis3201eea2019-10-24 17:30:41 +01001052 const Device* deviceWCoresWValidParentCategory = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001053 CHECK_NOTHROW(deviceWCoresWValidParentCategory =
Keith Davis3201eea2019-10-24 17:30:41 +01001054 counterDirectory.RegisterDevice(deviceWCoresWValidParentCategoryName, 4, categoryName));
Sadik Armagan1625efc2021-06-10 18:24:34 +01001055 CHECK(counterDirectory.GetDeviceCount() == 3);
1056 CHECK(deviceWCoresWValidParentCategory);
1057 CHECK(deviceWCoresWValidParentCategory->m_Name == deviceWCoresWValidParentCategoryName);
1058 CHECK(deviceWCoresWValidParentCategory->m_Uid >= 1);
1059 CHECK(deviceWCoresWValidParentCategory->m_Uid > device->m_Uid);
1060 CHECK(deviceWCoresWValidParentCategory->m_Uid > deviceWCores->m_Uid);
1061 CHECK(deviceWCoresWValidParentCategory->m_Cores == 4);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001062}
1063
Sadik Armagan1625efc2021-06-10 18:24:34 +01001064TEST_CASE("CheckCounterDirectoryRegisterCounterSet")
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001065{
1066 CounterDirectory counterDirectory;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001067 CHECK(counterDirectory.GetCategoryCount() == 0);
1068 CHECK(counterDirectory.GetDeviceCount() == 0);
1069 CHECK(counterDirectory.GetCounterSetCount() == 0);
1070 CHECK(counterDirectory.GetCounterCount() == 0);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001071
1072 // Register a counter set with an invalid name
1073 const CounterSet* noCounterSet = nullptr;
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001074 CHECK_THROWS_AS(noCounterSet = counterDirectory.RegisterCounterSet(""), arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001075 CHECK(counterDirectory.GetCounterSetCount() == 0);
1076 CHECK(!noCounterSet);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001077
1078 // Register a counter set with an invalid name
Sadik Armagan1625efc2021-06-10 18:24:34 +01001079 CHECK_THROWS_AS(noCounterSet = counterDirectory.RegisterCounterSet("invalid name"),
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001080 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001081 CHECK(counterDirectory.GetCounterSetCount() == 0);
1082 CHECK(!noCounterSet);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001083
1084 // Register a new counter set with no count or parent category
1085 const std::string counterSetName = "some_counter_set";
Keith Davis3201eea2019-10-24 17:30:41 +01001086 const CounterSet* counterSet = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001087 CHECK_NOTHROW(counterSet = counterDirectory.RegisterCounterSet(counterSetName));
1088 CHECK(counterDirectory.GetCounterSetCount() == 1);
1089 CHECK(counterSet);
1090 CHECK(counterSet->m_Name == counterSetName);
1091 CHECK(counterSet->m_Uid >= 1);
1092 CHECK(counterSet->m_Count == 0);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001093
Matteo Martincigh657ab2d2019-09-18 10:53:24 +01001094 // Try getting an unregistered counter set
1095 const CounterSet* unregisteredCounterSet = counterDirectory.GetCounterSet(9999);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001096 CHECK(!unregisteredCounterSet);
Matteo Martincigh657ab2d2019-09-18 10:53:24 +01001097
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001098 // Get the registered counter set
1099 const CounterSet* registeredCounterSet = counterDirectory.GetCounterSet(counterSet->m_Uid);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001100 CHECK(counterDirectory.GetCounterSetCount() == 1);
1101 CHECK(registeredCounterSet);
1102 CHECK(registeredCounterSet == counterSet);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001103
Matteo Martincigh657ab2d2019-09-18 10:53:24 +01001104 // Register a counter set with the name of a counter set already registered
1105 const CounterSet* counterSetSameName = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001106 CHECK_THROWS_AS(counterSetSameName = counterDirectory.RegisterCounterSet(counterSetName),
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001107 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001108 CHECK(counterDirectory.GetCounterSetCount() == 1);
1109 CHECK(!counterSetSameName);
Matteo Martincigh657ab2d2019-09-18 10:53:24 +01001110
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001111 // Register a new counter set with count and no parent category
1112 const std::string counterSetWCountName = "some_counter_set_with_count";
Keith Davis3201eea2019-10-24 17:30:41 +01001113 const CounterSet* counterSetWCount = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001114 CHECK_NOTHROW(counterSetWCount = counterDirectory.RegisterCounterSet(counterSetWCountName, 37));
1115 CHECK(counterDirectory.GetCounterSetCount() == 2);
1116 CHECK(counterSetWCount);
1117 CHECK(counterSetWCount->m_Name == counterSetWCountName);
1118 CHECK(counterSetWCount->m_Uid >= 1);
1119 CHECK(counterSetWCount->m_Uid > counterSet->m_Uid);
1120 CHECK(counterSetWCount->m_Count == 37);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001121
1122 // Get the registered counter set
1123 const CounterSet* registeredCounterSetWCount = counterDirectory.GetCounterSet(counterSetWCount->m_Uid);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001124 CHECK(counterDirectory.GetCounterSetCount() == 2);
1125 CHECK(registeredCounterSetWCount);
1126 CHECK(registeredCounterSetWCount == counterSetWCount);
1127 CHECK(registeredCounterSetWCount != counterSet);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001128
1129 // Register a new counter set with count and invalid parent category
1130 const std::string counterSetWCountWInvalidParentCategoryName = "some_counter_set_with_count_"
1131 "with_invalid_parent_category";
1132 const CounterSet* counterSetWCountWInvalidParentCategory = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001133 CHECK_THROWS_AS(counterSetWCountWInvalidParentCategory = counterDirectory.RegisterCounterSet(
Keith Davis3201eea2019-10-24 17:30:41 +01001134 counterSetWCountWInvalidParentCategoryName, 42, std::string("")),
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001135 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001136 CHECK(counterDirectory.GetCounterSetCount() == 2);
1137 CHECK(!counterSetWCountWInvalidParentCategory);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001138
1139 // Register a new counter set with count and invalid parent category
1140 const std::string counterSetWCountWInvalidParentCategoryName2 = "some_counter_set_with_count_"
1141 "with_invalid_parent_category2";
1142 const CounterSet* counterSetWCountWInvalidParentCategory2 = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001143 CHECK_THROWS_AS(counterSetWCountWInvalidParentCategory2 = counterDirectory.RegisterCounterSet(
Keith Davis3201eea2019-10-24 17:30:41 +01001144 counterSetWCountWInvalidParentCategoryName2, 42, std::string("invalid_parent_category")),
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001145 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001146 CHECK(counterDirectory.GetCounterSetCount() == 2);
1147 CHECK(!counterSetWCountWInvalidParentCategory2);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001148
1149 // Register a category for testing
1150 const std::string categoryName = "some_category";
Keith Davis3201eea2019-10-24 17:30:41 +01001151 const Category* category = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001152 CHECK_NOTHROW(category = counterDirectory.RegisterCategory(categoryName));
1153 CHECK(counterDirectory.GetCategoryCount() == 1);
1154 CHECK(category);
1155 CHECK(category->m_Name == categoryName);
1156 CHECK(category->m_Counters.empty());
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001157
1158 // Register a new counter set with count and valid parent category
1159 const std::string counterSetWCountWValidParentCategoryName = "some_counter_set_with_count_"
1160 "with_valid_parent_category";
1161 const CounterSet* counterSetWCountWValidParentCategory = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001162 CHECK_NOTHROW(counterSetWCountWValidParentCategory = counterDirectory.RegisterCounterSet(
Keith Davis3201eea2019-10-24 17:30:41 +01001163 counterSetWCountWValidParentCategoryName, 42, categoryName));
Sadik Armagan1625efc2021-06-10 18:24:34 +01001164 CHECK(counterDirectory.GetCounterSetCount() == 3);
1165 CHECK(counterSetWCountWValidParentCategory);
1166 CHECK(counterSetWCountWValidParentCategory->m_Name == counterSetWCountWValidParentCategoryName);
1167 CHECK(counterSetWCountWValidParentCategory->m_Uid >= 1);
1168 CHECK(counterSetWCountWValidParentCategory->m_Uid > counterSet->m_Uid);
1169 CHECK(counterSetWCountWValidParentCategory->m_Uid > counterSetWCount->m_Uid);
1170 CHECK(counterSetWCountWValidParentCategory->m_Count == 42);
Matteo Martincigh657ab2d2019-09-18 10:53:24 +01001171
Sadik Armagan4c998992020-02-25 12:44:44 +00001172 // Register a counter set associated to a category with invalid name
Matteo Martincigh657ab2d2019-09-18 10:53:24 +01001173 const std::string counterSetSameCategoryName = "some_counter_set_with_invalid_parent_category";
Sadik Armagan4c998992020-02-25 12:44:44 +00001174 const std::string invalidCategoryName = "";
Keith Davis3201eea2019-10-24 17:30:41 +01001175 const CounterSet* counterSetSameCategory = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001176 CHECK_THROWS_AS(counterSetSameCategory =
Sadik Armagan4c998992020-02-25 12:44:44 +00001177 counterDirectory.RegisterCounterSet(counterSetSameCategoryName, 0, invalidCategoryName),
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001178 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001179 CHECK(counterDirectory.GetCounterSetCount() == 3);
1180 CHECK(!counterSetSameCategory);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001181}
1182
Sadik Armagan1625efc2021-06-10 18:24:34 +01001183TEST_CASE("CheckCounterDirectoryRegisterCounter")
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001184{
1185 CounterDirectory counterDirectory;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001186 CHECK(counterDirectory.GetCategoryCount() == 0);
1187 CHECK(counterDirectory.GetDeviceCount() == 0);
1188 CHECK(counterDirectory.GetCounterSetCount() == 0);
1189 CHECK(counterDirectory.GetCounterCount() == 0);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001190
1191 // Register a counter with an invalid parent category name
1192 const Counter* noCounter = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001193 CHECK_THROWS_AS(noCounter =
Keith Davise394bd92019-12-02 15:12:19 +00001194 counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1195 0,
1196 "",
1197 0,
1198 1,
1199 123.45f,
1200 "valid ",
1201 "name"),
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001202 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001203 CHECK(counterDirectory.GetCounterCount() == 0);
1204 CHECK(!noCounter);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001205
1206 // Register a counter with an invalid parent category name
Sadik Armagan1625efc2021-06-10 18:24:34 +01001207 CHECK_THROWS_AS(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001208 1,
1209 "invalid parent category",
1210 0,
1211 1,
1212 123.45f,
1213 "valid name",
1214 "valid description"),
1215 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001216 CHECK(counterDirectory.GetCounterCount() == 0);
1217 CHECK(!noCounter);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001218
1219 // Register a counter with an invalid class
Sadik Armagan1625efc2021-06-10 18:24:34 +01001220 CHECK_THROWS_AS(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001221 2,
1222 "valid_parent_category",
1223 2,
1224 1,
1225 123.45f,
1226 "valid "
1227 "name",
1228 "valid description"),
1229 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001230 CHECK(counterDirectory.GetCounterCount() == 0);
1231 CHECK(!noCounter);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001232
1233 // Register a counter with an invalid interpolation
Sadik Armagan1625efc2021-06-10 18:24:34 +01001234 CHECK_THROWS_AS(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001235 4,
1236 "valid_parent_category",
1237 0,
1238 3,
1239 123.45f,
1240 "valid "
1241 "name",
1242 "valid description"),
1243 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001244 CHECK(counterDirectory.GetCounterCount() == 0);
1245 CHECK(!noCounter);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001246
1247 // Register a counter with an invalid multiplier
Sadik Armagan1625efc2021-06-10 18:24:34 +01001248 CHECK_THROWS_AS(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001249 5,
1250 "valid_parent_category",
1251 0,
1252 1,
1253 .0f,
1254 "valid "
1255 "name",
1256 "valid description"),
1257 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001258 CHECK(counterDirectory.GetCounterCount() == 0);
1259 CHECK(!noCounter);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001260
1261 // Register a counter with an invalid name
Sadik Armagan1625efc2021-06-10 18:24:34 +01001262 CHECK_THROWS_AS(
Keith Davise394bd92019-12-02 15:12:19 +00001263 noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1264 6,
1265 "valid_parent_category",
1266 0,
1267 1,
1268 123.45f,
1269 "",
1270 "valid description"),
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001271 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001272 CHECK(counterDirectory.GetCounterCount() == 0);
1273 CHECK(!noCounter);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001274
1275 // Register a counter with an invalid name
Sadik Armagan1625efc2021-06-10 18:24:34 +01001276 CHECK_THROWS_AS(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001277 7,
1278 "valid_parent_category",
1279 0,
1280 1,
1281 123.45f,
1282 "invalid nam€",
1283 "valid description"),
1284 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001285 CHECK(counterDirectory.GetCounterCount() == 0);
1286 CHECK(!noCounter);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001287
1288 // Register a counter with an invalid description
Sadik Armagan1625efc2021-06-10 18:24:34 +01001289 CHECK_THROWS_AS(noCounter =
Keith Davise394bd92019-12-02 15:12:19 +00001290 counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1291 8,
1292 "valid_parent_category",
1293 0,
1294 1,
1295 123.45f,
1296 "valid name",
1297 ""),
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001298 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001299 CHECK(counterDirectory.GetCounterCount() == 0);
1300 CHECK(!noCounter);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001301
1302 // Register a counter with an invalid description
Sadik Armagan1625efc2021-06-10 18:24:34 +01001303 CHECK_THROWS_AS(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001304 9,
1305 "valid_parent_category",
1306 0,
1307 1,
1308 123.45f,
1309 "valid "
1310 "name",
1311 "inv@lid description"),
1312 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001313 CHECK(counterDirectory.GetCounterCount() == 0);
1314 CHECK(!noCounter);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001315
1316 // Register a counter with an invalid unit2
Sadik Armagan1625efc2021-06-10 18:24:34 +01001317 CHECK_THROWS_AS(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001318 10,
1319 "valid_parent_category",
1320 0,
1321 1,
1322 123.45f,
1323 "valid name",
1324 "valid description",
1325 std::string("Mb/s2")),
1326 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001327 CHECK(counterDirectory.GetCounterCount() == 0);
1328 CHECK(!noCounter);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001329
1330 // Register a counter with a non-existing parent category name
Sadik Armagan1625efc2021-06-10 18:24:34 +01001331 CHECK_THROWS_AS(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001332 11,
1333 "invalid_parent_category",
1334 0,
1335 1,
1336 123.45f,
1337 "valid name",
1338 "valid description"),
1339 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001340 CHECK(counterDirectory.GetCounterCount() == 0);
1341 CHECK(!noCounter);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001342
Matteo Martincigh657ab2d2019-09-18 10:53:24 +01001343 // Try getting an unregistered counter
1344 const Counter* unregisteredCounter = counterDirectory.GetCounter(9999);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001345 CHECK(!unregisteredCounter);
Matteo Martincigh657ab2d2019-09-18 10:53:24 +01001346
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001347 // Register a category for testing
1348 const std::string categoryName = "some_category";
Keith Davis3201eea2019-10-24 17:30:41 +01001349 const Category* category = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001350 CHECK_NOTHROW(category = counterDirectory.RegisterCategory(categoryName));
1351 CHECK(counterDirectory.GetCategoryCount() == 1);
1352 CHECK(category);
1353 CHECK(category->m_Name == categoryName);
1354 CHECK(category->m_Counters.empty());
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001355
1356 // Register a counter with a valid parent category name
1357 const Counter* counter = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001358 CHECK_NOTHROW(
Keith Davise394bd92019-12-02 15:12:19 +00001359 counter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1360 12,
1361 categoryName,
1362 0,
1363 1,
1364 123.45f,
1365 "valid name",
1366 "valid description"));
Sadik Armagan1625efc2021-06-10 18:24:34 +01001367 CHECK(counterDirectory.GetCounterCount() == 1);
1368 CHECK(counter);
1369 CHECK(counter->m_MaxCounterUid == counter->m_Uid);
1370 CHECK(counter->m_Class == 0);
1371 CHECK(counter->m_Interpolation == 1);
1372 CHECK(counter->m_Multiplier == 123.45f);
1373 CHECK(counter->m_Name == "valid name");
1374 CHECK(counter->m_Description == "valid description");
1375 CHECK(counter->m_Units == "");
1376 CHECK(counter->m_DeviceUid == 0);
1377 CHECK(counter->m_CounterSetUid == 0);
1378 CHECK(category->m_Counters.size() == 1);
1379 CHECK(category->m_Counters.back() == counter->m_Uid);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001380
Matteo Martincigh657ab2d2019-09-18 10:53:24 +01001381 // Register a counter with a name of a counter already registered for the given parent category name
1382 const Counter* counterSameName = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001383 CHECK_THROWS_AS(counterSameName =
Keith Davise394bd92019-12-02 15:12:19 +00001384 counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1385 13,
1386 categoryName,
1387 0,
1388 0,
1389 1.0f,
1390 "valid name",
1391 "valid description",
1392 std::string("description")),
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001393 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001394 CHECK(counterDirectory.GetCounterCount() == 1);
1395 CHECK(!counterSameName);
Matteo Martincigh657ab2d2019-09-18 10:53:24 +01001396
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001397 // Register a counter with a valid parent category name and units
1398 const Counter* counterWUnits = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001399 CHECK_NOTHROW(counterWUnits = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001400 14,
1401 categoryName,
1402 0,
1403 1,
1404 123.45f,
1405 "valid name 2",
1406 "valid description",
1407 std::string("Mnnsq2"))); // Units
Sadik Armagan1625efc2021-06-10 18:24:34 +01001408 CHECK(counterDirectory.GetCounterCount() == 2);
1409 CHECK(counterWUnits);
1410 CHECK(counterWUnits->m_Uid > counter->m_Uid);
1411 CHECK(counterWUnits->m_MaxCounterUid == counterWUnits->m_Uid);
1412 CHECK(counterWUnits->m_Class == 0);
1413 CHECK(counterWUnits->m_Interpolation == 1);
1414 CHECK(counterWUnits->m_Multiplier == 123.45f);
1415 CHECK(counterWUnits->m_Name == "valid name 2");
1416 CHECK(counterWUnits->m_Description == "valid description");
1417 CHECK(counterWUnits->m_Units == "Mnnsq2");
1418 CHECK(counterWUnits->m_DeviceUid == 0);
1419 CHECK(counterWUnits->m_CounterSetUid == 0);
1420 CHECK(category->m_Counters.size() == 2);
1421 CHECK(category->m_Counters.back() == counterWUnits->m_Uid);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001422
1423 // Register a counter with a valid parent category name and not associated with a device
1424 const Counter* counterWoDevice = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001425 CHECK_NOTHROW(counterWoDevice = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001426 26,
1427 categoryName,
1428 0,
1429 1,
1430 123.45f,
1431 "valid name 3",
1432 "valid description",
1433 armnn::EmptyOptional(),// Units
1434 armnn::EmptyOptional(),// Number of cores
1435 0)); // Device UID
Sadik Armagan1625efc2021-06-10 18:24:34 +01001436 CHECK(counterDirectory.GetCounterCount() == 3);
1437 CHECK(counterWoDevice);
1438 CHECK(counterWoDevice->m_Uid > counter->m_Uid);
1439 CHECK(counterWoDevice->m_MaxCounterUid == counterWoDevice->m_Uid);
1440 CHECK(counterWoDevice->m_Class == 0);
1441 CHECK(counterWoDevice->m_Interpolation == 1);
1442 CHECK(counterWoDevice->m_Multiplier == 123.45f);
1443 CHECK(counterWoDevice->m_Name == "valid name 3");
1444 CHECK(counterWoDevice->m_Description == "valid description");
1445 CHECK(counterWoDevice->m_Units == "");
1446 CHECK(counterWoDevice->m_DeviceUid == 0);
1447 CHECK(counterWoDevice->m_CounterSetUid == 0);
1448 CHECK(category->m_Counters.size() == 3);
1449 CHECK(category->m_Counters.back() == counterWoDevice->m_Uid);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001450
1451 // Register a counter with a valid parent category name and associated to an invalid device
Sadik Armagan1625efc2021-06-10 18:24:34 +01001452 CHECK_THROWS_AS(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001453 15,
1454 categoryName,
1455 0,
1456 1,
1457 123.45f,
1458 "valid name 4",
1459 "valid description",
1460 armnn::EmptyOptional(), // Units
1461 armnn::EmptyOptional(), // Number of cores
1462 100), // Device UID
1463 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001464 CHECK(counterDirectory.GetCounterCount() == 3);
1465 CHECK(!noCounter);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001466
1467 // Register a device for testing
1468 const std::string deviceName = "some_device";
Keith Davis3201eea2019-10-24 17:30:41 +01001469 const Device* device = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001470 CHECK_NOTHROW(device = counterDirectory.RegisterDevice(deviceName));
1471 CHECK(counterDirectory.GetDeviceCount() == 1);
1472 CHECK(device);
1473 CHECK(device->m_Name == deviceName);
1474 CHECK(device->m_Uid >= 1);
1475 CHECK(device->m_Cores == 0);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001476
1477 // Register a counter with a valid parent category name and associated to a device
1478 const Counter* counterWDevice = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001479 CHECK_NOTHROW(counterWDevice = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001480 16,
1481 categoryName,
1482 0,
1483 1,
1484 123.45f,
1485 "valid name 5",
1486 std::string("valid description"),
1487 armnn::EmptyOptional(), // Units
1488 armnn::EmptyOptional(), // Number of cores
1489 device->m_Uid)); // Device UID
Sadik Armagan1625efc2021-06-10 18:24:34 +01001490 CHECK(counterDirectory.GetCounterCount() == 4);
1491 CHECK(counterWDevice);
1492 CHECK(counterWDevice->m_Uid > counter->m_Uid);
1493 CHECK(counterWDevice->m_MaxCounterUid == counterWDevice->m_Uid);
1494 CHECK(counterWDevice->m_Class == 0);
1495 CHECK(counterWDevice->m_Interpolation == 1);
1496 CHECK(counterWDevice->m_Multiplier == 123.45f);
1497 CHECK(counterWDevice->m_Name == "valid name 5");
1498 CHECK(counterWDevice->m_Description == "valid description");
1499 CHECK(counterWDevice->m_Units == "");
1500 CHECK(counterWDevice->m_DeviceUid == device->m_Uid);
1501 CHECK(counterWDevice->m_CounterSetUid == 0);
1502 CHECK(category->m_Counters.size() == 4);
1503 CHECK(category->m_Counters.back() == counterWDevice->m_Uid);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001504
1505 // Register a counter with a valid parent category name and not associated with a counter set
1506 const Counter* counterWoCounterSet = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001507 CHECK_NOTHROW(counterWoCounterSet = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001508 17,
1509 categoryName,
1510 0,
1511 1,
1512 123.45f,
1513 "valid name 6",
1514 "valid description",
1515 armnn::EmptyOptional(),// Units
1516 armnn::EmptyOptional(),// No of cores
1517 armnn::EmptyOptional(),// Device UID
1518 0)); // CounterSet UID
Sadik Armagan1625efc2021-06-10 18:24:34 +01001519 CHECK(counterDirectory.GetCounterCount() == 5);
1520 CHECK(counterWoCounterSet);
1521 CHECK(counterWoCounterSet->m_Uid > counter->m_Uid);
1522 CHECK(counterWoCounterSet->m_MaxCounterUid == counterWoCounterSet->m_Uid);
1523 CHECK(counterWoCounterSet->m_Class == 0);
1524 CHECK(counterWoCounterSet->m_Interpolation == 1);
1525 CHECK(counterWoCounterSet->m_Multiplier == 123.45f);
1526 CHECK(counterWoCounterSet->m_Name == "valid name 6");
1527 CHECK(counterWoCounterSet->m_Description == "valid description");
1528 CHECK(counterWoCounterSet->m_Units == "");
1529 CHECK(counterWoCounterSet->m_DeviceUid == 0);
1530 CHECK(counterWoCounterSet->m_CounterSetUid == 0);
1531 CHECK(category->m_Counters.size() == 5);
1532 CHECK(category->m_Counters.back() == counterWoCounterSet->m_Uid);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001533
1534 // Register a counter with a valid parent category name and associated to an invalid counter set
Sadik Armagan1625efc2021-06-10 18:24:34 +01001535 CHECK_THROWS_AS(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001536 18,
1537 categoryName,
1538 0,
1539 1,
1540 123.45f,
1541 "valid ",
1542 "name 7",
1543 std::string("valid description"),
1544 armnn::EmptyOptional(), // Units
1545 armnn::EmptyOptional(), // Number of cores
1546 100), // Counter set UID
1547 arm::pipe::InvalidArgumentException);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001548 CHECK(counterDirectory.GetCounterCount() == 5);
1549 CHECK(!noCounter);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001550
1551 // Register a counter with a valid parent category name and with a given number of cores
1552 const Counter* counterWNumberOfCores = nullptr;
Keith Davis3201eea2019-10-24 17:30:41 +01001553 uint16_t numberOfCores = 15;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001554 CHECK_NOTHROW(counterWNumberOfCores = counterDirectory.RegisterCounter(
Keith Davise394bd92019-12-02 15:12:19 +00001555 armnn::profiling::BACKEND_ID, 50,
Keith Davis3201eea2019-10-24 17:30:41 +01001556 categoryName, 0, 1, 123.45f, "valid name 8", "valid description",
1557 armnn::EmptyOptional(), // Units
1558 numberOfCores, // Number of cores
1559 armnn::EmptyOptional(), // Device UID
1560 armnn::EmptyOptional())); // Counter set UID
Sadik Armagan1625efc2021-06-10 18:24:34 +01001561 CHECK(counterDirectory.GetCounterCount() == 20);
1562 CHECK(counterWNumberOfCores);
1563 CHECK(counterWNumberOfCores->m_Uid > counter->m_Uid);
1564 CHECK(counterWNumberOfCores->m_MaxCounterUid == counterWNumberOfCores->m_Uid + numberOfCores - 1);
1565 CHECK(counterWNumberOfCores->m_Class == 0);
1566 CHECK(counterWNumberOfCores->m_Interpolation == 1);
1567 CHECK(counterWNumberOfCores->m_Multiplier == 123.45f);
1568 CHECK(counterWNumberOfCores->m_Name == "valid name 8");
1569 CHECK(counterWNumberOfCores->m_Description == "valid description");
1570 CHECK(counterWNumberOfCores->m_Units == "");
1571 CHECK(counterWNumberOfCores->m_DeviceUid == 0);
1572 CHECK(counterWNumberOfCores->m_CounterSetUid == 0);
1573 CHECK(category->m_Counters.size() == 20);
Keith Davis3201eea2019-10-24 17:30:41 +01001574 for (size_t i = 0; i < numberOfCores; i++)
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001575 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01001576 CHECK(category->m_Counters[category->m_Counters.size() - numberOfCores + i] ==
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001577 counterWNumberOfCores->m_Uid + i);
1578 }
1579
1580 // Register a multi-core device for testing
1581 const std::string multiCoreDeviceName = "some_multi_core_device";
Keith Davis3201eea2019-10-24 17:30:41 +01001582 const Device* multiCoreDevice = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001583 CHECK_NOTHROW(multiCoreDevice = counterDirectory.RegisterDevice(multiCoreDeviceName, 4));
1584 CHECK(counterDirectory.GetDeviceCount() == 2);
1585 CHECK(multiCoreDevice);
1586 CHECK(multiCoreDevice->m_Name == multiCoreDeviceName);
1587 CHECK(multiCoreDevice->m_Uid >= 1);
1588 CHECK(multiCoreDevice->m_Cores == 4);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001589
1590 // Register a counter with a valid parent category name and associated to the multi-core device
1591 const Counter* counterWMultiCoreDevice = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001592 CHECK_NOTHROW(counterWMultiCoreDevice = counterDirectory.RegisterCounter(
Keith Davise394bd92019-12-02 15:12:19 +00001593 armnn::profiling::BACKEND_ID, 19, categoryName, 0, 1,
1594 123.45f, "valid name 9", "valid description",
Keith Davis3201eea2019-10-24 17:30:41 +01001595 armnn::EmptyOptional(), // Units
1596 armnn::EmptyOptional(), // Number of cores
1597 multiCoreDevice->m_Uid, // Device UID
1598 armnn::EmptyOptional())); // Counter set UID
Sadik Armagan1625efc2021-06-10 18:24:34 +01001599 CHECK(counterDirectory.GetCounterCount() == 24);
1600 CHECK(counterWMultiCoreDevice);
1601 CHECK(counterWMultiCoreDevice->m_Uid > counter->m_Uid);
1602 CHECK(counterWMultiCoreDevice->m_MaxCounterUid ==
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001603 counterWMultiCoreDevice->m_Uid + multiCoreDevice->m_Cores - 1);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001604 CHECK(counterWMultiCoreDevice->m_Class == 0);
1605 CHECK(counterWMultiCoreDevice->m_Interpolation == 1);
1606 CHECK(counterWMultiCoreDevice->m_Multiplier == 123.45f);
1607 CHECK(counterWMultiCoreDevice->m_Name == "valid name 9");
1608 CHECK(counterWMultiCoreDevice->m_Description == "valid description");
1609 CHECK(counterWMultiCoreDevice->m_Units == "");
1610 CHECK(counterWMultiCoreDevice->m_DeviceUid == multiCoreDevice->m_Uid);
1611 CHECK(counterWMultiCoreDevice->m_CounterSetUid == 0);
1612 CHECK(category->m_Counters.size() == 24);
Keith Davis3201eea2019-10-24 17:30:41 +01001613 for (size_t i = 0; i < 4; i++)
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001614 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01001615 CHECK(category->m_Counters[category->m_Counters.size() - 4 + i] == counterWMultiCoreDevice->m_Uid + i);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001616 }
1617
Matteo Martincigh657ab2d2019-09-18 10:53:24 +01001618 // Register a multi-core device associate to a parent category for testing
1619 const std::string multiCoreDeviceNameWParentCategory = "some_multi_core_device_with_parent_category";
Keith Davis3201eea2019-10-24 17:30:41 +01001620 const Device* multiCoreDeviceWParentCategory = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001621 CHECK_NOTHROW(multiCoreDeviceWParentCategory =
Keith Davis3201eea2019-10-24 17:30:41 +01001622 counterDirectory.RegisterDevice(multiCoreDeviceNameWParentCategory, 2, categoryName));
Sadik Armagan1625efc2021-06-10 18:24:34 +01001623 CHECK(counterDirectory.GetDeviceCount() == 3);
1624 CHECK(multiCoreDeviceWParentCategory);
1625 CHECK(multiCoreDeviceWParentCategory->m_Name == multiCoreDeviceNameWParentCategory);
1626 CHECK(multiCoreDeviceWParentCategory->m_Uid >= 1);
1627 CHECK(multiCoreDeviceWParentCategory->m_Cores == 2);
Matteo Martincigh657ab2d2019-09-18 10:53:24 +01001628
1629 // Register a counter with a valid parent category name and getting the number of cores of the multi-core device
1630 // associated to that category
1631 const Counter* counterWMultiCoreDeviceWParentCategory = nullptr;
Sadik Armagan4c998992020-02-25 12:44:44 +00001632 uint16_t numberOfCourse = multiCoreDeviceWParentCategory->m_Cores;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001633 CHECK_NOTHROW(counterWMultiCoreDeviceWParentCategory =
Jim Flynnbbfe6032020-07-20 16:57:44 +01001634 counterDirectory.RegisterCounter(
1635 armnn::profiling::BACKEND_ID,
1636 100,
1637 categoryName,
1638 0,
1639 1,
1640 123.45f,
1641 "valid name 10",
1642 "valid description",
1643 armnn::EmptyOptional(), // Units
1644 numberOfCourse, // Number of cores
1645 armnn::EmptyOptional(), // Device UID
1646 armnn::EmptyOptional()));// Counter set UID
Sadik Armagan1625efc2021-06-10 18:24:34 +01001647 CHECK(counterDirectory.GetCounterCount() == 26);
1648 CHECK(counterWMultiCoreDeviceWParentCategory);
1649 CHECK(counterWMultiCoreDeviceWParentCategory->m_Uid > counter->m_Uid);
1650 CHECK(counterWMultiCoreDeviceWParentCategory->m_MaxCounterUid ==
Matteo Martincigh657ab2d2019-09-18 10:53:24 +01001651 counterWMultiCoreDeviceWParentCategory->m_Uid + multiCoreDeviceWParentCategory->m_Cores - 1);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001652 CHECK(counterWMultiCoreDeviceWParentCategory->m_Class == 0);
1653 CHECK(counterWMultiCoreDeviceWParentCategory->m_Interpolation == 1);
1654 CHECK(counterWMultiCoreDeviceWParentCategory->m_Multiplier == 123.45f);
1655 CHECK(counterWMultiCoreDeviceWParentCategory->m_Name == "valid name 10");
1656 CHECK(counterWMultiCoreDeviceWParentCategory->m_Description == "valid description");
1657 CHECK(counterWMultiCoreDeviceWParentCategory->m_Units == "");
1658 CHECK(category->m_Counters.size() == 26);
Keith Davis3201eea2019-10-24 17:30:41 +01001659 for (size_t i = 0; i < 2; i++)
Matteo Martincigh657ab2d2019-09-18 10:53:24 +01001660 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01001661 CHECK(category->m_Counters[category->m_Counters.size() - 2 + i] ==
Matteo Martincigh657ab2d2019-09-18 10:53:24 +01001662 counterWMultiCoreDeviceWParentCategory->m_Uid + i);
1663 }
1664
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001665 // Register a counter set for testing
1666 const std::string counterSetName = "some_counter_set";
Keith Davis3201eea2019-10-24 17:30:41 +01001667 const CounterSet* counterSet = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001668 CHECK_NOTHROW(counterSet = counterDirectory.RegisterCounterSet(counterSetName));
1669 CHECK(counterDirectory.GetCounterSetCount() == 1);
1670 CHECK(counterSet);
1671 CHECK(counterSet->m_Name == counterSetName);
1672 CHECK(counterSet->m_Uid >= 1);
1673 CHECK(counterSet->m_Count == 0);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001674
1675 // Register a counter with a valid parent category name and associated to a counter set
1676 const Counter* counterWCounterSet = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001677 CHECK_NOTHROW(counterWCounterSet = counterDirectory.RegisterCounter(
Keith Davise394bd92019-12-02 15:12:19 +00001678 armnn::profiling::BACKEND_ID, 300,
Keith Davis3201eea2019-10-24 17:30:41 +01001679 categoryName, 0, 1, 123.45f, "valid name 11", "valid description",
1680 armnn::EmptyOptional(), // Units
1681 0, // Number of cores
1682 armnn::EmptyOptional(), // Device UID
1683 counterSet->m_Uid)); // Counter set UID
Sadik Armagan1625efc2021-06-10 18:24:34 +01001684 CHECK(counterDirectory.GetCounterCount() == 27);
1685 CHECK(counterWCounterSet);
1686 CHECK(counterWCounterSet->m_Uid > counter->m_Uid);
1687 CHECK(counterWCounterSet->m_MaxCounterUid == counterWCounterSet->m_Uid);
1688 CHECK(counterWCounterSet->m_Class == 0);
1689 CHECK(counterWCounterSet->m_Interpolation == 1);
1690 CHECK(counterWCounterSet->m_Multiplier == 123.45f);
1691 CHECK(counterWCounterSet->m_Name == "valid name 11");
1692 CHECK(counterWCounterSet->m_Description == "valid description");
1693 CHECK(counterWCounterSet->m_Units == "");
1694 CHECK(counterWCounterSet->m_DeviceUid == 0);
1695 CHECK(counterWCounterSet->m_CounterSetUid == counterSet->m_Uid);
1696 CHECK(category->m_Counters.size() == 27);
1697 CHECK(category->m_Counters.back() == counterWCounterSet->m_Uid);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001698
1699 // Register a counter with a valid parent category name and associated to a device and a counter set
1700 const Counter* counterWDeviceWCounterSet = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001701 CHECK_NOTHROW(counterWDeviceWCounterSet = counterDirectory.RegisterCounter(
Keith Davise394bd92019-12-02 15:12:19 +00001702 armnn::profiling::BACKEND_ID, 23,
Keith Davis3201eea2019-10-24 17:30:41 +01001703 categoryName, 0, 1, 123.45f, "valid name 12", "valid description",
1704 armnn::EmptyOptional(), // Units
1705 1, // Number of cores
1706 device->m_Uid, // Device UID
1707 counterSet->m_Uid)); // Counter set UID
Sadik Armagan1625efc2021-06-10 18:24:34 +01001708 CHECK(counterDirectory.GetCounterCount() == 28);
1709 CHECK(counterWDeviceWCounterSet);
1710 CHECK(counterWDeviceWCounterSet->m_Uid > counter->m_Uid);
1711 CHECK(counterWDeviceWCounterSet->m_MaxCounterUid == counterWDeviceWCounterSet->m_Uid);
1712 CHECK(counterWDeviceWCounterSet->m_Class == 0);
1713 CHECK(counterWDeviceWCounterSet->m_Interpolation == 1);
1714 CHECK(counterWDeviceWCounterSet->m_Multiplier == 123.45f);
1715 CHECK(counterWDeviceWCounterSet->m_Name == "valid name 12");
1716 CHECK(counterWDeviceWCounterSet->m_Description == "valid description");
1717 CHECK(counterWDeviceWCounterSet->m_Units == "");
1718 CHECK(counterWDeviceWCounterSet->m_DeviceUid == device->m_Uid);
1719 CHECK(counterWDeviceWCounterSet->m_CounterSetUid == counterSet->m_Uid);
1720 CHECK(category->m_Counters.size() == 28);
1721 CHECK(category->m_Counters.back() == counterWDeviceWCounterSet->m_Uid);
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001722
1723 // Register another category for testing
1724 const std::string anotherCategoryName = "some_other_category";
Keith Davis3201eea2019-10-24 17:30:41 +01001725 const Category* anotherCategory = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001726 CHECK_NOTHROW(anotherCategory = counterDirectory.RegisterCategory(anotherCategoryName));
1727 CHECK(counterDirectory.GetCategoryCount() == 2);
1728 CHECK(anotherCategory);
1729 CHECK(anotherCategory != category);
1730 CHECK(anotherCategory->m_Name == anotherCategoryName);
1731 CHECK(anotherCategory->m_Counters.empty());
Matteo Martincigh6db5f202019-09-05 12:02:04 +01001732
1733 // Register a counter to the other category
1734 const Counter* anotherCounter = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +01001735 CHECK_NOTHROW(anotherCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID, 24,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001736 anotherCategoryName, 1, 0, .00043f,
1737 "valid name", "valid description",
1738 armnn::EmptyOptional(), // Units
1739 armnn::EmptyOptional(), // Number of cores
1740 device->m_Uid, // Device UID
1741 counterSet->m_Uid)); // Counter set UID
Sadik Armagan1625efc2021-06-10 18:24:34 +01001742 CHECK(counterDirectory.GetCounterCount() == 29);
1743 CHECK(anotherCounter);
1744 CHECK(anotherCounter->m_MaxCounterUid == anotherCounter->m_Uid);
1745 CHECK(anotherCounter->m_Class == 1);
1746 CHECK(anotherCounter->m_Interpolation == 0);
1747 CHECK(anotherCounter->m_Multiplier == .00043f);
1748 CHECK(anotherCounter->m_Name == "valid name");
1749 CHECK(anotherCounter->m_Description == "valid description");
1750 CHECK(anotherCounter->m_Units == "");
1751 CHECK(anotherCounter->m_DeviceUid == device->m_Uid);
1752 CHECK(anotherCounter->m_CounterSetUid == counterSet->m_Uid);
1753 CHECK(anotherCategory->m_Counters.size() == 1);
1754 CHECK(anotherCategory->m_Counters.back() == anotherCounter->m_Uid);
Matteo Martincighab173e92019-09-05 12:02:04 +01001755}
1756
Sadik Armagan1625efc2021-06-10 18:24:34 +01001757TEST_CASE("CounterSelectionCommandHandlerParseData")
Ferran Balaguer1b941722019-08-28 16:57:18 +01001758{
Matteo Martincigh5d737fb2019-10-07 13:05:13 +01001759 ProfilingStateMachine profilingStateMachine;
1760
Ferran Balaguer1b941722019-08-28 16:57:18 +01001761 class TestCaptureThread : public IPeriodicCounterCapture
1762 {
Keith Davis3201eea2019-10-24 17:30:41 +01001763 void Start() override
1764 {}
1765 void Stop() override
1766 {}
Ferran Balaguer1b941722019-08-28 16:57:18 +01001767 };
1768
Matteo Martincighe8485382019-10-10 14:08:21 +01001769 class TestReadCounterValues : public IReadCounterValues
1770 {
Keith Davis3201eea2019-10-24 17:30:41 +01001771 bool IsCounterRegistered(uint16_t counterUid) const override
1772 {
Jan Eilers8eb25602020-03-09 12:13:48 +00001773 armnn::IgnoreUnused(counterUid);
Keith Davis3201eea2019-10-24 17:30:41 +01001774 return true;
1775 }
Jim Flynn34430252022-03-04 15:03:58 +00001776 bool IsCounterRegistered(const std::string& counterName) const override
1777 {
1778 armnn::IgnoreUnused(counterName);
1779 return true;
1780 }
Keith Davis3201eea2019-10-24 17:30:41 +01001781 uint16_t GetCounterCount() const override
1782 {
1783 return 0;
1784 }
Finn Williamsf3fcf322020-05-11 14:38:02 +01001785 uint32_t GetAbsoluteCounterValue(uint16_t counterUid) const override
1786 {
1787 armnn::IgnoreUnused(counterUid);
1788 return 0;
1789 }
1790 uint32_t GetDeltaCounterValue(uint16_t counterUid) override
Keith Davis3201eea2019-10-24 17:30:41 +01001791 {
Jan Eilers8eb25602020-03-09 12:13:48 +00001792 armnn::IgnoreUnused(counterUid);
Keith Davis3201eea2019-10-24 17:30:41 +01001793 return 0;
1794 }
Matteo Martincighe8485382019-10-10 14:08:21 +01001795 };
Jim Flynn397043f2019-10-17 17:37:10 +01001796 const uint32_t familyId = 0;
Ferran Balaguer1b941722019-08-28 16:57:18 +01001797 const uint32_t packetId = 0x40000;
1798
1799 uint32_t version = 1;
Cathal Corbett6f073722022-03-04 12:11:09 +00001800 const std::unordered_map<std::string,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001801 std::shared_ptr<IBackendProfilingContext>> backendProfilingContext;
Finn Williams032bc742020-02-12 11:02:34 +00001802 CounterIdMap counterIdMap;
Ferran Balaguer1b941722019-08-28 16:57:18 +01001803 Holder holder;
1804 TestCaptureThread captureThread;
Matteo Martincighe8485382019-10-10 14:08:21 +01001805 TestReadCounterValues readCounterValues;
Narumol Prangnawarat404b2752019-09-24 17:23:16 +01001806 MockBufferManager mockBuffer(512);
Sadik Armagan3896b472020-02-10 12:24:15 +00001807 SendCounterPacket sendCounterPacket(mockBuffer);
1808 SendThread sendThread(profilingStateMachine, mockBuffer, sendCounterPacket);
Ferran Balaguer1b941722019-08-28 16:57:18 +01001809
Matthew Sloyan371b70e2020-09-11 10:14:57 +01001810 uint32_t sizeOfUint32 = armnn::numeric_cast<uint32_t>(sizeof(uint32_t));
1811 uint32_t sizeOfUint16 = armnn::numeric_cast<uint32_t>(sizeof(uint16_t));
Ferran Balaguer1b941722019-08-28 16:57:18 +01001812
1813 // Data with period and counters
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00001814 uint32_t period1 = arm::pipe::LOWEST_CAPTURE_PERIOD;
Ferran Balaguer1b941722019-08-28 16:57:18 +01001815 uint32_t dataLength1 = 8;
Keith Davis3201eea2019-10-24 17:30:41 +01001816 uint32_t offset = 0;
Ferran Balaguer1b941722019-08-28 16:57:18 +01001817
Matteo Martincigh67ef2a52019-10-10 13:29:02 +01001818 std::unique_ptr<unsigned char[]> uniqueData1 = std::make_unique<unsigned char[]>(dataLength1);
Keith Davis3201eea2019-10-24 17:30:41 +01001819 unsigned char* data1 = reinterpret_cast<unsigned char*>(uniqueData1.get());
FinnWilliamsArma0c78712019-09-16 12:06:47 +01001820
Ferran Balaguer1b941722019-08-28 16:57:18 +01001821 WriteUint32(data1, offset, period1);
1822 offset += sizeOfUint32;
1823 WriteUint16(data1, offset, 4000);
1824 offset += sizeOfUint16;
1825 WriteUint16(data1, offset, 5000);
1826
Jim Flynnbbfe6032020-07-20 16:57:44 +01001827 arm::pipe::Packet packetA(packetId, dataLength1, uniqueData1);
Ferran Balaguer1b941722019-08-28 16:57:18 +01001828
Finn Williams032bc742020-02-12 11:02:34 +00001829 PeriodicCounterSelectionCommandHandler commandHandler(familyId, packetId, version, backendProfilingContext,
1830 counterIdMap, holder, 10000u, captureThread,
Keith Davis3201eea2019-10-24 17:30:41 +01001831 readCounterValues, sendCounterPacket, profilingStateMachine);
Ferran Balaguer1b941722019-08-28 16:57:18 +01001832
Matteo Martincighe8485382019-10-10 14:08:21 +01001833 profilingStateMachine.TransitionToState(ProfilingState::Uninitialised);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001834 CHECK_THROWS_AS(commandHandler(packetA), armnn::RuntimeException);
Matteo Martincighe8485382019-10-10 14:08:21 +01001835 profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001836 CHECK_THROWS_AS(commandHandler(packetA), armnn::RuntimeException);
Matteo Martincighe8485382019-10-10 14:08:21 +01001837 profilingStateMachine.TransitionToState(ProfilingState::WaitingForAck);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001838 CHECK_THROWS_AS(commandHandler(packetA), armnn::RuntimeException);
Matteo Martincighe8485382019-10-10 14:08:21 +01001839 profilingStateMachine.TransitionToState(ProfilingState::Active);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001840 CHECK_NOTHROW(commandHandler(packetA));
Matteo Martincighe8485382019-10-10 14:08:21 +01001841
1842 const std::vector<uint16_t> counterIdsA = holder.GetCaptureData().GetCounterIds();
Ferran Balaguer1b941722019-08-28 16:57:18 +01001843
Sadik Armagan1625efc2021-06-10 18:24:34 +01001844 CHECK(holder.GetCaptureData().GetCapturePeriod() == period1);
1845 CHECK(counterIdsA.size() == 2);
1846 CHECK(counterIdsA[0] == 4000);
1847 CHECK(counterIdsA[1] == 5000);
Ferran Balaguer1b941722019-08-28 16:57:18 +01001848
Narumol Prangnawarat404b2752019-09-24 17:23:16 +01001849 auto readBuffer = mockBuffer.GetReadableBuffer();
Ferran Balaguer1b941722019-08-28 16:57:18 +01001850
1851 offset = 0;
1852
1853 uint32_t headerWord0 = ReadUint32(readBuffer, offset);
1854 offset += sizeOfUint32;
1855 uint32_t headerWord1 = ReadUint32(readBuffer, offset);
1856 offset += sizeOfUint32;
1857 uint32_t period = ReadUint32(readBuffer, offset);
1858
Sadik Armagan1625efc2021-06-10 18:24:34 +01001859 CHECK(((headerWord0 >> 26) & 0x3F) == 0); // packet family
1860 CHECK(((headerWord0 >> 16) & 0x3FF) == 4); // packet id
1861 CHECK(headerWord1 == 8); // data length
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00001862 CHECK(period == arm::pipe::LOWEST_CAPTURE_PERIOD); // capture period
Ferran Balaguer1b941722019-08-28 16:57:18 +01001863
1864 uint16_t counterId = 0;
1865 offset += sizeOfUint32;
1866 counterId = ReadUint16(readBuffer, offset);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001867 CHECK(counterId == 4000);
Ferran Balaguer1b941722019-08-28 16:57:18 +01001868 offset += sizeOfUint16;
1869 counterId = ReadUint16(readBuffer, offset);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001870 CHECK(counterId == 5000);
Ferran Balaguer1b941722019-08-28 16:57:18 +01001871
Narumol Prangnawarat404b2752019-09-24 17:23:16 +01001872 mockBuffer.MarkRead(readBuffer);
1873
Ferran Balaguer1b941722019-08-28 16:57:18 +01001874 // Data with period only
Colm Donelan02705242019-11-14 14:19:07 +00001875 uint32_t period2 = 9000; // We'll specify a value below LOWEST_CAPTURE_PERIOD. It should be pulled upwards.
Ferran Balaguer1b941722019-08-28 16:57:18 +01001876 uint32_t dataLength2 = 4;
Ferran Balaguer1b941722019-08-28 16:57:18 +01001877
Matteo Martincigh67ef2a52019-10-10 13:29:02 +01001878 std::unique_ptr<unsigned char[]> uniqueData2 = std::make_unique<unsigned char[]>(dataLength2);
Ferran Balaguer1b941722019-08-28 16:57:18 +01001879
FinnWilliamsArma0c78712019-09-16 12:06:47 +01001880 WriteUint32(reinterpret_cast<unsigned char*>(uniqueData2.get()), 0, period2);
1881
Jim Flynnbbfe6032020-07-20 16:57:44 +01001882 arm::pipe::Packet packetB(packetId, dataLength2, uniqueData2);
Ferran Balaguer1b941722019-08-28 16:57:18 +01001883
1884 commandHandler(packetB);
1885
Matteo Martincighe8485382019-10-10 14:08:21 +01001886 const std::vector<uint16_t> counterIdsB = holder.GetCaptureData().GetCounterIds();
Ferran Balaguer1b941722019-08-28 16:57:18 +01001887
Colm Donelan02705242019-11-14 14:19:07 +00001888 // Value should have been pulled up from 9000 to LOWEST_CAPTURE_PERIOD.
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00001889 CHECK(holder.GetCaptureData().GetCapturePeriod() == arm::pipe::LOWEST_CAPTURE_PERIOD);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001890 CHECK(counterIdsB.size() == 0);
Ferran Balaguer1b941722019-08-28 16:57:18 +01001891
Narumol Prangnawarat404b2752019-09-24 17:23:16 +01001892 readBuffer = mockBuffer.GetReadableBuffer();
Ferran Balaguer1b941722019-08-28 16:57:18 +01001893
1894 offset = 0;
1895
1896 headerWord0 = ReadUint32(readBuffer, offset);
1897 offset += sizeOfUint32;
1898 headerWord1 = ReadUint32(readBuffer, offset);
1899 offset += sizeOfUint32;
1900 period = ReadUint32(readBuffer, offset);
1901
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00001902 CHECK(((headerWord0 >> 26) & 0x3F) == 0); // packet family
1903 CHECK(((headerWord0 >> 16) & 0x3FF) == 4); // packet id
1904 CHECK(headerWord1 == 4); // data length
1905 CHECK(period == arm::pipe::LOWEST_CAPTURE_PERIOD); // capture period
Ferran Balaguer1b941722019-08-28 16:57:18 +01001906}
1907
Sadik Armagan1625efc2021-06-10 18:24:34 +01001908TEST_CASE("CheckTimelineActivationAndDeactivation")
Keith Davis33ed2212020-03-30 10:43:41 +01001909{
1910 class TestReportStructure : public IReportStructure
1911 {
1912 public:
Cathal Corbett19793552022-03-04 10:36:34 +00001913 virtual void ReportStructure(arm::pipe::IProfilingService& profilingService) override
Keith Davis33ed2212020-03-30 10:43:41 +01001914 {
1915 m_ReportStructureCalled = true;
1916 }
1917
1918 bool m_ReportStructureCalled = false;
1919 };
1920
1921 class TestNotifyBackends : public INotifyBackends
1922 {
1923 public:
1924 TestNotifyBackends() : m_timelineReporting(false) {}
1925 virtual void NotifyBackendsForTimelineReporting() override
1926 {
1927 m_TestNotifyBackendsCalled = m_timelineReporting.load();
1928 }
1929
1930 bool m_TestNotifyBackendsCalled = false;
1931 std::atomic<bool> m_timelineReporting;
1932 };
1933
Jim Flynnbbfe6032020-07-20 16:57:44 +01001934 arm::pipe::PacketVersionResolver packetVersionResolver;
Keith Davis33ed2212020-03-30 10:43:41 +01001935
1936 BufferManager bufferManager(512);
1937 SendTimelinePacket sendTimelinePacket(bufferManager);
1938 ProfilingStateMachine stateMachine;
1939 TestReportStructure testReportStructure;
1940 TestNotifyBackends testNotifyBackends;
1941
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00001942 ActivateTimelineReportingCommandHandler activateTimelineReportingCommandHandler(0,
Keith Davis33ed2212020-03-30 10:43:41 +01001943 6,
1944 packetVersionResolver.ResolvePacketVersion(0, 6)
1945 .GetEncodedValue(),
1946 sendTimelinePacket,
1947 stateMachine,
1948 testReportStructure,
1949 testNotifyBackends.m_timelineReporting,
1950 testNotifyBackends);
1951
1952 // Write an "ActivateTimelineReporting" packet into the mock profiling connection, to simulate an input from an
1953 // external profiling service
1954 const uint32_t packetFamily1 = 0;
1955 const uint32_t packetId1 = 6;
1956 uint32_t packetHeader1 = ConstructHeader(packetFamily1, packetId1);
1957
1958 // Create the ActivateTimelineReportingPacket
Jim Flynnbbfe6032020-07-20 16:57:44 +01001959 arm::pipe::Packet ActivateTimelineReportingPacket(packetHeader1); // Length == 0
Keith Davis33ed2212020-03-30 10:43:41 +01001960
Sadik Armagan1625efc2021-06-10 18:24:34 +01001961 CHECK_THROWS_AS(
Keith Davis33ed2212020-03-30 10:43:41 +01001962 activateTimelineReportingCommandHandler.operator()(ActivateTimelineReportingPacket), armnn::Exception);
1963
1964 stateMachine.TransitionToState(ProfilingState::NotConnected);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001965 CHECK_THROWS_AS(
Keith Davis33ed2212020-03-30 10:43:41 +01001966 activateTimelineReportingCommandHandler.operator()(ActivateTimelineReportingPacket), armnn::Exception);
1967
1968 stateMachine.TransitionToState(ProfilingState::WaitingForAck);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001969 CHECK_THROWS_AS(
Keith Davis33ed2212020-03-30 10:43:41 +01001970 activateTimelineReportingCommandHandler.operator()(ActivateTimelineReportingPacket), armnn::Exception);
1971
1972 stateMachine.TransitionToState(ProfilingState::Active);
1973 activateTimelineReportingCommandHandler.operator()(ActivateTimelineReportingPacket);
1974
Sadik Armagan1625efc2021-06-10 18:24:34 +01001975 CHECK(testReportStructure.m_ReportStructureCalled);
1976 CHECK(testNotifyBackends.m_TestNotifyBackendsCalled);
1977 CHECK(testNotifyBackends.m_timelineReporting.load());
Keith Davis33ed2212020-03-30 10:43:41 +01001978
1979 DeactivateTimelineReportingCommandHandler deactivateTimelineReportingCommandHandler(0,
1980 7,
1981 packetVersionResolver.ResolvePacketVersion(0, 7).GetEncodedValue(),
1982 testNotifyBackends.m_timelineReporting,
1983 stateMachine,
1984 testNotifyBackends);
1985
1986 const uint32_t packetFamily2 = 0;
1987 const uint32_t packetId2 = 7;
1988 uint32_t packetHeader2 = ConstructHeader(packetFamily2, packetId2);
1989
1990 // Create the DeactivateTimelineReportingPacket
Jim Flynnbbfe6032020-07-20 16:57:44 +01001991 arm::pipe::Packet deactivateTimelineReportingPacket(packetHeader2); // Length == 0
Keith Davis33ed2212020-03-30 10:43:41 +01001992
1993 stateMachine.Reset();
Sadik Armagan1625efc2021-06-10 18:24:34 +01001994 CHECK_THROWS_AS(
Keith Davis33ed2212020-03-30 10:43:41 +01001995 deactivateTimelineReportingCommandHandler.operator()(deactivateTimelineReportingPacket), armnn::Exception);
1996
1997 stateMachine.TransitionToState(ProfilingState::NotConnected);
Sadik Armagan1625efc2021-06-10 18:24:34 +01001998 CHECK_THROWS_AS(
Keith Davis33ed2212020-03-30 10:43:41 +01001999 deactivateTimelineReportingCommandHandler.operator()(deactivateTimelineReportingPacket), armnn::Exception);
2000
2001 stateMachine.TransitionToState(ProfilingState::WaitingForAck);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002002 CHECK_THROWS_AS(
Keith Davis33ed2212020-03-30 10:43:41 +01002003 deactivateTimelineReportingCommandHandler.operator()(deactivateTimelineReportingPacket), armnn::Exception);
2004
2005 stateMachine.TransitionToState(ProfilingState::Active);
2006 deactivateTimelineReportingCommandHandler.operator()(deactivateTimelineReportingPacket);
2007
Sadik Armagan1625efc2021-06-10 18:24:34 +01002008 CHECK(!testNotifyBackends.m_TestNotifyBackendsCalled);
2009 CHECK(!testNotifyBackends.m_timelineReporting.load());
Keith Davis33ed2212020-03-30 10:43:41 +01002010}
2011
Sadik Armagan1625efc2021-06-10 18:24:34 +01002012TEST_CASE("CheckProfilingServiceNotActive")
Keith Davis33ed2212020-03-30 10:43:41 +01002013{
2014 using namespace armnn;
Keith Davis33ed2212020-03-30 10:43:41 +01002015
2016 // Create runtime in which the test will run
2017 armnn::IRuntime::CreationOptions options;
2018 options.m_ProfilingOptions.m_EnableProfiling = true;
2019
Kevin Mayd92a6e42021-02-04 10:27:41 +00002020 armnn::RuntimeImpl runtime(options);
Jim Flynn34430252022-03-04 15:03:58 +00002021 armnn::ArmNNProfilingServiceInitialiser initialiser;
2022 ProfilingServiceRuntimeHelper profilingServiceHelper(
2023 arm::pipe::MAX_ARMNN_COUNTER, initialiser, GetProfilingService(&runtime));
Keith Davis33ed2212020-03-30 10:43:41 +01002024 profilingServiceHelper.ForceTransitionToState(ProfilingState::NotConnected);
2025 profilingServiceHelper.ForceTransitionToState(ProfilingState::WaitingForAck);
2026 profilingServiceHelper.ForceTransitionToState(ProfilingState::Active);
2027
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00002028 BufferManager& bufferManager = profilingServiceHelper.GetProfilingBufferManager();
Keith Davis33ed2212020-03-30 10:43:41 +01002029 auto readableBuffer = bufferManager.GetReadableBuffer();
2030
2031 // Profiling is enabled, the post-optimisation structure should be created
Sadik Armagan1625efc2021-06-10 18:24:34 +01002032 CHECK(readableBuffer == nullptr);
Keith Davis33ed2212020-03-30 10:43:41 +01002033}
2034
Sadik Armagan1625efc2021-06-10 18:24:34 +01002035TEST_CASE("CheckConnectionAcknowledged")
Sadik Armaganb5f01b22019-09-18 17:29:00 +01002036{
Keith Davis3201eea2019-10-24 17:30:41 +01002037 const uint32_t packetFamilyId = 0;
Sadik Armaganb5f01b22019-09-18 17:29:00 +01002038 const uint32_t connectionPacketId = 0x10000;
Keith Davis3201eea2019-10-24 17:30:41 +01002039 const uint32_t version = 1;
Sadik Armaganb5f01b22019-09-18 17:29:00 +01002040
Matthew Sloyan371b70e2020-09-11 10:14:57 +01002041 uint32_t sizeOfUint32 = armnn::numeric_cast<uint32_t>(sizeof(uint32_t));
2042 uint32_t sizeOfUint16 = armnn::numeric_cast<uint32_t>(sizeof(uint16_t));
Sadik Armaganb5f01b22019-09-18 17:29:00 +01002043
2044 // Data with period and counters
Keith Davis3201eea2019-10-24 17:30:41 +01002045 uint32_t period1 = 10;
Sadik Armaganb5f01b22019-09-18 17:29:00 +01002046 uint32_t dataLength1 = 8;
Keith Davis3201eea2019-10-24 17:30:41 +01002047 uint32_t offset = 0;
Sadik Armaganb5f01b22019-09-18 17:29:00 +01002048
Matteo Martincigh67ef2a52019-10-10 13:29:02 +01002049 std::unique_ptr<unsigned char[]> uniqueData1 = std::make_unique<unsigned char[]>(dataLength1);
Keith Davis3201eea2019-10-24 17:30:41 +01002050 unsigned char* data1 = reinterpret_cast<unsigned char*>(uniqueData1.get());
Sadik Armaganb5f01b22019-09-18 17:29:00 +01002051
2052 WriteUint32(data1, offset, period1);
2053 offset += sizeOfUint32;
2054 WriteUint16(data1, offset, 4000);
2055 offset += sizeOfUint16;
2056 WriteUint16(data1, offset, 5000);
2057
Jim Flynnbbfe6032020-07-20 16:57:44 +01002058 arm::pipe::Packet packetA(connectionPacketId, dataLength1, uniqueData1);
Sadik Armaganb5f01b22019-09-18 17:29:00 +01002059
2060 ProfilingStateMachine profilingState(ProfilingState::Uninitialised);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002061 CHECK(profilingState.GetCurrentState() == ProfilingState::Uninitialised);
Keith Davis3201eea2019-10-24 17:30:41 +01002062 CounterDirectory counterDirectory;
2063 MockBufferManager mockBuffer(1024);
Sadik Armagan3896b472020-02-10 12:24:15 +00002064 SendCounterPacket sendCounterPacket(mockBuffer);
2065 SendThread sendThread(profilingState, mockBuffer, sendCounterPacket);
Matteo Martincighcdfb9412019-11-08 11:23:06 +00002066 SendTimelinePacket sendTimelinePacket(mockBuffer);
Jim Flynn6398a982020-05-27 17:05:21 +01002067 MockProfilingServiceStatus mockProfilingServiceStatus;
Sadik Armaganb5f01b22019-09-18 17:29:00 +01002068
Jim Flynn6398a982020-05-27 17:05:21 +01002069 ConnectionAcknowledgedCommandHandler commandHandler(packetFamilyId,
2070 connectionPacketId,
2071 version,
2072 counterDirectory,
2073 sendCounterPacket,
2074 sendTimelinePacket,
2075 profilingState,
2076 mockProfilingServiceStatus);
Sadik Armaganb5f01b22019-09-18 17:29:00 +01002077
2078 // command handler received packet on ProfilingState::Uninitialised
Sadik Armagan1625efc2021-06-10 18:24:34 +01002079 CHECK_THROWS_AS(commandHandler(packetA), armnn::Exception);
Sadik Armaganb5f01b22019-09-18 17:29:00 +01002080
2081 profilingState.TransitionToState(ProfilingState::NotConnected);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002082 CHECK(profilingState.GetCurrentState() == ProfilingState::NotConnected);
Sadik Armaganb5f01b22019-09-18 17:29:00 +01002083 // command handler received packet on ProfilingState::NotConnected
Sadik Armagan1625efc2021-06-10 18:24:34 +01002084 CHECK_THROWS_AS(commandHandler(packetA), armnn::Exception);
Sadik Armaganb5f01b22019-09-18 17:29:00 +01002085
2086 profilingState.TransitionToState(ProfilingState::WaitingForAck);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002087 CHECK(profilingState.GetCurrentState() == ProfilingState::WaitingForAck);
Sadik Armaganb5f01b22019-09-18 17:29:00 +01002088 // command handler received packet on ProfilingState::WaitingForAck
Sadik Armagan1625efc2021-06-10 18:24:34 +01002089 CHECK_NOTHROW(commandHandler(packetA));
2090 CHECK(profilingState.GetCurrentState() == ProfilingState::Active);
Sadik Armaganb5f01b22019-09-18 17:29:00 +01002091
2092 // command handler received packet on ProfilingState::Active
Sadik Armagan1625efc2021-06-10 18:24:34 +01002093 CHECK_NOTHROW(commandHandler(packetA));
2094 CHECK(profilingState.GetCurrentState() == ProfilingState::Active);
Sadik Armaganb5f01b22019-09-18 17:29:00 +01002095
2096 // command handler received different packet
2097 const uint32_t differentPacketId = 0x40000;
Jim Flynnbbfe6032020-07-20 16:57:44 +01002098 arm::pipe::Packet packetB(differentPacketId, dataLength1, uniqueData1);
Matteo Martincighd0613b52019-10-09 16:47:04 +01002099 profilingState.TransitionToState(ProfilingState::NotConnected);
2100 profilingState.TransitionToState(ProfilingState::WaitingForAck);
Jim Flynn6398a982020-05-27 17:05:21 +01002101 ConnectionAcknowledgedCommandHandler differentCommandHandler(packetFamilyId,
2102 differentPacketId,
2103 version,
2104 counterDirectory,
2105 sendCounterPacket,
2106 sendTimelinePacket,
2107 profilingState,
2108 mockProfilingServiceStatus);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002109 CHECK_THROWS_AS(differentCommandHandler(packetB), armnn::Exception);
Sadik Armaganb5f01b22019-09-18 17:29:00 +01002110}
2111
Sadik Armagan1625efc2021-06-10 18:24:34 +01002112TEST_CASE("CheckSocketConnectionException")
Teresa Charlin9bab4962019-09-06 12:28:35 +01002113{
Sadik Armagana97a0be2020-03-03 10:44:56 +00002114 // Check that creating a SocketProfilingConnection armnnProfiling in an exception as the Gator UDS doesn't exist.
Sadik Armagan1625efc2021-06-10 18:24:34 +01002115 CHECK_THROWS_AS(new SocketProfilingConnection(), arm::pipe::SocketConnectionException);
Sadik Armagana97a0be2020-03-03 10:44:56 +00002116}
2117
Sadik Armagan1625efc2021-06-10 18:24:34 +01002118TEST_CASE("CheckSocketConnectionException2")
Sadik Armagana97a0be2020-03-03 10:44:56 +00002119{
2120 try
2121 {
2122 new SocketProfilingConnection();
2123 }
Jim Flynnbbfe6032020-07-20 16:57:44 +01002124 catch (const arm::pipe::SocketConnectionException& ex)
Sadik Armagana97a0be2020-03-03 10:44:56 +00002125 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01002126 CHECK(ex.GetSocketFd() == 0);
2127 CHECK(ex.GetErrorNo() == ECONNREFUSED);
2128 CHECK(ex.what()
Sadik Armagana97a0be2020-03-03 10:44:56 +00002129 == std::string("SocketProfilingConnection: Cannot connect to stream socket: Connection refused"));
2130 }
Teresa Charlin9bab4962019-09-06 12:28:35 +01002131}
2132
Sadik Armagan1625efc2021-06-10 18:24:34 +01002133TEST_CASE("SwTraceIsValidCharTest")
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002134{
2135 // Only ASCII 7-bit encoding supported
2136 for (unsigned char c = 0; c < 128; c++)
2137 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01002138 CHECK(arm::pipe::SwTraceCharPolicy::IsValidChar(c));
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002139 }
2140
2141 // Not ASCII
2142 for (unsigned char c = 255; c >= 128; c++)
2143 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01002144 CHECK(!arm::pipe::SwTraceCharPolicy::IsValidChar(c));
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002145 }
2146}
2147
Sadik Armagan1625efc2021-06-10 18:24:34 +01002148TEST_CASE("SwTraceIsValidNameCharTest")
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002149{
2150 // Only alpha-numeric and underscore ASCII 7-bit encoding supported
2151 const unsigned char validChars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
2152 for (unsigned char i = 0; i < sizeof(validChars) / sizeof(validChars[0]) - 1; i++)
2153 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01002154 CHECK(arm::pipe::SwTraceNameCharPolicy::IsValidChar(validChars[i]));
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002155 }
2156
2157 // Non alpha-numeric chars
2158 for (unsigned char c = 0; c < 48; c++)
2159 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01002160 CHECK(!arm::pipe::SwTraceNameCharPolicy::IsValidChar(c));
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002161 }
2162 for (unsigned char c = 58; c < 65; c++)
2163 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01002164 CHECK(!arm::pipe::SwTraceNameCharPolicy::IsValidChar(c));
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002165 }
2166 for (unsigned char c = 91; c < 95; c++)
2167 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01002168 CHECK(!arm::pipe::SwTraceNameCharPolicy::IsValidChar(c));
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002169 }
2170 for (unsigned char c = 96; c < 97; c++)
2171 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01002172 CHECK(!arm::pipe::SwTraceNameCharPolicy::IsValidChar(c));
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002173 }
2174 for (unsigned char c = 123; c < 128; c++)
2175 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01002176 CHECK(!arm::pipe::SwTraceNameCharPolicy::IsValidChar(c));
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002177 }
2178
2179 // Not ASCII
2180 for (unsigned char c = 255; c >= 128; c++)
2181 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01002182 CHECK(!arm::pipe::SwTraceNameCharPolicy::IsValidChar(c));
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002183 }
2184}
2185
Sadik Armagan1625efc2021-06-10 18:24:34 +01002186TEST_CASE("IsValidSwTraceStringTest")
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002187{
2188 // Valid SWTrace strings
Sadik Armagan1625efc2021-06-10 18:24:34 +01002189 CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>(""));
2190 CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("_"));
2191 CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("0123"));
2192 CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("valid_string"));
2193 CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("VALID_string_456"));
2194 CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>(" "));
2195 CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("valid string"));
2196 CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("!$%"));
2197 CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("valid|\\~string#123"));
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002198
2199 // Invalid SWTrace strings
Sadik Armagan1625efc2021-06-10 18:24:34 +01002200 CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("€£"));
2201 CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("invalid‡string"));
2202 CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("12Ž34"));
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002203}
2204
Sadik Armagan1625efc2021-06-10 18:24:34 +01002205TEST_CASE("IsValidSwTraceNameStringTest")
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002206{
2207 // Valid SWTrace name strings
Sadik Armagan1625efc2021-06-10 18:24:34 +01002208 CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>(""));
2209 CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("_"));
2210 CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("0123"));
2211 CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("valid_string"));
2212 CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("VALID_string_456"));
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002213
2214 // Invalid SWTrace name strings
Sadik Armagan1625efc2021-06-10 18:24:34 +01002215 CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>(" "));
2216 CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("invalid string"));
2217 CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("!$%"));
2218 CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("invalid|\\~string#123"));
2219 CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("€£"));
2220 CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("invalid‡string"));
2221 CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("12Ž34"));
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002222}
2223
2224template <typename SwTracePolicy>
2225void StringToSwTraceStringTestHelper(const std::string& testString, std::vector<uint32_t> buffer, size_t expectedSize)
2226{
2227 // Convert the test string to a SWTrace string
Sadik Armagan1625efc2021-06-10 18:24:34 +01002228 CHECK(arm::pipe::StringToSwTraceString<SwTracePolicy>(testString, buffer));
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002229
2230 // The buffer must contain at least the length of the string
Sadik Armagan1625efc2021-06-10 18:24:34 +01002231 CHECK(!buffer.empty());
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002232
2233 // The buffer must be of the expected size (in words)
Sadik Armagan1625efc2021-06-10 18:24:34 +01002234 CHECK(buffer.size() == expectedSize);
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002235
2236 // The first word of the byte must be the length of the string including the null-terminator
Sadik Armagan1625efc2021-06-10 18:24:34 +01002237 CHECK(buffer[0] == testString.size() + 1);
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002238
2239 // The contents of the buffer must match the test string
Sadik Armagan1625efc2021-06-10 18:24:34 +01002240 CHECK(std::memcmp(testString.data(), buffer.data() + 1, testString.size()) == 0);
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002241
2242 // The buffer must include the null-terminator at the end of the string
2243 size_t nullTerminatorIndex = sizeof(uint32_t) + testString.size();
Sadik Armagan1625efc2021-06-10 18:24:34 +01002244 CHECK(reinterpret_cast<unsigned char*>(buffer.data())[nullTerminatorIndex] == '\0');
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002245}
2246
Sadik Armagan1625efc2021-06-10 18:24:34 +01002247TEST_CASE("StringToSwTraceStringTest")
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002248{
2249 std::vector<uint32_t> buffer;
2250
2251 // Valid SWTrace strings (expected size in words)
Jim Flynnbbfe6032020-07-20 16:57:44 +01002252 StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>("", buffer, 2);
2253 StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>("_", buffer, 2);
2254 StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>("0123", buffer, 3);
2255 StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>("valid_string", buffer, 5);
2256 StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>("VALID_string_456", buffer, 6);
2257 StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>(" ", buffer, 2);
2258 StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>("valid string", buffer, 5);
2259 StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>("!$%", buffer, 2);
2260 StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>("valid|\\~string#123", buffer, 6);
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002261
2262 // Invalid SWTrace strings
Sadik Armagan1625efc2021-06-10 18:24:34 +01002263 CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceCharPolicy>("€£", buffer));
2264 CHECK(buffer.empty());
2265 CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceCharPolicy>("invalid‡string", buffer));
2266 CHECK(buffer.empty());
2267 CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceCharPolicy>("12Ž34", buffer));
2268 CHECK(buffer.empty());
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002269}
2270
Sadik Armagan1625efc2021-06-10 18:24:34 +01002271TEST_CASE("StringToSwTraceNameStringTest")
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002272{
2273 std::vector<uint32_t> buffer;
2274
2275 // Valid SWTrace namestrings (expected size in words)
Jim Flynnbbfe6032020-07-20 16:57:44 +01002276 StringToSwTraceStringTestHelper<arm::pipe::SwTraceNameCharPolicy>("", buffer, 2);
2277 StringToSwTraceStringTestHelper<arm::pipe::SwTraceNameCharPolicy>("_", buffer, 2);
2278 StringToSwTraceStringTestHelper<arm::pipe::SwTraceNameCharPolicy>("0123", buffer, 3);
2279 StringToSwTraceStringTestHelper<arm::pipe::SwTraceNameCharPolicy>("valid_string", buffer, 5);
2280 StringToSwTraceStringTestHelper<arm::pipe::SwTraceNameCharPolicy>("VALID_string_456", buffer, 6);
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002281
2282 // Invalid SWTrace namestrings
Sadik Armagan1625efc2021-06-10 18:24:34 +01002283 CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceNameCharPolicy>(" ", buffer));
2284 CHECK(buffer.empty());
2285 CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceNameCharPolicy>("invalid string", buffer));
2286 CHECK(buffer.empty());
2287 CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceNameCharPolicy>("!$%", buffer));
2288 CHECK(buffer.empty());
2289 CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceNameCharPolicy>("invalid|\\~string#123", buffer));
2290 CHECK(buffer.empty());
2291 CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceNameCharPolicy>("€£", buffer));
2292 CHECK(buffer.empty());
2293 CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceNameCharPolicy>("invalid‡string", buffer));
2294 CHECK(buffer.empty());
2295 CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceNameCharPolicy>("12Ž34", buffer));
2296 CHECK(buffer.empty());
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +01002297}
2298
Sadik Armagan1625efc2021-06-10 18:24:34 +01002299TEST_CASE("CheckPeriodicCounterCaptureThread")
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002300{
Matteo Martincighe0e6efc2019-10-04 17:17:42 +01002301 class CaptureReader : public IReadCounterValues
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002302 {
2303 public:
Finn Williamsf4d59a62019-10-14 15:55:18 +01002304 CaptureReader(uint16_t counterSize)
2305 {
Keith Davis3201eea2019-10-24 17:30:41 +01002306 for (uint16_t i = 0; i < counterSize; ++i)
Finn Williamsf4d59a62019-10-14 15:55:18 +01002307 {
2308 m_Data[i] = 0;
2309 }
2310 m_CounterSize = counterSize;
2311 }
2312 //not used
Matteo Martincighe8485382019-10-10 14:08:21 +01002313 bool IsCounterRegistered(uint16_t counterUid) const override
2314 {
Jan Eilers8eb25602020-03-09 12:13:48 +00002315 armnn::IgnoreUnused(counterUid);
Finn Williamsf4d59a62019-10-14 15:55:18 +01002316 return false;
Matteo Martincighe8485382019-10-10 14:08:21 +01002317 }
Jim Flynn34430252022-03-04 15:03:58 +00002318 bool IsCounterRegistered(const std::string& counterName) const override
2319 {
2320 armnn::IgnoreUnused(counterName);
2321 return false;
2322 }
Matteo Martincighe0e6efc2019-10-04 17:17:42 +01002323 uint16_t GetCounterCount() const override
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002324 {
Finn Williamsf4d59a62019-10-14 15:55:18 +01002325 return m_CounterSize;
Matteo Martincighe0e6efc2019-10-04 17:17:42 +01002326 }
2327
Finn Williamsf3fcf322020-05-11 14:38:02 +01002328 uint32_t GetAbsoluteCounterValue(uint16_t counterUid) const override
2329 {
2330 if (counterUid > m_CounterSize)
2331 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01002332 FAIL("Invalid counter Uid");
Finn Williamsf3fcf322020-05-11 14:38:02 +01002333 }
2334 return m_Data.at(counterUid).load();
2335 }
2336
2337 uint32_t GetDeltaCounterValue(uint16_t counterUid) override
Matteo Martincighe0e6efc2019-10-04 17:17:42 +01002338 {
Keith Davis3201eea2019-10-24 17:30:41 +01002339 if (counterUid > m_CounterSize)
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002340 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01002341 FAIL("Invalid counter Uid");
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002342 }
Matteo Martincighe8485382019-10-10 14:08:21 +01002343 return m_Data.at(counterUid).load();
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002344 }
2345
Matteo Martincighe8485382019-10-10 14:08:21 +01002346 void SetCounterValue(uint16_t counterUid, uint32_t value)
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002347 {
Keith Davis3201eea2019-10-24 17:30:41 +01002348 if (counterUid > m_CounterSize)
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002349 {
Sadik Armagan1625efc2021-06-10 18:24:34 +01002350 FAIL("Invalid counter Uid");
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002351 }
Finn Williamsf4d59a62019-10-14 15:55:18 +01002352 m_Data.at(counterUid).store(value);
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002353 }
2354
2355 private:
Matteo Martincighe8485382019-10-10 14:08:21 +01002356 std::unordered_map<uint16_t, std::atomic<uint32_t>> m_Data;
Finn Williamsf4d59a62019-10-14 15:55:18 +01002357 uint16_t m_CounterSize;
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002358 };
2359
Matteo Martincigh5d737fb2019-10-07 13:05:13 +01002360 ProfilingStateMachine profilingStateMachine;
2361
Cathal Corbett6f073722022-03-04 12:11:09 +00002362 const std::unordered_map<std::string,
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00002363 std::shared_ptr<IBackendProfilingContext>> backendProfilingContext;
Finn Williams032bc742020-02-12 11:02:34 +00002364 CounterIdMap counterIdMap;
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002365 Holder data;
2366 std::vector<uint16_t> captureIds1 = { 0, 1 };
2367 std::vector<uint16_t> captureIds2;
2368
Narumol Prangnawarat404b2752019-09-24 17:23:16 +01002369 MockBufferManager mockBuffer(512);
Sadik Armagan3896b472020-02-10 12:24:15 +00002370 SendCounterPacket sendCounterPacket(mockBuffer);
2371 SendThread sendThread(profilingStateMachine, mockBuffer, sendCounterPacket);
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002372
2373 std::vector<uint16_t> counterIds;
Finn Williamsf4d59a62019-10-14 15:55:18 +01002374 CaptureReader captureReader(2);
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002375
Keith Davis3201eea2019-10-24 17:30:41 +01002376 unsigned int valueA = 10;
2377 unsigned int valueB = 15;
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002378 unsigned int numSteps = 5;
2379
Finn Williams032bc742020-02-12 11:02:34 +00002380 PeriodicCounterCapture periodicCounterCapture(std::ref(data), std::ref(sendCounterPacket), captureReader,
2381 counterIdMap, backendProfilingContext);
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002382
Matteo Martincighe0e6efc2019-10-04 17:17:42 +01002383 for (unsigned int i = 0; i < numSteps; ++i)
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002384 {
Finn Williams032bc742020-02-12 11:02:34 +00002385 data.SetCaptureData(1, captureIds1, {});
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002386 captureReader.SetCounterValue(0, valueA * (i + 1));
2387 captureReader.SetCounterValue(1, valueB * (i + 1));
2388
2389 periodicCounterCapture.Start();
Finn Williamsf4d59a62019-10-14 15:55:18 +01002390 periodicCounterCapture.Stop();
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002391 }
2392
Narumol Prangnawarat404b2752019-09-24 17:23:16 +01002393 auto buffer = mockBuffer.GetReadableBuffer();
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002394
2395 uint32_t headerWord0 = ReadUint32(buffer, 0);
2396 uint32_t headerWord1 = ReadUint32(buffer, 4);
2397
Sadik Armagan1625efc2021-06-10 18:24:34 +01002398 CHECK(((headerWord0 >> 26) & 0x0000003F) == 3); // packet family
2399 CHECK(((headerWord0 >> 19) & 0x0000007F) == 0); // packet class
2400 CHECK(((headerWord0 >> 16) & 0x00000007) == 0); // packet type
2401 CHECK(headerWord1 == 20);
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002402
Keith Davis3201eea2019-10-24 17:30:41 +01002403 uint32_t offset = 16;
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002404 uint16_t readIndex = ReadUint16(buffer, offset);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002405 CHECK(0 == readIndex);
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002406
2407 offset += 2;
2408 uint32_t readValue = ReadUint32(buffer, offset);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002409 CHECK((valueA * numSteps) == readValue);
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002410
2411 offset += 4;
2412 readIndex = ReadUint16(buffer, offset);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002413 CHECK(1 == readIndex);
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002414
2415 offset += 2;
2416 readValue = ReadUint32(buffer, offset);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002417 CHECK((valueB * numSteps) == readValue);
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01002418}
2419
Sadik Armagan1625efc2021-06-10 18:24:34 +01002420TEST_CASE("RequestCounterDirectoryCommandHandlerTest1")
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002421{
Jim Flynn397043f2019-10-17 17:37:10 +01002422 const uint32_t familyId = 0;
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002423 const uint32_t packetId = 3;
Keith Davis3201eea2019-10-24 17:30:41 +01002424 const uint32_t version = 1;
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002425 ProfilingStateMachine profilingStateMachine;
2426 CounterDirectory counterDirectory;
Matteo Martincigh9723d022019-11-13 10:56:41 +00002427 MockBufferManager mockBuffer1(1024);
Sadik Armagan3896b472020-02-10 12:24:15 +00002428 SendCounterPacket sendCounterPacket(mockBuffer1);
2429 SendThread sendThread(profilingStateMachine, mockBuffer1, sendCounterPacket);
Matteo Martincigh9723d022019-11-13 10:56:41 +00002430 MockBufferManager mockBuffer2(1024);
2431 SendTimelinePacket sendTimelinePacket(mockBuffer2);
Keith Davis3201eea2019-10-24 17:30:41 +01002432 RequestCounterDirectoryCommandHandler commandHandler(familyId, packetId, version, counterDirectory,
Matteo Martincigh9723d022019-11-13 10:56:41 +00002433 sendCounterPacket, sendTimelinePacket, profilingStateMachine);
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002434
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002435 const uint32_t wrongPacketId = 47;
Keith Davis3201eea2019-10-24 17:30:41 +01002436 const uint32_t wrongHeader = (wrongPacketId & 0x000003FF) << 16;
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002437
Jim Flynnbbfe6032020-07-20 16:57:44 +01002438 arm::pipe::Packet wrongPacket(wrongHeader);
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002439
2440 profilingStateMachine.TransitionToState(ProfilingState::Uninitialised);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002441 CHECK_THROWS_AS(commandHandler(wrongPacket), armnn::RuntimeException); // Wrong profiling state
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002442 profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002443 CHECK_THROWS_AS(commandHandler(wrongPacket), armnn::RuntimeException); // Wrong profiling state
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002444 profilingStateMachine.TransitionToState(ProfilingState::WaitingForAck);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002445 CHECK_THROWS_AS(commandHandler(wrongPacket), armnn::RuntimeException); // Wrong profiling state
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002446 profilingStateMachine.TransitionToState(ProfilingState::Active);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002447 CHECK_THROWS_AS(commandHandler(wrongPacket), armnn::InvalidArgumentException); // Wrong packet
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002448
2449 const uint32_t rightHeader = (packetId & 0x000003FF) << 16;
2450
Jim Flynnbbfe6032020-07-20 16:57:44 +01002451 arm::pipe::Packet rightPacket(rightHeader);
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002452
Sadik Armagan1625efc2021-06-10 18:24:34 +01002453 CHECK_NOTHROW(commandHandler(rightPacket)); // Right packet
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002454
Matteo Martincigh9723d022019-11-13 10:56:41 +00002455 auto readBuffer1 = mockBuffer1.GetReadableBuffer();
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002456
Matteo Martincigh9723d022019-11-13 10:56:41 +00002457 uint32_t header1Word0 = ReadUint32(readBuffer1, 0);
2458 uint32_t header1Word1 = ReadUint32(readBuffer1, 4);
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002459
Matteo Martincigh9723d022019-11-13 10:56:41 +00002460 // Counter directory packet
Sadik Armagan1625efc2021-06-10 18:24:34 +01002461 CHECK(((header1Word0 >> 26) & 0x0000003F) == 0); // packet family
2462 CHECK(((header1Word0 >> 16) & 0x000003FF) == 2); // packet id
2463 CHECK(header1Word1 == 24); // data length
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002464
Matteo Martincigh9723d022019-11-13 10:56:41 +00002465 uint32_t bodyHeader1Word0 = ReadUint32(readBuffer1, 8);
Matthew Sloyan371b70e2020-09-11 10:14:57 +01002466 uint16_t deviceRecordCount = armnn::numeric_cast<uint16_t>(bodyHeader1Word0 >> 16);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002467 CHECK(deviceRecordCount == 0); // device_records_count
Matteo Martincigh9723d022019-11-13 10:56:41 +00002468
2469 auto readBuffer2 = mockBuffer2.GetReadableBuffer();
2470
2471 uint32_t header2Word0 = ReadUint32(readBuffer2, 0);
2472 uint32_t header2Word1 = ReadUint32(readBuffer2, 4);
2473
2474 // Timeline message directory packet
Sadik Armagan1625efc2021-06-10 18:24:34 +01002475 CHECK(((header2Word0 >> 26) & 0x0000003F) == 1); // packet family
2476 CHECK(((header2Word0 >> 16) & 0x000003FF) == 0); // packet id
2477 CHECK(header2Word1 == 443); // data length
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002478}
2479
Sadik Armagan1625efc2021-06-10 18:24:34 +01002480TEST_CASE("RequestCounterDirectoryCommandHandlerTest2")
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002481{
Jim Flynn397043f2019-10-17 17:37:10 +01002482 const uint32_t familyId = 0;
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002483 const uint32_t packetId = 3;
Keith Davis3201eea2019-10-24 17:30:41 +01002484 const uint32_t version = 1;
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002485 ProfilingStateMachine profilingStateMachine;
2486 CounterDirectory counterDirectory;
Matteo Martincigh9723d022019-11-13 10:56:41 +00002487 MockBufferManager mockBuffer1(1024);
Sadik Armagan3896b472020-02-10 12:24:15 +00002488 SendCounterPacket sendCounterPacket(mockBuffer1);
2489 SendThread sendThread(profilingStateMachine, mockBuffer1, sendCounterPacket);
Matteo Martincigh9723d022019-11-13 10:56:41 +00002490 MockBufferManager mockBuffer2(1024);
2491 SendTimelinePacket sendTimelinePacket(mockBuffer2);
Keith Davis3201eea2019-10-24 17:30:41 +01002492 RequestCounterDirectoryCommandHandler commandHandler(familyId, packetId, version, counterDirectory,
Matteo Martincigh9723d022019-11-13 10:56:41 +00002493 sendCounterPacket, sendTimelinePacket, profilingStateMachine);
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002494 const uint32_t header = (packetId & 0x000003FF) << 16;
Jim Flynnbbfe6032020-07-20 16:57:44 +01002495 const arm::pipe::Packet packet(header);
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002496
Matteo Martincigh9723d022019-11-13 10:56:41 +00002497 const Device* device = counterDirectory.RegisterDevice("deviceA", 1);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002498 CHECK(device != nullptr);
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002499 const CounterSet* counterSet = counterDirectory.RegisterCounterSet("countersetA");
Sadik Armagan1625efc2021-06-10 18:24:34 +01002500 CHECK(counterSet != nullptr);
Sadik Armagan4c998992020-02-25 12:44:44 +00002501 counterDirectory.RegisterCategory("categoryA");
Keith Davise394bd92019-12-02 15:12:19 +00002502 counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID, 24,
2503 "categoryA", 0, 1, 2.0f, "counterA", "descA");
2504 counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID, 25,
2505 "categoryA", 1, 1, 3.0f, "counterB", "descB");
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002506
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002507 profilingStateMachine.TransitionToState(ProfilingState::Uninitialised);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002508 CHECK_THROWS_AS(commandHandler(packet), armnn::RuntimeException); // Wrong profiling state
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002509 profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002510 CHECK_THROWS_AS(commandHandler(packet), armnn::RuntimeException); // Wrong profiling state
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002511 profilingStateMachine.TransitionToState(ProfilingState::WaitingForAck);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002512 CHECK_THROWS_AS(commandHandler(packet), armnn::RuntimeException); // Wrong profiling state
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002513 profilingStateMachine.TransitionToState(ProfilingState::Active);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002514 CHECK_NOTHROW(commandHandler(packet));
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002515
Matteo Martincigh9723d022019-11-13 10:56:41 +00002516 auto readBuffer1 = mockBuffer1.GetReadableBuffer();
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002517
Finn Williams985fecf2020-04-30 11:06:43 +01002518 const uint32_t header1Word0 = ReadUint32(readBuffer1, 0);
2519 const uint32_t header1Word1 = ReadUint32(readBuffer1, 4);
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002520
Sadik Armagan1625efc2021-06-10 18:24:34 +01002521 CHECK(((header1Word0 >> 26) & 0x0000003F) == 0); // packet family
2522 CHECK(((header1Word0 >> 16) & 0x000003FF) == 2); // packet id
2523 CHECK(header1Word1 == 236); // data length
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002524
Finn Williams985fecf2020-04-30 11:06:43 +01002525 const uint32_t bodyHeaderSizeBytes = bodyHeaderSize * sizeof(uint32_t);
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002526
Finn Williams985fecf2020-04-30 11:06:43 +01002527 const uint32_t bodyHeader1Word0 = ReadUint32(readBuffer1, 8);
2528 const uint32_t bodyHeader1Word1 = ReadUint32(readBuffer1, 12);
2529 const uint32_t bodyHeader1Word2 = ReadUint32(readBuffer1, 16);
2530 const uint32_t bodyHeader1Word3 = ReadUint32(readBuffer1, 20);
2531 const uint32_t bodyHeader1Word4 = ReadUint32(readBuffer1, 24);
2532 const uint32_t bodyHeader1Word5 = ReadUint32(readBuffer1, 28);
Matthew Sloyan371b70e2020-09-11 10:14:57 +01002533 const uint16_t deviceRecordCount = armnn::numeric_cast<uint16_t>(bodyHeader1Word0 >> 16);
2534 const uint16_t counterSetRecordCount = armnn::numeric_cast<uint16_t>(bodyHeader1Word2 >> 16);
2535 const uint16_t categoryRecordCount = armnn::numeric_cast<uint16_t>(bodyHeader1Word4 >> 16);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002536 CHECK(deviceRecordCount == 1); // device_records_count
2537 CHECK(bodyHeader1Word1 == 0 + bodyHeaderSizeBytes); // device_records_pointer_table_offset
2538 CHECK(counterSetRecordCount == 1); // counter_set_count
2539 CHECK(bodyHeader1Word3 == 4 + bodyHeaderSizeBytes); // counter_set_pointer_table_offset
2540 CHECK(categoryRecordCount == 1); // categories_count
2541 CHECK(bodyHeader1Word5 == 8 + bodyHeaderSizeBytes); // categories_pointer_table_offset
Finn Williams985fecf2020-04-30 11:06:43 +01002542
2543 const uint32_t deviceRecordOffset = ReadUint32(readBuffer1, 32);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002544 CHECK(deviceRecordOffset == 12);
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002545
Finn Williams985fecf2020-04-30 11:06:43 +01002546 const uint32_t counterSetRecordOffset = ReadUint32(readBuffer1, 36);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002547 CHECK(counterSetRecordOffset == 28);
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002548
Finn Williams985fecf2020-04-30 11:06:43 +01002549 const uint32_t categoryRecordOffset = ReadUint32(readBuffer1, 40);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002550 CHECK(categoryRecordOffset == 48);
Matteo Martincigh9723d022019-11-13 10:56:41 +00002551
2552 auto readBuffer2 = mockBuffer2.GetReadableBuffer();
2553
Finn Williams985fecf2020-04-30 11:06:43 +01002554 const uint32_t header2Word0 = ReadUint32(readBuffer2, 0);
2555 const uint32_t header2Word1 = ReadUint32(readBuffer2, 4);
Matteo Martincigh9723d022019-11-13 10:56:41 +00002556
2557 // Timeline message directory packet
Sadik Armagan1625efc2021-06-10 18:24:34 +01002558 CHECK(((header2Word0 >> 26) & 0x0000003F) == 1); // packet family
2559 CHECK(((header2Word0 >> 16) & 0x000003FF) == 0); // packet id
2560 CHECK(header2Word1 == 443); // data length
Narumol Prangnawarat48033692019-09-20 12:04:55 +01002561}
2562
Sadik Armagan1625efc2021-06-10 18:24:34 +01002563TEST_CASE("CheckProfilingServiceGoodConnectionAcknowledgedPacket")
Matteo Martincigh54fb9572019-10-02 12:50:57 +01002564{
Finn Williamsa0de0562020-04-22 12:27:37 +01002565 unsigned int streamMetadataPacketsize = GetStreamMetaDataPacketSize();
Matteo Martincigh54fb9572019-10-02 12:50:57 +01002566
Jim Flynn53e46992019-10-14 12:31:10 +01002567 // Reset the profiling service to the uninitialized state
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00002568 ProfilingOptions options;
Keith Davis3201eea2019-10-24 17:30:41 +01002569 options.m_EnableProfiling = true;
Jim Flynn34430252022-03-04 15:03:58 +00002570 armnn::ArmNNProfilingServiceInitialiser initialiser;
2571 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Matteo Martincigh54fb9572019-10-02 12:50:57 +01002572 profilingService.ResetExternalProfilingOptions(options, true);
2573
Sadik Armagan3184c902020-03-18 10:57:30 +00002574 // Swap the profiling connection factory in the profiling service instance with our mock one
Jim Flynn34430252022-03-04 15:03:58 +00002575 SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
Sadik Armagan3184c902020-03-18 10:57:30 +00002576
Matteo Martincigh54fb9572019-10-02 12:50:57 +01002577 // Bring the profiling service to the "WaitingForAck" state
Sadik Armagan1625efc2021-06-10 18:24:34 +01002578 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Keith Davis3201eea2019-10-24 17:30:41 +01002579 profilingService.Update(); // Initialize the counter directory
Sadik Armagan1625efc2021-06-10 18:24:34 +01002580 CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
Keith Davis3201eea2019-10-24 17:30:41 +01002581 profilingService.Update(); // Create the profiling connection
Matteo Martincigh54fb9572019-10-02 12:50:57 +01002582
Matteo Martincighd0613b52019-10-09 16:47:04 +01002583 // Get the mock profiling connection
2584 MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
Sadik Armagan1625efc2021-06-10 18:24:34 +01002585 CHECK(mockProfilingConnection);
Matteo Martincighd0613b52019-10-09 16:47:04 +01002586
Matteo Martincighe8485382019-10-10 14:08:21 +01002587 // Remove the packets received so far
2588 mockProfilingConnection->Clear();
2589
Sadik Armagan1625efc2021-06-10 18:24:34 +01002590 CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
Keith Davis3201eea2019-10-24 17:30:41 +01002591 profilingService.Update(); // Start the command handler and the send thread
Matteo Martincighe8485382019-10-10 14:08:21 +01002592
2593 // Wait for the Stream Metadata packet to be sent
Sadik Armagan1625efc2021-06-10 18:24:34 +01002594 CHECK(helper.WaitForPacketsSent(
Finn Williams09ad6f92019-12-19 17:05:18 +00002595 mockProfilingConnection, PacketType::StreamMetaData, streamMetadataPacketsize) >= 1);
Matteo Martincigh54fb9572019-10-02 12:50:57 +01002596
2597 // Write a valid "Connection Acknowledged" packet into the mock profiling connection, to simulate a valid
2598 // reply from an external profiling service
2599
2600 // Connection Acknowledged Packet header (word 0, word 1 is always zero):
2601 // 26:31 [6] packet_family: Control Packet Family, value 0b000000
2602 // 16:25 [10] packet_id: Packet identifier, value 0b0000000001
2603 // 8:15 [8] reserved: Reserved, value 0b00000000
2604 // 0:7 [8] reserved: Reserved, value 0b00000000
2605 uint32_t packetFamily = 0;
2606 uint32_t packetId = 1;
Keith Davis3201eea2019-10-24 17:30:41 +01002607 uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
Matteo Martincigh54fb9572019-10-02 12:50:57 +01002608
Matteo Martincighd0613b52019-10-09 16:47:04 +01002609 // Create the Connection Acknowledged Packet
Jim Flynnbbfe6032020-07-20 16:57:44 +01002610 arm::pipe::Packet connectionAcknowledgedPacket(header);
Matteo Martincigh54fb9572019-10-02 12:50:57 +01002611
2612 // Write the packet to the mock profiling connection
2613 mockProfilingConnection->WritePacket(std::move(connectionAcknowledgedPacket));
2614
Colm Donelan2ba48d22019-11-29 09:10:59 +00002615 // Wait for the counter directory packet to ensure the ConnectionAcknowledgedCommandHandler has run.
Sadik Armagan1625efc2021-06-10 18:24:34 +01002616 CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::CounterDirectory) == 1);
Matteo Martincigh54fb9572019-10-02 12:50:57 +01002617
2618 // The Connection Acknowledged Command Handler should have updated the profiling state accordingly
Sadik Armagan1625efc2021-06-10 18:24:34 +01002619 CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
Matteo Martincighd0613b52019-10-09 16:47:04 +01002620
2621 // Reset the profiling service to stop any running thread
2622 options.m_EnableProfiling = false;
2623 profilingService.ResetExternalProfilingOptions(options, true);
Matteo Martincigh54fb9572019-10-02 12:50:57 +01002624}
2625
Sadik Armagan1625efc2021-06-10 18:24:34 +01002626TEST_CASE("CheckProfilingServiceGoodRequestCounterDirectoryPacket")
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002627{
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002628 // Reset the profiling service to the uninitialized state
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00002629 ProfilingOptions options;
Keith Davis3201eea2019-10-24 17:30:41 +01002630 options.m_EnableProfiling = true;
Jim Flynn34430252022-03-04 15:03:58 +00002631 armnn::ArmNNProfilingServiceInitialiser initialiser;
2632 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002633 profilingService.ResetExternalProfilingOptions(options, true);
2634
Sadik Armagan3184c902020-03-18 10:57:30 +00002635 // Swap the profiling connection factory in the profiling service instance with our mock one
Jim Flynn34430252022-03-04 15:03:58 +00002636 SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
Sadik Armagan3184c902020-03-18 10:57:30 +00002637
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002638 // Bring the profiling service to the "Active" state
Sadik Armagan1625efc2021-06-10 18:24:34 +01002639 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Keith Davis3201eea2019-10-24 17:30:41 +01002640 profilingService.Update(); // Initialize the counter directory
Sadik Armagan1625efc2021-06-10 18:24:34 +01002641 CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
Keith Davis3201eea2019-10-24 17:30:41 +01002642 profilingService.Update(); // Create the profiling connection
Sadik Armagan1625efc2021-06-10 18:24:34 +01002643 CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
Keith Davis3201eea2019-10-24 17:30:41 +01002644 profilingService.Update(); // Start the command handler and the send thread
Matteo Martincighe8485382019-10-10 14:08:21 +01002645
Colm Donelan2ba48d22019-11-29 09:10:59 +00002646 // Get the mock profiling connection
2647 MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
Sadik Armagan1625efc2021-06-10 18:24:34 +01002648 CHECK(mockProfilingConnection);
Colm Donelan2ba48d22019-11-29 09:10:59 +00002649
Matteo Martincighe8485382019-10-10 14:08:21 +01002650 // Force the profiling service to the "Active" state
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002651 helper.ForceTransitionToState(ProfilingState::Active);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002652 CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002653
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002654 // Write a valid "Request Counter Directory" packet into the mock profiling connection, to simulate a valid
2655 // reply from an external profiling service
2656
2657 // Request Counter Directory packet header (word 0, word 1 is always zero):
2658 // 26:31 [6] packet_family: Control Packet Family, value 0b000000
2659 // 16:25 [10] packet_id: Packet identifier, value 0b0000000011
2660 // 8:15 [8] reserved: Reserved, value 0b00000000
2661 // 0:7 [8] reserved: Reserved, value 0b00000000
2662 uint32_t packetFamily = 0;
2663 uint32_t packetId = 3;
Keith Davis3201eea2019-10-24 17:30:41 +01002664 uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002665
2666 // Create the Request Counter Directory packet
Jim Flynnbbfe6032020-07-20 16:57:44 +01002667 arm::pipe::Packet requestCounterDirectoryPacket(header);
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002668
2669 // Write the packet to the mock profiling connection
2670 mockProfilingConnection->WritePacket(std::move(requestCounterDirectoryPacket));
2671
Sadik Armagan4c998992020-02-25 12:44:44 +00002672 // Expecting one CounterDirectory Packet of length 652
Jim Flynn6398a982020-05-27 17:05:21 +01002673 // and one TimelineMessageDirectory packet of length 451
Sadik Armagan1625efc2021-06-10 18:24:34 +01002674 CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::CounterDirectory, 652) == 1);
2675 CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::TimelineMessageDirectory, 451) == 1);
Matteo Martincighe8485382019-10-10 14:08:21 +01002676
2677 // The Request Counter Directory Command Handler should not have updated the profiling state
Sadik Armagan1625efc2021-06-10 18:24:34 +01002678 CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
Matteo Martincighe8485382019-10-10 14:08:21 +01002679
2680 // Reset the profiling service to stop any running thread
2681 options.m_EnableProfiling = false;
2682 profilingService.ResetExternalProfilingOptions(options, true);
2683}
2684
Sadik Armagan1625efc2021-06-10 18:24:34 +01002685TEST_CASE("CheckProfilingServiceBadPeriodicCounterSelectionPacketInvalidCounterUid")
Matteo Martincighe8485382019-10-10 14:08:21 +01002686{
Matteo Martincighe8485382019-10-10 14:08:21 +01002687 // Reset the profiling service to the uninitialized state
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00002688 ProfilingOptions options;
Keith Davis3201eea2019-10-24 17:30:41 +01002689 options.m_EnableProfiling = true;
Jim Flynn34430252022-03-04 15:03:58 +00002690 armnn::ArmNNProfilingServiceInitialiser initialiser;
2691 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Matteo Martincighe8485382019-10-10 14:08:21 +01002692 profilingService.ResetExternalProfilingOptions(options, true);
2693
Sadik Armagan3184c902020-03-18 10:57:30 +00002694 // Swap the profiling connection factory in the profiling service instance with our mock one
Jim Flynn34430252022-03-04 15:03:58 +00002695 SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
Sadik Armagan3184c902020-03-18 10:57:30 +00002696
Matteo Martincighe8485382019-10-10 14:08:21 +01002697 // Bring the profiling service to the "Active" state
Sadik Armagan1625efc2021-06-10 18:24:34 +01002698 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Keith Davis3201eea2019-10-24 17:30:41 +01002699 profilingService.Update(); // Initialize the counter directory
Sadik Armagan1625efc2021-06-10 18:24:34 +01002700 CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
Keith Davis3201eea2019-10-24 17:30:41 +01002701 profilingService.Update(); // Create the profiling connection
Sadik Armagan1625efc2021-06-10 18:24:34 +01002702 CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
Keith Davis3201eea2019-10-24 17:30:41 +01002703 profilingService.Update(); // Start the command handler and the send thread
Matteo Martincighe8485382019-10-10 14:08:21 +01002704
Colm Donelan2ba48d22019-11-29 09:10:59 +00002705 // Get the mock profiling connection
2706 MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
Sadik Armagan1625efc2021-06-10 18:24:34 +01002707 CHECK(mockProfilingConnection);
Colm Donelan2ba48d22019-11-29 09:10:59 +00002708
Matteo Martincighe8485382019-10-10 14:08:21 +01002709 // Force the profiling service to the "Active" state
2710 helper.ForceTransitionToState(ProfilingState::Active);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002711 CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
Matteo Martincighe8485382019-10-10 14:08:21 +01002712
Matteo Martincighe8485382019-10-10 14:08:21 +01002713 // Remove the packets received so far
2714 mockProfilingConnection->Clear();
2715
2716 // Write a "Periodic Counter Selection" packet into the mock profiling connection, to simulate an input from an
2717 // external profiling service
2718
2719 // Periodic Counter Selection packet header:
2720 // 26:31 [6] packet_family: Control Packet Family, value 0b000000
2721 // 16:25 [10] packet_id: Packet identifier, value 0b0000000100
2722 // 8:15 [8] reserved: Reserved, value 0b00000000
2723 // 0:7 [8] reserved: Reserved, value 0b00000000
2724 uint32_t packetFamily = 0;
2725 uint32_t packetId = 4;
Keith Davis3201eea2019-10-24 17:30:41 +01002726 uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
Matteo Martincighe8485382019-10-10 14:08:21 +01002727
Keith Davis3201eea2019-10-24 17:30:41 +01002728 uint32_t capturePeriod = 123456; // Some capture period (microseconds)
Matteo Martincighe8485382019-10-10 14:08:21 +01002729
2730 // Get the first valid counter UID
2731 const ICounterDirectory& counterDirectory = profilingService.GetCounterDirectory();
Keith Davis3201eea2019-10-24 17:30:41 +01002732 const Counters& counters = counterDirectory.GetCounters();
Sadik Armagan1625efc2021-06-10 18:24:34 +01002733 CHECK(counters.size() > 1);
Keith Davis3201eea2019-10-24 17:30:41 +01002734 uint16_t counterUidA = counters.begin()->first; // First valid counter UID
2735 uint16_t counterUidB = 9999; // Second invalid counter UID
Matteo Martincighe8485382019-10-10 14:08:21 +01002736
2737 uint32_t length = 8;
2738
2739 auto data = std::make_unique<unsigned char[]>(length);
2740 WriteUint32(data.get(), 0, capturePeriod);
2741 WriteUint16(data.get(), 4, counterUidA);
2742 WriteUint16(data.get(), 6, counterUidB);
2743
2744 // Create the Periodic Counter Selection packet
Jim Flynnbbfe6032020-07-20 16:57:44 +01002745 // Length > 0, this will start the Period Counter Capture thread
2746 arm::pipe::Packet periodicCounterSelectionPacket(header, length, data);
2747
Matteo Martincighe8485382019-10-10 14:08:21 +01002748
2749 // Write the packet to the mock profiling connection
2750 mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket));
2751
Finn Williams09ad6f92019-12-19 17:05:18 +00002752 // Expecting one Periodic Counter Selection packet of length 14
2753 // and at least one Periodic Counter Capture packet of length 22
Sadik Armagan1625efc2021-06-10 18:24:34 +01002754 CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::PeriodicCounterSelection, 14) == 1);
2755 CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::PeriodicCounterCapture, 22) >= 1);
Matteo Martincighe8485382019-10-10 14:08:21 +01002756
2757 // The Periodic Counter Selection Handler should not have updated the profiling state
Sadik Armagan1625efc2021-06-10 18:24:34 +01002758 CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
Matteo Martincighe8485382019-10-10 14:08:21 +01002759
2760 // Reset the profiling service to stop any running thread
2761 options.m_EnableProfiling = false;
2762 profilingService.ResetExternalProfilingOptions(options, true);
2763}
2764
Sadik Armagan1625efc2021-06-10 18:24:34 +01002765TEST_CASE("CheckProfilingServiceGoodPeriodicCounterSelectionPacketNoCounters")
Matteo Martincighe8485382019-10-10 14:08:21 +01002766{
Matteo Martincighe8485382019-10-10 14:08:21 +01002767 // Reset the profiling service to the uninitialized state
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00002768 ProfilingOptions options;
Keith Davis3201eea2019-10-24 17:30:41 +01002769 options.m_EnableProfiling = true;
Jim Flynn34430252022-03-04 15:03:58 +00002770 armnn::ArmNNProfilingServiceInitialiser initialiser;
2771 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Matteo Martincighe8485382019-10-10 14:08:21 +01002772 profilingService.ResetExternalProfilingOptions(options, true);
2773
Sadik Armagan3184c902020-03-18 10:57:30 +00002774 // Swap the profiling connection factory in the profiling service instance with our mock one
Jim Flynn34430252022-03-04 15:03:58 +00002775 SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
Sadik Armagan3184c902020-03-18 10:57:30 +00002776
Matteo Martincighe8485382019-10-10 14:08:21 +01002777 // Bring the profiling service to the "Active" state
Sadik Armagan1625efc2021-06-10 18:24:34 +01002778 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Keith Davis3201eea2019-10-24 17:30:41 +01002779 profilingService.Update(); // Initialize the counter directory
Sadik Armagan1625efc2021-06-10 18:24:34 +01002780 CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
Keith Davis3201eea2019-10-24 17:30:41 +01002781 profilingService.Update(); // Create the profiling connection
Sadik Armagan1625efc2021-06-10 18:24:34 +01002782 CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
Keith Davis3201eea2019-10-24 17:30:41 +01002783 profilingService.Update(); // Start the command handler and the send thread
Matteo Martincighe8485382019-10-10 14:08:21 +01002784
Colm Donelan2ba48d22019-11-29 09:10:59 +00002785 // Get the mock profiling connection
2786 MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
Sadik Armagan1625efc2021-06-10 18:24:34 +01002787 CHECK(mockProfilingConnection);
Colm Donelan2ba48d22019-11-29 09:10:59 +00002788
Matteo Martincighe8485382019-10-10 14:08:21 +01002789 // Wait for the Stream Metadata packet the be sent
2790 // (we are not testing the connection acknowledgement here so it will be ignored by this test)
Finn Williams09ad6f92019-12-19 17:05:18 +00002791 helper.WaitForPacketsSent(mockProfilingConnection, PacketType::StreamMetaData);
Matteo Martincighe8485382019-10-10 14:08:21 +01002792
2793 // Force the profiling service to the "Active" state
2794 helper.ForceTransitionToState(ProfilingState::Active);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002795 CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
Matteo Martincighe8485382019-10-10 14:08:21 +01002796
Matteo Martincighe8485382019-10-10 14:08:21 +01002797 // Write a "Periodic Counter Selection" packet into the mock profiling connection, to simulate an input from an
2798 // external profiling service
2799
2800 // Periodic Counter Selection packet header:
2801 // 26:31 [6] packet_family: Control Packet Family, value 0b000000
2802 // 16:25 [10] packet_id: Packet identifier, value 0b0000000100
2803 // 8:15 [8] reserved: Reserved, value 0b00000000
2804 // 0:7 [8] reserved: Reserved, value 0b00000000
2805 uint32_t packetFamily = 0;
2806 uint32_t packetId = 4;
Keith Davis3201eea2019-10-24 17:30:41 +01002807 uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
Matteo Martincighe8485382019-10-10 14:08:21 +01002808
2809 // Create the Periodic Counter Selection packet
Jim Flynnbbfe6032020-07-20 16:57:44 +01002810 // Length == 0, this will disable the collection of counters
2811 arm::pipe::Packet periodicCounterSelectionPacket(header);
Matteo Martincighe8485382019-10-10 14:08:21 +01002812
2813 // Write the packet to the mock profiling connection
2814 mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket));
2815
Finn Williams09ad6f92019-12-19 17:05:18 +00002816 // Wait for the Periodic Counter Selection packet of length 12 to be sent
2817 // The size of the expected Periodic Counter Selection (echos the sent one)
Sadik Armagan1625efc2021-06-10 18:24:34 +01002818 CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::PeriodicCounterSelection, 12) == 1);
Matteo Martincighe8485382019-10-10 14:08:21 +01002819
2820 // The Periodic Counter Selection Handler should not have updated the profiling state
Sadik Armagan1625efc2021-06-10 18:24:34 +01002821 CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
Matteo Martincighe8485382019-10-10 14:08:21 +01002822
Finn Williams09ad6f92019-12-19 17:05:18 +00002823 // No Periodic Counter packets are expected
Sadik Armagan1625efc2021-06-10 18:24:34 +01002824 CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::PeriodicCounterCapture, 0, 0) == 0);
Matteo Martincighe8485382019-10-10 14:08:21 +01002825
2826 // Reset the profiling service to stop any running thread
2827 options.m_EnableProfiling = false;
2828 profilingService.ResetExternalProfilingOptions(options, true);
2829}
2830
Sadik Armagan1625efc2021-06-10 18:24:34 +01002831TEST_CASE("CheckProfilingServiceGoodPeriodicCounterSelectionPacketSingleCounter")
Matteo Martincighe8485382019-10-10 14:08:21 +01002832{
Matteo Martincighe8485382019-10-10 14:08:21 +01002833 // Reset the profiling service to the uninitialized state
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00002834 ProfilingOptions options;
Keith Davis3201eea2019-10-24 17:30:41 +01002835 options.m_EnableProfiling = true;
Jim Flynn34430252022-03-04 15:03:58 +00002836 armnn::ArmNNProfilingServiceInitialiser initialiser;
2837 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Matteo Martincighe8485382019-10-10 14:08:21 +01002838 profilingService.ResetExternalProfilingOptions(options, true);
2839
Sadik Armagan3184c902020-03-18 10:57:30 +00002840 // Swap the profiling connection factory in the profiling service instance with our mock one
Jim Flynn34430252022-03-04 15:03:58 +00002841 SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
Sadik Armagan3184c902020-03-18 10:57:30 +00002842
Matteo Martincighe8485382019-10-10 14:08:21 +01002843 // Bring the profiling service to the "Active" state
Sadik Armagan1625efc2021-06-10 18:24:34 +01002844 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Keith Davis3201eea2019-10-24 17:30:41 +01002845 profilingService.Update(); // Initialize the counter directory
Sadik Armagan1625efc2021-06-10 18:24:34 +01002846 CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
Keith Davis3201eea2019-10-24 17:30:41 +01002847 profilingService.Update(); // Create the profiling connection
Sadik Armagan1625efc2021-06-10 18:24:34 +01002848 CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
Keith Davis3201eea2019-10-24 17:30:41 +01002849 profilingService.Update(); // Start the command handler and the send thread
Matteo Martincighe8485382019-10-10 14:08:21 +01002850
Colm Donelan2ba48d22019-11-29 09:10:59 +00002851 // Get the mock profiling connection
2852 MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
Sadik Armagan1625efc2021-06-10 18:24:34 +01002853 CHECK(mockProfilingConnection);
Colm Donelan2ba48d22019-11-29 09:10:59 +00002854
Finn Williams09ad6f92019-12-19 17:05:18 +00002855 // Wait for the Stream Metadata packet to be sent
Matteo Martincighe8485382019-10-10 14:08:21 +01002856 // (we are not testing the connection acknowledgement here so it will be ignored by this test)
Finn Williams09ad6f92019-12-19 17:05:18 +00002857 helper.WaitForPacketsSent(mockProfilingConnection, PacketType::StreamMetaData);
Matteo Martincighe8485382019-10-10 14:08:21 +01002858
2859 // Force the profiling service to the "Active" state
2860 helper.ForceTransitionToState(ProfilingState::Active);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002861 CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
Matteo Martincighe8485382019-10-10 14:08:21 +01002862
Matteo Martincighe8485382019-10-10 14:08:21 +01002863 // Write a "Periodic Counter Selection" packet into the mock profiling connection, to simulate an input from an
2864 // external profiling service
2865
2866 // Periodic Counter Selection packet header:
2867 // 26:31 [6] packet_family: Control Packet Family, value 0b000000
2868 // 16:25 [10] packet_id: Packet identifier, value 0b0000000100
2869 // 8:15 [8] reserved: Reserved, value 0b00000000
2870 // 0:7 [8] reserved: Reserved, value 0b00000000
2871 uint32_t packetFamily = 0;
2872 uint32_t packetId = 4;
Keith Davis3201eea2019-10-24 17:30:41 +01002873 uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
Matteo Martincighe8485382019-10-10 14:08:21 +01002874
Keith Davis3201eea2019-10-24 17:30:41 +01002875 uint32_t capturePeriod = 123456; // Some capture period (microseconds)
Matteo Martincighe8485382019-10-10 14:08:21 +01002876
2877 // Get the first valid counter UID
2878 const ICounterDirectory& counterDirectory = profilingService.GetCounterDirectory();
Keith Davis3201eea2019-10-24 17:30:41 +01002879 const Counters& counters = counterDirectory.GetCounters();
Sadik Armagan1625efc2021-06-10 18:24:34 +01002880 CHECK(!counters.empty());
Keith Davis3201eea2019-10-24 17:30:41 +01002881 uint16_t counterUid = counters.begin()->first; // Valid counter UID
Matteo Martincighe8485382019-10-10 14:08:21 +01002882
2883 uint32_t length = 6;
2884
2885 auto data = std::make_unique<unsigned char[]>(length);
2886 WriteUint32(data.get(), 0, capturePeriod);
2887 WriteUint16(data.get(), 4, counterUid);
2888
2889 // Create the Periodic Counter Selection packet
Jim Flynnbbfe6032020-07-20 16:57:44 +01002890 // Length > 0, this will start the Period Counter Capture thread
2891 arm::pipe::Packet periodicCounterSelectionPacket(header, length, data);
Matteo Martincighe8485382019-10-10 14:08:21 +01002892
2893 // Write the packet to the mock profiling connection
2894 mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket));
2895
Finn Williams09ad6f92019-12-19 17:05:18 +00002896 // Expecting one Periodic Counter Selection packet of length 14
2897 // and at least one Periodic Counter Capture packet of length 22
Sadik Armagan1625efc2021-06-10 18:24:34 +01002898 CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::PeriodicCounterSelection, 14) == 1);
2899 CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::PeriodicCounterCapture, 22) >= 1);
Matteo Martincighe8485382019-10-10 14:08:21 +01002900
2901 // The Periodic Counter Selection Handler should not have updated the profiling state
Sadik Armagan1625efc2021-06-10 18:24:34 +01002902 CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
Matteo Martincighe8485382019-10-10 14:08:21 +01002903
2904 // Reset the profiling service to stop any running thread
2905 options.m_EnableProfiling = false;
2906 profilingService.ResetExternalProfilingOptions(options, true);
2907}
2908
Sadik Armagan1625efc2021-06-10 18:24:34 +01002909TEST_CASE("CheckProfilingServiceGoodPeriodicCounterSelectionPacketMultipleCounters")
Matteo Martincighe8485382019-10-10 14:08:21 +01002910{
Matteo Martincighe8485382019-10-10 14:08:21 +01002911 // Reset the profiling service to the uninitialized state
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00002912 ProfilingOptions options;
Keith Davis3201eea2019-10-24 17:30:41 +01002913 options.m_EnableProfiling = true;
Jim Flynn34430252022-03-04 15:03:58 +00002914 armnn::ArmNNProfilingServiceInitialiser initialiser;
2915 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Matteo Martincighe8485382019-10-10 14:08:21 +01002916 profilingService.ResetExternalProfilingOptions(options, true);
2917
Sadik Armagan3184c902020-03-18 10:57:30 +00002918 // Swap the profiling connection factory in the profiling service instance with our mock one
Jim Flynn34430252022-03-04 15:03:58 +00002919 SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
Sadik Armagan3184c902020-03-18 10:57:30 +00002920
Matteo Martincighe8485382019-10-10 14:08:21 +01002921 // Bring the profiling service to the "Active" state
Sadik Armagan1625efc2021-06-10 18:24:34 +01002922 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Keith Davis3201eea2019-10-24 17:30:41 +01002923 profilingService.Update(); // Initialize the counter directory
Sadik Armagan1625efc2021-06-10 18:24:34 +01002924 CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
Keith Davis3201eea2019-10-24 17:30:41 +01002925 profilingService.Update(); // Create the profiling connection
Sadik Armagan1625efc2021-06-10 18:24:34 +01002926 CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
Keith Davis3201eea2019-10-24 17:30:41 +01002927 profilingService.Update(); // Start the command handler and the send thread
Matteo Martincighe8485382019-10-10 14:08:21 +01002928
Colm Donelan2ba48d22019-11-29 09:10:59 +00002929 // Get the mock profiling connection
2930 MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
Sadik Armagan1625efc2021-06-10 18:24:34 +01002931 CHECK(mockProfilingConnection);
Colm Donelan2ba48d22019-11-29 09:10:59 +00002932
Matteo Martincighe8485382019-10-10 14:08:21 +01002933 // Wait for the Stream Metadata packet the be sent
2934 // (we are not testing the connection acknowledgement here so it will be ignored by this test)
Finn Williams09ad6f92019-12-19 17:05:18 +00002935 helper.WaitForPacketsSent(mockProfilingConnection, PacketType::StreamMetaData);
Matteo Martincighe8485382019-10-10 14:08:21 +01002936
2937 // Force the profiling service to the "Active" state
2938 helper.ForceTransitionToState(ProfilingState::Active);
Sadik Armagan1625efc2021-06-10 18:24:34 +01002939 CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
Matteo Martincighe8485382019-10-10 14:08:21 +01002940
Matteo Martincighe8485382019-10-10 14:08:21 +01002941 // Write a "Periodic Counter Selection" packet into the mock profiling connection, to simulate an input from an
2942 // external profiling service
2943
2944 // Periodic Counter Selection packet header:
2945 // 26:31 [6] packet_family: Control Packet Family, value 0b000000
2946 // 16:25 [10] packet_id: Packet identifier, value 0b0000000100
2947 // 8:15 [8] reserved: Reserved, value 0b00000000
2948 // 0:7 [8] reserved: Reserved, value 0b00000000
2949 uint32_t packetFamily = 0;
2950 uint32_t packetId = 4;
Keith Davis3201eea2019-10-24 17:30:41 +01002951 uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
Matteo Martincighe8485382019-10-10 14:08:21 +01002952
Keith Davis3201eea2019-10-24 17:30:41 +01002953 uint32_t capturePeriod = 123456; // Some capture period (microseconds)
Matteo Martincighe8485382019-10-10 14:08:21 +01002954
2955 // Get the first valid counter UID
2956 const ICounterDirectory& counterDirectory = profilingService.GetCounterDirectory();
Keith Davis3201eea2019-10-24 17:30:41 +01002957 const Counters& counters = counterDirectory.GetCounters();
Sadik Armagan1625efc2021-06-10 18:24:34 +01002958 CHECK(counters.size() > 1);
Keith Davis3201eea2019-10-24 17:30:41 +01002959 uint16_t counterUidA = counters.begin()->first; // First valid counter UID
2960 uint16_t counterUidB = (counters.begin()++)->first; // Second valid counter UID
Matteo Martincighe8485382019-10-10 14:08:21 +01002961
2962 uint32_t length = 8;
2963
2964 auto data = std::make_unique<unsigned char[]>(length);
2965 WriteUint32(data.get(), 0, capturePeriod);
2966 WriteUint16(data.get(), 4, counterUidA);
2967 WriteUint16(data.get(), 6, counterUidB);
2968
2969 // Create the Periodic Counter Selection packet
Jim Flynnbbfe6032020-07-20 16:57:44 +01002970 // Length > 0, this will start the Period Counter Capture thread
2971 arm::pipe::Packet periodicCounterSelectionPacket(header, length, data);
Matteo Martincighe8485382019-10-10 14:08:21 +01002972
2973 // Write the packet to the mock profiling connection
2974 mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket));
2975
Finn Williams09ad6f92019-12-19 17:05:18 +00002976 // Expecting one PeriodicCounterSelection Packet with a length of 16
2977 // And at least one PeriodicCounterCapture Packet with a length of 28
Sadik Armagan1625efc2021-06-10 18:24:34 +01002978 CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::PeriodicCounterSelection, 16) == 1);
2979 CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::PeriodicCounterCapture, 28) >= 1);
Matteo Martincighe8485382019-10-10 14:08:21 +01002980
2981 // The Periodic Counter Selection Handler should not have updated the profiling state
Sadik Armagan1625efc2021-06-10 18:24:34 +01002982 CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
Matteo Martincigh8efc5002019-10-10 14:30:29 +01002983
2984 // Reset the profiling service to stop any running thread
2985 options.m_EnableProfiling = false;
2986 profilingService.ResetExternalProfilingOptions(options, true);
2987}
2988
Sadik Armagan1625efc2021-06-10 18:24:34 +01002989TEST_CASE("CheckProfilingServiceDisconnect")
Jim Flynn53e46992019-10-14 12:31:10 +01002990{
Jim Flynn53e46992019-10-14 12:31:10 +01002991 // Reset the profiling service to the uninitialized state
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00002992 ProfilingOptions options;
Keith Davis3201eea2019-10-24 17:30:41 +01002993 options.m_EnableProfiling = true;
Jim Flynn34430252022-03-04 15:03:58 +00002994 armnn::ArmNNProfilingServiceInitialiser initialiser;
2995 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Jim Flynn53e46992019-10-14 12:31:10 +01002996 profilingService.ResetExternalProfilingOptions(options, true);
2997
Sadik Armagan3184c902020-03-18 10:57:30 +00002998 // Swap the profiling connection factory in the profiling service instance with our mock one
Jim Flynn34430252022-03-04 15:03:58 +00002999 SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
Sadik Armagan3184c902020-03-18 10:57:30 +00003000
Jim Flynn53e46992019-10-14 12:31:10 +01003001 // Try to disconnect the profiling service while in the "Uninitialised" state
Sadik Armagan1625efc2021-06-10 18:24:34 +01003002 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Jim Flynn53e46992019-10-14 12:31:10 +01003003 profilingService.Disconnect();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003004 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised); // The state should not change
Jim Flynn53e46992019-10-14 12:31:10 +01003005
3006 // Try to disconnect the profiling service while in the "NotConnected" state
Keith Davis3201eea2019-10-24 17:30:41 +01003007 profilingService.Update(); // Initialize the counter directory
Sadik Armagan1625efc2021-06-10 18:24:34 +01003008 CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
Jim Flynn53e46992019-10-14 12:31:10 +01003009 profilingService.Disconnect();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003010 CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected); // The state should not change
Jim Flynn53e46992019-10-14 12:31:10 +01003011
3012 // Try to disconnect the profiling service while in the "WaitingForAck" state
Keith Davis3201eea2019-10-24 17:30:41 +01003013 profilingService.Update(); // Create the profiling connection
Sadik Armagan1625efc2021-06-10 18:24:34 +01003014 CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
Jim Flynn53e46992019-10-14 12:31:10 +01003015 profilingService.Disconnect();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003016 CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck); // The state should not change
Jim Flynn53e46992019-10-14 12:31:10 +01003017
3018 // Try to disconnect the profiling service while in the "Active" state
Keith Davis3201eea2019-10-24 17:30:41 +01003019 profilingService.Update(); // Start the command handler and the send thread
Jim Flynn53e46992019-10-14 12:31:10 +01003020
Colm Donelan2ba48d22019-11-29 09:10:59 +00003021 // Get the mock profiling connection
3022 MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003023 CHECK(mockProfilingConnection);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003024
Jim Flynn53e46992019-10-14 12:31:10 +01003025 // Wait for the Stream Metadata packet the be sent
3026 // (we are not testing the connection acknowledgement here so it will be ignored by this test)
Finn Williams09ad6f92019-12-19 17:05:18 +00003027 helper.WaitForPacketsSent(mockProfilingConnection, PacketType::StreamMetaData);
Jim Flynn53e46992019-10-14 12:31:10 +01003028
3029 // Force the profiling service to the "Active" state
3030 helper.ForceTransitionToState(ProfilingState::Active);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003031 CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
Jim Flynn53e46992019-10-14 12:31:10 +01003032
Jim Flynn53e46992019-10-14 12:31:10 +01003033 // Check that the profiling connection is open
Sadik Armagan1625efc2021-06-10 18:24:34 +01003034 CHECK(mockProfilingConnection->IsOpen());
Jim Flynn53e46992019-10-14 12:31:10 +01003035
3036 profilingService.Disconnect();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003037 CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected); // The state should have changed
Jim Flynn53e46992019-10-14 12:31:10 +01003038
3039 // Check that the profiling connection has been reset
3040 mockProfilingConnection = helper.GetMockProfilingConnection();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003041 CHECK(mockProfilingConnection == nullptr);
Jim Flynn53e46992019-10-14 12:31:10 +01003042
3043 // Reset the profiling service to stop any running thread
3044 options.m_EnableProfiling = false;
3045 profilingService.ResetExternalProfilingOptions(options, true);
3046}
3047
Sadik Armagan1625efc2021-06-10 18:24:34 +01003048TEST_CASE("CheckProfilingServiceGoodPerJobCounterSelectionPacket")
Matteo Martincigh994b5342019-10-11 17:19:56 +01003049{
Matteo Martincigh994b5342019-10-11 17:19:56 +01003050 // Reset the profiling service to the uninitialized state
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00003051 ProfilingOptions options;
Keith Davis3201eea2019-10-24 17:30:41 +01003052 options.m_EnableProfiling = true;
Jim Flynn34430252022-03-04 15:03:58 +00003053 armnn::ArmNNProfilingServiceInitialiser initialiser;
3054 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Matteo Martincigh994b5342019-10-11 17:19:56 +01003055 profilingService.ResetExternalProfilingOptions(options, true);
3056
Sadik Armagan3184c902020-03-18 10:57:30 +00003057 // Swap the profiling connection factory in the profiling service instance with our mock one
Jim Flynn34430252022-03-04 15:03:58 +00003058 SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
Sadik Armagan3184c902020-03-18 10:57:30 +00003059
Matteo Martincigh994b5342019-10-11 17:19:56 +01003060 // Bring the profiling service to the "Active" state
Sadik Armagan1625efc2021-06-10 18:24:34 +01003061 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Keith Davis3201eea2019-10-24 17:30:41 +01003062 profilingService.Update(); // Initialize the counter directory
Sadik Armagan1625efc2021-06-10 18:24:34 +01003063 CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
Keith Davis3201eea2019-10-24 17:30:41 +01003064 profilingService.Update(); // Create the profiling connection
Sadik Armagan1625efc2021-06-10 18:24:34 +01003065 CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
Keith Davis3201eea2019-10-24 17:30:41 +01003066 profilingService.Update(); // Start the command handler and the send thread
Matteo Martincigh994b5342019-10-11 17:19:56 +01003067
Colm Donelan2ba48d22019-11-29 09:10:59 +00003068 // Get the mock profiling connection
3069 MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003070 CHECK(mockProfilingConnection);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003071
Matteo Martincigh994b5342019-10-11 17:19:56 +01003072 // Wait for the Stream Metadata packet the be sent
3073 // (we are not testing the connection acknowledgement here so it will be ignored by this test)
Finn Williams09ad6f92019-12-19 17:05:18 +00003074 helper.WaitForPacketsSent(mockProfilingConnection, PacketType::StreamMetaData);
Matteo Martincigh994b5342019-10-11 17:19:56 +01003075
3076 // Force the profiling service to the "Active" state
3077 helper.ForceTransitionToState(ProfilingState::Active);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003078 CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
Matteo Martincigh994b5342019-10-11 17:19:56 +01003079
Matteo Martincigh994b5342019-10-11 17:19:56 +01003080 // Write a "Per-Job Counter Selection" packet into the mock profiling connection, to simulate an input from an
3081 // external profiling service
3082
3083 // Per-Job Counter Selection packet header:
3084 // 26:31 [6] packet_family: Control Packet Family, value 0b000000
3085 // 16:25 [10] packet_id: Packet identifier, value 0b0000000100
3086 // 8:15 [8] reserved: Reserved, value 0b00000000
3087 // 0:7 [8] reserved: Reserved, value 0b00000000
3088 uint32_t packetFamily = 0;
3089 uint32_t packetId = 5;
Keith Davis3201eea2019-10-24 17:30:41 +01003090 uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
Matteo Martincigh994b5342019-10-11 17:19:56 +01003091
3092 // Create the Per-Job Counter Selection packet
Jim Flynnbbfe6032020-07-20 16:57:44 +01003093 // Length == 0, this will disable the collection of counters
3094 arm::pipe::Packet periodicCounterSelectionPacket(header);
Matteo Martincigh994b5342019-10-11 17:19:56 +01003095
3096 // Write the packet to the mock profiling connection
3097 mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket));
3098
3099 // Wait for a bit (must at least be the delay value of the mock profiling connection) to make sure that
3100 // the Per-Job Counter Selection packet gets processed by the profiling service
Colm Donelan2ba48d22019-11-29 09:10:59 +00003101 std::this_thread::sleep_for(std::chrono::milliseconds(5));
Matteo Martincigh994b5342019-10-11 17:19:56 +01003102
Matteo Martincigh994b5342019-10-11 17:19:56 +01003103 // The Per-Job Counter Selection Command Handler should not have updated the profiling state
Sadik Armagan1625efc2021-06-10 18:24:34 +01003104 CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
Matteo Martincigh994b5342019-10-11 17:19:56 +01003105
Finn Williams09ad6f92019-12-19 17:05:18 +00003106 // The Per-Job Counter Selection packets are dropped silently, so there should be no reply coming
3107 // from the profiling service
3108 const auto StreamMetaDataSize = static_cast<unsigned long>(
3109 helper.WaitForPacketsSent(mockProfilingConnection, PacketType::StreamMetaData, 0, 0));
Sadik Armagan1625efc2021-06-10 18:24:34 +01003110 CHECK(StreamMetaDataSize == mockProfilingConnection->GetWrittenDataSize());
Finn Williams09ad6f92019-12-19 17:05:18 +00003111
Matteo Martincigh994b5342019-10-11 17:19:56 +01003112 // Reset the profiling service to stop any running thread
3113 options.m_EnableProfiling = false;
3114 profilingService.ResetExternalProfilingOptions(options, true);
3115}
3116
Sadik Armagan1625efc2021-06-10 18:24:34 +01003117TEST_CASE("CheckConfigureProfilingServiceOn")
Jim Flynn672d06e2019-10-15 10:18:11 +01003118{
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00003119 ProfilingOptions options;
Keith Davis3201eea2019-10-24 17:30:41 +01003120 options.m_EnableProfiling = true;
Jim Flynn34430252022-03-04 15:03:58 +00003121 armnn::ArmNNProfilingServiceInitialiser initialiser;
3122 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003123 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Jim Flynn672d06e2019-10-15 10:18:11 +01003124 profilingService.ConfigureProfilingService(options);
3125 // should get as far as NOT_CONNECTED
Sadik Armagan1625efc2021-06-10 18:24:34 +01003126 CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
Jim Flynn672d06e2019-10-15 10:18:11 +01003127 // Reset the profiling service to stop any running thread
3128 options.m_EnableProfiling = false;
3129 profilingService.ResetExternalProfilingOptions(options, true);
3130}
3131
Sadik Armagan1625efc2021-06-10 18:24:34 +01003132TEST_CASE("CheckConfigureProfilingServiceOff")
Jim Flynn672d06e2019-10-15 10:18:11 +01003133{
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00003134 ProfilingOptions options;
Jim Flynn34430252022-03-04 15:03:58 +00003135 armnn::ArmNNProfilingServiceInitialiser initialiser;
3136 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003137 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Jim Flynn672d06e2019-10-15 10:18:11 +01003138 profilingService.ConfigureProfilingService(options);
3139 // should not move from Uninitialised
Sadik Armagan1625efc2021-06-10 18:24:34 +01003140 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Jim Flynn672d06e2019-10-15 10:18:11 +01003141 // Reset the profiling service to stop any running thread
3142 options.m_EnableProfiling = false;
3143 profilingService.ResetExternalProfilingOptions(options, true);
3144}
3145
Sadik Armagan1625efc2021-06-10 18:24:34 +01003146TEST_CASE("CheckProfilingServiceEnabled")
Colm Donelan2ba48d22019-11-29 09:10:59 +00003147{
3148 // Locally reduce log level to "Warning", as this test needs to parse a warning message from the standard output
3149 LogLevelSwapper logLevelSwapper(armnn::LogSeverity::Warning);
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00003150 ProfilingOptions options;
Colm Donelan2ba48d22019-11-29 09:10:59 +00003151 options.m_EnableProfiling = true;
Jim Flynn34430252022-03-04 15:03:58 +00003152 armnn::ArmNNProfilingServiceInitialiser initialiser;
3153 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003154 profilingService.ResetExternalProfilingOptions(options, true);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003155 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003156 profilingService.Update();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003157 CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003158
3159 // Redirect the output to a local stream so that we can parse the warning message
3160 std::stringstream ss;
3161 StreamRedirector streamRedirector(std::cout, ss.rdbuf());
3162 profilingService.Update();
Finn Williams09ad6f92019-12-19 17:05:18 +00003163
3164 // Reset the profiling service to stop any running thread
3165 options.m_EnableProfiling = false;
3166 profilingService.ResetExternalProfilingOptions(options, true);
3167
Colm Donelan2ba48d22019-11-29 09:10:59 +00003168 streamRedirector.CancelRedirect();
3169
3170 // Check that the expected error has occurred and logged to the standard output
David Monahana8837bf2020-04-16 10:01:56 +01003171 if (ss.str().find("Cannot connect to stream socket: Connection refused") == std::string::npos)
Colm Donelan2ba48d22019-11-29 09:10:59 +00003172 {
3173 std::cout << ss.str();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003174 FAIL("Expected string not found.");
Colm Donelan2ba48d22019-11-29 09:10:59 +00003175 }
Colm Donelan2ba48d22019-11-29 09:10:59 +00003176}
3177
Sadik Armagan1625efc2021-06-10 18:24:34 +01003178TEST_CASE("CheckProfilingServiceEnabledRuntime")
Colm Donelan2ba48d22019-11-29 09:10:59 +00003179{
3180 // Locally reduce log level to "Warning", as this test needs to parse a warning message from the standard output
3181 LogLevelSwapper logLevelSwapper(armnn::LogSeverity::Warning);
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00003182 ProfilingOptions options;
Jim Flynn34430252022-03-04 15:03:58 +00003183 armnn::ArmNNProfilingServiceInitialiser initialiser;
3184 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003185 profilingService.ResetExternalProfilingOptions(options, true);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003186 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003187 profilingService.Update();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003188 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003189 options.m_EnableProfiling = true;
3190 profilingService.ResetExternalProfilingOptions(options);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003191 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003192 profilingService.Update();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003193 CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003194
3195 // Redirect the output to a local stream so that we can parse the warning message
3196 std::stringstream ss;
3197 StreamRedirector streamRedirector(std::cout, ss.rdbuf());
3198 profilingService.Update();
3199
Finn Williams09ad6f92019-12-19 17:05:18 +00003200 // Reset the profiling service to stop any running thread
3201 options.m_EnableProfiling = false;
3202 profilingService.ResetExternalProfilingOptions(options, true);
3203
Colm Donelan2ba48d22019-11-29 09:10:59 +00003204 streamRedirector.CancelRedirect();
3205
3206 // Check that the expected error has occurred and logged to the standard output
David Monahana8837bf2020-04-16 10:01:56 +01003207 if (ss.str().find("Cannot connect to stream socket: Connection refused") == std::string::npos)
Colm Donelan2ba48d22019-11-29 09:10:59 +00003208 {
3209 std::cout << ss.str();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003210 FAIL("Expected string not found.");
Colm Donelan2ba48d22019-11-29 09:10:59 +00003211 }
Colm Donelan2ba48d22019-11-29 09:10:59 +00003212}
3213
Sadik Armagan1625efc2021-06-10 18:24:34 +01003214TEST_CASE("CheckProfilingServiceBadConnectionAcknowledgedPacket")
Colm Donelan2ba48d22019-11-29 09:10:59 +00003215{
3216 // Locally reduce log level to "Warning", as this test needs to parse a warning message from the standard output
3217 LogLevelSwapper logLevelSwapper(armnn::LogSeverity::Warning);
Sadik Armagan3184c902020-03-18 10:57:30 +00003218
Colm Donelan2ba48d22019-11-29 09:10:59 +00003219
3220 // Redirect the standard output to a local stream so that we can parse the warning message
3221 std::stringstream ss;
3222 StreamRedirector streamRedirector(std::cout, ss.rdbuf());
3223
Colm Donelan2ba48d22019-11-29 09:10:59 +00003224 // Reset the profiling service to the uninitialized state
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00003225 ProfilingOptions options;
Colm Donelan2ba48d22019-11-29 09:10:59 +00003226 options.m_EnableProfiling = true;
Jim Flynn34430252022-03-04 15:03:58 +00003227 armnn::ArmNNProfilingServiceInitialiser initialiser;
3228 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003229 profilingService.ResetExternalProfilingOptions(options, true);
3230
Sadik Armagan3184c902020-03-18 10:57:30 +00003231 // Swap the profiling connection factory in the profiling service instance with our mock one
Jim Flynn34430252022-03-04 15:03:58 +00003232 SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
Sadik Armagan3184c902020-03-18 10:57:30 +00003233
Colm Donelan2ba48d22019-11-29 09:10:59 +00003234 // Bring the profiling service to the "WaitingForAck" state
Sadik Armagan1625efc2021-06-10 18:24:34 +01003235 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003236 profilingService.Update(); // Initialize the counter directory
Sadik Armagan1625efc2021-06-10 18:24:34 +01003237 CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003238 profilingService.Update(); // Create the profiling connection
3239
3240 // Get the mock profiling connection
3241 MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003242 CHECK(mockProfilingConnection);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003243
Sadik Armagan1625efc2021-06-10 18:24:34 +01003244 CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003245
3246 // Connection Acknowledged Packet header (word 0, word 1 is always zero):
3247 // 26:31 [6] packet_family: Control Packet Family, value 0b000000
3248 // 16:25 [10] packet_id: Packet identifier, value 0b0000000001
3249 // 8:15 [8] reserved: Reserved, value 0b00000000
3250 // 0:7 [8] reserved: Reserved, value 0b00000000
3251 uint32_t packetFamily = 0;
3252 uint32_t packetId = 37; // Wrong packet id!!!
3253 uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
3254
3255 // Create the Connection Acknowledged Packet
Jim Flynnbbfe6032020-07-20 16:57:44 +01003256 arm::pipe::Packet connectionAcknowledgedPacket(header);
Finn Williams09ad6f92019-12-19 17:05:18 +00003257 // Write an invalid "Connection Acknowledged" packet into the mock profiling connection, to simulate an invalid
3258 // reply from an external profiling service
Colm Donelan2ba48d22019-11-29 09:10:59 +00003259 mockProfilingConnection->WritePacket(std::move(connectionAcknowledgedPacket));
3260
Finn Williams09ad6f92019-12-19 17:05:18 +00003261 // Start the command thread
3262 profilingService.Update();
3263
3264 // Wait for the command thread to join
3265 options.m_EnableProfiling = false;
3266 profilingService.ResetExternalProfilingOptions(options, true);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003267
3268 streamRedirector.CancelRedirect();
3269
3270 // Check that the expected error has occurred and logged to the standard output
David Monahana8837bf2020-04-16 10:01:56 +01003271 if (ss.str().find("Functor with requested PacketId=37 and Version=4194304 does not exist") == std::string::npos)
Colm Donelan2ba48d22019-11-29 09:10:59 +00003272 {
3273 std::cout << ss.str();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003274 FAIL("Expected string not found.");
Colm Donelan2ba48d22019-11-29 09:10:59 +00003275 }
Colm Donelan2ba48d22019-11-29 09:10:59 +00003276}
3277
Sadik Armagan1625efc2021-06-10 18:24:34 +01003278TEST_CASE("CheckProfilingServiceBadRequestCounterDirectoryPacket")
Colm Donelan2ba48d22019-11-29 09:10:59 +00003279{
3280 // Locally reduce log level to "Warning", as this test needs to parse a warning message from the standard output
3281 LogLevelSwapper logLevelSwapper(armnn::LogSeverity::Warning);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003282
3283 // Redirect the standard output to a local stream so that we can parse the warning message
3284 std::stringstream ss;
3285 StreamRedirector streamRedirector(std::cout, ss.rdbuf());
3286
3287 // Reset the profiling service to the uninitialized state
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00003288 ProfilingOptions options;
Colm Donelan2ba48d22019-11-29 09:10:59 +00003289 options.m_EnableProfiling = true;
Jim Flynn34430252022-03-04 15:03:58 +00003290 armnn::ArmNNProfilingServiceInitialiser initialiser;
3291 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003292 profilingService.ResetExternalProfilingOptions(options, true);
3293
Sadik Armagan3184c902020-03-18 10:57:30 +00003294 // Swap the profiling connection factory in the profiling service instance with our mock one
Jim Flynn34430252022-03-04 15:03:58 +00003295 SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
Sadik Armagan3184c902020-03-18 10:57:30 +00003296
Colm Donelan2ba48d22019-11-29 09:10:59 +00003297 // Bring the profiling service to the "Active" state
Sadik Armagan1625efc2021-06-10 18:24:34 +01003298 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003299 helper.ForceTransitionToState(ProfilingState::NotConnected);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003300 CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003301 profilingService.Update(); // Create the profiling connection
Sadik Armagan1625efc2021-06-10 18:24:34 +01003302 CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003303
3304 // Get the mock profiling connection
3305 MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003306 CHECK(mockProfilingConnection);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003307
Colm Donelan2ba48d22019-11-29 09:10:59 +00003308 // Write a valid "Request Counter Directory" packet into the mock profiling connection, to simulate a valid
3309 // reply from an external profiling service
3310
3311 // Request Counter Directory packet header (word 0, word 1 is always zero):
3312 // 26:31 [6] packet_family: Control Packet Family, value 0b000000
3313 // 16:25 [10] packet_id: Packet identifier, value 0b0000000011
3314 // 8:15 [8] reserved: Reserved, value 0b00000000
3315 // 0:7 [8] reserved: Reserved, value 0b00000000
3316 uint32_t packetFamily = 0;
3317 uint32_t packetId = 123; // Wrong packet id!!!
3318 uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
3319
3320 // Create the Request Counter Directory packet
Jim Flynnbbfe6032020-07-20 16:57:44 +01003321 arm::pipe::Packet requestCounterDirectoryPacket(header);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003322
3323 // Write the packet to the mock profiling connection
3324 mockProfilingConnection->WritePacket(std::move(requestCounterDirectoryPacket));
3325
Finn Williams09ad6f92019-12-19 17:05:18 +00003326 // Start the command handler and the send thread
3327 profilingService.Update();
3328
3329 // Reset the profiling service to stop and join any running thread
3330 options.m_EnableProfiling = false;
3331 profilingService.ResetExternalProfilingOptions(options, true);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003332
3333 streamRedirector.CancelRedirect();
3334
3335 // Check that the expected error has occurred and logged to the standard output
David Monahana8837bf2020-04-16 10:01:56 +01003336 if (ss.str().find("Functor with requested PacketId=123 and Version=4194304 does not exist") == std::string::npos)
Colm Donelan2ba48d22019-11-29 09:10:59 +00003337 {
3338 std::cout << ss.str();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003339 FAIL("Expected string not found.");
Colm Donelan2ba48d22019-11-29 09:10:59 +00003340 }
Colm Donelan2ba48d22019-11-29 09:10:59 +00003341}
3342
Sadik Armagan1625efc2021-06-10 18:24:34 +01003343TEST_CASE("CheckProfilingServiceBadPeriodicCounterSelectionPacket")
Colm Donelan2ba48d22019-11-29 09:10:59 +00003344{
3345 // Locally reduce log level to "Warning", as this test needs to parse a warning message from the standard output
3346 LogLevelSwapper logLevelSwapper(armnn::LogSeverity::Warning);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003347
3348 // Redirect the standard output to a local stream so that we can parse the warning message
3349 std::stringstream ss;
3350 StreamRedirector streamRedirector(std::cout, ss.rdbuf());
3351
3352 // Reset the profiling service to the uninitialized state
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00003353 ProfilingOptions options;
Colm Donelan2ba48d22019-11-29 09:10:59 +00003354 options.m_EnableProfiling = true;
Jim Flynn34430252022-03-04 15:03:58 +00003355 armnn::ArmNNProfilingServiceInitialiser initialiser;
3356 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003357 profilingService.ResetExternalProfilingOptions(options, true);
3358
Sadik Armagan3184c902020-03-18 10:57:30 +00003359 // Swap the profiling connection factory in the profiling service instance with our mock one
Jim Flynn34430252022-03-04 15:03:58 +00003360 SwapProfilingConnectionFactoryHelper helper(arm::pipe::MAX_ARMNN_COUNTER, initialiser, profilingService);
Sadik Armagan3184c902020-03-18 10:57:30 +00003361
Colm Donelan2ba48d22019-11-29 09:10:59 +00003362 // Bring the profiling service to the "Active" state
Sadik Armagan1625efc2021-06-10 18:24:34 +01003363 CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003364 profilingService.Update(); // Initialize the counter directory
Sadik Armagan1625efc2021-06-10 18:24:34 +01003365 CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003366 profilingService.Update(); // Create the profiling connection
Sadik Armagan1625efc2021-06-10 18:24:34 +01003367 CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003368 profilingService.Update(); // Start the command handler and the send thread
3369
3370 // Get the mock profiling connection
3371 MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003372 CHECK(mockProfilingConnection);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003373
Colm Donelan2ba48d22019-11-29 09:10:59 +00003374 // Write a "Periodic Counter Selection" packet into the mock profiling connection, to simulate an input from an
3375 // external profiling service
3376
3377 // Periodic Counter Selection packet header:
3378 // 26:31 [6] packet_family: Control Packet Family, value 0b000000
3379 // 16:25 [10] packet_id: Packet identifier, value 0b0000000100
3380 // 8:15 [8] reserved: Reserved, value 0b00000000
3381 // 0:7 [8] reserved: Reserved, value 0b00000000
3382 uint32_t packetFamily = 0;
3383 uint32_t packetId = 999; // Wrong packet id!!!
3384 uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
3385
3386 // Create the Periodic Counter Selection packet
Jim Flynnbbfe6032020-07-20 16:57:44 +01003387 // Length == 0, this will disable the collection of counters
3388 arm::pipe::Packet periodicCounterSelectionPacket(header);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003389
3390 // Write the packet to the mock profiling connection
3391 mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket));
Finn Williams09ad6f92019-12-19 17:05:18 +00003392 profilingService.Update();
Colm Donelan2ba48d22019-11-29 09:10:59 +00003393
Finn Williams09ad6f92019-12-19 17:05:18 +00003394 // Reset the profiling service to stop any running thread
3395 options.m_EnableProfiling = false;
3396 profilingService.ResetExternalProfilingOptions(options, true);
Colm Donelan2ba48d22019-11-29 09:10:59 +00003397
3398 // Check that the expected error has occurred and logged to the standard output
3399 streamRedirector.CancelRedirect();
3400
3401 // Check that the expected error has occurred and logged to the standard output
David Monahana8837bf2020-04-16 10:01:56 +01003402 if (ss.str().find("Functor with requested PacketId=999 and Version=4194304 does not exist") == std::string::npos)
Colm Donelan2ba48d22019-11-29 09:10:59 +00003403 {
3404 std::cout << ss.str();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003405 FAIL("Expected string not found.");
Colm Donelan2ba48d22019-11-29 09:10:59 +00003406 }
Colm Donelan2ba48d22019-11-29 09:10:59 +00003407}
Jim Flynn97897022020-02-02 12:52:59 +00003408
Sadik Armagan1625efc2021-06-10 18:24:34 +01003409TEST_CASE("CheckCounterIdMap")
David Monahande803072020-01-30 12:44:23 +00003410{
3411 CounterIdMap counterIdMap;
Sadik Armagan1625efc2021-06-10 18:24:34 +01003412 CHECK_THROWS_AS(counterIdMap.GetBackendId(0), armnn::Exception);
3413 CHECK_THROWS_AS(counterIdMap.GetGlobalId(0, armnn::profiling::BACKEND_ID), armnn::Exception);
David Monahande803072020-01-30 12:44:23 +00003414
3415 uint16_t globalCounterIds = 0;
3416
Cathal Corbett6f073722022-03-04 12:11:09 +00003417 std::string cpuRefId(GetComputeDeviceAsCString(armnn::Compute::CpuRef));
3418 std::string cpuAccId(GetComputeDeviceAsCString(armnn::Compute::CpuAcc));
David Monahande803072020-01-30 12:44:23 +00003419
3420 std::vector<uint16_t> cpuRefCounters = {0, 1, 2, 3};
3421 std::vector<uint16_t> cpuAccCounters = {0, 1};
3422
3423 for (uint16_t backendCounterId : cpuRefCounters)
3424 {
3425 counterIdMap.RegisterMapping(globalCounterIds, backendCounterId, cpuRefId);
3426 ++globalCounterIds;
3427 }
3428 for (uint16_t backendCounterId : cpuAccCounters)
3429 {
3430 counterIdMap.RegisterMapping(globalCounterIds, backendCounterId, cpuAccId);
3431 ++globalCounterIds;
3432 }
3433
Cathal Corbett6f073722022-03-04 12:11:09 +00003434 CHECK(counterIdMap.GetBackendId(0) == (std::pair<uint16_t, std::string>(0, cpuRefId)));
3435 CHECK(counterIdMap.GetBackendId(1) == (std::pair<uint16_t, std::string>(1, cpuRefId)));
3436 CHECK(counterIdMap.GetBackendId(2) == (std::pair<uint16_t, std::string>(2, cpuRefId)));
3437 CHECK(counterIdMap.GetBackendId(3) == (std::pair<uint16_t, std::string>(3, cpuRefId)));
3438 CHECK(counterIdMap.GetBackendId(4) == (std::pair<uint16_t, std::string>(0, cpuAccId)));
3439 CHECK(counterIdMap.GetBackendId(5) == (std::pair<uint16_t, std::string>(1, cpuAccId)));
David Monahande803072020-01-30 12:44:23 +00003440
Sadik Armagan1625efc2021-06-10 18:24:34 +01003441 CHECK(counterIdMap.GetGlobalId(0, cpuRefId) == 0);
3442 CHECK(counterIdMap.GetGlobalId(1, cpuRefId) == 1);
3443 CHECK(counterIdMap.GetGlobalId(2, cpuRefId) == 2);
3444 CHECK(counterIdMap.GetGlobalId(3, cpuRefId) == 3);
3445 CHECK(counterIdMap.GetGlobalId(0, cpuAccId) == 4);
3446 CHECK(counterIdMap.GetGlobalId(1, cpuAccId) == 5);
David Monahande803072020-01-30 12:44:23 +00003447}
Colm Donelan2ba48d22019-11-29 09:10:59 +00003448
Sadik Armagan1625efc2021-06-10 18:24:34 +01003449TEST_CASE("CheckRegisterBackendCounters")
Jim Flynn97897022020-02-02 12:52:59 +00003450{
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00003451 uint16_t globalCounterIds = INFERENCES_RUN;
Cathal Corbett6f073722022-03-04 12:11:09 +00003452 std::string cpuRefId(GetComputeDeviceAsCString(armnn::Compute::CpuRef));
Jim Flynn97897022020-02-02 12:52:59 +00003453
Jim Flynn97897022020-02-02 12:52:59 +00003454 // Reset the profiling service to the uninitialized state
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00003455 ProfilingOptions options;
Jim Flynn97897022020-02-02 12:52:59 +00003456 options.m_EnableProfiling = true;
Jim Flynn34430252022-03-04 15:03:58 +00003457 armnn::ArmNNProfilingServiceInitialiser initialiser;
3458 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Jim Flynn97897022020-02-02 12:52:59 +00003459 profilingService.ResetExternalProfilingOptions(options, true);
3460
Sadik Armagan3184c902020-03-18 10:57:30 +00003461 RegisterBackendCounters registerBackendCounters(globalCounterIds, cpuRefId, profilingService);
3462
3463
3464
Sadik Armagan1625efc2021-06-10 18:24:34 +01003465 CHECK(profilingService.GetCounterDirectory().GetCategories().empty());
Jim Flynn97897022020-02-02 12:52:59 +00003466 registerBackendCounters.RegisterCategory("categoryOne");
3467 auto categoryOnePtr = profilingService.GetCounterDirectory().GetCategory("categoryOne");
Sadik Armagan1625efc2021-06-10 18:24:34 +01003468 CHECK(categoryOnePtr);
Jim Flynn97897022020-02-02 12:52:59 +00003469
Sadik Armagan1625efc2021-06-10 18:24:34 +01003470 CHECK(profilingService.GetCounterDirectory().GetDevices().empty());
Jim Flynn97897022020-02-02 12:52:59 +00003471 globalCounterIds = registerBackendCounters.RegisterDevice("deviceOne");
3472 auto deviceOnePtr = profilingService.GetCounterDirectory().GetDevice(globalCounterIds);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003473 CHECK(deviceOnePtr);
3474 CHECK(deviceOnePtr->m_Name == "deviceOne");
Jim Flynn97897022020-02-02 12:52:59 +00003475
Sadik Armagan1625efc2021-06-10 18:24:34 +01003476 CHECK(profilingService.GetCounterDirectory().GetCounterSets().empty());
Jim Flynn97897022020-02-02 12:52:59 +00003477 globalCounterIds = registerBackendCounters.RegisterCounterSet("counterSetOne");
3478 auto counterSetOnePtr = profilingService.GetCounterDirectory().GetCounterSet(globalCounterIds);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003479 CHECK(counterSetOnePtr);
3480 CHECK(counterSetOnePtr->m_Name == "counterSetOne");
Jim Flynn97897022020-02-02 12:52:59 +00003481
3482 uint16_t newGlobalCounterId = registerBackendCounters.RegisterCounter(0,
3483 "categoryOne",
3484 0,
3485 0,
3486 1.f,
3487 "CounterOne",
3488 "first test counter");
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00003489 CHECK((newGlobalCounterId = INFERENCES_RUN + 1));
Jim Flynn97897022020-02-02 12:52:59 +00003490 uint16_t mappedGlobalId = profilingService.GetCounterMappings().GetGlobalId(0, cpuRefId);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003491 CHECK(mappedGlobalId == newGlobalCounterId);
Jim Flynn97897022020-02-02 12:52:59 +00003492 auto backendMapping = profilingService.GetCounterMappings().GetBackendId(newGlobalCounterId);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003493 CHECK(backendMapping.first == 0);
3494 CHECK(backendMapping.second == cpuRefId);
Jim Flynn97897022020-02-02 12:52:59 +00003495
3496 // Reset the profiling service to stop any running thread
3497 options.m_EnableProfiling = false;
3498 profilingService.ResetExternalProfilingOptions(options, true);
3499}
3500
Sadik Armagan1625efc2021-06-10 18:24:34 +01003501TEST_CASE("CheckCounterStatusQuery")
James Conroy2dcd3fe2020-02-06 18:34:52 +00003502{
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00003503 ProfilingOptions options;
3504 options.m_EnableProfiling = true;
James Conroy2dcd3fe2020-02-06 18:34:52 +00003505
3506 // Reset the profiling service to the uninitialized state
Jim Flynn34430252022-03-04 15:03:58 +00003507 armnn::ArmNNProfilingServiceInitialiser initialiser;
3508 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00003509 profilingService.ResetExternalProfilingOptions(options, true);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003510
Cathal Corbett6f073722022-03-04 12:11:09 +00003511 const std::string cpuRefId(GetComputeDeviceAsCString(armnn::Compute::CpuRef));
3512 const std::string cpuAccId(GetComputeDeviceAsCString(armnn::Compute::CpuAcc));
James Conroy2dcd3fe2020-02-06 18:34:52 +00003513
3514 // Create BackendProfiling for each backend
3515 BackendProfiling backendProfilingCpuRef(options, profilingService, cpuRefId);
3516 BackendProfiling backendProfilingCpuAcc(options, profilingService, cpuAccId);
3517
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00003518 uint16_t initialNumGlobalCounterIds = INFERENCES_RUN;
James Conroy2dcd3fe2020-02-06 18:34:52 +00003519
3520 // Create RegisterBackendCounters for CpuRef
Sadik Armagan3184c902020-03-18 10:57:30 +00003521 RegisterBackendCounters registerBackendCountersCpuRef(initialNumGlobalCounterIds, cpuRefId, profilingService);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003522
3523 // Create 'testCategory' in CounterDirectory (backend agnostic)
Sadik Armagan1625efc2021-06-10 18:24:34 +01003524 CHECK(profilingService.GetCounterDirectory().GetCategories().empty());
James Conroy2dcd3fe2020-02-06 18:34:52 +00003525 registerBackendCountersCpuRef.RegisterCategory("testCategory");
3526 auto categoryOnePtr = profilingService.GetCounterDirectory().GetCategory("testCategory");
Sadik Armagan1625efc2021-06-10 18:24:34 +01003527 CHECK(categoryOnePtr);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003528
3529 // Counters:
3530 // Global | Local | Backend
3531 // 5 | 0 | CpuRef
3532 // 6 | 1 | CpuRef
3533 // 7 | 1 | CpuAcc
3534
3535 std::vector<uint16_t> cpuRefCounters = {0, 1};
3536 std::vector<uint16_t> cpuAccCounters = {0};
3537
3538 // Register the backend counters for CpuRef and validate GetGlobalId and GetBackendId
3539 uint16_t currentNumGlobalCounterIds = registerBackendCountersCpuRef.RegisterCounter(
3540 0, "testCategory", 0, 0, 1.f, "CpuRefCounter0", "Zeroth CpuRef Counter");
Sadik Armagan1625efc2021-06-10 18:24:34 +01003541 CHECK(currentNumGlobalCounterIds == initialNumGlobalCounterIds + 1);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003542 uint16_t mappedGlobalId = profilingService.GetCounterMappings().GetGlobalId(0, cpuRefId);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003543 CHECK(mappedGlobalId == currentNumGlobalCounterIds);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003544 auto backendMapping = profilingService.GetCounterMappings().GetBackendId(currentNumGlobalCounterIds);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003545 CHECK(backendMapping.first == 0);
3546 CHECK(backendMapping.second == cpuRefId);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003547
3548 currentNumGlobalCounterIds = registerBackendCountersCpuRef.RegisterCounter(
3549 1, "testCategory", 0, 0, 1.f, "CpuRefCounter1", "First CpuRef Counter");
Sadik Armagan1625efc2021-06-10 18:24:34 +01003550 CHECK(currentNumGlobalCounterIds == initialNumGlobalCounterIds + 2);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003551 mappedGlobalId = profilingService.GetCounterMappings().GetGlobalId(1, cpuRefId);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003552 CHECK(mappedGlobalId == currentNumGlobalCounterIds);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003553 backendMapping = profilingService.GetCounterMappings().GetBackendId(currentNumGlobalCounterIds);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003554 CHECK(backendMapping.first == 1);
3555 CHECK(backendMapping.second == cpuRefId);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003556
3557 // Create RegisterBackendCounters for CpuAcc
Sadik Armagan3184c902020-03-18 10:57:30 +00003558 RegisterBackendCounters registerBackendCountersCpuAcc(currentNumGlobalCounterIds, cpuAccId, profilingService);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003559
3560 // Register the backend counter for CpuAcc and validate GetGlobalId and GetBackendId
3561 currentNumGlobalCounterIds = registerBackendCountersCpuAcc.RegisterCounter(
3562 0, "testCategory", 0, 0, 1.f, "CpuAccCounter0", "Zeroth CpuAcc Counter");
Sadik Armagan1625efc2021-06-10 18:24:34 +01003563 CHECK(currentNumGlobalCounterIds == initialNumGlobalCounterIds + 3);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003564 mappedGlobalId = profilingService.GetCounterMappings().GetGlobalId(0, cpuAccId);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003565 CHECK(mappedGlobalId == currentNumGlobalCounterIds);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003566 backendMapping = profilingService.GetCounterMappings().GetBackendId(currentNumGlobalCounterIds);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003567 CHECK(backendMapping.first == 0);
3568 CHECK(backendMapping.second == cpuAccId);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003569
3570 // Create vectors for active counters
3571 const std::vector<uint16_t> activeGlobalCounterIds = {5}; // CpuRef(0) activated
3572 const std::vector<uint16_t> newActiveGlobalCounterIds = {6, 7}; // CpuRef(0) and CpuAcc(1) activated
3573
3574 const uint32_t capturePeriod = 200;
3575 const uint32_t newCapturePeriod = 100;
3576
3577 // Set capture period and active counters in CaptureData
Finn Williams032bc742020-02-12 11:02:34 +00003578 profilingService.SetCaptureData(capturePeriod, activeGlobalCounterIds, {});
James Conroy2dcd3fe2020-02-06 18:34:52 +00003579
3580 // Get vector of active counters for CpuRef and CpuAcc backends
3581 std::vector<CounterStatus> cpuRefCounterStatus = backendProfilingCpuRef.GetActiveCounters();
3582 std::vector<CounterStatus> cpuAccCounterStatus = backendProfilingCpuAcc.GetActiveCounters();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003583 CHECK_EQ(cpuRefCounterStatus.size(), 1);
3584 CHECK_EQ(cpuAccCounterStatus.size(), 0);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003585
3586 // Check active CpuRef counter
Sadik Armagan1625efc2021-06-10 18:24:34 +01003587 CHECK_EQ(cpuRefCounterStatus[0].m_GlobalCounterId, activeGlobalCounterIds[0]);
3588 CHECK_EQ(cpuRefCounterStatus[0].m_BackendCounterId, cpuRefCounters[0]);
3589 CHECK_EQ(cpuRefCounterStatus[0].m_SamplingRateInMicroseconds, capturePeriod);
3590 CHECK_EQ(cpuRefCounterStatus[0].m_Enabled, true);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003591
3592 // Check inactive CpuRef counter
3593 CounterStatus inactiveCpuRefCounter = backendProfilingCpuRef.GetCounterStatus(cpuRefCounters[1]);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003594 CHECK_EQ(inactiveCpuRefCounter.m_GlobalCounterId, 6);
3595 CHECK_EQ(inactiveCpuRefCounter.m_BackendCounterId, cpuRefCounters[1]);
3596 CHECK_EQ(inactiveCpuRefCounter.m_SamplingRateInMicroseconds, 0);
3597 CHECK_EQ(inactiveCpuRefCounter.m_Enabled, false);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003598
3599 // Check inactive CpuAcc counter
3600 CounterStatus inactiveCpuAccCounter = backendProfilingCpuAcc.GetCounterStatus(cpuAccCounters[0]);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003601 CHECK_EQ(inactiveCpuAccCounter.m_GlobalCounterId, 7);
3602 CHECK_EQ(inactiveCpuAccCounter.m_BackendCounterId, cpuAccCounters[0]);
3603 CHECK_EQ(inactiveCpuAccCounter.m_SamplingRateInMicroseconds, 0);
3604 CHECK_EQ(inactiveCpuAccCounter.m_Enabled, false);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003605
3606 // Set new capture period and new active counters in CaptureData
Finn Williams032bc742020-02-12 11:02:34 +00003607 profilingService.SetCaptureData(newCapturePeriod, newActiveGlobalCounterIds, {});
James Conroy2dcd3fe2020-02-06 18:34:52 +00003608
3609 // Get vector of active counters for CpuRef and CpuAcc backends
3610 cpuRefCounterStatus = backendProfilingCpuRef.GetActiveCounters();
3611 cpuAccCounterStatus = backendProfilingCpuAcc.GetActiveCounters();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003612 CHECK_EQ(cpuRefCounterStatus.size(), 1);
3613 CHECK_EQ(cpuAccCounterStatus.size(), 1);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003614
3615 // Check active CpuRef counter
Sadik Armagan1625efc2021-06-10 18:24:34 +01003616 CHECK_EQ(cpuRefCounterStatus[0].m_GlobalCounterId, newActiveGlobalCounterIds[0]);
3617 CHECK_EQ(cpuRefCounterStatus[0].m_BackendCounterId, cpuRefCounters[1]);
3618 CHECK_EQ(cpuRefCounterStatus[0].m_SamplingRateInMicroseconds, newCapturePeriod);
3619 CHECK_EQ(cpuRefCounterStatus[0].m_Enabled, true);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003620
3621 // Check active CpuAcc counter
Sadik Armagan1625efc2021-06-10 18:24:34 +01003622 CHECK_EQ(cpuAccCounterStatus[0].m_GlobalCounterId, newActiveGlobalCounterIds[1]);
3623 CHECK_EQ(cpuAccCounterStatus[0].m_BackendCounterId, cpuAccCounters[0]);
3624 CHECK_EQ(cpuAccCounterStatus[0].m_SamplingRateInMicroseconds, newCapturePeriod);
3625 CHECK_EQ(cpuAccCounterStatus[0].m_Enabled, true);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003626
3627 // Check inactive CpuRef counter
3628 inactiveCpuRefCounter = backendProfilingCpuRef.GetCounterStatus(cpuRefCounters[0]);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003629 CHECK_EQ(inactiveCpuRefCounter.m_GlobalCounterId, 5);
3630 CHECK_EQ(inactiveCpuRefCounter.m_BackendCounterId, cpuRefCounters[0]);
3631 CHECK_EQ(inactiveCpuRefCounter.m_SamplingRateInMicroseconds, 0);
3632 CHECK_EQ(inactiveCpuRefCounter.m_Enabled, false);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003633
3634 // Reset the profiling service to stop any running thread
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00003635 options.m_EnableProfiling = false;
3636 profilingService.ResetExternalProfilingOptions(options, true);
James Conroy2dcd3fe2020-02-06 18:34:52 +00003637}
3638
Sadik Armagan1625efc2021-06-10 18:24:34 +01003639TEST_CASE("CheckRegisterCounters")
Sadik Armagancab588a2020-02-17 11:33:31 +00003640{
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00003641 ProfilingOptions options;
3642 options.m_EnableProfiling = true;
Sadik Armagancab588a2020-02-17 11:33:31 +00003643 MockBufferManager mockBuffer(1024);
Sadik Armagan3184c902020-03-18 10:57:30 +00003644
Sadik Armagancab588a2020-02-17 11:33:31 +00003645 CaptureData captureData;
Jim Flynn34430252022-03-04 15:03:58 +00003646
3647 armnn::ArmNNProfilingServiceInitialiser initialiser;
3648 MockProfilingService mockProfilingService(
3649 arm::pipe::MAX_ARMNN_COUNTER, initialiser, mockBuffer, options.m_EnableProfiling, captureData);
Cathal Corbett6f073722022-03-04 12:11:09 +00003650 std::string cpuRefId(GetComputeDeviceAsCString(armnn::Compute::CpuRef));
Sadik Armagancab588a2020-02-17 11:33:31 +00003651
3652 mockProfilingService.RegisterMapping(6, 0, cpuRefId);
3653 mockProfilingService.RegisterMapping(7, 1, cpuRefId);
3654 mockProfilingService.RegisterMapping(8, 2, cpuRefId);
3655
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00003656 BackendProfiling backendProfiling(options,
Sadik Armagancab588a2020-02-17 11:33:31 +00003657 mockProfilingService,
3658 cpuRefId);
3659
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00003660 Timestamp timestamp;
Sadik Armagancab588a2020-02-17 11:33:31 +00003661 timestamp.timestamp = 1000998;
3662 timestamp.counterValues.emplace_back(0, 700);
3663 timestamp.counterValues.emplace_back(2, 93);
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00003664 std::vector<Timestamp> timestamps;
Sadik Armagancab588a2020-02-17 11:33:31 +00003665 timestamps.push_back(timestamp);
3666 backendProfiling.ReportCounters(timestamps);
3667
3668 auto readBuffer = mockBuffer.GetReadableBuffer();
3669
3670 uint32_t headerWord0 = ReadUint32(readBuffer, 0);
3671 uint32_t headerWord1 = ReadUint32(readBuffer, 4);
3672 uint64_t readTimestamp = ReadUint64(readBuffer, 8);
3673
Sadik Armagan1625efc2021-06-10 18:24:34 +01003674 CHECK(((headerWord0 >> 26) & 0x0000003F) == 3); // packet family
3675 CHECK(((headerWord0 >> 19) & 0x0000007F) == 0); // packet class
3676 CHECK(((headerWord0 >> 16) & 0x00000007) == 0); // packet type
3677 CHECK(headerWord1 == 20); // data length
3678 CHECK(1000998 == readTimestamp); // capture period
Sadik Armagancab588a2020-02-17 11:33:31 +00003679
3680 uint32_t offset = 16;
3681 // Check Counter Index
3682 uint16_t readIndex = ReadUint16(readBuffer, offset);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003683 CHECK(6 == readIndex);
Sadik Armagancab588a2020-02-17 11:33:31 +00003684
3685 // Check Counter Value
3686 offset += 2;
3687 uint32_t readValue = ReadUint32(readBuffer, offset);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003688 CHECK(700 == readValue);
Sadik Armagancab588a2020-02-17 11:33:31 +00003689
3690 // Check Counter Index
3691 offset += 4;
3692 readIndex = ReadUint16(readBuffer, offset);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003693 CHECK(8 == readIndex);
Sadik Armagancab588a2020-02-17 11:33:31 +00003694
3695 // Check Counter Value
3696 offset += 2;
3697 readValue = ReadUint32(readBuffer, offset);
Sadik Armagan1625efc2021-06-10 18:24:34 +01003698 CHECK(93 == readValue);
Sadik Armagancab588a2020-02-17 11:33:31 +00003699}
3700
Sadik Armagan1625efc2021-06-10 18:24:34 +01003701TEST_CASE("CheckFileFormat") {
Isabella Gottardia0687ee2020-03-11 18:04:20 +00003702 // Locally reduce log level to "Warning", as this test needs to parse a warning message from the standard output
3703 LogLevelSwapper logLevelSwapper(armnn::LogSeverity::Warning);
3704
3705 // Create profiling options.
Jim Flynn4c9ed1d2022-01-23 23:57:20 +00003706 ProfilingOptions options;
Isabella Gottardia0687ee2020-03-11 18:04:20 +00003707 options.m_EnableProfiling = true;
3708 // Check the default value set to binary
Sadik Armagan1625efc2021-06-10 18:24:34 +01003709 CHECK(options.m_FileFormat == "binary");
Isabella Gottardia0687ee2020-03-11 18:04:20 +00003710
3711 // Change file format to an unsupported value
3712 options.m_FileFormat = "json";
3713 // Enable the profiling service
Jim Flynn34430252022-03-04 15:03:58 +00003714 armnn::ArmNNProfilingServiceInitialiser initialiser;
3715 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, initialiser);
Isabella Gottardia0687ee2020-03-11 18:04:20 +00003716 profilingService.ResetExternalProfilingOptions(options, true);
3717 // Start the command handler and the send thread
3718 profilingService.Update();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003719 CHECK(profilingService.GetCurrentState()==ProfilingState::NotConnected);
Isabella Gottardia0687ee2020-03-11 18:04:20 +00003720
3721 // Redirect the output to a local stream so that we can parse the warning message
3722 std::stringstream ss;
3723 StreamRedirector streamRedirector(std::cout, ss.rdbuf());
3724
3725 // When Update is called and the current state is ProfilingState::NotConnected
3726 // an exception will be raised from GetProfilingConnection and displayed as warning in the output local stream
3727 profilingService.Update();
3728
3729 streamRedirector.CancelRedirect();
3730
3731 // Check that the expected error has occurred and logged to the standard output
David Monahana8837bf2020-04-16 10:01:56 +01003732 if (ss.str().find("Unsupported profiling file format, only binary is supported") == std::string::npos)
Isabella Gottardia0687ee2020-03-11 18:04:20 +00003733 {
3734 std::cout << ss.str();
Sadik Armagan1625efc2021-06-10 18:24:34 +01003735 FAIL("Expected string not found.");
Isabella Gottardia0687ee2020-03-11 18:04:20 +00003736 }
3737}
3738
Sadik Armagan1625efc2021-06-10 18:24:34 +01003739}