blob: 06f2c6588b01d446f8c5aa61d8e0c1c039373f77 [file] [log] [blame]
Ferran Balaguer1b941722019-08-28 16:57:18 +01001//
Jim Flynnbbfe6032020-07-20 16:57:44 +01002// Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
Ferran Balaguer1b941722019-08-28 16:57:18 +01003// SPDX-License-Identifier: MIT
4//
5
6#include "PeriodicCounterSelectionCommandHandler.hpp"
7#include "ProfilingUtils.hpp"
8
Jim Flynn27761832022-03-20 21:52:17 +00009#include <client/include/ProfilingOptions.hpp>
10
Jim Flynn75c14f42022-03-10 22:05:42 +000011#include <common/include/NumericCast.hpp>
Matthew Sloyan371b70e2020-09-11 10:14:57 +010012
Jan Eilers156113c2020-09-09 19:11:16 +010013#include <fmt/format.h>
Matteo Martincighe8485382019-10-10 14:08:21 +010014
15#include <vector>
Ferran Balaguer1b941722019-08-28 16:57:18 +010016
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000017namespace arm
Ferran Balaguer1b941722019-08-28 16:57:18 +010018{
19
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000020namespace pipe
Ferran Balaguer1b941722019-08-28 16:57:18 +010021{
22
Jim Flynnbbfe6032020-07-20 16:57:44 +010023void PeriodicCounterSelectionCommandHandler::ParseData(const arm::pipe::Packet& packet, CaptureData& captureData)
Ferran Balaguer1b941722019-08-28 16:57:18 +010024{
25 std::vector<uint16_t> counterIds;
Jim Flynn75c14f42022-03-10 22:05:42 +000026 uint32_t sizeOfUint32 = arm::pipe::numeric_cast<uint32_t>(sizeof(uint32_t));
27 uint32_t sizeOfUint16 = arm::pipe::numeric_cast<uint32_t>(sizeof(uint16_t));
Ferran Balaguer1b941722019-08-28 16:57:18 +010028 uint32_t offset = 0;
29
Matteo Martincighe8485382019-10-10 14:08:21 +010030 if (packet.GetLength() < 4)
Ferran Balaguer1b941722019-08-28 16:57:18 +010031 {
Matteo Martincighe8485382019-10-10 14:08:21 +010032 // Insufficient packet size
33 return;
34 }
35
36 // Parse the capture period
37 uint32_t capturePeriod = ReadUint32(packet.GetData(), offset);
38
39 // Set the capture period
40 captureData.SetCapturePeriod(capturePeriod);
41
42 // Parse the counter ids
43 unsigned int counters = (packet.GetLength() - 4) / 2;
44 if (counters > 0)
45 {
46 counterIds.reserve(counters);
47 offset += sizeOfUint32;
48 for (unsigned int i = 0; i < counters; ++i)
Ferran Balaguer1b941722019-08-28 16:57:18 +010049 {
Matteo Martincighe8485382019-10-10 14:08:21 +010050 // Parse the counter id
51 uint16_t counterId = ReadUint16(packet.GetData(), offset);
52 counterIds.emplace_back(counterId);
53 offset += sizeOfUint16;
Ferran Balaguer1b941722019-08-28 16:57:18 +010054 }
55 }
Matteo Martincighe8485382019-10-10 14:08:21 +010056
57 // Set the counter ids
58 captureData.SetCounterIds(counterIds);
Ferran Balaguer1b941722019-08-28 16:57:18 +010059}
60
Jim Flynnbbfe6032020-07-20 16:57:44 +010061void PeriodicCounterSelectionCommandHandler::operator()(const arm::pipe::Packet& packet)
Ferran Balaguer1b941722019-08-28 16:57:18 +010062{
Matteo Martincighe8485382019-10-10 14:08:21 +010063 ProfilingState currentState = m_StateMachine.GetCurrentState();
64 switch (currentState)
65 {
66 case ProfilingState::Uninitialised:
67 case ProfilingState::NotConnected:
68 case ProfilingState::WaitingForAck:
Jim Flynnf9db3ef2022-03-08 21:23:44 +000069 throw arm::pipe::ProfilingException(fmt::format("Periodic Counter Selection Command Handler invoked while in "
70 "an wrong state: {}",
71 GetProfilingStateName(currentState)));
Matteo Martincighe8485382019-10-10 14:08:21 +010072 case ProfilingState::Active:
73 {
74 // Process the packet
75 if (!(packet.GetPacketFamily() == 0u && packet.GetPacketId() == 4u))
76 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +000077 throw arm::pipe::InvalidArgumentException(fmt::format("Expected Packet family = 0, id = 4 but "
78 "received family = {}, id = {}",
79 packet.GetPacketFamily(),
80 packet.GetPacketId()));
Matteo Martincighe8485382019-10-10 14:08:21 +010081 }
Ferran Balaguer1b941722019-08-28 16:57:18 +010082
Matteo Martincighe8485382019-10-10 14:08:21 +010083 // Parse the packet to get the capture period and counter UIDs
84 CaptureData captureData;
85 ParseData(packet, captureData);
Ferran Balaguer1b941722019-08-28 16:57:18 +010086
Matteo Martincighe8485382019-10-10 14:08:21 +010087 // Get the capture data
Colm Donelan02705242019-11-14 14:19:07 +000088 uint32_t capturePeriod = captureData.GetCapturePeriod();
89 // Validate that the capture period is within the acceptable range.
Jim Flynn4c9ed1d2022-01-23 23:57:20 +000090 if (capturePeriod > 0 && capturePeriod < arm::pipe::LOWEST_CAPTURE_PERIOD)
Colm Donelan02705242019-11-14 14:19:07 +000091 {
Jim Flynn4c9ed1d2022-01-23 23:57:20 +000092 capturePeriod = arm::pipe::LOWEST_CAPTURE_PERIOD;
Colm Donelan02705242019-11-14 14:19:07 +000093 }
Matteo Martincighe8485382019-10-10 14:08:21 +010094 const std::vector<uint16_t>& counterIds = captureData.GetCounterIds();
Ferran Balaguer1b941722019-08-28 16:57:18 +010095
Matteo Martincighe8485382019-10-10 14:08:21 +010096 // Check whether the selected counter UIDs are valid
97 std::vector<uint16_t> validCounterIds;
98 for (uint16_t counterId : counterIds)
99 {
100 // Check whether the counter is registered
101 if (!m_ReadCounterValues.IsCounterRegistered(counterId))
102 {
103 // Invalid counter UID, ignore it and continue
104 continue;
105 }
Matteo Martincighe8485382019-10-10 14:08:21 +0100106 // The counter is valid
Finn Williams032bc742020-02-12 11:02:34 +0000107 validCounterIds.emplace_back(counterId);
Matteo Martincighe8485382019-10-10 14:08:21 +0100108 }
Ferran Balaguer1b941722019-08-28 16:57:18 +0100109
Finn Williams032bc742020-02-12 11:02:34 +0000110 std::sort(validCounterIds.begin(), validCounterIds.end());
111
112 auto backendIdStart = std::find_if(validCounterIds.begin(), validCounterIds.end(), [&](uint16_t& counterId)
113 {
114 return counterId > m_MaxArmCounterId;
115 });
116
Cathal Corbett6f073722022-03-04 12:11:09 +0000117 std::set<std::string> activeBackends;
Finn Williams032bc742020-02-12 11:02:34 +0000118 std::set<uint16_t> backendCounterIds = std::set<uint16_t>(backendIdStart, validCounterIds.end());
119
120 if (m_BackendCounterMap.size() != 0)
121 {
122 std::set<uint16_t> newCounterIds;
123 std::set<uint16_t> unusedCounterIds;
124
125 // Get any backend counter ids that is in backendCounterIds but not in m_PrevBackendCounterIds
126 std::set_difference(backendCounterIds.begin(), backendCounterIds.end(),
127 m_PrevBackendCounterIds.begin(), m_PrevBackendCounterIds.end(),
128 std::inserter(newCounterIds, newCounterIds.begin()));
129
130 // Get any backend counter ids that is in m_PrevBackendCounterIds but not in backendCounterIds
131 std::set_difference(m_PrevBackendCounterIds.begin(), m_PrevBackendCounterIds.end(),
132 backendCounterIds.begin(), backendCounterIds.end(),
133 std::inserter(unusedCounterIds, unusedCounterIds.begin()));
134
135 activeBackends = ProcessBackendCounterIds(capturePeriod, newCounterIds, unusedCounterIds);
136 }
137 else
138 {
139 activeBackends = ProcessBackendCounterIds(capturePeriod, backendCounterIds, {});
140 }
141
142 // save the new backend counter ids for next time
143 m_PrevBackendCounterIds = backendCounterIds;
144
Finn Williams032bc742020-02-12 11:02:34 +0000145 // Set the capture data with only the valid armnn counter UIDs
146 m_CaptureDataHolder.SetCaptureData(capturePeriod, {validCounterIds.begin(), backendIdStart}, activeBackends);
Matteo Martincighe8485382019-10-10 14:08:21 +0100147
148 // Echo back the Periodic Counter Selection packet to the Counter Stream Buffer
149 m_SendCounterPacket.SendPeriodicCounterSelectionPacket(capturePeriod, validCounterIds);
150
Finn Williamsf4d59a62019-10-14 15:55:18 +0100151 if (capturePeriod == 0 || validCounterIds.empty())
152 {
153 // No data capture stop the thread
154 m_PeriodicCounterCapture.Stop();
155 }
156 else
157 {
158 // Start the Period Counter Capture thread (if not running already)
159 m_PeriodicCounterCapture.Start();
160 }
Matteo Martincighe8485382019-10-10 14:08:21 +0100161
162 break;
163 }
164 default:
Jim Flynnf9db3ef2022-03-08 21:23:44 +0000165 throw arm::pipe::ProfilingException(fmt::format("Unknown profiling service state: {}",
166 static_cast<int>(currentState)));
Matteo Martincighe8485382019-10-10 14:08:21 +0100167 }
Ferran Balaguer1b941722019-08-28 16:57:18 +0100168}
169
Cathal Corbett6f073722022-03-04 12:11:09 +0000170std::set<std::string> PeriodicCounterSelectionCommandHandler::ProcessBackendCounterIds(
Rob Hughesb98032f2020-04-24 11:41:34 +0100171 const uint32_t capturePeriod,
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100172 const std::set<uint16_t> newCounterIds,
173 const std::set<uint16_t> unusedCounterIds)
Finn Williams032bc742020-02-12 11:02:34 +0000174{
Cathal Corbett6f073722022-03-04 12:11:09 +0000175 std::set<std::string> changedBackends;
176 std::set<std::string> activeBackends = m_CaptureDataHolder.GetCaptureData().GetActiveBackends();
Finn Williams032bc742020-02-12 11:02:34 +0000177
178 for (uint16_t counterId : newCounterIds)
179 {
180 auto backendId = m_CounterIdMap.GetBackendId(counterId);
181 m_BackendCounterMap[backendId.second].emplace_back(backendId.first);
182 changedBackends.insert(backendId.second);
183 }
184 // Add any new backends to active backends
185 activeBackends.insert(changedBackends.begin(), changedBackends.end());
186
187 for (uint16_t counterId : unusedCounterIds)
188 {
189 auto backendId = m_CounterIdMap.GetBackendId(counterId);
190 std::vector<uint16_t>& backendCounters = m_BackendCounterMap[backendId.second];
191
192 backendCounters.erase(std::remove(backendCounters.begin(), backendCounters.end(), backendId.first));
193
194 if(backendCounters.size() == 0)
195 {
196 // If a backend has no counters associated with it we remove it from active backends and
197 // send a capture period of zero with an empty vector, this will deactivate all the backends counters
198 activeBackends.erase(backendId.second);
Cathal Corbett6f073722022-03-04 12:11:09 +0000199 ActivateBackendCounters(backendId.second, 0, {});
Finn Williams032bc742020-02-12 11:02:34 +0000200 }
201 else
202 {
203 changedBackends.insert(backendId.second);
204 }
205 }
206
207 // If the capture period remains the same we only need to update the backends who's counters have changed
208 if(capturePeriod == m_PrevCapturePeriod)
209 {
210 for (auto backend : changedBackends)
211 {
Cathal Corbett6f073722022-03-04 12:11:09 +0000212 ActivateBackendCounters(backend, capturePeriod, m_BackendCounterMap[backend]);
Finn Williams032bc742020-02-12 11:02:34 +0000213 }
214 }
215 // Otherwise update all the backends with the new capture period and any new/unused counters
216 else
217 {
218 for (auto backend : m_BackendCounterMap)
219 {
Cathal Corbett6f073722022-03-04 12:11:09 +0000220 ActivateBackendCounters(backend.first, capturePeriod, backend.second);
Finn Williams032bc742020-02-12 11:02:34 +0000221 }
222 if(capturePeriod == 0)
223 {
224 activeBackends = {};
225 }
226 m_PrevCapturePeriod = capturePeriod;
227 }
228
229 return activeBackends;
230}
231
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000232} // namespace pipe
Ferran Balaguer1b941722019-08-28 16:57:18 +0100233
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000234} // namespace arm