ArmNN
 20.08
ProfilingTests.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "ProfilingTests.hpp"
7 #include "ProfilingTestUtils.hpp"
8 
10 #include <common/include/EncodeVersion.hpp>
11 #include <common/include/PacketVersionResolver.hpp>
12 #include <common/include/SwTrace.hpp>
13 #include <CommandHandler.hpp>
15 #include <CounterDirectory.hpp>
16 #include <CounterIdMap.hpp>
17 #include <Holder.hpp>
18 #include <ICounterValues.hpp>
22 #include <ProfilingUtils.hpp>
25 #include <Runtime.hpp>
27 #include <SendCounterPacket.hpp>
28 #include <SendThread.hpp>
29 #include <SendTimelinePacket.hpp>
30 
31 #include <armnn/Conversion.hpp>
32 #include <armnn/Types.hpp>
33 
34 #include <armnn/Utils.hpp>
36 
37 #include <common/include/CommandHandlerKey.hpp>
38 #include <common/include/CommandHandlerRegistry.hpp>
39 #include <common/include/SocketConnectionException.hpp>
40 #include <common/include/Packet.hpp>
41 
42 #include <boost/numeric/conversion/cast.hpp>
43 
44 #include <cstdint>
45 #include <cstring>
46 #include <iostream>
47 #include <limits>
48 #include <map>
49 #include <random>
50 
51 
52 using namespace armnn::profiling;
54 
55 BOOST_AUTO_TEST_SUITE(ExternalProfiling)
56 
57 BOOST_AUTO_TEST_CASE(CheckCommandHandlerKeyComparisons)
58 {
59  arm::pipe::CommandHandlerKey testKey1_0(1, 1, 1);
60  arm::pipe::CommandHandlerKey testKey1_1(1, 1, 1);
61  arm::pipe::CommandHandlerKey testKey1_2(1, 2, 1);
62 
63  arm::pipe::CommandHandlerKey testKey0(0, 1, 1);
64  arm::pipe::CommandHandlerKey testKey1(0, 1, 1);
65  arm::pipe::CommandHandlerKey testKey2(0, 1, 1);
66  arm::pipe::CommandHandlerKey testKey3(0, 0, 0);
67  arm::pipe::CommandHandlerKey testKey4(0, 2, 2);
68  arm::pipe::CommandHandlerKey testKey5(0, 0, 2);
69 
70  BOOST_CHECK(testKey1_0 > testKey0);
71  BOOST_CHECK(testKey1_0 == testKey1_1);
72  BOOST_CHECK(testKey1_0 < testKey1_2);
73 
74  BOOST_CHECK(testKey1 < testKey4);
75  BOOST_CHECK(testKey1 > testKey3);
76  BOOST_CHECK(testKey1 <= testKey4);
77  BOOST_CHECK(testKey1 >= testKey3);
78  BOOST_CHECK(testKey1 <= testKey2);
79  BOOST_CHECK(testKey1 >= testKey2);
80  BOOST_CHECK(testKey1 == testKey2);
81  BOOST_CHECK(testKey1 == testKey1);
82 
83  BOOST_CHECK(!(testKey1 == testKey5));
84  BOOST_CHECK(!(testKey1 != testKey1));
85  BOOST_CHECK(testKey1 != testKey5);
86 
87  BOOST_CHECK(testKey1 == testKey2 && testKey2 == testKey1);
88  BOOST_CHECK(testKey0 == testKey1 && testKey1 == testKey2 && testKey0 == testKey2);
89 
90  BOOST_CHECK(testKey1.GetPacketId() == 1);
91  BOOST_CHECK(testKey1.GetVersion() == 1);
92 
93  std::vector<arm::pipe::CommandHandlerKey> vect = {
94  arm::pipe::CommandHandlerKey(0, 0, 1), arm::pipe::CommandHandlerKey(0, 2, 0),
95  arm::pipe::CommandHandlerKey(0, 1, 0), arm::pipe::CommandHandlerKey(0, 2, 1),
96  arm::pipe::CommandHandlerKey(0, 1, 1), arm::pipe::CommandHandlerKey(0, 0, 1),
97  arm::pipe::CommandHandlerKey(0, 2, 0), arm::pipe::CommandHandlerKey(0, 0, 0) };
98 
99  std::sort(vect.begin(), vect.end());
100 
101  std::vector<arm::pipe::CommandHandlerKey> expectedVect = {
102  arm::pipe::CommandHandlerKey(0, 0, 0), arm::pipe::CommandHandlerKey(0, 0, 1),
103  arm::pipe::CommandHandlerKey(0, 0, 1), arm::pipe::CommandHandlerKey(0, 1, 0),
104  arm::pipe::CommandHandlerKey(0, 1, 1), arm::pipe::CommandHandlerKey(0, 2, 0),
105  arm::pipe::CommandHandlerKey(0, 2, 0), arm::pipe::CommandHandlerKey(0, 2, 1) };
106 
107  BOOST_CHECK(vect == expectedVect);
108 }
109 
110 BOOST_AUTO_TEST_CASE(CheckPacketKeyComparisons)
111 {
112  arm::pipe::PacketKey key0(0, 0);
113  arm::pipe::PacketKey key1(0, 0);
114  arm::pipe::PacketKey key2(0, 1);
115  arm::pipe::PacketKey key3(0, 2);
116  arm::pipe::PacketKey key4(1, 0);
117  arm::pipe::PacketKey key5(1, 0);
118  arm::pipe::PacketKey key6(1, 1);
119 
120  BOOST_CHECK(!(key0 < key1));
121  BOOST_CHECK(!(key0 > key1));
122  BOOST_CHECK(key0 <= key1);
123  BOOST_CHECK(key0 >= key1);
124  BOOST_CHECK(key0 == key1);
125  BOOST_CHECK(key0 < key2);
126  BOOST_CHECK(key2 < key3);
127  BOOST_CHECK(key3 > key0);
128  BOOST_CHECK(key4 == key5);
129  BOOST_CHECK(key4 > key0);
130  BOOST_CHECK(key5 < key6);
131  BOOST_CHECK(key5 <= key6);
132  BOOST_CHECK(key5 != key6);
133 }
134 
135 BOOST_AUTO_TEST_CASE(CheckCommandHandler)
136 {
137  arm::pipe::PacketVersionResolver packetVersionResolver;
138  ProfilingStateMachine profilingStateMachine;
139 
140  TestProfilingConnectionBase testProfilingConnectionBase;
141  TestProfilingConnectionTimeoutError testProfilingConnectionTimeOutError;
142  TestProfilingConnectionArmnnError testProfilingConnectionArmnnError;
143  CounterDirectory counterDirectory;
144  MockBufferManager mockBuffer(1024);
145  SendCounterPacket sendCounterPacket(mockBuffer);
146  SendThread sendThread(profilingStateMachine, mockBuffer, sendCounterPacket);
147  SendTimelinePacket sendTimelinePacket(mockBuffer);
148  MockProfilingServiceStatus mockProfilingServiceStatus;
149 
150  ConnectionAcknowledgedCommandHandler connectionAcknowledgedCommandHandler(0, 1, 4194304, counterDirectory,
151  sendCounterPacket, sendTimelinePacket,
152  profilingStateMachine,
153  mockProfilingServiceStatus);
154  arm::pipe::CommandHandlerRegistry commandHandlerRegistry;
155 
156  commandHandlerRegistry.RegisterFunctor(&connectionAcknowledgedCommandHandler);
157 
158  profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
159  profilingStateMachine.TransitionToState(ProfilingState::WaitingForAck);
160 
161  CommandHandler commandHandler0(1, true, commandHandlerRegistry, packetVersionResolver);
162 
163  // This should start the command handler thread return the connection ack and put the profiling
164  // service into active state.
165  commandHandler0.Start(testProfilingConnectionBase);
166  // Try to start the send thread many times, it must only start once
167  commandHandler0.Start(testProfilingConnectionBase);
168 
169  // This could take up to 20mSec but we'll check often.
170  for (int i = 0; i < 10; i++)
171  {
172  if (profilingStateMachine.GetCurrentState() == ProfilingState::Active)
173  {
174  break;
175  }
176  std::this_thread::sleep_for(std::chrono::milliseconds(2));
177  }
178 
179  BOOST_CHECK(profilingStateMachine.GetCurrentState() == ProfilingState::Active);
180 
181  // Close the thread again.
182  commandHandler0.Stop();
183 
184  profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
185  profilingStateMachine.TransitionToState(ProfilingState::WaitingForAck);
186 
187  // In this test we'll simulate a timeout without a connection ack packet being received.
188  // Stop after timeout is set so we expect the command handler to stop almost immediately.
189  CommandHandler commandHandler1(1, true, commandHandlerRegistry, packetVersionResolver);
190 
191  commandHandler1.Start(testProfilingConnectionTimeOutError);
192  // Wait until we know a timeout exception has been sent at least once.
193  for (int i = 0; i < 10; i++)
194  {
195  if (testProfilingConnectionTimeOutError.ReadCalledCount())
196  {
197  break;
198  }
199  std::this_thread::sleep_for(std::chrono::milliseconds(2));
200  }
201 
202  // The command handler loop should have stopped after the timeout.
203  // wait for the timeout exception to be processed and the loop to break.
204  uint32_t timeout = 50;
205  uint32_t timeSlept = 0;
206  while (commandHandler1.IsRunning())
207  {
208  if (timeSlept >= timeout)
209  {
210  BOOST_FAIL("Timeout: The command handler loop did not stop after the timeout");
211  }
212  std::this_thread::sleep_for(std::chrono::milliseconds(1));
213  timeSlept ++;
214  }
215 
216  commandHandler1.Stop();
217  // The state machine should never have received the ack so will still be in WaitingForAck.
218  BOOST_CHECK(profilingStateMachine.GetCurrentState() == ProfilingState::WaitingForAck);
219 
220  // Now try sending a bad connection acknowledged packet
221  TestProfilingConnectionBadAckPacket testProfilingConnectionBadAckPacket;
222  commandHandler1.Start(testProfilingConnectionBadAckPacket);
223  commandHandler1.Stop();
224  // This should also not change the state machine
225  BOOST_CHECK(profilingStateMachine.GetCurrentState() == ProfilingState::WaitingForAck);
226 
227  // Disable stop after timeout and now commandHandler1 should persist after a timeout
228  commandHandler1.SetStopAfterTimeout(false);
229  // Restart the thread.
230  commandHandler1.Start(testProfilingConnectionTimeOutError);
231 
232  // Wait for at the three timeouts and the ack to be sent.
233  for (int i = 0; i < 10; i++)
234  {
235  if (testProfilingConnectionTimeOutError.ReadCalledCount() > 3)
236  {
237  break;
238  }
239  std::this_thread::sleep_for(std::chrono::milliseconds(2));
240  }
241  commandHandler1.Stop();
242 
243  // Even after the 3 exceptions the ack packet should have transitioned the command handler to active.
244  BOOST_CHECK(profilingStateMachine.GetCurrentState() == ProfilingState::Active);
245 
246  // A command handler that gets exceptions other than timeouts should keep going.
247  CommandHandler commandHandler2(1, false, commandHandlerRegistry, packetVersionResolver);
248 
249  commandHandler2.Start(testProfilingConnectionArmnnError);
250 
251  // Wait for two exceptions to be thrown.
252  for (int i = 0; i < 10; i++)
253  {
254  if (testProfilingConnectionTimeOutError.ReadCalledCount() >= 2)
255  {
256  break;
257  }
258  std::this_thread::sleep_for(std::chrono::milliseconds(2));
259  }
260 
261  BOOST_CHECK(commandHandler2.IsRunning());
262  commandHandler2.Stop();
263 }
264 
265 BOOST_AUTO_TEST_CASE(CheckEncodeVersion)
266 {
267  arm::pipe::Version version1(12);
268 
269  BOOST_CHECK(version1.GetMajor() == 0);
270  BOOST_CHECK(version1.GetMinor() == 0);
271  BOOST_CHECK(version1.GetPatch() == 12);
272 
273  arm::pipe::Version version2(4108);
274 
275  BOOST_CHECK(version2.GetMajor() == 0);
276  BOOST_CHECK(version2.GetMinor() == 1);
277  BOOST_CHECK(version2.GetPatch() == 12);
278 
279  arm::pipe::Version version3(4198412);
280 
281  BOOST_CHECK(version3.GetMajor() == 1);
282  BOOST_CHECK(version3.GetMinor() == 1);
283  BOOST_CHECK(version3.GetPatch() == 12);
284 
285  arm::pipe::Version version4(0);
286 
287  BOOST_CHECK(version4.GetMajor() == 0);
288  BOOST_CHECK(version4.GetMinor() == 0);
289  BOOST_CHECK(version4.GetPatch() == 0);
290 
291  arm::pipe::Version version5(1, 0, 0);
292  BOOST_CHECK(version5.GetEncodedValue() == 4194304);
293 }
294 
295 BOOST_AUTO_TEST_CASE(CheckPacketClass)
296 {
297  uint32_t length = 4;
298  std::unique_ptr<unsigned char[]> packetData0 = std::make_unique<unsigned char[]>(length);
299  std::unique_ptr<unsigned char[]> packetData1 = std::make_unique<unsigned char[]>(0);
300  std::unique_ptr<unsigned char[]> nullPacketData;
301 
302  arm::pipe::Packet packetTest0(472580096, length, packetData0);
303 
304  BOOST_CHECK(packetTest0.GetHeader() == 472580096);
305  BOOST_CHECK(packetTest0.GetPacketFamily() == 7);
306  BOOST_CHECK(packetTest0.GetPacketId() == 43);
307  BOOST_CHECK(packetTest0.GetLength() == length);
308  BOOST_CHECK(packetTest0.GetPacketType() == 3);
309  BOOST_CHECK(packetTest0.GetPacketClass() == 5);
310 
311  BOOST_CHECK_THROW(arm::pipe::Packet packetTest1(472580096, 0, packetData1), arm::pipe::InvalidArgumentException);
312  BOOST_CHECK_NO_THROW(arm::pipe::Packet packetTest2(472580096, 0, nullPacketData));
313 
314  arm::pipe::Packet packetTest3(472580096, 0, nullPacketData);
315  BOOST_CHECK(packetTest3.GetLength() == 0);
316  BOOST_CHECK(packetTest3.GetData() == nullptr);
317 
318  const unsigned char* packetTest0Data = packetTest0.GetData();
319  arm::pipe::Packet packetTest4(std::move(packetTest0));
320 
321  BOOST_CHECK(packetTest0.GetData() == nullptr);
322  BOOST_CHECK(packetTest4.GetData() == packetTest0Data);
323 
324  BOOST_CHECK(packetTest4.GetHeader() == 472580096);
325  BOOST_CHECK(packetTest4.GetPacketFamily() == 7);
326  BOOST_CHECK(packetTest4.GetPacketId() == 43);
327  BOOST_CHECK(packetTest4.GetLength() == length);
328  BOOST_CHECK(packetTest4.GetPacketType() == 3);
329  BOOST_CHECK(packetTest4.GetPacketClass() == 5);
330 }
331 
332 BOOST_AUTO_TEST_CASE(CheckCommandHandlerFunctor)
333 {
334  // Hard code the version as it will be the same during a single profiling session
335  uint32_t version = 1;
336 
337  TestFunctorA testFunctorA(7, 461, version);
338  TestFunctorB testFunctorB(8, 963, version);
339  TestFunctorC testFunctorC(5, 983, version);
340 
341  arm::pipe::CommandHandlerKey keyA(
342  testFunctorA.GetFamilyId(), testFunctorA.GetPacketId(), testFunctorA.GetVersion());
343  arm::pipe::CommandHandlerKey keyB(
344  testFunctorB.GetFamilyId(), testFunctorB.GetPacketId(), testFunctorB.GetVersion());
345  arm::pipe::CommandHandlerKey keyC(
346  testFunctorC.GetFamilyId(), testFunctorC.GetPacketId(), testFunctorC.GetVersion());
347 
348  // Create the unwrapped map to simulate the Command Handler Registry
349  std::map<arm::pipe::CommandHandlerKey, arm::pipe::CommandHandlerFunctor*> registry;
350 
351  registry.insert(std::make_pair(keyB, &testFunctorB));
352  registry.insert(std::make_pair(keyA, &testFunctorA));
353  registry.insert(std::make_pair(keyC, &testFunctorC));
354 
355  // Check the order of the map is correct
356  auto it = registry.begin();
357  BOOST_CHECK(it->first == keyC); // familyId == 5
358  it++;
359  BOOST_CHECK(it->first == keyA); // familyId == 7
360  it++;
361  BOOST_CHECK(it->first == keyB); // familyId == 8
362 
363  std::unique_ptr<unsigned char[]> packetDataA;
364  std::unique_ptr<unsigned char[]> packetDataB;
365  std::unique_ptr<unsigned char[]> packetDataC;
366 
367  arm::pipe::Packet packetA(500000000, 0, packetDataA);
368  arm::pipe::Packet packetB(600000000, 0, packetDataB);
369  arm::pipe::Packet packetC(400000000, 0, packetDataC);
370 
371  // Check the correct operator of derived class is called
372  registry.at(arm::pipe::CommandHandlerKey(
373  packetA.GetPacketFamily(), packetA.GetPacketId(), version))->operator()(packetA);
374  BOOST_CHECK(testFunctorA.GetCount() == 1);
375  BOOST_CHECK(testFunctorB.GetCount() == 0);
376  BOOST_CHECK(testFunctorC.GetCount() == 0);
377 
378  registry.at(arm::pipe::CommandHandlerKey(
379  packetB.GetPacketFamily(), packetB.GetPacketId(), version))->operator()(packetB);
380  BOOST_CHECK(testFunctorA.GetCount() == 1);
381  BOOST_CHECK(testFunctorB.GetCount() == 1);
382  BOOST_CHECK(testFunctorC.GetCount() == 0);
383 
384  registry.at(arm::pipe::CommandHandlerKey(
385  packetC.GetPacketFamily(), packetC.GetPacketId(), version))->operator()(packetC);
386  BOOST_CHECK(testFunctorA.GetCount() == 1);
387  BOOST_CHECK(testFunctorB.GetCount() == 1);
388  BOOST_CHECK(testFunctorC.GetCount() == 1);
389 }
390 
391 BOOST_AUTO_TEST_CASE(CheckCommandHandlerRegistry)
392 {
393  // Hard code the version as it will be the same during a single profiling session
394  uint32_t version = 1;
395 
396  TestFunctorA testFunctorA(7, 461, version);
397  TestFunctorB testFunctorB(8, 963, version);
398  TestFunctorC testFunctorC(5, 983, version);
399 
400  // Create the Command Handler Registry
401  arm::pipe::CommandHandlerRegistry registry;
402 
403  // Register multiple different derived classes
404  registry.RegisterFunctor(&testFunctorA);
405  registry.RegisterFunctor(&testFunctorB);
406  registry.RegisterFunctor(&testFunctorC);
407 
408  std::unique_ptr<unsigned char[]> packetDataA;
409  std::unique_ptr<unsigned char[]> packetDataB;
410  std::unique_ptr<unsigned char[]> packetDataC;
411 
412  arm::pipe::Packet packetA(500000000, 0, packetDataA);
413  arm::pipe::Packet packetB(600000000, 0, packetDataB);
414  arm::pipe::Packet packetC(400000000, 0, packetDataC);
415 
416  // Check the correct operator of derived class is called
417  registry.GetFunctor(packetA.GetPacketFamily(), packetA.GetPacketId(), version)->operator()(packetA);
418  BOOST_CHECK(testFunctorA.GetCount() == 1);
419  BOOST_CHECK(testFunctorB.GetCount() == 0);
420  BOOST_CHECK(testFunctorC.GetCount() == 0);
421 
422  registry.GetFunctor(packetB.GetPacketFamily(), packetB.GetPacketId(), version)->operator()(packetB);
423  BOOST_CHECK(testFunctorA.GetCount() == 1);
424  BOOST_CHECK(testFunctorB.GetCount() == 1);
425  BOOST_CHECK(testFunctorC.GetCount() == 0);
426 
427  registry.GetFunctor(packetC.GetPacketFamily(), packetC.GetPacketId(), version)->operator()(packetC);
428  BOOST_CHECK(testFunctorA.GetCount() == 1);
429  BOOST_CHECK(testFunctorB.GetCount() == 1);
430  BOOST_CHECK(testFunctorC.GetCount() == 1);
431 
432  // Re-register an existing key with a new function
433  registry.RegisterFunctor(&testFunctorC, testFunctorA.GetFamilyId(), testFunctorA.GetPacketId(), version);
434  registry.GetFunctor(packetA.GetPacketFamily(), packetA.GetPacketId(), version)->operator()(packetC);
435  BOOST_CHECK(testFunctorA.GetCount() == 1);
436  BOOST_CHECK(testFunctorB.GetCount() == 1);
437  BOOST_CHECK(testFunctorC.GetCount() == 2);
438 
439  // Check that non-existent key returns nullptr for its functor
440  BOOST_CHECK_THROW(registry.GetFunctor(0, 0, 0), arm::pipe::ProfilingException);
441 }
442 
443 BOOST_AUTO_TEST_CASE(CheckPacketVersionResolver)
444 {
445  // Set up random number generator for generating packetId values
446  std::random_device device;
447  std::mt19937 generator(device());
448  std::uniform_int_distribution<uint32_t> distribution(std::numeric_limits<uint32_t>::min(),
449  std::numeric_limits<uint32_t>::max());
450 
451  // NOTE: Expected version is always 1.0.0, regardless of packetId
452  const arm::pipe::Version expectedVersion(1, 0, 0);
453 
454  arm::pipe::PacketVersionResolver packetVersionResolver;
455 
456  constexpr unsigned int numTests = 10u;
457 
458  for (unsigned int i = 0u; i < numTests; ++i)
459  {
460  const uint32_t familyId = distribution(generator);
461  const uint32_t packetId = distribution(generator);
462  arm::pipe::Version resolvedVersion = packetVersionResolver.ResolvePacketVersion(familyId, packetId);
463 
464  BOOST_TEST(resolvedVersion == expectedVersion);
465  }
466 }
467 
469 {
471  states.GetCurrentState();
472  states.TransitionToState(newState);
473 }
474 
475 BOOST_AUTO_TEST_CASE(CheckProfilingStateMachine)
476 {
479  BOOST_CHECK(profilingState1.GetCurrentState() == ProfilingState::Uninitialised);
480 
482  profilingState2.TransitionToState(ProfilingState::NotConnected);
483  BOOST_CHECK(profilingState2.GetCurrentState() == ProfilingState::NotConnected);
484 
486  profilingState3.TransitionToState(ProfilingState::NotConnected);
487  BOOST_CHECK(profilingState3.GetCurrentState() == ProfilingState::NotConnected);
488 
490  profilingState4.TransitionToState(ProfilingState::WaitingForAck);
491  BOOST_CHECK(profilingState4.GetCurrentState() == ProfilingState::WaitingForAck);
492 
494  profilingState5.TransitionToState(ProfilingState::WaitingForAck);
495  BOOST_CHECK(profilingState5.GetCurrentState() == ProfilingState::WaitingForAck);
496 
498  profilingState6.TransitionToState(ProfilingState::Active);
499  BOOST_CHECK(profilingState6.GetCurrentState() == ProfilingState::Active);
500 
502  profilingState7.TransitionToState(ProfilingState::NotConnected);
503  BOOST_CHECK(profilingState7.GetCurrentState() == ProfilingState::NotConnected);
504 
506  profilingState8.TransitionToState(ProfilingState::Active);
507  BOOST_CHECK(profilingState8.GetCurrentState() == ProfilingState::Active);
508 
510  BOOST_CHECK_THROW(profilingState9.TransitionToState(ProfilingState::WaitingForAck), armnn::Exception);
511 
513  BOOST_CHECK_THROW(profilingState10.TransitionToState(ProfilingState::Active), armnn::Exception);
514 
516  BOOST_CHECK_THROW(profilingState11.TransitionToState(ProfilingState::Uninitialised), armnn::Exception);
517 
519  BOOST_CHECK_THROW(profilingState12.TransitionToState(ProfilingState::Active), armnn::Exception);
520 
522  BOOST_CHECK_THROW(profilingState13.TransitionToState(ProfilingState::Uninitialised), armnn::Exception);
523 
525  profilingState14.TransitionToState(ProfilingState::NotConnected);
526  BOOST_CHECK(profilingState14.GetCurrentState() == ProfilingState::NotConnected);
527 
529  BOOST_CHECK_THROW(profilingState15.TransitionToState(ProfilingState::Uninitialised), armnn::Exception);
530 
532  BOOST_CHECK_THROW(profilingState16.TransitionToState(ProfilingState::WaitingForAck), armnn::Exception);
533 
535 
536  std::thread thread1(ProfilingCurrentStateThreadImpl, std::ref(profilingState17));
537  std::thread thread2(ProfilingCurrentStateThreadImpl, std::ref(profilingState17));
538  std::thread thread3(ProfilingCurrentStateThreadImpl, std::ref(profilingState17));
539  std::thread thread4(ProfilingCurrentStateThreadImpl, std::ref(profilingState17));
540  std::thread thread5(ProfilingCurrentStateThreadImpl, std::ref(profilingState17));
541 
542  thread1.join();
543  thread2.join();
544  thread3.join();
545  thread4.join();
546  thread5.join();
547 
548  BOOST_TEST((profilingState17.GetCurrentState() == ProfilingState::NotConnected));
549 }
550 
551 void CaptureDataWriteThreadImpl(Holder& holder, uint32_t capturePeriod, const std::vector<uint16_t>& counterIds)
552 {
553  holder.SetCaptureData(capturePeriod, counterIds, {});
554 }
555 
556 void CaptureDataReadThreadImpl(const Holder& holder, CaptureData& captureData)
557 {
558  captureData = holder.GetCaptureData();
559 }
560 
561 BOOST_AUTO_TEST_CASE(CheckCaptureDataHolder)
562 {
563  std::map<uint32_t, std::vector<uint16_t>> periodIdMap;
564  std::vector<uint16_t> counterIds;
565  uint32_t numThreads = 10;
566  for (uint32_t i = 0; i < numThreads; ++i)
567  {
568  counterIds.emplace_back(i);
569  periodIdMap.insert(std::make_pair(i, counterIds));
570  }
571 
572  // Verify the read and write threads set the holder correctly
573  // and retrieve the expected values
574  Holder holder;
575  BOOST_CHECK((holder.GetCaptureData()).GetCapturePeriod() == 0);
576  BOOST_CHECK(((holder.GetCaptureData()).GetCounterIds()).empty());
577 
578  // Check Holder functions
579  std::thread thread1(CaptureDataWriteThreadImpl, std::ref(holder), 2, std::ref(periodIdMap[2]));
580  thread1.join();
581  BOOST_CHECK((holder.GetCaptureData()).GetCapturePeriod() == 2);
582  BOOST_CHECK((holder.GetCaptureData()).GetCounterIds() == periodIdMap[2]);
583  // NOTE: now that we have some initial values in the holder we don't have to worry
584  // in the multi-threaded section below about a read thread accessing the holder
585  // before any write thread has gotten to it so we read period = 0, counterIds empty
586  // instead of period = 0, counterIds = {0} as will the case when write thread 0
587  // has executed.
588 
589  CaptureData captureData;
590  std::thread thread2(CaptureDataReadThreadImpl, std::ref(holder), std::ref(captureData));
591  thread2.join();
592  BOOST_CHECK(captureData.GetCapturePeriod() == 2);
593  BOOST_CHECK(captureData.GetCounterIds() == periodIdMap[2]);
594 
595  std::map<uint32_t, CaptureData> captureDataIdMap;
596  for (uint32_t i = 0; i < numThreads; ++i)
597  {
598  CaptureData perThreadCaptureData;
599  captureDataIdMap.insert(std::make_pair(i, perThreadCaptureData));
600  }
601 
602  std::vector<std::thread> threadsVect;
603  std::vector<std::thread> readThreadsVect;
604  for (uint32_t i = 0; i < numThreads; ++i)
605  {
606  threadsVect.emplace_back(
607  std::thread(CaptureDataWriteThreadImpl, std::ref(holder), i, std::ref(periodIdMap[i])));
608 
609  // Verify that the CaptureData goes into the thread in a virgin state
610  BOOST_CHECK(captureDataIdMap.at(i).GetCapturePeriod() == 0);
611  BOOST_CHECK(captureDataIdMap.at(i).GetCounterIds().empty());
612  readThreadsVect.emplace_back(
613  std::thread(CaptureDataReadThreadImpl, std::ref(holder), std::ref(captureDataIdMap.at(i))));
614  }
615 
616  for (uint32_t i = 0; i < numThreads; ++i)
617  {
618  threadsVect[i].join();
619  readThreadsVect[i].join();
620  }
621 
622  // Look at the CaptureData that each read thread has filled
623  // the capture period it read should match the counter ids entry
624  for (uint32_t i = 0; i < numThreads; ++i)
625  {
626  CaptureData perThreadCaptureData = captureDataIdMap.at(i);
627  BOOST_CHECK(perThreadCaptureData.GetCounterIds() == periodIdMap.at(perThreadCaptureData.GetCapturePeriod()));
628  }
629 }
630 
631 BOOST_AUTO_TEST_CASE(CaptureDataMethods)
632 {
633  // Check CaptureData setter and getter functions
634  std::vector<uint16_t> counterIds = { 42, 29, 13 };
635  CaptureData captureData;
636  BOOST_CHECK(captureData.GetCapturePeriod() == 0);
637  BOOST_CHECK((captureData.GetCounterIds()).empty());
638  captureData.SetCapturePeriod(150);
639  captureData.SetCounterIds(counterIds);
640  BOOST_CHECK(captureData.GetCapturePeriod() == 150);
641  BOOST_CHECK(captureData.GetCounterIds() == counterIds);
642 
643  // Check assignment operator
644  CaptureData secondCaptureData;
645 
646  secondCaptureData = captureData;
647  BOOST_CHECK(secondCaptureData.GetCapturePeriod() == 150);
648  BOOST_CHECK(secondCaptureData.GetCounterIds() == counterIds);
649 
650  // Check copy constructor
651  CaptureData copyConstructedCaptureData(captureData);
652 
653  BOOST_CHECK(copyConstructedCaptureData.GetCapturePeriod() == 150);
654  BOOST_CHECK(copyConstructedCaptureData.GetCounterIds() == counterIds);
655 }
656 
657 BOOST_AUTO_TEST_CASE(CheckProfilingServiceDisabled)
658 {
659  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
660  armnn::profiling::ProfilingService profilingService;
661  profilingService.ResetExternalProfilingOptions(options, true);
662  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
663  profilingService.Update();
664  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
665 }
666 
667 BOOST_AUTO_TEST_CASE(CheckProfilingServiceCounterDirectory)
668 {
669  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
670  armnn::profiling::ProfilingService profilingService;
671  profilingService.ResetExternalProfilingOptions(options, true);
672 
673  const ICounterDirectory& counterDirectory0 = profilingService.GetCounterDirectory();
674  BOOST_CHECK(counterDirectory0.GetCounterCount() == 0);
675  profilingService.Update();
676  BOOST_CHECK(counterDirectory0.GetCounterCount() == 0);
677 
678  options.m_EnableProfiling = true;
679  profilingService.ResetExternalProfilingOptions(options);
680 
681  const ICounterDirectory& counterDirectory1 = profilingService.GetCounterDirectory();
682  BOOST_CHECK(counterDirectory1.GetCounterCount() == 0);
683  profilingService.Update();
684  BOOST_CHECK(counterDirectory1.GetCounterCount() != 0);
685  // Reset the profiling service to stop any running thread
686  options.m_EnableProfiling = false;
687  profilingService.ResetExternalProfilingOptions(options, true);
688 }
689 
690 BOOST_AUTO_TEST_CASE(CheckProfilingServiceCounterValues)
691 {
692  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
693  options.m_EnableProfiling = true;
694  armnn::profiling::ProfilingService profilingService;
695  profilingService.ResetExternalProfilingOptions(options, true);
696 
697  profilingService.Update();
698  const ICounterDirectory& counterDirectory = profilingService.GetCounterDirectory();
699  const Counters& counters = counterDirectory.GetCounters();
700  BOOST_CHECK(!counters.empty());
701 
702  std::vector<std::thread> writers;
703 
704  BOOST_CHECK(!counters.empty());
705 
706  // Test GetAbsoluteCounterValue
707  for (int i = 0; i < 4; ++i)
708  {
709  // Increment and decrement the INFERENCES_RUN counter 250 times
710  writers.push_back(std::thread([&profilingService]()
711  {
712  for (int i = 0; i < 250; ++i)
713  {
714  profilingService.IncrementCounterValue(INFERENCES_RUN);
715  }
716  }));
717  // Add 10 to the INFERENCES_RUN counter 200 times
718  writers.push_back(std::thread([&profilingService]()
719  {
720  for (int i = 0; i < 200; ++i)
721  {
722  profilingService.AddCounterValue(INFERENCES_RUN, 10);
723  }
724  }));
725  // Subtract 5 from the INFERENCES_RUN counter 200 times
726  writers.push_back(std::thread([&profilingService]()
727  {
728  for (int i = 0; i < 200; ++i)
729  {
730  profilingService.SubtractCounterValue(INFERENCES_RUN, 5);
731  }
732  }));
733  }
734 
735  std::for_each(writers.begin(), writers.end(), mem_fn(&std::thread::join));
736 
737  uint32_t absoluteCounterValue = 0;
738 
739  BOOST_CHECK_NO_THROW(absoluteCounterValue = profilingService.GetAbsoluteCounterValue(INFERENCES_RUN));
740  BOOST_CHECK(absoluteCounterValue = 5000);
741 
742  // Test SetCounterValue
743  BOOST_CHECK_NO_THROW(profilingService.SetCounterValue(INFERENCES_RUN, 0));
744  BOOST_CHECK_NO_THROW(absoluteCounterValue = profilingService.GetAbsoluteCounterValue(INFERENCES_RUN));
745  BOOST_CHECK(absoluteCounterValue == 0);
746 
747  // Test GetDeltaCounterValue
748  writers.clear();
749  uint32_t deltaCounterValue = 0;
750  //Start a reading thread to randomly read the INFERENCES_RUN counter value
751  std::thread reader([&profilingService](uint32_t& deltaCounterValue)
752  {
753  for (int i = 0; i < 300; ++i)
754  {
755  deltaCounterValue += profilingService.GetDeltaCounterValue(INFERENCES_RUN);
756  }
757  }, std::ref(deltaCounterValue));
758 
759  for (int i = 0; i < 4; ++i)
760  {
761  // Increment and decrement the INFERENCES_RUN counter 250 times
762  writers.push_back(std::thread([&profilingService]()
763  {
764  for (int i = 0; i < 250; ++i)
765  {
766  profilingService.IncrementCounterValue(INFERENCES_RUN);
767  }
768  }));
769  // Add 10 to the INFERENCES_RUN counter 200 times
770  writers.push_back(std::thread([&profilingService]()
771  {
772  for (int i = 0; i < 200; ++i)
773  {
774  profilingService.AddCounterValue(INFERENCES_RUN, 10);
775  }
776  }));
777  // Subtract 5 from the INFERENCES_RUN counter 200 times
778  writers.push_back(std::thread([&profilingService]()
779  {
780  for (int i = 0; i < 200; ++i)
781  {
782  profilingService.SubtractCounterValue(INFERENCES_RUN, 5);
783  }
784  }));
785  }
786 
787  std::for_each(writers.begin(), writers.end(), mem_fn(&std::thread::join));
788  reader.join();
789 
790  // Do one last read in case the reader stopped early
791  deltaCounterValue += profilingService.GetDeltaCounterValue(INFERENCES_RUN);
792  BOOST_CHECK(deltaCounterValue == 5000);
793 
794  // Reset the profiling service to stop any running thread
795  options.m_EnableProfiling = false;
796  profilingService.ResetExternalProfilingOptions(options, true);
797 }
798 
799 BOOST_AUTO_TEST_CASE(CheckProfilingObjectUids)
800 {
801  uint16_t uid = 0;
802  BOOST_CHECK_NO_THROW(uid = GetNextUid());
803  BOOST_CHECK(uid >= 1);
804 
805  uint16_t nextUid = 0;
806  BOOST_CHECK_NO_THROW(nextUid = GetNextUid());
807  BOOST_CHECK(nextUid > uid);
808 
809  std::vector<uint16_t> counterUids;
810  BOOST_CHECK_NO_THROW(counterUids = GetNextCounterUids(uid,0));
811  BOOST_CHECK(counterUids.size() == 1);
812 
813  std::vector<uint16_t> nextCounterUids;
814  BOOST_CHECK_NO_THROW(nextCounterUids = GetNextCounterUids(nextUid, 2));
815  BOOST_CHECK(nextCounterUids.size() == 2);
816  BOOST_CHECK(nextCounterUids[0] > counterUids[0]);
817 
818  std::vector<uint16_t> counterUidsMultiCore;
819  uint16_t thirdUid = 4;
820  uint16_t numberOfCores = 13;
821  BOOST_CHECK_NO_THROW(counterUidsMultiCore = GetNextCounterUids(thirdUid, numberOfCores));
822  BOOST_CHECK(counterUidsMultiCore.size() == numberOfCores);
823  BOOST_CHECK(counterUidsMultiCore.front() >= nextCounterUids[0]);
824  for (size_t i = 1; i < numberOfCores; i++)
825  {
826  BOOST_CHECK(counterUidsMultiCore[i] == counterUidsMultiCore[i - 1] + 1);
827  }
828  BOOST_CHECK(counterUidsMultiCore.back() == counterUidsMultiCore.front() + numberOfCores - 1);
829 }
830 
831 BOOST_AUTO_TEST_CASE(CheckCounterDirectoryRegisterCategory)
832 {
833  CounterDirectory counterDirectory;
834  BOOST_CHECK(counterDirectory.GetCategoryCount() == 0);
835  BOOST_CHECK(counterDirectory.GetDeviceCount() == 0);
836  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 0);
837  BOOST_CHECK(counterDirectory.GetCounterCount() == 0);
838 
839  // Register a category with an invalid name
840  const Category* noCategory = nullptr;
841  BOOST_CHECK_THROW(noCategory = counterDirectory.RegisterCategory(""), armnn::InvalidArgumentException);
842  BOOST_CHECK(counterDirectory.GetCategoryCount() == 0);
843  BOOST_CHECK(!noCategory);
844 
845  // Register a category with an invalid name
846  BOOST_CHECK_THROW(noCategory = counterDirectory.RegisterCategory("invalid category"),
848  BOOST_CHECK(counterDirectory.GetCategoryCount() == 0);
849  BOOST_CHECK(!noCategory);
850 
851  // Register a new category
852  const std::string categoryName = "some_category";
853  const Category* category = nullptr;
854  BOOST_CHECK_NO_THROW(category = counterDirectory.RegisterCategory(categoryName));
855  BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
856  BOOST_CHECK(category);
857  BOOST_CHECK(category->m_Name == categoryName);
858  BOOST_CHECK(category->m_Counters.empty());
859 
860  // Get the registered category
861  const Category* registeredCategory = counterDirectory.GetCategory(categoryName);
862  BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
863  BOOST_CHECK(registeredCategory);
864  BOOST_CHECK(registeredCategory == category);
865 
866  // Try to get a category not registered
867  const Category* notRegisteredCategory = counterDirectory.GetCategory("not_registered_category");
868  BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
869  BOOST_CHECK(!notRegisteredCategory);
870 
871  // Register a category already registered
872  const Category* anotherCategory = nullptr;
873  BOOST_CHECK_THROW(anotherCategory = counterDirectory.RegisterCategory(categoryName),
875  BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
876  BOOST_CHECK(!anotherCategory);
877 
878  // Register a device for testing
879  const std::string deviceName = "some_device";
880  const Device* device = nullptr;
881  BOOST_CHECK_NO_THROW(device = counterDirectory.RegisterDevice(deviceName));
882  BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
883  BOOST_CHECK(device);
884  BOOST_CHECK(device->m_Uid >= 1);
885  BOOST_CHECK(device->m_Name == deviceName);
886  BOOST_CHECK(device->m_Cores == 0);
887 
888  // Register a new category not associated to any device
889  const std::string categoryWoDeviceName = "some_category_without_device";
890  const Category* categoryWoDevice = nullptr;
891  BOOST_CHECK_NO_THROW(categoryWoDevice = counterDirectory.RegisterCategory(categoryWoDeviceName));
892  BOOST_CHECK(counterDirectory.GetCategoryCount() == 2);
893  BOOST_CHECK(categoryWoDevice);
894  BOOST_CHECK(categoryWoDevice->m_Name == categoryWoDeviceName);
895  BOOST_CHECK(categoryWoDevice->m_Counters.empty());
896 
897  // Register a new category associated to an invalid device name (already exist)
898  const Category* categoryInvalidDeviceName = nullptr;
899  BOOST_CHECK_THROW(categoryInvalidDeviceName =
900  counterDirectory.RegisterCategory(categoryWoDeviceName),
902  BOOST_CHECK(counterDirectory.GetCategoryCount() == 2);
903  BOOST_CHECK(!categoryInvalidDeviceName);
904 
905  // Register a new category associated to a valid device
906  const std::string categoryWValidDeviceName = "some_category_with_valid_device";
907  const Category* categoryWValidDevice = nullptr;
908  BOOST_CHECK_NO_THROW(categoryWValidDevice =
909  counterDirectory.RegisterCategory(categoryWValidDeviceName));
910  BOOST_CHECK(counterDirectory.GetCategoryCount() == 3);
911  BOOST_CHECK(categoryWValidDevice);
912  BOOST_CHECK(categoryWValidDevice != category);
913  BOOST_CHECK(categoryWValidDevice->m_Name == categoryWValidDeviceName);
914 
915  // Register a counter set for testing
916  const std::string counterSetName = "some_counter_set";
917  const CounterSet* counterSet = nullptr;
918  BOOST_CHECK_NO_THROW(counterSet = counterDirectory.RegisterCounterSet(counterSetName));
919  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 1);
920  BOOST_CHECK(counterSet);
921  BOOST_CHECK(counterSet->m_Uid >= 1);
922  BOOST_CHECK(counterSet->m_Name == counterSetName);
923  BOOST_CHECK(counterSet->m_Count == 0);
924 
925  // Register a new category not associated to any counter set
926  const std::string categoryWoCounterSetName = "some_category_without_counter_set";
927  const Category* categoryWoCounterSet = nullptr;
928  BOOST_CHECK_NO_THROW(categoryWoCounterSet =
929  counterDirectory.RegisterCategory(categoryWoCounterSetName));
930  BOOST_CHECK(counterDirectory.GetCategoryCount() == 4);
931  BOOST_CHECK(categoryWoCounterSet);
932  BOOST_CHECK(categoryWoCounterSet->m_Name == categoryWoCounterSetName);
933 
934  // Register a new category associated to a valid counter set
935  const std::string categoryWValidCounterSetName = "some_category_with_valid_counter_set";
936  const Category* categoryWValidCounterSet = nullptr;
937  BOOST_CHECK_NO_THROW(categoryWValidCounterSet = counterDirectory.RegisterCategory(categoryWValidCounterSetName));
938  BOOST_CHECK(counterDirectory.GetCategoryCount() == 5);
939  BOOST_CHECK(categoryWValidCounterSet);
940  BOOST_CHECK(categoryWValidCounterSet != category);
941  BOOST_CHECK(categoryWValidCounterSet->m_Name == categoryWValidCounterSetName);
942 
943  // Register a new category associated to a valid device and counter set
944  const std::string categoryWValidDeviceAndValidCounterSetName = "some_category_with_valid_device_and_counter_set";
945  const Category* categoryWValidDeviceAndValidCounterSet = nullptr;
946  BOOST_CHECK_NO_THROW(categoryWValidDeviceAndValidCounterSet = counterDirectory.RegisterCategory(
947  categoryWValidDeviceAndValidCounterSetName));
948  BOOST_CHECK(counterDirectory.GetCategoryCount() == 6);
949  BOOST_CHECK(categoryWValidDeviceAndValidCounterSet);
950  BOOST_CHECK(categoryWValidDeviceAndValidCounterSet != category);
951  BOOST_CHECK(categoryWValidDeviceAndValidCounterSet->m_Name == categoryWValidDeviceAndValidCounterSetName);
952 }
953 
954 BOOST_AUTO_TEST_CASE(CheckCounterDirectoryRegisterDevice)
955 {
956  CounterDirectory counterDirectory;
957  BOOST_CHECK(counterDirectory.GetCategoryCount() == 0);
958  BOOST_CHECK(counterDirectory.GetDeviceCount() == 0);
959  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 0);
960  BOOST_CHECK(counterDirectory.GetCounterCount() == 0);
961 
962  // Register a device with an invalid name
963  const Device* noDevice = nullptr;
964  BOOST_CHECK_THROW(noDevice = counterDirectory.RegisterDevice(""), armnn::InvalidArgumentException);
965  BOOST_CHECK(counterDirectory.GetDeviceCount() == 0);
966  BOOST_CHECK(!noDevice);
967 
968  // Register a device with an invalid name
969  BOOST_CHECK_THROW(noDevice = counterDirectory.RegisterDevice("inv@lid nam€"), armnn::InvalidArgumentException);
970  BOOST_CHECK(counterDirectory.GetDeviceCount() == 0);
971  BOOST_CHECK(!noDevice);
972 
973  // Register a new device with no cores or parent category
974  const std::string deviceName = "some_device";
975  const Device* device = nullptr;
976  BOOST_CHECK_NO_THROW(device = counterDirectory.RegisterDevice(deviceName));
977  BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
978  BOOST_CHECK(device);
979  BOOST_CHECK(device->m_Name == deviceName);
980  BOOST_CHECK(device->m_Uid >= 1);
981  BOOST_CHECK(device->m_Cores == 0);
982 
983  // Try getting an unregistered device
984  const Device* unregisteredDevice = counterDirectory.GetDevice(9999);
985  BOOST_CHECK(!unregisteredDevice);
986 
987  // Get the registered device
988  const Device* registeredDevice = counterDirectory.GetDevice(device->m_Uid);
989  BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
990  BOOST_CHECK(registeredDevice);
991  BOOST_CHECK(registeredDevice == device);
992 
993  // Register a device with the name of a device already registered
994  const Device* deviceSameName = nullptr;
995  BOOST_CHECK_THROW(deviceSameName = counterDirectory.RegisterDevice(deviceName), armnn::InvalidArgumentException);
996  BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
997  BOOST_CHECK(!deviceSameName);
998 
999  // Register a new device with cores and no parent category
1000  const std::string deviceWCoresName = "some_device_with_cores";
1001  const Device* deviceWCores = nullptr;
1002  BOOST_CHECK_NO_THROW(deviceWCores = counterDirectory.RegisterDevice(deviceWCoresName, 2));
1003  BOOST_CHECK(counterDirectory.GetDeviceCount() == 2);
1004  BOOST_CHECK(deviceWCores);
1005  BOOST_CHECK(deviceWCores->m_Name == deviceWCoresName);
1006  BOOST_CHECK(deviceWCores->m_Uid >= 1);
1007  BOOST_CHECK(deviceWCores->m_Uid > device->m_Uid);
1008  BOOST_CHECK(deviceWCores->m_Cores == 2);
1009 
1010  // Get the registered device
1011  const Device* registeredDeviceWCores = counterDirectory.GetDevice(deviceWCores->m_Uid);
1012  BOOST_CHECK(counterDirectory.GetDeviceCount() == 2);
1013  BOOST_CHECK(registeredDeviceWCores);
1014  BOOST_CHECK(registeredDeviceWCores == deviceWCores);
1015  BOOST_CHECK(registeredDeviceWCores != device);
1016 
1017  // Register a new device with cores and invalid parent category
1018  const std::string deviceWCoresWInvalidParentCategoryName = "some_device_with_cores_with_invalid_parent_category";
1019  const Device* deviceWCoresWInvalidParentCategory = nullptr;
1020  BOOST_CHECK_THROW(deviceWCoresWInvalidParentCategory =
1021  counterDirectory.RegisterDevice(deviceWCoresWInvalidParentCategoryName, 3, std::string("")),
1023  BOOST_CHECK(counterDirectory.GetDeviceCount() == 2);
1024  BOOST_CHECK(!deviceWCoresWInvalidParentCategory);
1025 
1026  // Register a new device with cores and invalid parent category
1027  const std::string deviceWCoresWInvalidParentCategoryName2 = "some_device_with_cores_with_invalid_parent_category2";
1028  const Device* deviceWCoresWInvalidParentCategory2 = nullptr;
1029  BOOST_CHECK_THROW(deviceWCoresWInvalidParentCategory2 = counterDirectory.RegisterDevice(
1030  deviceWCoresWInvalidParentCategoryName2, 3, std::string("invalid_parent_category")),
1032  BOOST_CHECK(counterDirectory.GetDeviceCount() == 2);
1033  BOOST_CHECK(!deviceWCoresWInvalidParentCategory2);
1034 
1035  // Register a category for testing
1036  const std::string categoryName = "some_category";
1037  const Category* category = nullptr;
1038  BOOST_CHECK_NO_THROW(category = counterDirectory.RegisterCategory(categoryName));
1039  BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
1040  BOOST_CHECK(category);
1041  BOOST_CHECK(category->m_Name == categoryName);
1042  BOOST_CHECK(category->m_Counters.empty());
1043 
1044  // Register a new device with cores and valid parent category
1045  const std::string deviceWCoresWValidParentCategoryName = "some_device_with_cores_with_valid_parent_category";
1046  const Device* deviceWCoresWValidParentCategory = nullptr;
1047  BOOST_CHECK_NO_THROW(deviceWCoresWValidParentCategory =
1048  counterDirectory.RegisterDevice(deviceWCoresWValidParentCategoryName, 4, categoryName));
1049  BOOST_CHECK(counterDirectory.GetDeviceCount() == 3);
1050  BOOST_CHECK(deviceWCoresWValidParentCategory);
1051  BOOST_CHECK(deviceWCoresWValidParentCategory->m_Name == deviceWCoresWValidParentCategoryName);
1052  BOOST_CHECK(deviceWCoresWValidParentCategory->m_Uid >= 1);
1053  BOOST_CHECK(deviceWCoresWValidParentCategory->m_Uid > device->m_Uid);
1054  BOOST_CHECK(deviceWCoresWValidParentCategory->m_Uid > deviceWCores->m_Uid);
1055  BOOST_CHECK(deviceWCoresWValidParentCategory->m_Cores == 4);
1056 }
1057 
1058 BOOST_AUTO_TEST_CASE(CheckCounterDirectoryRegisterCounterSet)
1059 {
1060  CounterDirectory counterDirectory;
1061  BOOST_CHECK(counterDirectory.GetCategoryCount() == 0);
1062  BOOST_CHECK(counterDirectory.GetDeviceCount() == 0);
1063  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 0);
1064  BOOST_CHECK(counterDirectory.GetCounterCount() == 0);
1065 
1066  // Register a counter set with an invalid name
1067  const CounterSet* noCounterSet = nullptr;
1068  BOOST_CHECK_THROW(noCounterSet = counterDirectory.RegisterCounterSet(""), armnn::InvalidArgumentException);
1069  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 0);
1070  BOOST_CHECK(!noCounterSet);
1071 
1072  // Register a counter set with an invalid name
1073  BOOST_CHECK_THROW(noCounterSet = counterDirectory.RegisterCounterSet("invalid name"),
1075  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 0);
1076  BOOST_CHECK(!noCounterSet);
1077 
1078  // Register a new counter set with no count or parent category
1079  const std::string counterSetName = "some_counter_set";
1080  const CounterSet* counterSet = nullptr;
1081  BOOST_CHECK_NO_THROW(counterSet = counterDirectory.RegisterCounterSet(counterSetName));
1082  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 1);
1083  BOOST_CHECK(counterSet);
1084  BOOST_CHECK(counterSet->m_Name == counterSetName);
1085  BOOST_CHECK(counterSet->m_Uid >= 1);
1086  BOOST_CHECK(counterSet->m_Count == 0);
1087 
1088  // Try getting an unregistered counter set
1089  const CounterSet* unregisteredCounterSet = counterDirectory.GetCounterSet(9999);
1090  BOOST_CHECK(!unregisteredCounterSet);
1091 
1092  // Get the registered counter set
1093  const CounterSet* registeredCounterSet = counterDirectory.GetCounterSet(counterSet->m_Uid);
1094  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 1);
1095  BOOST_CHECK(registeredCounterSet);
1096  BOOST_CHECK(registeredCounterSet == counterSet);
1097 
1098  // Register a counter set with the name of a counter set already registered
1099  const CounterSet* counterSetSameName = nullptr;
1100  BOOST_CHECK_THROW(counterSetSameName = counterDirectory.RegisterCounterSet(counterSetName),
1102  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 1);
1103  BOOST_CHECK(!counterSetSameName);
1104 
1105  // Register a new counter set with count and no parent category
1106  const std::string counterSetWCountName = "some_counter_set_with_count";
1107  const CounterSet* counterSetWCount = nullptr;
1108  BOOST_CHECK_NO_THROW(counterSetWCount = counterDirectory.RegisterCounterSet(counterSetWCountName, 37));
1109  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 2);
1110  BOOST_CHECK(counterSetWCount);
1111  BOOST_CHECK(counterSetWCount->m_Name == counterSetWCountName);
1112  BOOST_CHECK(counterSetWCount->m_Uid >= 1);
1113  BOOST_CHECK(counterSetWCount->m_Uid > counterSet->m_Uid);
1114  BOOST_CHECK(counterSetWCount->m_Count == 37);
1115 
1116  // Get the registered counter set
1117  const CounterSet* registeredCounterSetWCount = counterDirectory.GetCounterSet(counterSetWCount->m_Uid);
1118  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 2);
1119  BOOST_CHECK(registeredCounterSetWCount);
1120  BOOST_CHECK(registeredCounterSetWCount == counterSetWCount);
1121  BOOST_CHECK(registeredCounterSetWCount != counterSet);
1122 
1123  // Register a new counter set with count and invalid parent category
1124  const std::string counterSetWCountWInvalidParentCategoryName = "some_counter_set_with_count_"
1125  "with_invalid_parent_category";
1126  const CounterSet* counterSetWCountWInvalidParentCategory = nullptr;
1127  BOOST_CHECK_THROW(counterSetWCountWInvalidParentCategory = counterDirectory.RegisterCounterSet(
1128  counterSetWCountWInvalidParentCategoryName, 42, std::string("")),
1130  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 2);
1131  BOOST_CHECK(!counterSetWCountWInvalidParentCategory);
1132 
1133  // Register a new counter set with count and invalid parent category
1134  const std::string counterSetWCountWInvalidParentCategoryName2 = "some_counter_set_with_count_"
1135  "with_invalid_parent_category2";
1136  const CounterSet* counterSetWCountWInvalidParentCategory2 = nullptr;
1137  BOOST_CHECK_THROW(counterSetWCountWInvalidParentCategory2 = counterDirectory.RegisterCounterSet(
1138  counterSetWCountWInvalidParentCategoryName2, 42, std::string("invalid_parent_category")),
1140  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 2);
1141  BOOST_CHECK(!counterSetWCountWInvalidParentCategory2);
1142 
1143  // Register a category for testing
1144  const std::string categoryName = "some_category";
1145  const Category* category = nullptr;
1146  BOOST_CHECK_NO_THROW(category = counterDirectory.RegisterCategory(categoryName));
1147  BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
1148  BOOST_CHECK(category);
1149  BOOST_CHECK(category->m_Name == categoryName);
1150  BOOST_CHECK(category->m_Counters.empty());
1151 
1152  // Register a new counter set with count and valid parent category
1153  const std::string counterSetWCountWValidParentCategoryName = "some_counter_set_with_count_"
1154  "with_valid_parent_category";
1155  const CounterSet* counterSetWCountWValidParentCategory = nullptr;
1156  BOOST_CHECK_NO_THROW(counterSetWCountWValidParentCategory = counterDirectory.RegisterCounterSet(
1157  counterSetWCountWValidParentCategoryName, 42, categoryName));
1158  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 3);
1159  BOOST_CHECK(counterSetWCountWValidParentCategory);
1160  BOOST_CHECK(counterSetWCountWValidParentCategory->m_Name == counterSetWCountWValidParentCategoryName);
1161  BOOST_CHECK(counterSetWCountWValidParentCategory->m_Uid >= 1);
1162  BOOST_CHECK(counterSetWCountWValidParentCategory->m_Uid > counterSet->m_Uid);
1163  BOOST_CHECK(counterSetWCountWValidParentCategory->m_Uid > counterSetWCount->m_Uid);
1164  BOOST_CHECK(counterSetWCountWValidParentCategory->m_Count == 42);
1165 
1166  // Register a counter set associated to a category with invalid name
1167  const std::string counterSetSameCategoryName = "some_counter_set_with_invalid_parent_category";
1168  const std::string invalidCategoryName = "";
1169  const CounterSet* counterSetSameCategory = nullptr;
1170  BOOST_CHECK_THROW(counterSetSameCategory =
1171  counterDirectory.RegisterCounterSet(counterSetSameCategoryName, 0, invalidCategoryName),
1173  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 3);
1174  BOOST_CHECK(!counterSetSameCategory);
1175 }
1176 
1177 BOOST_AUTO_TEST_CASE(CheckCounterDirectoryRegisterCounter)
1178 {
1179  CounterDirectory counterDirectory;
1180  BOOST_CHECK(counterDirectory.GetCategoryCount() == 0);
1181  BOOST_CHECK(counterDirectory.GetDeviceCount() == 0);
1182  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 0);
1183  BOOST_CHECK(counterDirectory.GetCounterCount() == 0);
1184 
1185  // Register a counter with an invalid parent category name
1186  const Counter* noCounter = nullptr;
1187  BOOST_CHECK_THROW(noCounter =
1188  counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1189  0,
1190  "",
1191  0,
1192  1,
1193  123.45f,
1194  "valid ",
1195  "name"),
1197  BOOST_CHECK(counterDirectory.GetCounterCount() == 0);
1198  BOOST_CHECK(!noCounter);
1199 
1200  // Register a counter with an invalid parent category name
1201  BOOST_CHECK_THROW(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1202  1,
1203  "invalid parent category",
1204  0,
1205  1,
1206  123.45f,
1207  "valid name",
1208  "valid description"),
1210  BOOST_CHECK(counterDirectory.GetCounterCount() == 0);
1211  BOOST_CHECK(!noCounter);
1212 
1213  // Register a counter with an invalid class
1214  BOOST_CHECK_THROW(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1215  2,
1216  "valid_parent_category",
1217  2,
1218  1,
1219  123.45f,
1220  "valid "
1221  "name",
1222  "valid description"),
1224  BOOST_CHECK(counterDirectory.GetCounterCount() == 0);
1225  BOOST_CHECK(!noCounter);
1226 
1227  // Register a counter with an invalid interpolation
1228  BOOST_CHECK_THROW(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1229  4,
1230  "valid_parent_category",
1231  0,
1232  3,
1233  123.45f,
1234  "valid "
1235  "name",
1236  "valid description"),
1238  BOOST_CHECK(counterDirectory.GetCounterCount() == 0);
1239  BOOST_CHECK(!noCounter);
1240 
1241  // Register a counter with an invalid multiplier
1242  BOOST_CHECK_THROW(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1243  5,
1244  "valid_parent_category",
1245  0,
1246  1,
1247  .0f,
1248  "valid "
1249  "name",
1250  "valid description"),
1252  BOOST_CHECK(counterDirectory.GetCounterCount() == 0);
1253  BOOST_CHECK(!noCounter);
1254 
1255  // Register a counter with an invalid name
1256  BOOST_CHECK_THROW(
1257  noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1258  6,
1259  "valid_parent_category",
1260  0,
1261  1,
1262  123.45f,
1263  "",
1264  "valid description"),
1266  BOOST_CHECK(counterDirectory.GetCounterCount() == 0);
1267  BOOST_CHECK(!noCounter);
1268 
1269  // Register a counter with an invalid name
1270  BOOST_CHECK_THROW(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1271  7,
1272  "valid_parent_category",
1273  0,
1274  1,
1275  123.45f,
1276  "invalid nam€",
1277  "valid description"),
1279  BOOST_CHECK(counterDirectory.GetCounterCount() == 0);
1280  BOOST_CHECK(!noCounter);
1281 
1282  // Register a counter with an invalid description
1283  BOOST_CHECK_THROW(noCounter =
1284  counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1285  8,
1286  "valid_parent_category",
1287  0,
1288  1,
1289  123.45f,
1290  "valid name",
1291  ""),
1293  BOOST_CHECK(counterDirectory.GetCounterCount() == 0);
1294  BOOST_CHECK(!noCounter);
1295 
1296  // Register a counter with an invalid description
1297  BOOST_CHECK_THROW(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1298  9,
1299  "valid_parent_category",
1300  0,
1301  1,
1302  123.45f,
1303  "valid "
1304  "name",
1305  "inv@lid description"),
1307  BOOST_CHECK(counterDirectory.GetCounterCount() == 0);
1308  BOOST_CHECK(!noCounter);
1309 
1310  // Register a counter with an invalid unit2
1311  BOOST_CHECK_THROW(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1312  10,
1313  "valid_parent_category",
1314  0,
1315  1,
1316  123.45f,
1317  "valid name",
1318  "valid description",
1319  std::string("Mb/s2")),
1321  BOOST_CHECK(counterDirectory.GetCounterCount() == 0);
1322  BOOST_CHECK(!noCounter);
1323 
1324  // Register a counter with a non-existing parent category name
1325  BOOST_CHECK_THROW(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1326  11,
1327  "invalid_parent_category",
1328  0,
1329  1,
1330  123.45f,
1331  "valid name",
1332  "valid description"),
1334  BOOST_CHECK(counterDirectory.GetCounterCount() == 0);
1335  BOOST_CHECK(!noCounter);
1336 
1337  // Try getting an unregistered counter
1338  const Counter* unregisteredCounter = counterDirectory.GetCounter(9999);
1339  BOOST_CHECK(!unregisteredCounter);
1340 
1341  // Register a category for testing
1342  const std::string categoryName = "some_category";
1343  const Category* category = nullptr;
1344  BOOST_CHECK_NO_THROW(category = counterDirectory.RegisterCategory(categoryName));
1345  BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
1346  BOOST_CHECK(category);
1347  BOOST_CHECK(category->m_Name == categoryName);
1348  BOOST_CHECK(category->m_Counters.empty());
1349 
1350  // Register a counter with a valid parent category name
1351  const Counter* counter = nullptr;
1352  BOOST_CHECK_NO_THROW(
1353  counter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1354  12,
1355  categoryName,
1356  0,
1357  1,
1358  123.45f,
1359  "valid name",
1360  "valid description"));
1361  BOOST_CHECK(counterDirectory.GetCounterCount() == 1);
1362  BOOST_CHECK(counter);
1363  BOOST_CHECK(counter->m_MaxCounterUid == counter->m_Uid);
1364  BOOST_CHECK(counter->m_Class == 0);
1365  BOOST_CHECK(counter->m_Interpolation == 1);
1366  BOOST_CHECK(counter->m_Multiplier == 123.45f);
1367  BOOST_CHECK(counter->m_Name == "valid name");
1368  BOOST_CHECK(counter->m_Description == "valid description");
1369  BOOST_CHECK(counter->m_Units == "");
1370  BOOST_CHECK(counter->m_DeviceUid == 0);
1371  BOOST_CHECK(counter->m_CounterSetUid == 0);
1372  BOOST_CHECK(category->m_Counters.size() == 1);
1373  BOOST_CHECK(category->m_Counters.back() == counter->m_Uid);
1374 
1375  // Register a counter with a name of a counter already registered for the given parent category name
1376  const Counter* counterSameName = nullptr;
1377  BOOST_CHECK_THROW(counterSameName =
1378  counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1379  13,
1380  categoryName,
1381  0,
1382  0,
1383  1.0f,
1384  "valid name",
1385  "valid description",
1386  std::string("description")),
1388  BOOST_CHECK(counterDirectory.GetCounterCount() == 1);
1389  BOOST_CHECK(!counterSameName);
1390 
1391  // Register a counter with a valid parent category name and units
1392  const Counter* counterWUnits = nullptr;
1393  BOOST_CHECK_NO_THROW(counterWUnits = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1394  14,
1395  categoryName,
1396  0,
1397  1,
1398  123.45f,
1399  "valid name 2",
1400  "valid description",
1401  std::string("Mnnsq2"))); // Units
1402  BOOST_CHECK(counterDirectory.GetCounterCount() == 2);
1403  BOOST_CHECK(counterWUnits);
1404  BOOST_CHECK(counterWUnits->m_Uid > counter->m_Uid);
1405  BOOST_CHECK(counterWUnits->m_MaxCounterUid == counterWUnits->m_Uid);
1406  BOOST_CHECK(counterWUnits->m_Class == 0);
1407  BOOST_CHECK(counterWUnits->m_Interpolation == 1);
1408  BOOST_CHECK(counterWUnits->m_Multiplier == 123.45f);
1409  BOOST_CHECK(counterWUnits->m_Name == "valid name 2");
1410  BOOST_CHECK(counterWUnits->m_Description == "valid description");
1411  BOOST_CHECK(counterWUnits->m_Units == "Mnnsq2");
1412  BOOST_CHECK(counterWUnits->m_DeviceUid == 0);
1413  BOOST_CHECK(counterWUnits->m_CounterSetUid == 0);
1414  BOOST_CHECK(category->m_Counters.size() == 2);
1415  BOOST_CHECK(category->m_Counters.back() == counterWUnits->m_Uid);
1416 
1417  // Register a counter with a valid parent category name and not associated with a device
1418  const Counter* counterWoDevice = nullptr;
1419  BOOST_CHECK_NO_THROW(counterWoDevice = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1420  26,
1421  categoryName,
1422  0,
1423  1,
1424  123.45f,
1425  "valid name 3",
1426  "valid description",
1427  armnn::EmptyOptional(),// Units
1428  armnn::EmptyOptional(),// Number of cores
1429  0)); // Device UID
1430  BOOST_CHECK(counterDirectory.GetCounterCount() == 3);
1431  BOOST_CHECK(counterWoDevice);
1432  BOOST_CHECK(counterWoDevice->m_Uid > counter->m_Uid);
1433  BOOST_CHECK(counterWoDevice->m_MaxCounterUid == counterWoDevice->m_Uid);
1434  BOOST_CHECK(counterWoDevice->m_Class == 0);
1435  BOOST_CHECK(counterWoDevice->m_Interpolation == 1);
1436  BOOST_CHECK(counterWoDevice->m_Multiplier == 123.45f);
1437  BOOST_CHECK(counterWoDevice->m_Name == "valid name 3");
1438  BOOST_CHECK(counterWoDevice->m_Description == "valid description");
1439  BOOST_CHECK(counterWoDevice->m_Units == "");
1440  BOOST_CHECK(counterWoDevice->m_DeviceUid == 0);
1441  BOOST_CHECK(counterWoDevice->m_CounterSetUid == 0);
1442  BOOST_CHECK(category->m_Counters.size() == 3);
1443  BOOST_CHECK(category->m_Counters.back() == counterWoDevice->m_Uid);
1444 
1445  // Register a counter with a valid parent category name and associated to an invalid device
1446  BOOST_CHECK_THROW(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1447  15,
1448  categoryName,
1449  0,
1450  1,
1451  123.45f,
1452  "valid name 4",
1453  "valid description",
1454  armnn::EmptyOptional(), // Units
1455  armnn::EmptyOptional(), // Number of cores
1456  100), // Device UID
1458  BOOST_CHECK(counterDirectory.GetCounterCount() == 3);
1459  BOOST_CHECK(!noCounter);
1460 
1461  // Register a device for testing
1462  const std::string deviceName = "some_device";
1463  const Device* device = nullptr;
1464  BOOST_CHECK_NO_THROW(device = counterDirectory.RegisterDevice(deviceName));
1465  BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
1466  BOOST_CHECK(device);
1467  BOOST_CHECK(device->m_Name == deviceName);
1468  BOOST_CHECK(device->m_Uid >= 1);
1469  BOOST_CHECK(device->m_Cores == 0);
1470 
1471  // Register a counter with a valid parent category name and associated to a device
1472  const Counter* counterWDevice = nullptr;
1473  BOOST_CHECK_NO_THROW(counterWDevice = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1474  16,
1475  categoryName,
1476  0,
1477  1,
1478  123.45f,
1479  "valid name 5",
1480  std::string("valid description"),
1481  armnn::EmptyOptional(), // Units
1482  armnn::EmptyOptional(), // Number of cores
1483  device->m_Uid)); // Device UID
1484  BOOST_CHECK(counterDirectory.GetCounterCount() == 4);
1485  BOOST_CHECK(counterWDevice);
1486  BOOST_CHECK(counterWDevice->m_Uid > counter->m_Uid);
1487  BOOST_CHECK(counterWDevice->m_MaxCounterUid == counterWDevice->m_Uid);
1488  BOOST_CHECK(counterWDevice->m_Class == 0);
1489  BOOST_CHECK(counterWDevice->m_Interpolation == 1);
1490  BOOST_CHECK(counterWDevice->m_Multiplier == 123.45f);
1491  BOOST_CHECK(counterWDevice->m_Name == "valid name 5");
1492  BOOST_CHECK(counterWDevice->m_Description == "valid description");
1493  BOOST_CHECK(counterWDevice->m_Units == "");
1494  BOOST_CHECK(counterWDevice->m_DeviceUid == device->m_Uid);
1495  BOOST_CHECK(counterWDevice->m_CounterSetUid == 0);
1496  BOOST_CHECK(category->m_Counters.size() == 4);
1497  BOOST_CHECK(category->m_Counters.back() == counterWDevice->m_Uid);
1498 
1499  // Register a counter with a valid parent category name and not associated with a counter set
1500  const Counter* counterWoCounterSet = nullptr;
1501  BOOST_CHECK_NO_THROW(counterWoCounterSet = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1502  17,
1503  categoryName,
1504  0,
1505  1,
1506  123.45f,
1507  "valid name 6",
1508  "valid description",
1509  armnn::EmptyOptional(),// Units
1510  armnn::EmptyOptional(),// No of cores
1511  armnn::EmptyOptional(),// Device UID
1512  0)); // CounterSet UID
1513  BOOST_CHECK(counterDirectory.GetCounterCount() == 5);
1514  BOOST_CHECK(counterWoCounterSet);
1515  BOOST_CHECK(counterWoCounterSet->m_Uid > counter->m_Uid);
1516  BOOST_CHECK(counterWoCounterSet->m_MaxCounterUid == counterWoCounterSet->m_Uid);
1517  BOOST_CHECK(counterWoCounterSet->m_Class == 0);
1518  BOOST_CHECK(counterWoCounterSet->m_Interpolation == 1);
1519  BOOST_CHECK(counterWoCounterSet->m_Multiplier == 123.45f);
1520  BOOST_CHECK(counterWoCounterSet->m_Name == "valid name 6");
1521  BOOST_CHECK(counterWoCounterSet->m_Description == "valid description");
1522  BOOST_CHECK(counterWoCounterSet->m_Units == "");
1523  BOOST_CHECK(counterWoCounterSet->m_DeviceUid == 0);
1524  BOOST_CHECK(counterWoCounterSet->m_CounterSetUid == 0);
1525  BOOST_CHECK(category->m_Counters.size() == 5);
1526  BOOST_CHECK(category->m_Counters.back() == counterWoCounterSet->m_Uid);
1527 
1528  // Register a counter with a valid parent category name and associated to an invalid counter set
1529  BOOST_CHECK_THROW(noCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1530  18,
1531  categoryName,
1532  0,
1533  1,
1534  123.45f,
1535  "valid ",
1536  "name 7",
1537  std::string("valid description"),
1538  armnn::EmptyOptional(), // Units
1539  armnn::EmptyOptional(), // Number of cores
1540  100), // Counter set UID
1542  BOOST_CHECK(counterDirectory.GetCounterCount() == 5);
1543  BOOST_CHECK(!noCounter);
1544 
1545  // Register a counter with a valid parent category name and with a given number of cores
1546  const Counter* counterWNumberOfCores = nullptr;
1547  uint16_t numberOfCores = 15;
1548  BOOST_CHECK_NO_THROW(counterWNumberOfCores = counterDirectory.RegisterCounter(
1549  armnn::profiling::BACKEND_ID, 50,
1550  categoryName, 0, 1, 123.45f, "valid name 8", "valid description",
1551  armnn::EmptyOptional(), // Units
1552  numberOfCores, // Number of cores
1553  armnn::EmptyOptional(), // Device UID
1554  armnn::EmptyOptional())); // Counter set UID
1555  BOOST_CHECK(counterDirectory.GetCounterCount() == 20);
1556  BOOST_CHECK(counterWNumberOfCores);
1557  BOOST_CHECK(counterWNumberOfCores->m_Uid > counter->m_Uid);
1558  BOOST_CHECK(counterWNumberOfCores->m_MaxCounterUid == counterWNumberOfCores->m_Uid + numberOfCores - 1);
1559  BOOST_CHECK(counterWNumberOfCores->m_Class == 0);
1560  BOOST_CHECK(counterWNumberOfCores->m_Interpolation == 1);
1561  BOOST_CHECK(counterWNumberOfCores->m_Multiplier == 123.45f);
1562  BOOST_CHECK(counterWNumberOfCores->m_Name == "valid name 8");
1563  BOOST_CHECK(counterWNumberOfCores->m_Description == "valid description");
1564  BOOST_CHECK(counterWNumberOfCores->m_Units == "");
1565  BOOST_CHECK(counterWNumberOfCores->m_DeviceUid == 0);
1566  BOOST_CHECK(counterWNumberOfCores->m_CounterSetUid == 0);
1567  BOOST_CHECK(category->m_Counters.size() == 20);
1568  for (size_t i = 0; i < numberOfCores; i++)
1569  {
1570  BOOST_CHECK(category->m_Counters[category->m_Counters.size() - numberOfCores + i] ==
1571  counterWNumberOfCores->m_Uid + i);
1572  }
1573 
1574  // Register a multi-core device for testing
1575  const std::string multiCoreDeviceName = "some_multi_core_device";
1576  const Device* multiCoreDevice = nullptr;
1577  BOOST_CHECK_NO_THROW(multiCoreDevice = counterDirectory.RegisterDevice(multiCoreDeviceName, 4));
1578  BOOST_CHECK(counterDirectory.GetDeviceCount() == 2);
1579  BOOST_CHECK(multiCoreDevice);
1580  BOOST_CHECK(multiCoreDevice->m_Name == multiCoreDeviceName);
1581  BOOST_CHECK(multiCoreDevice->m_Uid >= 1);
1582  BOOST_CHECK(multiCoreDevice->m_Cores == 4);
1583 
1584  // Register a counter with a valid parent category name and associated to the multi-core device
1585  const Counter* counterWMultiCoreDevice = nullptr;
1586  BOOST_CHECK_NO_THROW(counterWMultiCoreDevice = counterDirectory.RegisterCounter(
1587  armnn::profiling::BACKEND_ID, 19, categoryName, 0, 1,
1588  123.45f, "valid name 9", "valid description",
1589  armnn::EmptyOptional(), // Units
1590  armnn::EmptyOptional(), // Number of cores
1591  multiCoreDevice->m_Uid, // Device UID
1592  armnn::EmptyOptional())); // Counter set UID
1593  BOOST_CHECK(counterDirectory.GetCounterCount() == 24);
1594  BOOST_CHECK(counterWMultiCoreDevice);
1595  BOOST_CHECK(counterWMultiCoreDevice->m_Uid > counter->m_Uid);
1596  BOOST_CHECK(counterWMultiCoreDevice->m_MaxCounterUid ==
1597  counterWMultiCoreDevice->m_Uid + multiCoreDevice->m_Cores - 1);
1598  BOOST_CHECK(counterWMultiCoreDevice->m_Class == 0);
1599  BOOST_CHECK(counterWMultiCoreDevice->m_Interpolation == 1);
1600  BOOST_CHECK(counterWMultiCoreDevice->m_Multiplier == 123.45f);
1601  BOOST_CHECK(counterWMultiCoreDevice->m_Name == "valid name 9");
1602  BOOST_CHECK(counterWMultiCoreDevice->m_Description == "valid description");
1603  BOOST_CHECK(counterWMultiCoreDevice->m_Units == "");
1604  BOOST_CHECK(counterWMultiCoreDevice->m_DeviceUid == multiCoreDevice->m_Uid);
1605  BOOST_CHECK(counterWMultiCoreDevice->m_CounterSetUid == 0);
1606  BOOST_CHECK(category->m_Counters.size() == 24);
1607  for (size_t i = 0; i < 4; i++)
1608  {
1609  BOOST_CHECK(category->m_Counters[category->m_Counters.size() - 4 + i] == counterWMultiCoreDevice->m_Uid + i);
1610  }
1611 
1612  // Register a multi-core device associate to a parent category for testing
1613  const std::string multiCoreDeviceNameWParentCategory = "some_multi_core_device_with_parent_category";
1614  const Device* multiCoreDeviceWParentCategory = nullptr;
1615  BOOST_CHECK_NO_THROW(multiCoreDeviceWParentCategory =
1616  counterDirectory.RegisterDevice(multiCoreDeviceNameWParentCategory, 2, categoryName));
1617  BOOST_CHECK(counterDirectory.GetDeviceCount() == 3);
1618  BOOST_CHECK(multiCoreDeviceWParentCategory);
1619  BOOST_CHECK(multiCoreDeviceWParentCategory->m_Name == multiCoreDeviceNameWParentCategory);
1620  BOOST_CHECK(multiCoreDeviceWParentCategory->m_Uid >= 1);
1621  BOOST_CHECK(multiCoreDeviceWParentCategory->m_Cores == 2);
1622 
1623  // Register a counter with a valid parent category name and getting the number of cores of the multi-core device
1624  // associated to that category
1625  const Counter* counterWMultiCoreDeviceWParentCategory = nullptr;
1626  uint16_t numberOfCourse = multiCoreDeviceWParentCategory->m_Cores;
1627  BOOST_CHECK_NO_THROW(counterWMultiCoreDeviceWParentCategory =
1628  counterDirectory.RegisterCounter(
1629  armnn::profiling::BACKEND_ID,
1630  100,
1631  categoryName,
1632  0,
1633  1,
1634  123.45f,
1635  "valid name 10",
1636  "valid description",
1637  armnn::EmptyOptional(), // Units
1638  numberOfCourse, // Number of cores
1639  armnn::EmptyOptional(), // Device UID
1640  armnn::EmptyOptional()));// Counter set UID
1641  BOOST_CHECK(counterDirectory.GetCounterCount() == 26);
1642  BOOST_CHECK(counterWMultiCoreDeviceWParentCategory);
1643  BOOST_CHECK(counterWMultiCoreDeviceWParentCategory->m_Uid > counter->m_Uid);
1644  BOOST_CHECK(counterWMultiCoreDeviceWParentCategory->m_MaxCounterUid ==
1645  counterWMultiCoreDeviceWParentCategory->m_Uid + multiCoreDeviceWParentCategory->m_Cores - 1);
1646  BOOST_CHECK(counterWMultiCoreDeviceWParentCategory->m_Class == 0);
1647  BOOST_CHECK(counterWMultiCoreDeviceWParentCategory->m_Interpolation == 1);
1648  BOOST_CHECK(counterWMultiCoreDeviceWParentCategory->m_Multiplier == 123.45f);
1649  BOOST_CHECK(counterWMultiCoreDeviceWParentCategory->m_Name == "valid name 10");
1650  BOOST_CHECK(counterWMultiCoreDeviceWParentCategory->m_Description == "valid description");
1651  BOOST_CHECK(counterWMultiCoreDeviceWParentCategory->m_Units == "");
1652  BOOST_CHECK(category->m_Counters.size() == 26);
1653  for (size_t i = 0; i < 2; i++)
1654  {
1655  BOOST_CHECK(category->m_Counters[category->m_Counters.size() - 2 + i] ==
1656  counterWMultiCoreDeviceWParentCategory->m_Uid + i);
1657  }
1658 
1659  // Register a counter set for testing
1660  const std::string counterSetName = "some_counter_set";
1661  const CounterSet* counterSet = nullptr;
1662  BOOST_CHECK_NO_THROW(counterSet = counterDirectory.RegisterCounterSet(counterSetName));
1663  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 1);
1664  BOOST_CHECK(counterSet);
1665  BOOST_CHECK(counterSet->m_Name == counterSetName);
1666  BOOST_CHECK(counterSet->m_Uid >= 1);
1667  BOOST_CHECK(counterSet->m_Count == 0);
1668 
1669  // Register a counter with a valid parent category name and associated to a counter set
1670  const Counter* counterWCounterSet = nullptr;
1671  BOOST_CHECK_NO_THROW(counterWCounterSet = counterDirectory.RegisterCounter(
1672  armnn::profiling::BACKEND_ID, 300,
1673  categoryName, 0, 1, 123.45f, "valid name 11", "valid description",
1674  armnn::EmptyOptional(), // Units
1675  0, // Number of cores
1676  armnn::EmptyOptional(), // Device UID
1677  counterSet->m_Uid)); // Counter set UID
1678  BOOST_CHECK(counterDirectory.GetCounterCount() == 27);
1679  BOOST_CHECK(counterWCounterSet);
1680  BOOST_CHECK(counterWCounterSet->m_Uid > counter->m_Uid);
1681  BOOST_CHECK(counterWCounterSet->m_MaxCounterUid == counterWCounterSet->m_Uid);
1682  BOOST_CHECK(counterWCounterSet->m_Class == 0);
1683  BOOST_CHECK(counterWCounterSet->m_Interpolation == 1);
1684  BOOST_CHECK(counterWCounterSet->m_Multiplier == 123.45f);
1685  BOOST_CHECK(counterWCounterSet->m_Name == "valid name 11");
1686  BOOST_CHECK(counterWCounterSet->m_Description == "valid description");
1687  BOOST_CHECK(counterWCounterSet->m_Units == "");
1688  BOOST_CHECK(counterWCounterSet->m_DeviceUid == 0);
1689  BOOST_CHECK(counterWCounterSet->m_CounterSetUid == counterSet->m_Uid);
1690  BOOST_CHECK(category->m_Counters.size() == 27);
1691  BOOST_CHECK(category->m_Counters.back() == counterWCounterSet->m_Uid);
1692 
1693  // Register a counter with a valid parent category name and associated to a device and a counter set
1694  const Counter* counterWDeviceWCounterSet = nullptr;
1695  BOOST_CHECK_NO_THROW(counterWDeviceWCounterSet = counterDirectory.RegisterCounter(
1696  armnn::profiling::BACKEND_ID, 23,
1697  categoryName, 0, 1, 123.45f, "valid name 12", "valid description",
1698  armnn::EmptyOptional(), // Units
1699  1, // Number of cores
1700  device->m_Uid, // Device UID
1701  counterSet->m_Uid)); // Counter set UID
1702  BOOST_CHECK(counterDirectory.GetCounterCount() == 28);
1703  BOOST_CHECK(counterWDeviceWCounterSet);
1704  BOOST_CHECK(counterWDeviceWCounterSet->m_Uid > counter->m_Uid);
1705  BOOST_CHECK(counterWDeviceWCounterSet->m_MaxCounterUid == counterWDeviceWCounterSet->m_Uid);
1706  BOOST_CHECK(counterWDeviceWCounterSet->m_Class == 0);
1707  BOOST_CHECK(counterWDeviceWCounterSet->m_Interpolation == 1);
1708  BOOST_CHECK(counterWDeviceWCounterSet->m_Multiplier == 123.45f);
1709  BOOST_CHECK(counterWDeviceWCounterSet->m_Name == "valid name 12");
1710  BOOST_CHECK(counterWDeviceWCounterSet->m_Description == "valid description");
1711  BOOST_CHECK(counterWDeviceWCounterSet->m_Units == "");
1712  BOOST_CHECK(counterWDeviceWCounterSet->m_DeviceUid == device->m_Uid);
1713  BOOST_CHECK(counterWDeviceWCounterSet->m_CounterSetUid == counterSet->m_Uid);
1714  BOOST_CHECK(category->m_Counters.size() == 28);
1715  BOOST_CHECK(category->m_Counters.back() == counterWDeviceWCounterSet->m_Uid);
1716 
1717  // Register another category for testing
1718  const std::string anotherCategoryName = "some_other_category";
1719  const Category* anotherCategory = nullptr;
1720  BOOST_CHECK_NO_THROW(anotherCategory = counterDirectory.RegisterCategory(anotherCategoryName));
1721  BOOST_CHECK(counterDirectory.GetCategoryCount() == 2);
1722  BOOST_CHECK(anotherCategory);
1723  BOOST_CHECK(anotherCategory != category);
1724  BOOST_CHECK(anotherCategory->m_Name == anotherCategoryName);
1725  BOOST_CHECK(anotherCategory->m_Counters.empty());
1726 
1727  // Register a counter to the other category
1728  const Counter* anotherCounter = nullptr;
1729  BOOST_CHECK_NO_THROW(anotherCounter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID, 24,
1730  anotherCategoryName, 1, 0, .00043f,
1731  "valid name", "valid description",
1732  armnn::EmptyOptional(), // Units
1733  armnn::EmptyOptional(), // Number of cores
1734  device->m_Uid, // Device UID
1735  counterSet->m_Uid)); // Counter set UID
1736  BOOST_CHECK(counterDirectory.GetCounterCount() == 29);
1737  BOOST_CHECK(anotherCounter);
1738  BOOST_CHECK(anotherCounter->m_MaxCounterUid == anotherCounter->m_Uid);
1739  BOOST_CHECK(anotherCounter->m_Class == 1);
1740  BOOST_CHECK(anotherCounter->m_Interpolation == 0);
1741  BOOST_CHECK(anotherCounter->m_Multiplier == .00043f);
1742  BOOST_CHECK(anotherCounter->m_Name == "valid name");
1743  BOOST_CHECK(anotherCounter->m_Description == "valid description");
1744  BOOST_CHECK(anotherCounter->m_Units == "");
1745  BOOST_CHECK(anotherCounter->m_DeviceUid == device->m_Uid);
1746  BOOST_CHECK(anotherCounter->m_CounterSetUid == counterSet->m_Uid);
1747  BOOST_CHECK(anotherCategory->m_Counters.size() == 1);
1748  BOOST_CHECK(anotherCategory->m_Counters.back() == anotherCounter->m_Uid);
1749 }
1750 
1751 BOOST_AUTO_TEST_CASE(CounterSelectionCommandHandlerParseData)
1752 {
1753  using boost::numeric_cast;
1754 
1755  ProfilingStateMachine profilingStateMachine;
1756 
1757  class TestCaptureThread : public IPeriodicCounterCapture
1758  {
1759  void Start() override
1760  {}
1761  void Stop() override
1762  {}
1763  };
1764 
1765  class TestReadCounterValues : public IReadCounterValues
1766  {
1767  bool IsCounterRegistered(uint16_t counterUid) const override
1768  {
1769  armnn::IgnoreUnused(counterUid);
1770  return true;
1771  }
1772  uint16_t GetCounterCount() const override
1773  {
1774  return 0;
1775  }
1776  uint32_t GetAbsoluteCounterValue(uint16_t counterUid) const override
1777  {
1778  armnn::IgnoreUnused(counterUid);
1779  return 0;
1780  }
1781  uint32_t GetDeltaCounterValue(uint16_t counterUid) override
1782  {
1783  armnn::IgnoreUnused(counterUid);
1784  return 0;
1785  }
1786  };
1787  const uint32_t familyId = 0;
1788  const uint32_t packetId = 0x40000;
1789 
1790  uint32_t version = 1;
1791  const std::unordered_map<armnn::BackendId,
1792  std::shared_ptr<armnn::profiling::IBackendProfilingContext>> backendProfilingContext;
1793  CounterIdMap counterIdMap;
1794  Holder holder;
1795  TestCaptureThread captureThread;
1796  TestReadCounterValues readCounterValues;
1797  MockBufferManager mockBuffer(512);
1798  SendCounterPacket sendCounterPacket(mockBuffer);
1799  SendThread sendThread(profilingStateMachine, mockBuffer, sendCounterPacket);
1800 
1801  uint32_t sizeOfUint32 = numeric_cast<uint32_t>(sizeof(uint32_t));
1802  uint32_t sizeOfUint16 = numeric_cast<uint32_t>(sizeof(uint16_t));
1803 
1804  // Data with period and counters
1805  uint32_t period1 = armnn::LOWEST_CAPTURE_PERIOD;
1806  uint32_t dataLength1 = 8;
1807  uint32_t offset = 0;
1808 
1809  std::unique_ptr<unsigned char[]> uniqueData1 = std::make_unique<unsigned char[]>(dataLength1);
1810  unsigned char* data1 = reinterpret_cast<unsigned char*>(uniqueData1.get());
1811 
1812  WriteUint32(data1, offset, period1);
1813  offset += sizeOfUint32;
1814  WriteUint16(data1, offset, 4000);
1815  offset += sizeOfUint16;
1816  WriteUint16(data1, offset, 5000);
1817 
1818  arm::pipe::Packet packetA(packetId, dataLength1, uniqueData1);
1819 
1820  PeriodicCounterSelectionCommandHandler commandHandler(familyId, packetId, version, backendProfilingContext,
1821  counterIdMap, holder, 10000u, captureThread,
1822  readCounterValues, sendCounterPacket, profilingStateMachine);
1823 
1824  profilingStateMachine.TransitionToState(ProfilingState::Uninitialised);
1825  BOOST_CHECK_THROW(commandHandler(packetA), armnn::RuntimeException);
1826  profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
1827  BOOST_CHECK_THROW(commandHandler(packetA), armnn::RuntimeException);
1828  profilingStateMachine.TransitionToState(ProfilingState::WaitingForAck);
1829  BOOST_CHECK_THROW(commandHandler(packetA), armnn::RuntimeException);
1830  profilingStateMachine.TransitionToState(ProfilingState::Active);
1831  BOOST_CHECK_NO_THROW(commandHandler(packetA));
1832 
1833  const std::vector<uint16_t> counterIdsA = holder.GetCaptureData().GetCounterIds();
1834 
1835  BOOST_TEST(holder.GetCaptureData().GetCapturePeriod() == period1);
1836  BOOST_TEST(counterIdsA.size() == 2);
1837  BOOST_TEST(counterIdsA[0] == 4000);
1838  BOOST_TEST(counterIdsA[1] == 5000);
1839 
1840  auto readBuffer = mockBuffer.GetReadableBuffer();
1841 
1842  offset = 0;
1843 
1844  uint32_t headerWord0 = ReadUint32(readBuffer, offset);
1845  offset += sizeOfUint32;
1846  uint32_t headerWord1 = ReadUint32(readBuffer, offset);
1847  offset += sizeOfUint32;
1848  uint32_t period = ReadUint32(readBuffer, offset);
1849 
1850  BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family
1851  BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 4); // packet id
1852  BOOST_TEST(headerWord1 == 8); // data length
1853  BOOST_TEST(period == armnn::LOWEST_CAPTURE_PERIOD); // capture period
1854 
1855  uint16_t counterId = 0;
1856  offset += sizeOfUint32;
1857  counterId = ReadUint16(readBuffer, offset);
1858  BOOST_TEST(counterId == 4000);
1859  offset += sizeOfUint16;
1860  counterId = ReadUint16(readBuffer, offset);
1861  BOOST_TEST(counterId == 5000);
1862 
1863  mockBuffer.MarkRead(readBuffer);
1864 
1865  // Data with period only
1866  uint32_t period2 = 9000; // We'll specify a value below LOWEST_CAPTURE_PERIOD. It should be pulled upwards.
1867  uint32_t dataLength2 = 4;
1868 
1869  std::unique_ptr<unsigned char[]> uniqueData2 = std::make_unique<unsigned char[]>(dataLength2);
1870 
1871  WriteUint32(reinterpret_cast<unsigned char*>(uniqueData2.get()), 0, period2);
1872 
1873  arm::pipe::Packet packetB(packetId, dataLength2, uniqueData2);
1874 
1875  commandHandler(packetB);
1876 
1877  const std::vector<uint16_t> counterIdsB = holder.GetCaptureData().GetCounterIds();
1878 
1879  // Value should have been pulled up from 9000 to LOWEST_CAPTURE_PERIOD.
1881  BOOST_TEST(counterIdsB.size() == 0);
1882 
1883  readBuffer = mockBuffer.GetReadableBuffer();
1884 
1885  offset = 0;
1886 
1887  headerWord0 = ReadUint32(readBuffer, offset);
1888  offset += sizeOfUint32;
1889  headerWord1 = ReadUint32(readBuffer, offset);
1890  offset += sizeOfUint32;
1891  period = ReadUint32(readBuffer, offset);
1892 
1893  BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family
1894  BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 4); // packet id
1895  BOOST_TEST(headerWord1 == 4); // data length
1896  BOOST_TEST(period == armnn::LOWEST_CAPTURE_PERIOD); // capture period
1897 }
1898 
1899 BOOST_AUTO_TEST_CASE(CheckTimelineActivationAndDeactivation)
1900 {
1901  class TestReportStructure : public IReportStructure
1902  {
1903  public:
1904  virtual void ReportStructure() override
1905  {
1906  m_ReportStructureCalled = true;
1907  }
1908 
1909  bool m_ReportStructureCalled = false;
1910  };
1911 
1912  class TestNotifyBackends : public INotifyBackends
1913  {
1914  public:
1915  TestNotifyBackends() : m_timelineReporting(false) {}
1916  virtual void NotifyBackendsForTimelineReporting() override
1917  {
1918  m_TestNotifyBackendsCalled = m_timelineReporting.load();
1919  }
1920 
1921  bool m_TestNotifyBackendsCalled = false;
1922  std::atomic<bool> m_timelineReporting;
1923  };
1924 
1925  arm::pipe::PacketVersionResolver packetVersionResolver;
1926 
1927  BufferManager bufferManager(512);
1928  SendTimelinePacket sendTimelinePacket(bufferManager);
1929  ProfilingStateMachine stateMachine;
1930  TestReportStructure testReportStructure;
1931  TestNotifyBackends testNotifyBackends;
1932 
1933  profiling::ActivateTimelineReportingCommandHandler activateTimelineReportingCommandHandler(0,
1934  6,
1935  packetVersionResolver.ResolvePacketVersion(0, 6)
1936  .GetEncodedValue(),
1937  sendTimelinePacket,
1938  stateMachine,
1939  testReportStructure,
1940  testNotifyBackends.m_timelineReporting,
1941  testNotifyBackends);
1942 
1943  // Write an "ActivateTimelineReporting" packet into the mock profiling connection, to simulate an input from an
1944  // external profiling service
1945  const uint32_t packetFamily1 = 0;
1946  const uint32_t packetId1 = 6;
1947  uint32_t packetHeader1 = ConstructHeader(packetFamily1, packetId1);
1948 
1949  // Create the ActivateTimelineReportingPacket
1950  arm::pipe::Packet ActivateTimelineReportingPacket(packetHeader1); // Length == 0
1951 
1952  BOOST_CHECK_THROW(
1953  activateTimelineReportingCommandHandler.operator()(ActivateTimelineReportingPacket), armnn::Exception);
1954 
1955  stateMachine.TransitionToState(ProfilingState::NotConnected);
1956  BOOST_CHECK_THROW(
1957  activateTimelineReportingCommandHandler.operator()(ActivateTimelineReportingPacket), armnn::Exception);
1958 
1959  stateMachine.TransitionToState(ProfilingState::WaitingForAck);
1960  BOOST_CHECK_THROW(
1961  activateTimelineReportingCommandHandler.operator()(ActivateTimelineReportingPacket), armnn::Exception);
1962 
1963  stateMachine.TransitionToState(ProfilingState::Active);
1964  activateTimelineReportingCommandHandler.operator()(ActivateTimelineReportingPacket);
1965 
1966  BOOST_CHECK(testReportStructure.m_ReportStructureCalled);
1967  BOOST_CHECK(testNotifyBackends.m_TestNotifyBackendsCalled);
1968  BOOST_CHECK(testNotifyBackends.m_timelineReporting.load());
1969 
1970  DeactivateTimelineReportingCommandHandler deactivateTimelineReportingCommandHandler(0,
1971  7,
1972  packetVersionResolver.ResolvePacketVersion(0, 7).GetEncodedValue(),
1973  testNotifyBackends.m_timelineReporting,
1974  stateMachine,
1975  testNotifyBackends);
1976 
1977  const uint32_t packetFamily2 = 0;
1978  const uint32_t packetId2 = 7;
1979  uint32_t packetHeader2 = ConstructHeader(packetFamily2, packetId2);
1980 
1981  // Create the DeactivateTimelineReportingPacket
1982  arm::pipe::Packet deactivateTimelineReportingPacket(packetHeader2); // Length == 0
1983 
1984  stateMachine.Reset();
1985  BOOST_CHECK_THROW(
1986  deactivateTimelineReportingCommandHandler.operator()(deactivateTimelineReportingPacket), armnn::Exception);
1987 
1988  stateMachine.TransitionToState(ProfilingState::NotConnected);
1989  BOOST_CHECK_THROW(
1990  deactivateTimelineReportingCommandHandler.operator()(deactivateTimelineReportingPacket), armnn::Exception);
1991 
1992  stateMachine.TransitionToState(ProfilingState::WaitingForAck);
1993  BOOST_CHECK_THROW(
1994  deactivateTimelineReportingCommandHandler.operator()(deactivateTimelineReportingPacket), armnn::Exception);
1995 
1996  stateMachine.TransitionToState(ProfilingState::Active);
1997  deactivateTimelineReportingCommandHandler.operator()(deactivateTimelineReportingPacket);
1998 
1999  BOOST_CHECK(!testNotifyBackends.m_TestNotifyBackendsCalled);
2000  BOOST_CHECK(!testNotifyBackends.m_timelineReporting.load());
2001 }
2002 
2003 BOOST_AUTO_TEST_CASE(CheckProfilingServiceNotActive)
2004 {
2005  using namespace armnn;
2006  using namespace armnn::profiling;
2007 
2008  // Create runtime in which the test will run
2010  options.m_ProfilingOptions.m_EnableProfiling = true;
2011 
2012  armnn::Runtime runtime(options);
2013  profiling::ProfilingServiceRuntimeHelper profilingServiceHelper(GetProfilingService(&runtime));
2014  profilingServiceHelper.ForceTransitionToState(ProfilingState::NotConnected);
2015  profilingServiceHelper.ForceTransitionToState(ProfilingState::WaitingForAck);
2016  profilingServiceHelper.ForceTransitionToState(ProfilingState::Active);
2017 
2018  profiling::BufferManager& bufferManager = profilingServiceHelper.GetProfilingBufferManager();
2019  auto readableBuffer = bufferManager.GetReadableBuffer();
2020 
2021  // Profiling is enabled, the post-optimisation structure should be created
2022  BOOST_CHECK(readableBuffer == nullptr);
2023 }
2024 
2025 BOOST_AUTO_TEST_CASE(CheckConnectionAcknowledged)
2026 {
2027  using boost::numeric_cast;
2028 
2029  const uint32_t packetFamilyId = 0;
2030  const uint32_t connectionPacketId = 0x10000;
2031  const uint32_t version = 1;
2032 
2033  uint32_t sizeOfUint32 = numeric_cast<uint32_t>(sizeof(uint32_t));
2034  uint32_t sizeOfUint16 = numeric_cast<uint32_t>(sizeof(uint16_t));
2035 
2036  // Data with period and counters
2037  uint32_t period1 = 10;
2038  uint32_t dataLength1 = 8;
2039  uint32_t offset = 0;
2040 
2041  std::unique_ptr<unsigned char[]> uniqueData1 = std::make_unique<unsigned char[]>(dataLength1);
2042  unsigned char* data1 = reinterpret_cast<unsigned char*>(uniqueData1.get());
2043 
2044  WriteUint32(data1, offset, period1);
2045  offset += sizeOfUint32;
2046  WriteUint16(data1, offset, 4000);
2047  offset += sizeOfUint16;
2048  WriteUint16(data1, offset, 5000);
2049 
2050  arm::pipe::Packet packetA(connectionPacketId, dataLength1, uniqueData1);
2051 
2053  BOOST_CHECK(profilingState.GetCurrentState() == ProfilingState::Uninitialised);
2054  CounterDirectory counterDirectory;
2055  MockBufferManager mockBuffer(1024);
2056  SendCounterPacket sendCounterPacket(mockBuffer);
2057  SendThread sendThread(profilingState, mockBuffer, sendCounterPacket);
2058  SendTimelinePacket sendTimelinePacket(mockBuffer);
2059  MockProfilingServiceStatus mockProfilingServiceStatus;
2060 
2061  ConnectionAcknowledgedCommandHandler commandHandler(packetFamilyId,
2062  connectionPacketId,
2063  version,
2064  counterDirectory,
2065  sendCounterPacket,
2066  sendTimelinePacket,
2067  profilingState,
2068  mockProfilingServiceStatus);
2069 
2070  // command handler received packet on ProfilingState::Uninitialised
2071  BOOST_CHECK_THROW(commandHandler(packetA), armnn::Exception);
2072 
2074  BOOST_CHECK(profilingState.GetCurrentState() == ProfilingState::NotConnected);
2075  // command handler received packet on ProfilingState::NotConnected
2076  BOOST_CHECK_THROW(commandHandler(packetA), armnn::Exception);
2077 
2079  BOOST_CHECK(profilingState.GetCurrentState() == ProfilingState::WaitingForAck);
2080  // command handler received packet on ProfilingState::WaitingForAck
2081  BOOST_CHECK_NO_THROW(commandHandler(packetA));
2082  BOOST_CHECK(profilingState.GetCurrentState() == ProfilingState::Active);
2083 
2084  // command handler received packet on ProfilingState::Active
2085  BOOST_CHECK_NO_THROW(commandHandler(packetA));
2086  BOOST_CHECK(profilingState.GetCurrentState() == ProfilingState::Active);
2087 
2088  // command handler received different packet
2089  const uint32_t differentPacketId = 0x40000;
2090  arm::pipe::Packet packetB(differentPacketId, dataLength1, uniqueData1);
2093  ConnectionAcknowledgedCommandHandler differentCommandHandler(packetFamilyId,
2094  differentPacketId,
2095  version,
2096  counterDirectory,
2097  sendCounterPacket,
2098  sendTimelinePacket,
2099  profilingState,
2100  mockProfilingServiceStatus);
2101  BOOST_CHECK_THROW(differentCommandHandler(packetB), armnn::Exception);
2102 }
2103 
2104 BOOST_AUTO_TEST_CASE(CheckSocketConnectionException)
2105 {
2106  // Check that creating a SocketProfilingConnection armnnProfiling in an exception as the Gator UDS doesn't exist.
2107  BOOST_CHECK_THROW(new SocketProfilingConnection(), arm::pipe::SocketConnectionException);
2108 }
2109 
2110 BOOST_AUTO_TEST_CASE(CheckSocketConnectionException2)
2111 {
2112  try
2113  {
2115  }
2116  catch (const arm::pipe::SocketConnectionException& ex)
2117  {
2118  BOOST_CHECK(ex.GetSocketFd() == 0);
2119  BOOST_CHECK(ex.GetErrorNo() == 111);
2120  BOOST_CHECK(ex.what()
2121  == std::string("SocketProfilingConnection: Cannot connect to stream socket: Connection refused"));
2122  }
2123 }
2124 
2125 BOOST_AUTO_TEST_CASE(SwTraceIsValidCharTest)
2126 {
2127  // Only ASCII 7-bit encoding supported
2128  for (unsigned char c = 0; c < 128; c++)
2129  {
2130  BOOST_CHECK(arm::pipe::SwTraceCharPolicy::IsValidChar(c));
2131  }
2132 
2133  // Not ASCII
2134  for (unsigned char c = 255; c >= 128; c++)
2135  {
2136  BOOST_CHECK(!arm::pipe::SwTraceCharPolicy::IsValidChar(c));
2137  }
2138 }
2139 
2140 BOOST_AUTO_TEST_CASE(SwTraceIsValidNameCharTest)
2141 {
2142  // Only alpha-numeric and underscore ASCII 7-bit encoding supported
2143  const unsigned char validChars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
2144  for (unsigned char i = 0; i < sizeof(validChars) / sizeof(validChars[0]) - 1; i++)
2145  {
2146  BOOST_CHECK(arm::pipe::SwTraceNameCharPolicy::IsValidChar(validChars[i]));
2147  }
2148 
2149  // Non alpha-numeric chars
2150  for (unsigned char c = 0; c < 48; c++)
2151  {
2152  BOOST_CHECK(!arm::pipe::SwTraceNameCharPolicy::IsValidChar(c));
2153  }
2154  for (unsigned char c = 58; c < 65; c++)
2155  {
2156  BOOST_CHECK(!arm::pipe::SwTraceNameCharPolicy::IsValidChar(c));
2157  }
2158  for (unsigned char c = 91; c < 95; c++)
2159  {
2160  BOOST_CHECK(!arm::pipe::SwTraceNameCharPolicy::IsValidChar(c));
2161  }
2162  for (unsigned char c = 96; c < 97; c++)
2163  {
2164  BOOST_CHECK(!arm::pipe::SwTraceNameCharPolicy::IsValidChar(c));
2165  }
2166  for (unsigned char c = 123; c < 128; c++)
2167  {
2168  BOOST_CHECK(!arm::pipe::SwTraceNameCharPolicy::IsValidChar(c));
2169  }
2170 
2171  // Not ASCII
2172  for (unsigned char c = 255; c >= 128; c++)
2173  {
2174  BOOST_CHECK(!arm::pipe::SwTraceNameCharPolicy::IsValidChar(c));
2175  }
2176 }
2177 
2178 BOOST_AUTO_TEST_CASE(IsValidSwTraceStringTest)
2179 {
2180  // Valid SWTrace strings
2181  BOOST_CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>(""));
2182  BOOST_CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("_"));
2183  BOOST_CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("0123"));
2184  BOOST_CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("valid_string"));
2185  BOOST_CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("VALID_string_456"));
2186  BOOST_CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>(" "));
2187  BOOST_CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("valid string"));
2188  BOOST_CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("!$%"));
2189  BOOST_CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("valid|\\~string#123"));
2190 
2191  // Invalid SWTrace strings
2192  BOOST_CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("€£"));
2193  BOOST_CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("invalid‡string"));
2194  BOOST_CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>("12Ž34"));
2195 }
2196 
2197 BOOST_AUTO_TEST_CASE(IsValidSwTraceNameStringTest)
2198 {
2199  // Valid SWTrace name strings
2200  BOOST_CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>(""));
2201  BOOST_CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("_"));
2202  BOOST_CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("0123"));
2203  BOOST_CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("valid_string"));
2204  BOOST_CHECK(arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("VALID_string_456"));
2205 
2206  // Invalid SWTrace name strings
2207  BOOST_CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>(" "));
2208  BOOST_CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("invalid string"));
2209  BOOST_CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("!$%"));
2210  BOOST_CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("invalid|\\~string#123"));
2211  BOOST_CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("€£"));
2212  BOOST_CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("invalid‡string"));
2213  BOOST_CHECK(!arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>("12Ž34"));
2214 }
2215 
2216 template <typename SwTracePolicy>
2217 void StringToSwTraceStringTestHelper(const std::string& testString, std::vector<uint32_t> buffer, size_t expectedSize)
2218 {
2219  // Convert the test string to a SWTrace string
2220  BOOST_CHECK(arm::pipe::StringToSwTraceString<SwTracePolicy>(testString, buffer));
2221 
2222  // The buffer must contain at least the length of the string
2223  BOOST_CHECK(!buffer.empty());
2224 
2225  // The buffer must be of the expected size (in words)
2226  BOOST_CHECK(buffer.size() == expectedSize);
2227 
2228  // The first word of the byte must be the length of the string including the null-terminator
2229  BOOST_CHECK(buffer[0] == testString.size() + 1);
2230 
2231  // The contents of the buffer must match the test string
2232  BOOST_CHECK(std::memcmp(testString.data(), buffer.data() + 1, testString.size()) == 0);
2233 
2234  // The buffer must include the null-terminator at the end of the string
2235  size_t nullTerminatorIndex = sizeof(uint32_t) + testString.size();
2236  BOOST_CHECK(reinterpret_cast<unsigned char*>(buffer.data())[nullTerminatorIndex] == '\0');
2237 }
2238 
2239 BOOST_AUTO_TEST_CASE(StringToSwTraceStringTest)
2240 {
2241  std::vector<uint32_t> buffer;
2242 
2243  // Valid SWTrace strings (expected size in words)
2244  StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>("", buffer, 2);
2245  StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>("_", buffer, 2);
2246  StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>("0123", buffer, 3);
2247  StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>("valid_string", buffer, 5);
2248  StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>("VALID_string_456", buffer, 6);
2249  StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>(" ", buffer, 2);
2250  StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>("valid string", buffer, 5);
2251  StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>("!$%", buffer, 2);
2252  StringToSwTraceStringTestHelper<arm::pipe::SwTraceCharPolicy>("valid|\\~string#123", buffer, 6);
2253 
2254  // Invalid SWTrace strings
2255  BOOST_CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceCharPolicy>("€£", buffer));
2256  BOOST_CHECK(buffer.empty());
2257  BOOST_CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceCharPolicy>("invalid‡string", buffer));
2258  BOOST_CHECK(buffer.empty());
2259  BOOST_CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceCharPolicy>("12Ž34", buffer));
2260  BOOST_CHECK(buffer.empty());
2261 }
2262 
2263 BOOST_AUTO_TEST_CASE(StringToSwTraceNameStringTest)
2264 {
2265  std::vector<uint32_t> buffer;
2266 
2267  // Valid SWTrace namestrings (expected size in words)
2268  StringToSwTraceStringTestHelper<arm::pipe::SwTraceNameCharPolicy>("", buffer, 2);
2269  StringToSwTraceStringTestHelper<arm::pipe::SwTraceNameCharPolicy>("_", buffer, 2);
2270  StringToSwTraceStringTestHelper<arm::pipe::SwTraceNameCharPolicy>("0123", buffer, 3);
2271  StringToSwTraceStringTestHelper<arm::pipe::SwTraceNameCharPolicy>("valid_string", buffer, 5);
2272  StringToSwTraceStringTestHelper<arm::pipe::SwTraceNameCharPolicy>("VALID_string_456", buffer, 6);
2273 
2274  // Invalid SWTrace namestrings
2275  BOOST_CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceNameCharPolicy>(" ", buffer));
2276  BOOST_CHECK(buffer.empty());
2277  BOOST_CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceNameCharPolicy>("invalid string", buffer));
2278  BOOST_CHECK(buffer.empty());
2279  BOOST_CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceNameCharPolicy>("!$%", buffer));
2280  BOOST_CHECK(buffer.empty());
2281  BOOST_CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceNameCharPolicy>("invalid|\\~string#123", buffer));
2282  BOOST_CHECK(buffer.empty());
2283  BOOST_CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceNameCharPolicy>("€£", buffer));
2284  BOOST_CHECK(buffer.empty());
2285  BOOST_CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceNameCharPolicy>("invalid‡string", buffer));
2286  BOOST_CHECK(buffer.empty());
2287  BOOST_CHECK(!arm::pipe::StringToSwTraceString<arm::pipe::SwTraceNameCharPolicy>("12Ž34", buffer));
2288  BOOST_CHECK(buffer.empty());
2289 }
2290 
2291 BOOST_AUTO_TEST_CASE(CheckPeriodicCounterCaptureThread)
2292 {
2293  class CaptureReader : public IReadCounterValues
2294  {
2295  public:
2296  CaptureReader(uint16_t counterSize)
2297  {
2298  for (uint16_t i = 0; i < counterSize; ++i)
2299  {
2300  m_Data[i] = 0;
2301  }
2302  m_CounterSize = counterSize;
2303  }
2304  //not used
2305  bool IsCounterRegistered(uint16_t counterUid) const override
2306  {
2307  armnn::IgnoreUnused(counterUid);
2308  return false;
2309  }
2310 
2311  uint16_t GetCounterCount() const override
2312  {
2313  return m_CounterSize;
2314  }
2315 
2316  uint32_t GetAbsoluteCounterValue(uint16_t counterUid) const override
2317  {
2318  if (counterUid > m_CounterSize)
2319  {
2320  BOOST_FAIL("Invalid counter Uid");
2321  }
2322  return m_Data.at(counterUid).load();
2323  }
2324 
2325  uint32_t GetDeltaCounterValue(uint16_t counterUid) override
2326  {
2327  if (counterUid > m_CounterSize)
2328  {
2329  BOOST_FAIL("Invalid counter Uid");
2330  }
2331  return m_Data.at(counterUid).load();
2332  }
2333 
2334  void SetCounterValue(uint16_t counterUid, uint32_t value)
2335  {
2336  if (counterUid > m_CounterSize)
2337  {
2338  BOOST_FAIL("Invalid counter Uid");
2339  }
2340  m_Data.at(counterUid).store(value);
2341  }
2342 
2343  private:
2344  std::unordered_map<uint16_t, std::atomic<uint32_t>> m_Data;
2345  uint16_t m_CounterSize;
2346  };
2347 
2348  ProfilingStateMachine profilingStateMachine;
2349 
2350  const std::unordered_map<armnn::BackendId,
2351  std::shared_ptr<armnn::profiling::IBackendProfilingContext>> backendProfilingContext;
2352  CounterIdMap counterIdMap;
2353  Holder data;
2354  std::vector<uint16_t> captureIds1 = { 0, 1 };
2355  std::vector<uint16_t> captureIds2;
2356 
2357  MockBufferManager mockBuffer(512);
2358  SendCounterPacket sendCounterPacket(mockBuffer);
2359  SendThread sendThread(profilingStateMachine, mockBuffer, sendCounterPacket);
2360 
2361  std::vector<uint16_t> counterIds;
2362  CaptureReader captureReader(2);
2363 
2364  unsigned int valueA = 10;
2365  unsigned int valueB = 15;
2366  unsigned int numSteps = 5;
2367 
2368  PeriodicCounterCapture periodicCounterCapture(std::ref(data), std::ref(sendCounterPacket), captureReader,
2369  counterIdMap, backendProfilingContext);
2370 
2371  for (unsigned int i = 0; i < numSteps; ++i)
2372  {
2373  data.SetCaptureData(1, captureIds1, {});
2374  captureReader.SetCounterValue(0, valueA * (i + 1));
2375  captureReader.SetCounterValue(1, valueB * (i + 1));
2376 
2377  periodicCounterCapture.Start();
2378  periodicCounterCapture.Stop();
2379  }
2380 
2381  auto buffer = mockBuffer.GetReadableBuffer();
2382 
2383  uint32_t headerWord0 = ReadUint32(buffer, 0);
2384  uint32_t headerWord1 = ReadUint32(buffer, 4);
2385 
2386  BOOST_TEST(((headerWord0 >> 26) & 0x0000003F) == 3); // packet family
2387  BOOST_TEST(((headerWord0 >> 19) & 0x0000007F) == 0); // packet class
2388  BOOST_TEST(((headerWord0 >> 16) & 0x00000007) == 0); // packet type
2389  BOOST_TEST(headerWord1 == 20);
2390 
2391  uint32_t offset = 16;
2392  uint16_t readIndex = ReadUint16(buffer, offset);
2393  BOOST_TEST(0 == readIndex);
2394 
2395  offset += 2;
2396  uint32_t readValue = ReadUint32(buffer, offset);
2397  BOOST_TEST((valueA * numSteps) == readValue);
2398 
2399  offset += 4;
2400  readIndex = ReadUint16(buffer, offset);
2401  BOOST_TEST(1 == readIndex);
2402 
2403  offset += 2;
2404  readValue = ReadUint32(buffer, offset);
2405  BOOST_TEST((valueB * numSteps) == readValue);
2406 }
2407 
2408 BOOST_AUTO_TEST_CASE(RequestCounterDirectoryCommandHandlerTest1)
2409 {
2410  using boost::numeric_cast;
2411 
2412  const uint32_t familyId = 0;
2413  const uint32_t packetId = 3;
2414  const uint32_t version = 1;
2415  ProfilingStateMachine profilingStateMachine;
2416  CounterDirectory counterDirectory;
2417  MockBufferManager mockBuffer1(1024);
2418  SendCounterPacket sendCounterPacket(mockBuffer1);
2419  SendThread sendThread(profilingStateMachine, mockBuffer1, sendCounterPacket);
2420  MockBufferManager mockBuffer2(1024);
2421  SendTimelinePacket sendTimelinePacket(mockBuffer2);
2422  RequestCounterDirectoryCommandHandler commandHandler(familyId, packetId, version, counterDirectory,
2423  sendCounterPacket, sendTimelinePacket, profilingStateMachine);
2424 
2425  const uint32_t wrongPacketId = 47;
2426  const uint32_t wrongHeader = (wrongPacketId & 0x000003FF) << 16;
2427 
2428  arm::pipe::Packet wrongPacket(wrongHeader);
2429 
2430  profilingStateMachine.TransitionToState(ProfilingState::Uninitialised);
2431  BOOST_CHECK_THROW(commandHandler(wrongPacket), armnn::RuntimeException); // Wrong profiling state
2432  profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
2433  BOOST_CHECK_THROW(commandHandler(wrongPacket), armnn::RuntimeException); // Wrong profiling state
2434  profilingStateMachine.TransitionToState(ProfilingState::WaitingForAck);
2435  BOOST_CHECK_THROW(commandHandler(wrongPacket), armnn::RuntimeException); // Wrong profiling state
2436  profilingStateMachine.TransitionToState(ProfilingState::Active);
2437  BOOST_CHECK_THROW(commandHandler(wrongPacket), armnn::InvalidArgumentException); // Wrong packet
2438 
2439  const uint32_t rightHeader = (packetId & 0x000003FF) << 16;
2440 
2441  arm::pipe::Packet rightPacket(rightHeader);
2442 
2443  BOOST_CHECK_NO_THROW(commandHandler(rightPacket)); // Right packet
2444 
2445  auto readBuffer1 = mockBuffer1.GetReadableBuffer();
2446 
2447  uint32_t header1Word0 = ReadUint32(readBuffer1, 0);
2448  uint32_t header1Word1 = ReadUint32(readBuffer1, 4);
2449 
2450  // Counter directory packet
2451  BOOST_TEST(((header1Word0 >> 26) & 0x0000003F) == 0); // packet family
2452  BOOST_TEST(((header1Word0 >> 16) & 0x000003FF) == 2); // packet id
2453  BOOST_TEST(header1Word1 == 24); // data length
2454 
2455  uint32_t bodyHeader1Word0 = ReadUint32(readBuffer1, 8);
2456  uint16_t deviceRecordCount = numeric_cast<uint16_t>(bodyHeader1Word0 >> 16);
2457  BOOST_TEST(deviceRecordCount == 0); // device_records_count
2458 
2459  auto readBuffer2 = mockBuffer2.GetReadableBuffer();
2460 
2461  uint32_t header2Word0 = ReadUint32(readBuffer2, 0);
2462  uint32_t header2Word1 = ReadUint32(readBuffer2, 4);
2463 
2464  // Timeline message directory packet
2465  BOOST_TEST(((header2Word0 >> 26) & 0x0000003F) == 1); // packet family
2466  BOOST_TEST(((header2Word0 >> 16) & 0x000003FF) == 0); // packet id
2467  BOOST_TEST(header2Word1 == 443); // data length
2468 }
2469 
2470 BOOST_AUTO_TEST_CASE(RequestCounterDirectoryCommandHandlerTest2)
2471 {
2472  using boost::numeric_cast;
2473 
2474  const uint32_t familyId = 0;
2475  const uint32_t packetId = 3;
2476  const uint32_t version = 1;
2477  ProfilingStateMachine profilingStateMachine;
2478  CounterDirectory counterDirectory;
2479  MockBufferManager mockBuffer1(1024);
2480  SendCounterPacket sendCounterPacket(mockBuffer1);
2481  SendThread sendThread(profilingStateMachine, mockBuffer1, sendCounterPacket);
2482  MockBufferManager mockBuffer2(1024);
2483  SendTimelinePacket sendTimelinePacket(mockBuffer2);
2484  RequestCounterDirectoryCommandHandler commandHandler(familyId, packetId, version, counterDirectory,
2485  sendCounterPacket, sendTimelinePacket, profilingStateMachine);
2486  const uint32_t header = (packetId & 0x000003FF) << 16;
2487  const arm::pipe::Packet packet(header);
2488 
2489  const Device* device = counterDirectory.RegisterDevice("deviceA", 1);
2490  BOOST_CHECK(device != nullptr);
2491  const CounterSet* counterSet = counterDirectory.RegisterCounterSet("countersetA");
2492  BOOST_CHECK(counterSet != nullptr);
2493  counterDirectory.RegisterCategory("categoryA");
2494  counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID, 24,
2495  "categoryA", 0, 1, 2.0f, "counterA", "descA");
2496  counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID, 25,
2497  "categoryA", 1, 1, 3.0f, "counterB", "descB");
2498 
2499  profilingStateMachine.TransitionToState(ProfilingState::Uninitialised);
2500  BOOST_CHECK_THROW(commandHandler(packet), armnn::RuntimeException); // Wrong profiling state
2501  profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
2502  BOOST_CHECK_THROW(commandHandler(packet), armnn::RuntimeException); // Wrong profiling state
2503  profilingStateMachine.TransitionToState(ProfilingState::WaitingForAck);
2504  BOOST_CHECK_THROW(commandHandler(packet), armnn::RuntimeException); // Wrong profiling state
2505  profilingStateMachine.TransitionToState(ProfilingState::Active);
2506  BOOST_CHECK_NO_THROW(commandHandler(packet));
2507 
2508  auto readBuffer1 = mockBuffer1.GetReadableBuffer();
2509 
2510  const uint32_t header1Word0 = ReadUint32(readBuffer1, 0);
2511  const uint32_t header1Word1 = ReadUint32(readBuffer1, 4);
2512 
2513  BOOST_TEST(((header1Word0 >> 26) & 0x0000003F) == 0); // packet family
2514  BOOST_TEST(((header1Word0 >> 16) & 0x000003FF) == 2); // packet id
2515  BOOST_TEST(header1Word1 == 236); // data length
2516 
2517  const uint32_t bodyHeaderSizeBytes = bodyHeaderSize * sizeof(uint32_t);
2518 
2519  const uint32_t bodyHeader1Word0 = ReadUint32(readBuffer1, 8);
2520  const uint32_t bodyHeader1Word1 = ReadUint32(readBuffer1, 12);
2521  const uint32_t bodyHeader1Word2 = ReadUint32(readBuffer1, 16);
2522  const uint32_t bodyHeader1Word3 = ReadUint32(readBuffer1, 20);
2523  const uint32_t bodyHeader1Word4 = ReadUint32(readBuffer1, 24);
2524  const uint32_t bodyHeader1Word5 = ReadUint32(readBuffer1, 28);
2525  const uint16_t deviceRecordCount = numeric_cast<uint16_t>(bodyHeader1Word0 >> 16);
2526  const uint16_t counterSetRecordCount = numeric_cast<uint16_t>(bodyHeader1Word2 >> 16);
2527  const uint16_t categoryRecordCount = numeric_cast<uint16_t>(bodyHeader1Word4 >> 16);
2528  BOOST_TEST(deviceRecordCount == 1); // device_records_count
2529  BOOST_TEST(bodyHeader1Word1 == 0 + bodyHeaderSizeBytes); // device_records_pointer_table_offset
2530  BOOST_TEST(counterSetRecordCount == 1); // counter_set_count
2531  BOOST_TEST(bodyHeader1Word3 == 4 + bodyHeaderSizeBytes); // counter_set_pointer_table_offset
2532  BOOST_TEST(categoryRecordCount == 1); // categories_count
2533  BOOST_TEST(bodyHeader1Word5 == 8 + bodyHeaderSizeBytes); // categories_pointer_table_offset
2534 
2535  const uint32_t deviceRecordOffset = ReadUint32(readBuffer1, 32);
2536  BOOST_TEST(deviceRecordOffset == 12);
2537 
2538  const uint32_t counterSetRecordOffset = ReadUint32(readBuffer1, 36);
2539  BOOST_TEST(counterSetRecordOffset == 28);
2540 
2541  const uint32_t categoryRecordOffset = ReadUint32(readBuffer1, 40);
2542  BOOST_TEST(categoryRecordOffset == 48);
2543 
2544  auto readBuffer2 = mockBuffer2.GetReadableBuffer();
2545 
2546  const uint32_t header2Word0 = ReadUint32(readBuffer2, 0);
2547  const uint32_t header2Word1 = ReadUint32(readBuffer2, 4);
2548 
2549  // Timeline message directory packet
2550  BOOST_TEST(((header2Word0 >> 26) & 0x0000003F) == 1); // packet family
2551  BOOST_TEST(((header2Word0 >> 16) & 0x000003FF) == 0); // packet id
2552  BOOST_TEST(header2Word1 == 443); // data length
2553 }
2554 
2555 BOOST_AUTO_TEST_CASE(CheckProfilingServiceGoodConnectionAcknowledgedPacket)
2556 {
2557  unsigned int streamMetadataPacketsize = GetStreamMetaDataPacketSize();
2558 
2559  // Reset the profiling service to the uninitialized state
2560  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
2561  options.m_EnableProfiling = true;
2562  armnn::profiling::ProfilingService profilingService;
2563  profilingService.ResetExternalProfilingOptions(options, true);
2564 
2565  // Swap the profiling connection factory in the profiling service instance with our mock one
2566  SwapProfilingConnectionFactoryHelper helper(profilingService);
2567 
2568  // Bring the profiling service to the "WaitingForAck" state
2569  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
2570  profilingService.Update(); // Initialize the counter directory
2571  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
2572  profilingService.Update(); // Create the profiling connection
2573 
2574  // Get the mock profiling connection
2575  MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
2576  BOOST_CHECK(mockProfilingConnection);
2577 
2578  // Remove the packets received so far
2579  mockProfilingConnection->Clear();
2580 
2581  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
2582  profilingService.Update(); // Start the command handler and the send thread
2583 
2584  // Wait for the Stream Metadata packet to be sent
2585  BOOST_CHECK(helper.WaitForPacketsSent(
2586  mockProfilingConnection, PacketType::StreamMetaData, streamMetadataPacketsize) >= 1);
2587 
2588  // Write a valid "Connection Acknowledged" packet into the mock profiling connection, to simulate a valid
2589  // reply from an external profiling service
2590 
2591  // Connection Acknowledged Packet header (word 0, word 1 is always zero):
2592  // 26:31 [6] packet_family: Control Packet Family, value 0b000000
2593  // 16:25 [10] packet_id: Packet identifier, value 0b0000000001
2594  // 8:15 [8] reserved: Reserved, value 0b00000000
2595  // 0:7 [8] reserved: Reserved, value 0b00000000
2596  uint32_t packetFamily = 0;
2597  uint32_t packetId = 1;
2598  uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
2599 
2600  // Create the Connection Acknowledged Packet
2601  arm::pipe::Packet connectionAcknowledgedPacket(header);
2602 
2603  // Write the packet to the mock profiling connection
2604  mockProfilingConnection->WritePacket(std::move(connectionAcknowledgedPacket));
2605 
2606  // Wait for the counter directory packet to ensure the ConnectionAcknowledgedCommandHandler has run.
2607  BOOST_CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::CounterDirectory) == 1);
2608 
2609  // The Connection Acknowledged Command Handler should have updated the profiling state accordingly
2610  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
2611 
2612  // Reset the profiling service to stop any running thread
2613  options.m_EnableProfiling = false;
2614  profilingService.ResetExternalProfilingOptions(options, true);
2615 }
2616 
2617 BOOST_AUTO_TEST_CASE(CheckProfilingServiceGoodRequestCounterDirectoryPacket)
2618 {
2619  // Reset the profiling service to the uninitialized state
2620  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
2621  options.m_EnableProfiling = true;
2622  armnn::profiling::ProfilingService profilingService;
2623  profilingService.ResetExternalProfilingOptions(options, true);
2624 
2625  // Swap the profiling connection factory in the profiling service instance with our mock one
2626  SwapProfilingConnectionFactoryHelper helper(profilingService);
2627 
2628  // Bring the profiling service to the "Active" state
2629  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
2630  profilingService.Update(); // Initialize the counter directory
2631  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
2632  profilingService.Update(); // Create the profiling connection
2633  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
2634  profilingService.Update(); // Start the command handler and the send thread
2635 
2636  // Get the mock profiling connection
2637  MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
2638  BOOST_CHECK(mockProfilingConnection);
2639 
2640  // Force the profiling service to the "Active" state
2642  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
2643 
2644  // Write a valid "Request Counter Directory" packet into the mock profiling connection, to simulate a valid
2645  // reply from an external profiling service
2646 
2647  // Request Counter Directory packet header (word 0, word 1 is always zero):
2648  // 26:31 [6] packet_family: Control Packet Family, value 0b000000
2649  // 16:25 [10] packet_id: Packet identifier, value 0b0000000011
2650  // 8:15 [8] reserved: Reserved, value 0b00000000
2651  // 0:7 [8] reserved: Reserved, value 0b00000000
2652  uint32_t packetFamily = 0;
2653  uint32_t packetId = 3;
2654  uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
2655 
2656  // Create the Request Counter Directory packet
2657  arm::pipe::Packet requestCounterDirectoryPacket(header);
2658 
2659  // Write the packet to the mock profiling connection
2660  mockProfilingConnection->WritePacket(std::move(requestCounterDirectoryPacket));
2661 
2662  // Expecting one CounterDirectory Packet of length 652
2663  // and one TimelineMessageDirectory packet of length 451
2664  BOOST_CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::CounterDirectory, 652) == 1);
2665  BOOST_CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::TimelineMessageDirectory, 451) == 1);
2666 
2667  // The Request Counter Directory Command Handler should not have updated the profiling state
2668  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
2669 
2670  // Reset the profiling service to stop any running thread
2671  options.m_EnableProfiling = false;
2672  profilingService.ResetExternalProfilingOptions(options, true);
2673 }
2674 
2675 BOOST_AUTO_TEST_CASE(CheckProfilingServiceBadPeriodicCounterSelectionPacketInvalidCounterUid)
2676 {
2677  // Reset the profiling service to the uninitialized state
2678  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
2679  options.m_EnableProfiling = true;
2680  armnn::profiling::ProfilingService profilingService;
2681  profilingService.ResetExternalProfilingOptions(options, true);
2682 
2683  // Swap the profiling connection factory in the profiling service instance with our mock one
2684  SwapProfilingConnectionFactoryHelper helper(profilingService);
2685 
2686  // Bring the profiling service to the "Active" state
2687  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
2688  profilingService.Update(); // Initialize the counter directory
2689  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
2690  profilingService.Update(); // Create the profiling connection
2691  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
2692  profilingService.Update(); // Start the command handler and the send thread
2693 
2694  // Get the mock profiling connection
2695  MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
2696  BOOST_CHECK(mockProfilingConnection);
2697 
2698  // Force the profiling service to the "Active" state
2700  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
2701 
2702  // Remove the packets received so far
2703  mockProfilingConnection->Clear();
2704 
2705  // Write a "Periodic Counter Selection" packet into the mock profiling connection, to simulate an input from an
2706  // external profiling service
2707 
2708  // Periodic Counter Selection packet header:
2709  // 26:31 [6] packet_family: Control Packet Family, value 0b000000
2710  // 16:25 [10] packet_id: Packet identifier, value 0b0000000100
2711  // 8:15 [8] reserved: Reserved, value 0b00000000
2712  // 0:7 [8] reserved: Reserved, value 0b00000000
2713  uint32_t packetFamily = 0;
2714  uint32_t packetId = 4;
2715  uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
2716 
2717  uint32_t capturePeriod = 123456; // Some capture period (microseconds)
2718 
2719  // Get the first valid counter UID
2720  const ICounterDirectory& counterDirectory = profilingService.GetCounterDirectory();
2721  const Counters& counters = counterDirectory.GetCounters();
2722  BOOST_CHECK(counters.size() > 1);
2723  uint16_t counterUidA = counters.begin()->first; // First valid counter UID
2724  uint16_t counterUidB = 9999; // Second invalid counter UID
2725 
2726  uint32_t length = 8;
2727 
2728  auto data = std::make_unique<unsigned char[]>(length);
2729  WriteUint32(data.get(), 0, capturePeriod);
2730  WriteUint16(data.get(), 4, counterUidA);
2731  WriteUint16(data.get(), 6, counterUidB);
2732 
2733  // Create the Periodic Counter Selection packet
2734  // Length > 0, this will start the Period Counter Capture thread
2735  arm::pipe::Packet periodicCounterSelectionPacket(header, length, data);
2736 
2737 
2738  // Write the packet to the mock profiling connection
2739  mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket));
2740 
2741  // Expecting one Periodic Counter Selection packet of length 14
2742  // and at least one Periodic Counter Capture packet of length 22
2743  BOOST_CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::PeriodicCounterSelection, 14) == 1);
2744  BOOST_CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::PeriodicCounterCapture, 22) >= 1);
2745 
2746  // The Periodic Counter Selection Handler should not have updated the profiling state
2747  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
2748 
2749  // Reset the profiling service to stop any running thread
2750  options.m_EnableProfiling = false;
2751  profilingService.ResetExternalProfilingOptions(options, true);
2752 }
2753 
2754 BOOST_AUTO_TEST_CASE(CheckProfilingServiceGoodPeriodicCounterSelectionPacketNoCounters)
2755 {
2756  // Reset the profiling service to the uninitialized state
2757  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
2758  options.m_EnableProfiling = true;
2759  armnn::profiling::ProfilingService profilingService;
2760  profilingService.ResetExternalProfilingOptions(options, true);
2761 
2762  // Swap the profiling connection factory in the profiling service instance with our mock one
2763  SwapProfilingConnectionFactoryHelper helper(profilingService);
2764 
2765  // Bring the profiling service to the "Active" state
2766  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
2767  profilingService.Update(); // Initialize the counter directory
2768  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
2769  profilingService.Update(); // Create the profiling connection
2770  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
2771  profilingService.Update(); // Start the command handler and the send thread
2772 
2773  // Get the mock profiling connection
2774  MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
2775  BOOST_CHECK(mockProfilingConnection);
2776 
2777  // Wait for the Stream Metadata packet the be sent
2778  // (we are not testing the connection acknowledgement here so it will be ignored by this test)
2779  helper.WaitForPacketsSent(mockProfilingConnection, PacketType::StreamMetaData);
2780 
2781  // Force the profiling service to the "Active" state
2783  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
2784 
2785  // Write a "Periodic Counter Selection" packet into the mock profiling connection, to simulate an input from an
2786  // external profiling service
2787 
2788  // Periodic Counter Selection packet header:
2789  // 26:31 [6] packet_family: Control Packet Family, value 0b000000
2790  // 16:25 [10] packet_id: Packet identifier, value 0b0000000100
2791  // 8:15 [8] reserved: Reserved, value 0b00000000
2792  // 0:7 [8] reserved: Reserved, value 0b00000000
2793  uint32_t packetFamily = 0;
2794  uint32_t packetId = 4;
2795  uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
2796 
2797  // Create the Periodic Counter Selection packet
2798  // Length == 0, this will disable the collection of counters
2799  arm::pipe::Packet periodicCounterSelectionPacket(header);
2800 
2801  // Write the packet to the mock profiling connection
2802  mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket));
2803 
2804  // Wait for the Periodic Counter Selection packet of length 12 to be sent
2805  // The size of the expected Periodic Counter Selection (echos the sent one)
2806  BOOST_CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::PeriodicCounterSelection, 12) == 1);
2807 
2808  // The Periodic Counter Selection Handler should not have updated the profiling state
2809  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
2810 
2811  // No Periodic Counter packets are expected
2812  BOOST_CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::PeriodicCounterCapture, 0, 0) == 0);
2813 
2814  // Reset the profiling service to stop any running thread
2815  options.m_EnableProfiling = false;
2816  profilingService.ResetExternalProfilingOptions(options, true);
2817 }
2818 
2819 BOOST_AUTO_TEST_CASE(CheckProfilingServiceGoodPeriodicCounterSelectionPacketSingleCounter)
2820 {
2821  // Reset the profiling service to the uninitialized state
2822  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
2823  options.m_EnableProfiling = true;
2824  armnn::profiling::ProfilingService profilingService;
2825  profilingService.ResetExternalProfilingOptions(options, true);
2826 
2827  // Swap the profiling connection factory in the profiling service instance with our mock one
2828  SwapProfilingConnectionFactoryHelper helper(profilingService);
2829 
2830  // Bring the profiling service to the "Active" state
2831  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
2832  profilingService.Update(); // Initialize the counter directory
2833  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
2834  profilingService.Update(); // Create the profiling connection
2835  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
2836  profilingService.Update(); // Start the command handler and the send thread
2837 
2838  // Get the mock profiling connection
2839  MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
2840  BOOST_CHECK(mockProfilingConnection);
2841 
2842  // Wait for the Stream Metadata packet to be sent
2843  // (we are not testing the connection acknowledgement here so it will be ignored by this test)
2844  helper.WaitForPacketsSent(mockProfilingConnection, PacketType::StreamMetaData);
2845 
2846  // Force the profiling service to the "Active" state
2848  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
2849 
2850  // Write a "Periodic Counter Selection" packet into the mock profiling connection, to simulate an input from an
2851  // external profiling service
2852 
2853  // Periodic Counter Selection packet header:
2854  // 26:31 [6] packet_family: Control Packet Family, value 0b000000
2855  // 16:25 [10] packet_id: Packet identifier, value 0b0000000100
2856  // 8:15 [8] reserved: Reserved, value 0b00000000
2857  // 0:7 [8] reserved: Reserved, value 0b00000000
2858  uint32_t packetFamily = 0;
2859  uint32_t packetId = 4;
2860  uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
2861 
2862  uint32_t capturePeriod = 123456; // Some capture period (microseconds)
2863 
2864  // Get the first valid counter UID
2865  const ICounterDirectory& counterDirectory = profilingService.GetCounterDirectory();
2866  const Counters& counters = counterDirectory.GetCounters();
2867  BOOST_CHECK(!counters.empty());
2868  uint16_t counterUid = counters.begin()->first; // Valid counter UID
2869 
2870  uint32_t length = 6;
2871 
2872  auto data = std::make_unique<unsigned char[]>(length);
2873  WriteUint32(data.get(), 0, capturePeriod);
2874  WriteUint16(data.get(), 4, counterUid);
2875 
2876  // Create the Periodic Counter Selection packet
2877  // Length > 0, this will start the Period Counter Capture thread
2878  arm::pipe::Packet periodicCounterSelectionPacket(header, length, data);
2879 
2880  // Write the packet to the mock profiling connection
2881  mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket));
2882 
2883  // Expecting one Periodic Counter Selection packet of length 14
2884  // and at least one Periodic Counter Capture packet of length 22
2885  BOOST_CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::PeriodicCounterSelection, 14) == 1);
2886  BOOST_CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::PeriodicCounterCapture, 22) >= 1);
2887 
2888  // The Periodic Counter Selection Handler should not have updated the profiling state
2889  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
2890 
2891  // Reset the profiling service to stop any running thread
2892  options.m_EnableProfiling = false;
2893  profilingService.ResetExternalProfilingOptions(options, true);
2894 }
2895 
2896 BOOST_AUTO_TEST_CASE(CheckProfilingServiceGoodPeriodicCounterSelectionPacketMultipleCounters)
2897 {
2898  // Reset the profiling service to the uninitialized state
2899  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
2900  options.m_EnableProfiling = true;
2901  armnn::profiling::ProfilingService profilingService;
2902  profilingService.ResetExternalProfilingOptions(options, true);
2903 
2904  // Swap the profiling connection factory in the profiling service instance with our mock one
2905  SwapProfilingConnectionFactoryHelper helper(profilingService);
2906 
2907  // Bring the profiling service to the "Active" state
2908  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
2909  profilingService.Update(); // Initialize the counter directory
2910  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
2911  profilingService.Update(); // Create the profiling connection
2912  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
2913  profilingService.Update(); // Start the command handler and the send thread
2914 
2915  // Get the mock profiling connection
2916  MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
2917  BOOST_CHECK(mockProfilingConnection);
2918 
2919  // Wait for the Stream Metadata packet the be sent
2920  // (we are not testing the connection acknowledgement here so it will be ignored by this test)
2921  helper.WaitForPacketsSent(mockProfilingConnection, PacketType::StreamMetaData);
2922 
2923  // Force the profiling service to the "Active" state
2925  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
2926 
2927  // Write a "Periodic Counter Selection" packet into the mock profiling connection, to simulate an input from an
2928  // external profiling service
2929 
2930  // Periodic Counter Selection packet header:
2931  // 26:31 [6] packet_family: Control Packet Family, value 0b000000
2932  // 16:25 [10] packet_id: Packet identifier, value 0b0000000100
2933  // 8:15 [8] reserved: Reserved, value 0b00000000
2934  // 0:7 [8] reserved: Reserved, value 0b00000000
2935  uint32_t packetFamily = 0;
2936  uint32_t packetId = 4;
2937  uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
2938 
2939  uint32_t capturePeriod = 123456; // Some capture period (microseconds)
2940 
2941  // Get the first valid counter UID
2942  const ICounterDirectory& counterDirectory = profilingService.GetCounterDirectory();
2943  const Counters& counters = counterDirectory.GetCounters();
2944  BOOST_CHECK(counters.size() > 1);
2945  uint16_t counterUidA = counters.begin()->first; // First valid counter UID
2946  uint16_t counterUidB = (counters.begin()++)->first; // Second valid counter UID
2947 
2948  uint32_t length = 8;
2949 
2950  auto data = std::make_unique<unsigned char[]>(length);
2951  WriteUint32(data.get(), 0, capturePeriod);
2952  WriteUint16(data.get(), 4, counterUidA);
2953  WriteUint16(data.get(), 6, counterUidB);
2954 
2955  // Create the Periodic Counter Selection packet
2956  // Length > 0, this will start the Period Counter Capture thread
2957  arm::pipe::Packet periodicCounterSelectionPacket(header, length, data);
2958 
2959  // Write the packet to the mock profiling connection
2960  mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket));
2961 
2962  // Expecting one PeriodicCounterSelection Packet with a length of 16
2963  // And at least one PeriodicCounterCapture Packet with a length of 28
2964  BOOST_CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::PeriodicCounterSelection, 16) == 1);
2965  BOOST_CHECK(helper.WaitForPacketsSent(mockProfilingConnection, PacketType::PeriodicCounterCapture, 28) >= 1);
2966 
2967  // The Periodic Counter Selection Handler should not have updated the profiling state
2968  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
2969 
2970  // Reset the profiling service to stop any running thread
2971  options.m_EnableProfiling = false;
2972  profilingService.ResetExternalProfilingOptions(options, true);
2973 }
2974 
2975 BOOST_AUTO_TEST_CASE(CheckProfilingServiceDisconnect)
2976 {
2977  // Reset the profiling service to the uninitialized state
2978  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
2979  options.m_EnableProfiling = true;
2980  armnn::profiling::ProfilingService profilingService;
2981  profilingService.ResetExternalProfilingOptions(options, true);
2982 
2983  // Swap the profiling connection factory in the profiling service instance with our mock one
2984  SwapProfilingConnectionFactoryHelper helper(profilingService);
2985 
2986  // Try to disconnect the profiling service while in the "Uninitialised" state
2987  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
2988  profilingService.Disconnect();
2989  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised); // The state should not change
2990 
2991  // Try to disconnect the profiling service while in the "NotConnected" state
2992  profilingService.Update(); // Initialize the counter directory
2993  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
2994  profilingService.Disconnect();
2995  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected); // The state should not change
2996 
2997  // Try to disconnect the profiling service while in the "WaitingForAck" state
2998  profilingService.Update(); // Create the profiling connection
2999  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
3000  profilingService.Disconnect();
3001  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck); // The state should not change
3002 
3003  // Try to disconnect the profiling service while in the "Active" state
3004  profilingService.Update(); // Start the command handler and the send thread
3005 
3006  // Get the mock profiling connection
3007  MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
3008  BOOST_CHECK(mockProfilingConnection);
3009 
3010  // Wait for the Stream Metadata packet the be sent
3011  // (we are not testing the connection acknowledgement here so it will be ignored by this test)
3012  helper.WaitForPacketsSent(mockProfilingConnection, PacketType::StreamMetaData);
3013 
3014  // Force the profiling service to the "Active" state
3016  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
3017 
3018  // Check that the profiling connection is open
3019  BOOST_CHECK(mockProfilingConnection->IsOpen());
3020 
3021  profilingService.Disconnect();
3022  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected); // The state should have changed
3023 
3024  // Check that the profiling connection has been reset
3025  mockProfilingConnection = helper.GetMockProfilingConnection();
3026  BOOST_CHECK(mockProfilingConnection == nullptr);
3027 
3028  // Reset the profiling service to stop any running thread
3029  options.m_EnableProfiling = false;
3030  profilingService.ResetExternalProfilingOptions(options, true);
3031 }
3032 
3033 BOOST_AUTO_TEST_CASE(CheckProfilingServiceGoodPerJobCounterSelectionPacket)
3034 {
3035  // Reset the profiling service to the uninitialized state
3036  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
3037  options.m_EnableProfiling = true;
3038  armnn::profiling::ProfilingService profilingService;
3039  profilingService.ResetExternalProfilingOptions(options, true);
3040 
3041  // Swap the profiling connection factory in the profiling service instance with our mock one
3042  SwapProfilingConnectionFactoryHelper helper(profilingService);
3043 
3044  // Bring the profiling service to the "Active" state
3045  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
3046  profilingService.Update(); // Initialize the counter directory
3047  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
3048  profilingService.Update(); // Create the profiling connection
3049  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
3050  profilingService.Update(); // Start the command handler and the send thread
3051 
3052  // Get the mock profiling connection
3053  MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
3054  BOOST_CHECK(mockProfilingConnection);
3055 
3056  // Wait for the Stream Metadata packet the be sent
3057  // (we are not testing the connection acknowledgement here so it will be ignored by this test)
3058  helper.WaitForPacketsSent(mockProfilingConnection, PacketType::StreamMetaData);
3059 
3060  // Force the profiling service to the "Active" state
3062  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
3063 
3064  // Write a "Per-Job Counter Selection" packet into the mock profiling connection, to simulate an input from an
3065  // external profiling service
3066 
3067  // Per-Job Counter Selection packet header:
3068  // 26:31 [6] packet_family: Control Packet Family, value 0b000000
3069  // 16:25 [10] packet_id: Packet identifier, value 0b0000000100
3070  // 8:15 [8] reserved: Reserved, value 0b00000000
3071  // 0:7 [8] reserved: Reserved, value 0b00000000
3072  uint32_t packetFamily = 0;
3073  uint32_t packetId = 5;
3074  uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
3075 
3076  // Create the Per-Job Counter Selection packet
3077  // Length == 0, this will disable the collection of counters
3078  arm::pipe::Packet periodicCounterSelectionPacket(header);
3079 
3080  // Write the packet to the mock profiling connection
3081  mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket));
3082 
3083  // Wait for a bit (must at least be the delay value of the mock profiling connection) to make sure that
3084  // the Per-Job Counter Selection packet gets processed by the profiling service
3085  std::this_thread::sleep_for(std::chrono::milliseconds(5));
3086 
3087  // The Per-Job Counter Selection Command Handler should not have updated the profiling state
3088  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
3089 
3090  // The Per-Job Counter Selection packets are dropped silently, so there should be no reply coming
3091  // from the profiling service
3092  const auto StreamMetaDataSize = static_cast<unsigned long>(
3093  helper.WaitForPacketsSent(mockProfilingConnection, PacketType::StreamMetaData, 0, 0));
3094  BOOST_CHECK(StreamMetaDataSize == mockProfilingConnection->GetWrittenDataSize());
3095 
3096  // Reset the profiling service to stop any running thread
3097  options.m_EnableProfiling = false;
3098  profilingService.ResetExternalProfilingOptions(options, true);
3099 }
3100 
3101 BOOST_AUTO_TEST_CASE(CheckConfigureProfilingServiceOn)
3102 {
3103  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
3104  options.m_EnableProfiling = true;
3105  armnn::profiling::ProfilingService profilingService;
3106  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
3107  profilingService.ConfigureProfilingService(options);
3108  // should get as far as NOT_CONNECTED
3109  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
3110  // Reset the profiling service to stop any running thread
3111  options.m_EnableProfiling = false;
3112  profilingService.ResetExternalProfilingOptions(options, true);
3113 }
3114 
3115 BOOST_AUTO_TEST_CASE(CheckConfigureProfilingServiceOff)
3116 {
3117  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
3118  armnn::profiling::ProfilingService profilingService;
3119  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
3120  profilingService.ConfigureProfilingService(options);
3121  // should not move from Uninitialised
3122  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
3123  // Reset the profiling service to stop any running thread
3124  options.m_EnableProfiling = false;
3125  profilingService.ResetExternalProfilingOptions(options, true);
3126 }
3127 
3128 BOOST_AUTO_TEST_CASE(CheckProfilingServiceEnabled)
3129 {
3130  // Locally reduce log level to "Warning", as this test needs to parse a warning message from the standard output
3132  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
3133  options.m_EnableProfiling = true;
3134  armnn::profiling::ProfilingService profilingService;
3135  profilingService.ResetExternalProfilingOptions(options, true);
3136  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
3137  profilingService.Update();
3138  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
3139 
3140  // Redirect the output to a local stream so that we can parse the warning message
3141  std::stringstream ss;
3142  StreamRedirector streamRedirector(std::cout, ss.rdbuf());
3143  profilingService.Update();
3144 
3145  // Reset the profiling service to stop any running thread
3146  options.m_EnableProfiling = false;
3147  profilingService.ResetExternalProfilingOptions(options, true);
3148 
3149  streamRedirector.CancelRedirect();
3150 
3151  // Check that the expected error has occurred and logged to the standard output
3152  if (ss.str().find("Cannot connect to stream socket: Connection refused") == std::string::npos)
3153  {
3154  std::cout << ss.str();
3155  BOOST_FAIL("Expected string not found.");
3156  }
3157 }
3158 
3159 BOOST_AUTO_TEST_CASE(CheckProfilingServiceEnabledRuntime)
3160 {
3161  // Locally reduce log level to "Warning", as this test needs to parse a warning message from the standard output
3163  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
3164  armnn::profiling::ProfilingService profilingService;
3165  profilingService.ResetExternalProfilingOptions(options, true);
3166  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
3167  profilingService.Update();
3168  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
3169  options.m_EnableProfiling = true;
3170  profilingService.ResetExternalProfilingOptions(options);
3171  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
3172  profilingService.Update();
3173  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
3174 
3175  // Redirect the output to a local stream so that we can parse the warning message
3176  std::stringstream ss;
3177  StreamRedirector streamRedirector(std::cout, ss.rdbuf());
3178  profilingService.Update();
3179 
3180  // Reset the profiling service to stop any running thread
3181  options.m_EnableProfiling = false;
3182  profilingService.ResetExternalProfilingOptions(options, true);
3183 
3184  streamRedirector.CancelRedirect();
3185 
3186  // Check that the expected error has occurred and logged to the standard output
3187  if (ss.str().find("Cannot connect to stream socket: Connection refused") == std::string::npos)
3188  {
3189  std::cout << ss.str();
3190  BOOST_FAIL("Expected string not found.");
3191  }
3192 }
3193 
3194 BOOST_AUTO_TEST_CASE(CheckProfilingServiceBadConnectionAcknowledgedPacket)
3195 {
3196  // Locally reduce log level to "Warning", as this test needs to parse a warning message from the standard output
3198 
3199 
3200  // Redirect the standard output to a local stream so that we can parse the warning message
3201  std::stringstream ss;
3202  StreamRedirector streamRedirector(std::cout, ss.rdbuf());
3203 
3204  // Reset the profiling service to the uninitialized state
3205  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
3206  options.m_EnableProfiling = true;
3207  armnn::profiling::ProfilingService profilingService;
3208  profilingService.ResetExternalProfilingOptions(options, true);
3209 
3210  // Swap the profiling connection factory in the profiling service instance with our mock one
3211  SwapProfilingConnectionFactoryHelper helper(profilingService);
3212 
3213  // Bring the profiling service to the "WaitingForAck" state
3214  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
3215  profilingService.Update(); // Initialize the counter directory
3216  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
3217  profilingService.Update(); // Create the profiling connection
3218 
3219  // Get the mock profiling connection
3220  MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
3221  BOOST_CHECK(mockProfilingConnection);
3222 
3223  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
3224 
3225  // Connection Acknowledged Packet header (word 0, word 1 is always zero):
3226  // 26:31 [6] packet_family: Control Packet Family, value 0b000000
3227  // 16:25 [10] packet_id: Packet identifier, value 0b0000000001
3228  // 8:15 [8] reserved: Reserved, value 0b00000000
3229  // 0:7 [8] reserved: Reserved, value 0b00000000
3230  uint32_t packetFamily = 0;
3231  uint32_t packetId = 37; // Wrong packet id!!!
3232  uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
3233 
3234  // Create the Connection Acknowledged Packet
3235  arm::pipe::Packet connectionAcknowledgedPacket(header);
3236  // Write an invalid "Connection Acknowledged" packet into the mock profiling connection, to simulate an invalid
3237  // reply from an external profiling service
3238  mockProfilingConnection->WritePacket(std::move(connectionAcknowledgedPacket));
3239 
3240  // Start the command thread
3241  profilingService.Update();
3242 
3243  // Wait for the command thread to join
3244  options.m_EnableProfiling = false;
3245  profilingService.ResetExternalProfilingOptions(options, true);
3246 
3247  streamRedirector.CancelRedirect();
3248 
3249  // Check that the expected error has occurred and logged to the standard output
3250  if (ss.str().find("Functor with requested PacketId=37 and Version=4194304 does not exist") == std::string::npos)
3251  {
3252  std::cout << ss.str();
3253  BOOST_FAIL("Expected string not found.");
3254  }
3255 }
3256 
3257 BOOST_AUTO_TEST_CASE(CheckProfilingServiceBadRequestCounterDirectoryPacket)
3258 {
3259  // Locally reduce log level to "Warning", as this test needs to parse a warning message from the standard output
3261 
3262  // Redirect the standard output to a local stream so that we can parse the warning message
3263  std::stringstream ss;
3264  StreamRedirector streamRedirector(std::cout, ss.rdbuf());
3265 
3266  // Reset the profiling service to the uninitialized state
3267  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
3268  options.m_EnableProfiling = true;
3269  armnn::profiling::ProfilingService profilingService;
3270  profilingService.ResetExternalProfilingOptions(options, true);
3271 
3272  // Swap the profiling connection factory in the profiling service instance with our mock one
3273  SwapProfilingConnectionFactoryHelper helper(profilingService);
3274 
3275  // Bring the profiling service to the "Active" state
3276  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
3278  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
3279  profilingService.Update(); // Create the profiling connection
3280  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
3281 
3282  // Get the mock profiling connection
3283  MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
3284  BOOST_CHECK(mockProfilingConnection);
3285 
3286  // Write a valid "Request Counter Directory" packet into the mock profiling connection, to simulate a valid
3287  // reply from an external profiling service
3288 
3289  // Request Counter Directory packet header (word 0, word 1 is always zero):
3290  // 26:31 [6] packet_family: Control Packet Family, value 0b000000
3291  // 16:25 [10] packet_id: Packet identifier, value 0b0000000011
3292  // 8:15 [8] reserved: Reserved, value 0b00000000
3293  // 0:7 [8] reserved: Reserved, value 0b00000000
3294  uint32_t packetFamily = 0;
3295  uint32_t packetId = 123; // Wrong packet id!!!
3296  uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
3297 
3298  // Create the Request Counter Directory packet
3299  arm::pipe::Packet requestCounterDirectoryPacket(header);
3300 
3301  // Write the packet to the mock profiling connection
3302  mockProfilingConnection->WritePacket(std::move(requestCounterDirectoryPacket));
3303 
3304  // Start the command handler and the send thread
3305  profilingService.Update();
3306 
3307  // Reset the profiling service to stop and join any running thread
3308  options.m_EnableProfiling = false;
3309  profilingService.ResetExternalProfilingOptions(options, true);
3310 
3311  streamRedirector.CancelRedirect();
3312 
3313  // Check that the expected error has occurred and logged to the standard output
3314  if (ss.str().find("Functor with requested PacketId=123 and Version=4194304 does not exist") == std::string::npos)
3315  {
3316  std::cout << ss.str();
3317  BOOST_FAIL("Expected string not found.");
3318  }
3319 }
3320 
3321 BOOST_AUTO_TEST_CASE(CheckProfilingServiceBadPeriodicCounterSelectionPacket)
3322 {
3323  // Locally reduce log level to "Warning", as this test needs to parse a warning message from the standard output
3325 
3326  // Redirect the standard output to a local stream so that we can parse the warning message
3327  std::stringstream ss;
3328  StreamRedirector streamRedirector(std::cout, ss.rdbuf());
3329 
3330  // Reset the profiling service to the uninitialized state
3331  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
3332  options.m_EnableProfiling = true;
3333  armnn::profiling::ProfilingService profilingService;
3334  profilingService.ResetExternalProfilingOptions(options, true);
3335 
3336  // Swap the profiling connection factory in the profiling service instance with our mock one
3337  SwapProfilingConnectionFactoryHelper helper(profilingService);
3338 
3339  // Bring the profiling service to the "Active" state
3340  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
3341  profilingService.Update(); // Initialize the counter directory
3342  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
3343  profilingService.Update(); // Create the profiling connection
3344  BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
3345  profilingService.Update(); // Start the command handler and the send thread
3346 
3347  // Get the mock profiling connection
3348  MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
3349  BOOST_CHECK(mockProfilingConnection);
3350 
3351  // Write a "Periodic Counter Selection" packet into the mock profiling connection, to simulate an input from an
3352  // external profiling service
3353 
3354  // Periodic Counter Selection packet header:
3355  // 26:31 [6] packet_family: Control Packet Family, value 0b000000
3356  // 16:25 [10] packet_id: Packet identifier, value 0b0000000100
3357  // 8:15 [8] reserved: Reserved, value 0b00000000
3358  // 0:7 [8] reserved: Reserved, value 0b00000000
3359  uint32_t packetFamily = 0;
3360  uint32_t packetId = 999; // Wrong packet id!!!
3361  uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
3362 
3363  // Create the Periodic Counter Selection packet
3364  // Length == 0, this will disable the collection of counters
3365  arm::pipe::Packet periodicCounterSelectionPacket(header);
3366 
3367  // Write the packet to the mock profiling connection
3368  mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket));
3369  profilingService.Update();
3370 
3371  // Reset the profiling service to stop any running thread
3372  options.m_EnableProfiling = false;
3373  profilingService.ResetExternalProfilingOptions(options, true);
3374 
3375  // Check that the expected error has occurred and logged to the standard output
3376  streamRedirector.CancelRedirect();
3377 
3378  // Check that the expected error has occurred and logged to the standard output
3379  if (ss.str().find("Functor with requested PacketId=999 and Version=4194304 does not exist") == std::string::npos)
3380  {
3381  std::cout << ss.str();
3382  BOOST_FAIL("Expected string not found.");
3383  }
3384 }
3385 
3386 BOOST_AUTO_TEST_CASE(CheckCounterIdMap)
3387 {
3388  CounterIdMap counterIdMap;
3389  BOOST_CHECK_THROW(counterIdMap.GetBackendId(0), armnn::Exception);
3390  BOOST_CHECK_THROW(counterIdMap.GetGlobalId(0, armnn::profiling::BACKEND_ID), armnn::Exception);
3391 
3392  uint16_t globalCounterIds = 0;
3393 
3396 
3397  std::vector<uint16_t> cpuRefCounters = {0, 1, 2, 3};
3398  std::vector<uint16_t> cpuAccCounters = {0, 1};
3399 
3400  for (uint16_t backendCounterId : cpuRefCounters)
3401  {
3402  counterIdMap.RegisterMapping(globalCounterIds, backendCounterId, cpuRefId);
3403  ++globalCounterIds;
3404  }
3405  for (uint16_t backendCounterId : cpuAccCounters)
3406  {
3407  counterIdMap.RegisterMapping(globalCounterIds, backendCounterId, cpuAccId);
3408  ++globalCounterIds;
3409  }
3410 
3411  BOOST_CHECK(counterIdMap.GetBackendId(0) == (std::pair<uint16_t, armnn::BackendId>(0, cpuRefId)));
3412  BOOST_CHECK(counterIdMap.GetBackendId(1) == (std::pair<uint16_t, armnn::BackendId>(1, cpuRefId)));
3413  BOOST_CHECK(counterIdMap.GetBackendId(2) == (std::pair<uint16_t, armnn::BackendId>(2, cpuRefId)));
3414  BOOST_CHECK(counterIdMap.GetBackendId(3) == (std::pair<uint16_t, armnn::BackendId>(3, cpuRefId)));
3415  BOOST_CHECK(counterIdMap.GetBackendId(4) == (std::pair<uint16_t, armnn::BackendId>(0, cpuAccId)));
3416  BOOST_CHECK(counterIdMap.GetBackendId(5) == (std::pair<uint16_t, armnn::BackendId>(1, cpuAccId)));
3417 
3418  BOOST_CHECK(counterIdMap.GetGlobalId(0, cpuRefId) == 0);
3419  BOOST_CHECK(counterIdMap.GetGlobalId(1, cpuRefId) == 1);
3420  BOOST_CHECK(counterIdMap.GetGlobalId(2, cpuRefId) == 2);
3421  BOOST_CHECK(counterIdMap.GetGlobalId(3, cpuRefId) == 3);
3422  BOOST_CHECK(counterIdMap.GetGlobalId(0, cpuAccId) == 4);
3423  BOOST_CHECK(counterIdMap.GetGlobalId(1, cpuAccId) == 5);
3424 }
3425 
3426 BOOST_AUTO_TEST_CASE(CheckRegisterBackendCounters)
3427 {
3428  uint16_t globalCounterIds = armnn::profiling::INFERENCES_RUN;
3430 
3431  // Reset the profiling service to the uninitialized state
3432  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
3433  options.m_EnableProfiling = true;
3434  ProfilingService profilingService;
3435  profilingService.ResetExternalProfilingOptions(options, true);
3436 
3437  RegisterBackendCounters registerBackendCounters(globalCounterIds, cpuRefId, profilingService);
3438 
3439 
3440 
3441  BOOST_CHECK(profilingService.GetCounterDirectory().GetCategories().empty());
3442  registerBackendCounters.RegisterCategory("categoryOne");
3443  auto categoryOnePtr = profilingService.GetCounterDirectory().GetCategory("categoryOne");
3444  BOOST_CHECK(categoryOnePtr);
3445 
3446  BOOST_CHECK(profilingService.GetCounterDirectory().GetDevices().empty());
3447  globalCounterIds = registerBackendCounters.RegisterDevice("deviceOne");
3448  auto deviceOnePtr = profilingService.GetCounterDirectory().GetDevice(globalCounterIds);
3449  BOOST_CHECK(deviceOnePtr);
3450  BOOST_CHECK(deviceOnePtr->m_Name == "deviceOne");
3451 
3452  BOOST_CHECK(profilingService.GetCounterDirectory().GetCounterSets().empty());
3453  globalCounterIds = registerBackendCounters.RegisterCounterSet("counterSetOne");
3454  auto counterSetOnePtr = profilingService.GetCounterDirectory().GetCounterSet(globalCounterIds);
3455  BOOST_CHECK(counterSetOnePtr);
3456  BOOST_CHECK(counterSetOnePtr->m_Name == "counterSetOne");
3457 
3458  uint16_t newGlobalCounterId = registerBackendCounters.RegisterCounter(0,
3459  "categoryOne",
3460  0,
3461  0,
3462  1.f,
3463  "CounterOne",
3464  "first test counter");
3465  BOOST_CHECK(newGlobalCounterId = armnn::profiling::INFERENCES_RUN + 1);
3466  uint16_t mappedGlobalId = profilingService.GetCounterMappings().GetGlobalId(0, cpuRefId);
3467  BOOST_CHECK(mappedGlobalId == newGlobalCounterId);
3468  auto backendMapping = profilingService.GetCounterMappings().GetBackendId(newGlobalCounterId);
3469  BOOST_CHECK(backendMapping.first == 0);
3470  BOOST_CHECK(backendMapping.second == cpuRefId);
3471 
3472  // Reset the profiling service to stop any running thread
3473  options.m_EnableProfiling = false;
3474  profilingService.ResetExternalProfilingOptions(options, true);
3475 }
3476 
3477 BOOST_AUTO_TEST_CASE(CheckCounterStatusQuery)
3478 {
3480  options.m_ProfilingOptions.m_EnableProfiling = true;
3481 
3482  // Reset the profiling service to the uninitialized state
3483  ProfilingService profilingService;
3484  profilingService.ResetExternalProfilingOptions(options.m_ProfilingOptions, true);
3485 
3486  const armnn::BackendId cpuRefId(armnn::Compute::CpuRef);
3487  const armnn::BackendId cpuAccId(armnn::Compute::CpuAcc);
3488 
3489  // Create BackendProfiling for each backend
3490  BackendProfiling backendProfilingCpuRef(options, profilingService, cpuRefId);
3491  BackendProfiling backendProfilingCpuAcc(options, profilingService, cpuAccId);
3492 
3493  uint16_t initialNumGlobalCounterIds = armnn::profiling::INFERENCES_RUN;
3494 
3495  // Create RegisterBackendCounters for CpuRef
3496  RegisterBackendCounters registerBackendCountersCpuRef(initialNumGlobalCounterIds, cpuRefId, profilingService);
3497 
3498  // Create 'testCategory' in CounterDirectory (backend agnostic)
3499  BOOST_CHECK(profilingService.GetCounterDirectory().GetCategories().empty());
3500  registerBackendCountersCpuRef.RegisterCategory("testCategory");
3501  auto categoryOnePtr = profilingService.GetCounterDirectory().GetCategory("testCategory");
3502  BOOST_CHECK(categoryOnePtr);
3503 
3504  // Counters:
3505  // Global | Local | Backend
3506  // 5 | 0 | CpuRef
3507  // 6 | 1 | CpuRef
3508  // 7 | 1 | CpuAcc
3509 
3510  std::vector<uint16_t> cpuRefCounters = {0, 1};
3511  std::vector<uint16_t> cpuAccCounters = {0};
3512 
3513  // Register the backend counters for CpuRef and validate GetGlobalId and GetBackendId
3514  uint16_t currentNumGlobalCounterIds = registerBackendCountersCpuRef.RegisterCounter(
3515  0, "testCategory", 0, 0, 1.f, "CpuRefCounter0", "Zeroth CpuRef Counter");
3516  BOOST_CHECK(currentNumGlobalCounterIds == initialNumGlobalCounterIds + 1);
3517  uint16_t mappedGlobalId = profilingService.GetCounterMappings().GetGlobalId(0, cpuRefId);
3518  BOOST_CHECK(mappedGlobalId == currentNumGlobalCounterIds);
3519  auto backendMapping = profilingService.GetCounterMappings().GetBackendId(currentNumGlobalCounterIds);
3520  BOOST_CHECK(backendMapping.first == 0);
3521  BOOST_CHECK(backendMapping.second == cpuRefId);
3522 
3523  currentNumGlobalCounterIds = registerBackendCountersCpuRef.RegisterCounter(
3524  1, "testCategory", 0, 0, 1.f, "CpuRefCounter1", "First CpuRef Counter");
3525  BOOST_CHECK(currentNumGlobalCounterIds == initialNumGlobalCounterIds + 2);
3526  mappedGlobalId = profilingService.GetCounterMappings().GetGlobalId(1, cpuRefId);
3527  BOOST_CHECK(mappedGlobalId == currentNumGlobalCounterIds);
3528  backendMapping = profilingService.GetCounterMappings().GetBackendId(currentNumGlobalCounterIds);
3529  BOOST_CHECK(backendMapping.first == 1);
3530  BOOST_CHECK(backendMapping.second == cpuRefId);
3531 
3532  // Create RegisterBackendCounters for CpuAcc
3533  RegisterBackendCounters registerBackendCountersCpuAcc(currentNumGlobalCounterIds, cpuAccId, profilingService);
3534 
3535  // Register the backend counter for CpuAcc and validate GetGlobalId and GetBackendId
3536  currentNumGlobalCounterIds = registerBackendCountersCpuAcc.RegisterCounter(
3537  0, "testCategory", 0, 0, 1.f, "CpuAccCounter0", "Zeroth CpuAcc Counter");
3538  BOOST_CHECK(currentNumGlobalCounterIds == initialNumGlobalCounterIds + 3);
3539  mappedGlobalId = profilingService.GetCounterMappings().GetGlobalId(0, cpuAccId);
3540  BOOST_CHECK(mappedGlobalId == currentNumGlobalCounterIds);
3541  backendMapping = profilingService.GetCounterMappings().GetBackendId(currentNumGlobalCounterIds);
3542  BOOST_CHECK(backendMapping.first == 0);
3543  BOOST_CHECK(backendMapping.second == cpuAccId);
3544 
3545  // Create vectors for active counters
3546  const std::vector<uint16_t> activeGlobalCounterIds = {5}; // CpuRef(0) activated
3547  const std::vector<uint16_t> newActiveGlobalCounterIds = {6, 7}; // CpuRef(0) and CpuAcc(1) activated
3548 
3549  const uint32_t capturePeriod = 200;
3550  const uint32_t newCapturePeriod = 100;
3551 
3552  // Set capture period and active counters in CaptureData
3553  profilingService.SetCaptureData(capturePeriod, activeGlobalCounterIds, {});
3554 
3555  // Get vector of active counters for CpuRef and CpuAcc backends
3556  std::vector<CounterStatus> cpuRefCounterStatus = backendProfilingCpuRef.GetActiveCounters();
3557  std::vector<CounterStatus> cpuAccCounterStatus = backendProfilingCpuAcc.GetActiveCounters();
3558  BOOST_CHECK_EQUAL(cpuRefCounterStatus.size(), 1);
3559  BOOST_CHECK_EQUAL(cpuAccCounterStatus.size(), 0);
3560 
3561  // Check active CpuRef counter
3562  BOOST_CHECK_EQUAL(cpuRefCounterStatus[0].m_GlobalCounterId, activeGlobalCounterIds[0]);
3563  BOOST_CHECK_EQUAL(cpuRefCounterStatus[0].m_BackendCounterId, cpuRefCounters[0]);
3564  BOOST_CHECK_EQUAL(cpuRefCounterStatus[0].m_SamplingRateInMicroseconds, capturePeriod);
3565  BOOST_CHECK_EQUAL(cpuRefCounterStatus[0].m_Enabled, true);
3566 
3567  // Check inactive CpuRef counter
3568  CounterStatus inactiveCpuRefCounter = backendProfilingCpuRef.GetCounterStatus(cpuRefCounters[1]);
3569  BOOST_CHECK_EQUAL(inactiveCpuRefCounter.m_GlobalCounterId, 6);
3570  BOOST_CHECK_EQUAL(inactiveCpuRefCounter.m_BackendCounterId, cpuRefCounters[1]);
3571  BOOST_CHECK_EQUAL(inactiveCpuRefCounter.m_SamplingRateInMicroseconds, 0);
3572  BOOST_CHECK_EQUAL(inactiveCpuRefCounter.m_Enabled, false);
3573 
3574  // Check inactive CpuAcc counter
3575  CounterStatus inactiveCpuAccCounter = backendProfilingCpuAcc.GetCounterStatus(cpuAccCounters[0]);
3576  BOOST_CHECK_EQUAL(inactiveCpuAccCounter.m_GlobalCounterId, 7);
3577  BOOST_CHECK_EQUAL(inactiveCpuAccCounter.m_BackendCounterId, cpuAccCounters[0]);
3578  BOOST_CHECK_EQUAL(inactiveCpuAccCounter.m_SamplingRateInMicroseconds, 0);
3579  BOOST_CHECK_EQUAL(inactiveCpuAccCounter.m_Enabled, false);
3580 
3581  // Set new capture period and new active counters in CaptureData
3582  profilingService.SetCaptureData(newCapturePeriod, newActiveGlobalCounterIds, {});
3583 
3584  // Get vector of active counters for CpuRef and CpuAcc backends
3585  cpuRefCounterStatus = backendProfilingCpuRef.GetActiveCounters();
3586  cpuAccCounterStatus = backendProfilingCpuAcc.GetActiveCounters();
3587  BOOST_CHECK_EQUAL(cpuRefCounterStatus.size(), 1);
3588  BOOST_CHECK_EQUAL(cpuAccCounterStatus.size(), 1);
3589 
3590  // Check active CpuRef counter
3591  BOOST_CHECK_EQUAL(cpuRefCounterStatus[0].m_GlobalCounterId, newActiveGlobalCounterIds[0]);
3592  BOOST_CHECK_EQUAL(cpuRefCounterStatus[0].m_BackendCounterId, cpuRefCounters[1]);
3593  BOOST_CHECK_EQUAL(cpuRefCounterStatus[0].m_SamplingRateInMicroseconds, newCapturePeriod);
3594  BOOST_CHECK_EQUAL(cpuRefCounterStatus[0].m_Enabled, true);
3595 
3596  // Check active CpuAcc counter
3597  BOOST_CHECK_EQUAL(cpuAccCounterStatus[0].m_GlobalCounterId, newActiveGlobalCounterIds[1]);
3598  BOOST_CHECK_EQUAL(cpuAccCounterStatus[0].m_BackendCounterId, cpuAccCounters[0]);
3599  BOOST_CHECK_EQUAL(cpuAccCounterStatus[0].m_SamplingRateInMicroseconds, newCapturePeriod);
3600  BOOST_CHECK_EQUAL(cpuAccCounterStatus[0].m_Enabled, true);
3601 
3602  // Check inactive CpuRef counter
3603  inactiveCpuRefCounter = backendProfilingCpuRef.GetCounterStatus(cpuRefCounters[0]);
3604  BOOST_CHECK_EQUAL(inactiveCpuRefCounter.m_GlobalCounterId, 5);
3605  BOOST_CHECK_EQUAL(inactiveCpuRefCounter.m_BackendCounterId, cpuRefCounters[0]);
3606  BOOST_CHECK_EQUAL(inactiveCpuRefCounter.m_SamplingRateInMicroseconds, 0);
3607  BOOST_CHECK_EQUAL(inactiveCpuRefCounter.m_Enabled, false);
3608 
3609  // Reset the profiling service to stop any running thread
3610  options.m_ProfilingOptions.m_EnableProfiling = false;
3611  profilingService.ResetExternalProfilingOptions(options.m_ProfilingOptions, true);
3612 }
3613 
3614 BOOST_AUTO_TEST_CASE(CheckRegisterCounters)
3615 {
3617  options.m_ProfilingOptions.m_EnableProfiling = true;
3618  MockBufferManager mockBuffer(1024);
3619 
3620  CaptureData captureData;
3621  MockProfilingService mockProfilingService(mockBuffer, options.m_ProfilingOptions.m_EnableProfiling, captureData);
3623 
3624  mockProfilingService.RegisterMapping(6, 0, cpuRefId);
3625  mockProfilingService.RegisterMapping(7, 1, cpuRefId);
3626  mockProfilingService.RegisterMapping(8, 2, cpuRefId);
3627 
3628  armnn::profiling::BackendProfiling backendProfiling(options,
3629  mockProfilingService,
3630  cpuRefId);
3631 
3632  armnn::profiling::Timestamp timestamp;
3633  timestamp.timestamp = 1000998;
3634  timestamp.counterValues.emplace_back(0, 700);
3635  timestamp.counterValues.emplace_back(2, 93);
3636  std::vector<armnn::profiling::Timestamp> timestamps;
3637  timestamps.push_back(timestamp);
3638  backendProfiling.ReportCounters(timestamps);
3639 
3640  auto readBuffer = mockBuffer.GetReadableBuffer();
3641 
3642  uint32_t headerWord0 = ReadUint32(readBuffer, 0);
3643  uint32_t headerWord1 = ReadUint32(readBuffer, 4);
3644  uint64_t readTimestamp = ReadUint64(readBuffer, 8);
3645 
3646  BOOST_TEST(((headerWord0 >> 26) & 0x0000003F) == 3); // packet family
3647  BOOST_TEST(((headerWord0 >> 19) & 0x0000007F) == 0); // packet class
3648  BOOST_TEST(((headerWord0 >> 16) & 0x00000007) == 0); // packet type
3649  BOOST_TEST(headerWord1 == 20); // data length
3650  BOOST_TEST(1000998 == readTimestamp); // capture period
3651 
3652  uint32_t offset = 16;
3653  // Check Counter Index
3654  uint16_t readIndex = ReadUint16(readBuffer, offset);
3655  BOOST_TEST(6 == readIndex);
3656 
3657  // Check Counter Value
3658  offset += 2;
3659  uint32_t readValue = ReadUint32(readBuffer, offset);
3660  BOOST_TEST(700 == readValue);
3661 
3662  // Check Counter Index
3663  offset += 4;
3664  readIndex = ReadUint16(readBuffer, offset);
3665  BOOST_TEST(8 == readIndex);
3666 
3667  // Check Counter Value
3668  offset += 2;
3669  readValue = ReadUint32(readBuffer, offset);
3670  BOOST_TEST(93 == readValue);
3671 }
3672 
3673 BOOST_AUTO_TEST_CASE(CheckFileFormat) {
3674  // Locally reduce log level to "Warning", as this test needs to parse a warning message from the standard output
3676 
3677  // Create profiling options.
3678  armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
3679  options.m_EnableProfiling = true;
3680  // Check the default value set to binary
3681  BOOST_CHECK(options.m_FileFormat == "binary");
3682 
3683  // Change file format to an unsupported value
3684  options.m_FileFormat = "json";
3685  // Enable the profiling service
3686  armnn::profiling::ProfilingService profilingService;
3687  profilingService.ResetExternalProfilingOptions(options, true);
3688  // Start the command handler and the send thread
3689  profilingService.Update();
3690  BOOST_CHECK(profilingService.GetCurrentState()==ProfilingState::NotConnected);
3691 
3692  // Redirect the output to a local stream so that we can parse the warning message
3693  std::stringstream ss;
3694  StreamRedirector streamRedirector(std::cout, ss.rdbuf());
3695 
3696  // When Update is called and the current state is ProfilingState::NotConnected
3697  // an exception will be raised from GetProfilingConnection and displayed as warning in the output local stream
3698  profilingService.Update();
3699 
3700  streamRedirector.CancelRedirect();
3701 
3702  // Check that the expected error has occurred and logged to the standard output
3703  if (ss.str().find("Unsupported profiling file format, only binary is supported") == std::string::npos)
3704  {
3705  std::cout << ss.str();
3706  BOOST_FAIL("Expected string not found.");
3707  }
3708 }
3709 
BOOST_AUTO_TEST_SUITE(TensorflowLiteParser)
const Category * RegisterCategory(const std::string &categoryName) override
void ProfilingCurrentStateThreadImpl(ProfilingStateMachine &states)
const Counter * RegisterCounter(const BackendId &backendId, const uint16_t uid, const std::string &parentCategoryName, uint16_t counterClass, uint16_t interpolation, double multiplier, const std::string &name, const std::string &description, const Optional< std::string > &units=EmptyOptional(), const Optional< uint16_t > &numberOfCores=EmptyOptional(), const Optional< uint16_t > &deviceUid=EmptyOptional(), const Optional< uint16_t > &counterSetUid=EmptyOptional()) override
void StringToSwTraceStringTestHelper(const std::string &testString, std::vector< uint32_t > buffer, size_t expectedSize)
uint32_t GetAbsoluteCounterValue(uint16_t counterUid) const override
uint16_t GetGlobalId(uint16_t backendCounterId, const armnn::BackendId &backendId) const override
std::vector< CounterStatus > GetActiveCounters() override
CPU Execution: Reference C++ kernels.
long WaitForPacketsSent(MockProfilingConnection *mockProfilingConnection, MockProfilingConnection::PacketType packetType, uint32_t length=0, uint32_t timeout=1000)
ProfilingState GetCurrentState() const
void Start(IProfilingConnection &profilingConnection)
void WriteUint16(const IPacketBufferPtr &packetBuffer, unsigned int offset, uint16_t value)
const std::vector< uint16_t > & GetCounterIds() const
Definition: Holder.cpp:49
void WriteUint32(const IPacketBufferPtr &packetBuffer, unsigned int offset, uint32_t value)
uint64_t ReadUint64(const IPacketBufferPtr &packetBuffer, unsigned int offset)
void ForceTransitionToState(ProfilingState newState)
std::unordered_map< uint16_t, CounterPtr > Counters
virtual const Category * GetCategory(const std::string &name) const =0
uint16_t RegisterDevice(const std::string &deviceName, uint16_t cores=0, const Optional< std::string > &parentCategoryName=EmptyOptional()) override
uint32_t GetStreamMetaDataPacketSize()
void ReportCounters(const std::vector< Timestamp > &) override
const Device * GetDevice(uint16_t uid) const override
virtual uint16_t GetCounterCount() const =0
uint16_t ReadUint16(const IPacketBufferPtr &packetBuffer, unsigned int offset)
uint16_t GetCounterSetCount() const override
virtual const Device * GetDevice(uint16_t uid) const =0
Copyright (c) 2020 ARM Limited.
void IgnoreUnused(Ts &&...)
virtual const CounterSets & GetCounterSets() const =0
void RegisterMapping(uint16_t globalCounterId, uint16_t backendCounterId, const armnn::BackendId &backendId) override
uint32_t IncrementCounterValue(uint16_t counterUid) override
void CaptureDataReadThreadImpl(const Holder &holder, CaptureData &captureData)
virtual const Categories & GetCategories() const =0
uint16_t GetNextUid(bool peekOnly)
uint16_t GetDeviceCount() const override
uint32_t GetDeltaCounterValue(uint16_t counterUid) override
uint32_t SubtractCounterValue(uint16_t counterUid, uint32_t value) override
CounterStatus GetCounterStatus(uint16_t backendCounterId) override
virtual const Devices & GetDevices() const =0
void MarkRead(IPacketBufferPtr &packetBuffer) override
void SetCapturePeriod(uint32_t capturePeriod)
Definition: Holder.cpp:29
uint32_t GetCapturePeriod() const
Definition: Holder.cpp:44
virtual const CounterSet * GetCounterSet(uint16_t uid) const =0
profiling::ProfilingService & GetProfilingService(armnn::Runtime *runtime)
Definition: TestUtils.cpp:25
CaptureData GetCaptureData() const
Definition: Holder.cpp:54
void SetCaptureData(uint32_t capturePeriod, const std::vector< uint16_t > &counterIds, const std::set< BackendId > &activeBackends)
void SetCaptureData(uint32_t capturePeriod, const std::vector< uint16_t > &counterIds, const std::set< armnn::BackendId > &activeBackends)
Definition: Holder.cpp:74
std::vector< uint16_t > GetNextCounterUids(uint16_t firstUid, uint16_t cores)
const std::pair< uint16_t, armnn::BackendId > & GetBackendId(uint16_t globalCounterId) const override
uint16_t RegisterCounterSet(const std::string &counterSetName, uint16_t count=0, const Optional< std::string > &parentCategoryName=EmptyOptional()) override
IPacketBufferPtr GetReadableBuffer() override
const ICounterMappings & GetCounterMappings() const override
void ResetExternalProfilingOptions(const ExternalProfilingOptions &options, bool resetProfilingService=false)
uint32_t ConstructHeader(uint32_t packetFamily, uint32_t packetId)
uint32_t AddCounterValue(uint16_t counterUid, uint32_t value) override
uint16_t GetCategoryCount() const override
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
Definition: NumericCast.hpp:33
constexpr unsigned int LOWEST_CAPTURE_PERIOD
The lowest performance data capture interval we support is 10 miliseconds.
Definition: Types.hpp:21
BOOST_AUTO_TEST_CASE(CheckConvolution2dLayer)
std::vector< CounterValue > counterValues
IPacketBufferPtr GetReadableBuffer() override
uint16_t RegisterCounter(const uint16_t uid, const std::string &parentCategoryName, uint16_t counterClass, uint16_t interpolation, double multiplier, const std::string &name, const std::string &description, const Optional< std::string > &units=EmptyOptional(), const Optional< uint16_t > &numberOfCores=EmptyOptional(), const Optional< uint16_t > &deviceUid=EmptyOptional(), const Optional< uint16_t > &counterSetUid=EmptyOptional()) override
uint32_t ReadUint32(const IPacketBufferPtr &packetBuffer, unsigned int offset)
std::vector< uint16_t > m_Counters
void SetCounterValue(uint16_t counterUid, uint32_t value) override
const Counter * GetCounter(uint16_t uid) const override
BOOST_AUTO_TEST_SUITE_END()
void RegisterCategory(const std::string &categoryName) override
const Category * GetCategory(const std::string &name) const override
EmptyOptional is used to initialize the Optional class in case we want to have default value for an O...
Definition: Optional.hpp:32
void CaptureDataWriteThreadImpl(Holder &holder, uint32_t capturePeriod, const std::vector< uint16_t > &counterIds)
const Device * RegisterDevice(const std::string &deviceName, uint16_t cores=0, const Optional< std::string > &parentCategoryName=EmptyOptional()) override
Base class for all ArmNN exceptions so that users can filter to just those.
Definition: Exceptions.hpp:46
CPU Execution: NEON: ArmCompute.
void SetCounterIds(const std::vector< uint16_t > &counterIds)
Definition: Holder.cpp:34
bool WritePacket(const unsigned char *buffer, uint32_t length) override
uint16_t GetCounterCount() const override
void TransitionToState(ProfilingState newState)
virtual const Counters & GetCounters() const =0
const CounterSet * RegisterCounterSet(const std::string &counterSetName, uint16_t count=0, const Optional< std::string > &parentCategoryName=EmptyOptional()) override
virtual const std::pair< uint16_t, armnn::BackendId > & GetBackendId(uint16_t globalCounterId) const =0
void SetStopAfterTimeout(bool stopAfterTimeout)
const CounterSet * GetCounterSet(uint16_t uid) const override
ExternalProfilingOptions m_ProfilingOptions
Definition: IRuntime.hpp:83
const ICounterDirectory & GetCounterDirectory() const
ProfilingState ConfigureProfilingService(const ExternalProfilingOptions &options, bool resetProfilingService=false)
void RegisterMapping(uint16_t globalCounterId, uint16_t backendCounterId, const armnn::BackendId &backendId)
virtual uint16_t GetGlobalId(uint16_t backendCounterId, const armnn::BackendId &backendId) const =0