2 // Copyright © 2019 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
6 #include "PeriodicCounterSelectionCommandHandler.hpp"
7 #include "ProfilingUtils.hpp"
9 #include <boost/numeric/conversion/cast.hpp>
10 #include <boost/format.hpp>
20 void PeriodicCounterSelectionCommandHandler::ParseData(const Packet& packet, CaptureData& captureData)
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));
27 if (packet.GetLength() < 4)
29 // Insufficient packet size
33 // Parse the capture period
34 uint32_t capturePeriod = ReadUint32(packet.GetData(), offset);
36 // Set the capture period
37 captureData.SetCapturePeriod(capturePeriod);
39 // Parse the counter ids
40 unsigned int counters = (packet.GetLength() - 4) / 2;
43 counterIds.reserve(counters);
44 offset += sizeOfUint32;
45 for (unsigned int i = 0; i < counters; ++i)
47 // Parse the counter id
48 uint16_t counterId = ReadUint16(packet.GetData(), offset);
49 counterIds.emplace_back(counterId);
50 offset += sizeOfUint16;
54 // Set the counter ids
55 captureData.SetCounterIds(counterIds);
58 void PeriodicCounterSelectionCommandHandler::operator()(const Packet& packet)
60 ProfilingState currentState = m_StateMachine.GetCurrentState();
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:
72 if (!(packet.GetPacketFamily() == 0u && packet.GetPacketId() == 4u))
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()));
80 // Parse the packet to get the capture period and counter UIDs
81 CaptureData captureData;
82 ParseData(packet, captureData);
84 // Get the capture data
85 const uint32_t capturePeriod = captureData.GetCapturePeriod();
86 const std::vector<uint16_t>& counterIds = captureData.GetCounterIds();
88 // Check whether the selected counter UIDs are valid
89 std::vector<uint16_t> validCounterIds;
90 for (uint16_t counterId : counterIds)
92 // Check whether the counter is registered
93 if (!m_ReadCounterValues.IsCounterRegistered(counterId))
95 // Invalid counter UID, ignore it and continue
99 // The counter is valid
100 validCounterIds.push_back(counterId);
103 // Set the capture data with only the valid counter UIDs
104 m_CaptureDataHolder.SetCaptureData(capturePeriod, validCounterIds);
106 // Echo back the Periodic Counter Selection packet to the Counter Stream Buffer
107 m_SendCounterPacket.SendPeriodicCounterSelectionPacket(capturePeriod, validCounterIds);
109 // Notify the Send Thread that new data is available in the Counter Stream Buffer
110 m_SendCounterPacket.SetReadyToRead();
112 if (capturePeriod == 0 || validCounterIds.empty())
114 // No data capture stop the thread
115 m_PeriodicCounterCapture.Stop();
119 // Start the Period Counter Capture thread (if not running already)
120 m_PeriodicCounterCapture.Start();
126 throw RuntimeException(boost::str(boost::format("Unknown profiling service state: %1%")
127 % static_cast<int>(currentState)));
131 } // namespace profiling