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