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