blob: a6b6a050adf667fba6d81d8838ae25b018f6311f [file] [log] [blame]
Ferran Balaguer1b941722019-08-28 16:57:18 +01001//
2// Copyright © 2019 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "PeriodicCounterSelectionCommandHandler.hpp"
7#include "ProfilingUtils.hpp"
8
Colm Donelan02705242019-11-14 14:19:07 +00009#include <armnn/Types.hpp>
Ferran Balaguer1b941722019-08-28 16:57:18 +010010#include <boost/numeric/conversion/cast.hpp>
Matteo Martincighe8485382019-10-10 14:08:21 +010011#include <boost/format.hpp>
12
13#include <vector>
Ferran Balaguer1b941722019-08-28 16:57:18 +010014
15namespace armnn
16{
17
18namespace profiling
19{
20
Ferran Balaguer1b941722019-08-28 16:57:18 +010021void PeriodicCounterSelectionCommandHandler::ParseData(const Packet& packet, CaptureData& captureData)
22{
23 std::vector<uint16_t> counterIds;
Matteo Martincighe8485382019-10-10 14:08:21 +010024 uint32_t sizeOfUint32 = boost::numeric_cast<uint32_t>(sizeof(uint32_t));
25 uint32_t sizeOfUint16 = boost::numeric_cast<uint32_t>(sizeof(uint16_t));
Ferran Balaguer1b941722019-08-28 16:57:18 +010026 uint32_t offset = 0;
27
Matteo Martincighe8485382019-10-10 14:08:21 +010028 if (packet.GetLength() < 4)
Ferran Balaguer1b941722019-08-28 16:57:18 +010029 {
Matteo Martincighe8485382019-10-10 14:08:21 +010030 // Insufficient packet size
31 return;
32 }
33
34 // Parse the capture period
35 uint32_t capturePeriod = ReadUint32(packet.GetData(), offset);
36
37 // Set the capture period
38 captureData.SetCapturePeriod(capturePeriod);
39
40 // Parse the counter ids
41 unsigned int counters = (packet.GetLength() - 4) / 2;
42 if (counters > 0)
43 {
44 counterIds.reserve(counters);
45 offset += sizeOfUint32;
46 for (unsigned int i = 0; i < counters; ++i)
Ferran Balaguer1b941722019-08-28 16:57:18 +010047 {
Matteo Martincighe8485382019-10-10 14:08:21 +010048 // Parse the counter id
49 uint16_t counterId = ReadUint16(packet.GetData(), offset);
50 counterIds.emplace_back(counterId);
51 offset += sizeOfUint16;
Ferran Balaguer1b941722019-08-28 16:57:18 +010052 }
53 }
Matteo Martincighe8485382019-10-10 14:08:21 +010054
55 // Set the counter ids
56 captureData.SetCounterIds(counterIds);
Ferran Balaguer1b941722019-08-28 16:57:18 +010057}
58
59void PeriodicCounterSelectionCommandHandler::operator()(const Packet& packet)
60{
Matteo Martincighe8485382019-10-10 14:08:21 +010061 ProfilingState currentState = m_StateMachine.GetCurrentState();
62 switch (currentState)
63 {
64 case ProfilingState::Uninitialised:
65 case ProfilingState::NotConnected:
66 case ProfilingState::WaitingForAck:
67 throw RuntimeException(boost::str(boost::format("Periodic Counter Selection Command Handler invoked while in "
68 "an wrong state: %1%")
69 % GetProfilingStateName(currentState)));
70 case ProfilingState::Active:
71 {
72 // Process the packet
73 if (!(packet.GetPacketFamily() == 0u && packet.GetPacketId() == 4u))
74 {
75 throw armnn::InvalidArgumentException(boost::str(boost::format("Expected Packet family = 0, id = 4 but "
76 "received family = %1%, id = %2%")
77 % packet.GetPacketFamily()
78 % packet.GetPacketId()));
79 }
Ferran Balaguer1b941722019-08-28 16:57:18 +010080
Matteo Martincighe8485382019-10-10 14:08:21 +010081 // Parse the packet to get the capture period and counter UIDs
82 CaptureData captureData;
83 ParseData(packet, captureData);
Ferran Balaguer1b941722019-08-28 16:57:18 +010084
Matteo Martincighe8485382019-10-10 14:08:21 +010085 // Get the capture data
Colm Donelan02705242019-11-14 14:19:07 +000086 uint32_t capturePeriod = captureData.GetCapturePeriod();
87 // Validate that the capture period is within the acceptable range.
88 if (capturePeriod > 0 && capturePeriod < LOWEST_CAPTURE_PERIOD)
89 {
90 capturePeriod = LOWEST_CAPTURE_PERIOD;
91 }
Matteo Martincighe8485382019-10-10 14:08:21 +010092 const std::vector<uint16_t>& counterIds = captureData.GetCounterIds();
Ferran Balaguer1b941722019-08-28 16:57:18 +010093
Matteo Martincighe8485382019-10-10 14:08:21 +010094 // Check whether the selected counter UIDs are valid
95 std::vector<uint16_t> validCounterIds;
96 for (uint16_t counterId : counterIds)
97 {
98 // Check whether the counter is registered
99 if (!m_ReadCounterValues.IsCounterRegistered(counterId))
100 {
101 // Invalid counter UID, ignore it and continue
102 continue;
103 }
Ferran Balaguer1b941722019-08-28 16:57:18 +0100104
Matteo Martincighe8485382019-10-10 14:08:21 +0100105 // The counter is valid
106 validCounterIds.push_back(counterId);
107 }
Ferran Balaguer1b941722019-08-28 16:57:18 +0100108
Matteo Martincighe8485382019-10-10 14:08:21 +0100109 // Set the capture data with only the valid counter UIDs
110 m_CaptureDataHolder.SetCaptureData(capturePeriod, validCounterIds);
111
112 // Echo back the Periodic Counter Selection packet to the Counter Stream Buffer
113 m_SendCounterPacket.SendPeriodicCounterSelectionPacket(capturePeriod, validCounterIds);
114
115 // Notify the Send Thread that new data is available in the Counter Stream Buffer
116 m_SendCounterPacket.SetReadyToRead();
117
Finn Williamsf4d59a62019-10-14 15:55:18 +0100118 if (capturePeriod == 0 || validCounterIds.empty())
119 {
120 // No data capture stop the thread
121 m_PeriodicCounterCapture.Stop();
122 }
123 else
124 {
125 // Start the Period Counter Capture thread (if not running already)
126 m_PeriodicCounterCapture.Start();
127 }
Matteo Martincighe8485382019-10-10 14:08:21 +0100128
129 break;
130 }
131 default:
132 throw RuntimeException(boost::str(boost::format("Unknown profiling service state: %1%")
133 % static_cast<int>(currentState)));
134 }
Ferran Balaguer1b941722019-08-28 16:57:18 +0100135}
136
137} // namespace profiling
138
Matteo Martincighe8485382019-10-10 14:08:21 +0100139} // namespace armnn