3df0f22c1cab99adfcb5a3d7c1162e7c83610ac8
[platform/upstream/armnn.git] / src / profiling / PeriodicCounterSelectionCommandHandler.cpp
1 //
2 // Copyright © 2019 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include "PeriodicCounterSelectionCommandHandler.hpp"
7 #include "ProfilingUtils.hpp"
8
9 #include <boost/numeric/conversion/cast.hpp>
10 #include <boost/format.hpp>
11
12 #include <vector>
13
14 namespace armnn
15 {
16
17 namespace profiling
18 {
19
20 void PeriodicCounterSelectionCommandHandler::ParseData(const Packet& packet, CaptureData& captureData)
21 {
22     std::vector<uint16_t> counterIds;
23     uint32_t sizeOfUint32 = boost::numeric_cast<uint32_t>(sizeof(uint32_t));
24     uint32_t sizeOfUint16 = boost::numeric_cast<uint32_t>(sizeof(uint16_t));
25     uint32_t offset = 0;
26
27     if (packet.GetLength() < 4)
28     {
29         // Insufficient packet size
30         return;
31     }
32
33     // Parse the capture period
34     uint32_t capturePeriod = ReadUint32(packet.GetData(), offset);
35
36     // Set the capture period
37     captureData.SetCapturePeriod(capturePeriod);
38
39     // Parse the counter ids
40     unsigned int counters = (packet.GetLength() - 4) / 2;
41     if (counters > 0)
42     {
43         counterIds.reserve(counters);
44         offset += sizeOfUint32;
45         for (unsigned int i = 0; i < counters; ++i)
46         {
47             // Parse the counter id
48             uint16_t counterId = ReadUint16(packet.GetData(), offset);
49             counterIds.emplace_back(counterId);
50             offset += sizeOfUint16;
51         }
52     }
53
54     // Set the counter ids
55     captureData.SetCounterIds(counterIds);
56 }
57
58 void PeriodicCounterSelectionCommandHandler::operator()(const Packet& packet)
59 {
60     ProfilingState currentState = m_StateMachine.GetCurrentState();
61     switch (currentState)
62     {
63     case ProfilingState::Uninitialised:
64     case ProfilingState::NotConnected:
65     case ProfilingState::WaitingForAck:
66         throw RuntimeException(boost::str(boost::format("Periodic Counter Selection Command Handler invoked while in "
67                                                         "an wrong state: %1%")
68                                           % GetProfilingStateName(currentState)));
69     case ProfilingState::Active:
70     {
71         // Process the packet
72         if (!(packet.GetPacketFamily() == 0u && packet.GetPacketId() == 4u))
73         {
74             throw armnn::InvalidArgumentException(boost::str(boost::format("Expected Packet family = 0, id = 4 but "
75                                                                            "received family = %1%, id = %2%")
76                                                   % packet.GetPacketFamily()
77                                                   % packet.GetPacketId()));
78         }
79
80         // Parse the packet to get the capture period and counter UIDs
81         CaptureData captureData;
82         ParseData(packet, captureData);
83
84         // Get the capture data
85         const uint32_t capturePeriod = captureData.GetCapturePeriod();
86         const std::vector<uint16_t>& counterIds = captureData.GetCounterIds();
87
88         // Check whether the selected counter UIDs are valid
89         std::vector<uint16_t> validCounterIds;
90         for (uint16_t counterId : counterIds)
91         {
92             // Check whether the counter is registered
93             if (!m_ReadCounterValues.IsCounterRegistered(counterId))
94             {
95                 // Invalid counter UID, ignore it and continue
96                 continue;
97             }
98
99             // The counter is valid
100             validCounterIds.push_back(counterId);
101         }
102
103         // Set the capture data with only the valid counter UIDs
104         m_CaptureDataHolder.SetCaptureData(capturePeriod, validCounterIds);
105
106         // Echo back the Periodic Counter Selection packet to the Counter Stream Buffer
107         m_SendCounterPacket.SendPeriodicCounterSelectionPacket(capturePeriod, validCounterIds);
108
109         // Notify the Send Thread that new data is available in the Counter Stream Buffer
110         m_SendCounterPacket.SetReadyToRead();
111
112         if (capturePeriod == 0 || validCounterIds.empty())
113         {
114             // No data capture stop the thread
115             m_PeriodicCounterCapture.Stop();
116         }
117         else
118         {
119             // Start the Period Counter Capture thread (if not running already)
120             m_PeriodicCounterCapture.Start();
121         }
122
123         break;
124     }
125     default:
126         throw RuntimeException(boost::str(boost::format("Unknown profiling service state: %1%")
127                                           % static_cast<int>(currentState)));
128     }
129 }
130
131 } // namespace profiling
132
133 } // namespace armnn