blob: f338858498ffc27465d0ead68741200c892fdbce [file] [log] [blame]
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +01001//
Jim Flynnbbfe6032020-07-20 16:57:44 +01002// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +01003// SPDX-License-Identifier: MIT
4//
5
Jim Flynnc454ac92022-03-16 18:43:18 +00006#include <common/include/CounterDirectory.hpp>
7#include <common/include/CommonProfilingUtils.hpp>
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +01008
Jim Flynn6730fe92022-03-10 22:57:47 +00009#include <common/include/Assert.hpp>
Jim Flynnbbfe6032020-07-20 16:57:44 +010010#include <common/include/SwTrace.hpp>
11
Jan Eilers156113c2020-09-09 19:11:16 +010012#include <fmt/format.h>
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +010013
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000014namespace arm
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +010015{
16
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000017namespace pipe
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +010018{
19
Sadik Armagan4c998992020-02-25 12:44:44 +000020const Category* CounterDirectory::RegisterCategory(const std::string& categoryName)
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +010021{
Matteo Martincigh6db5f202019-09-05 12:02:04 +010022 // Check that the given category name is valid
23 if (categoryName.empty() ||
Jim Flynnbbfe6032020-07-20 16:57:44 +010024 !arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>(categoryName))
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +010025 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +000026 throw arm::pipe::InvalidArgumentException("Trying to register a category with an invalid name");
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +010027 }
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +010028
Matteo Martincigh6db5f202019-09-05 12:02:04 +010029 // Check that the given category is not already registered
Matteo Martincigha84edee2019-10-02 12:50:57 +010030 if (IsCategoryRegistered(categoryName))
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +010031 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +000032 throw arm::pipe::InvalidArgumentException(fmt::format(
33 "Trying to register a category already registered (\"{}\")",
34 categoryName));
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +010035 }
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +010036
Matteo Martincigh6db5f202019-09-05 12:02:04 +010037 // Create the category
Sadik Armagan4c998992020-02-25 12:44:44 +000038 CategoryPtr category = std::make_unique<Category>(categoryName);
Jim Flynn6730fe92022-03-10 22:57:47 +000039 ARM_PIPE_ASSERT(category);
Matteo Martincigh6db5f202019-09-05 12:02:04 +010040
41 // Get the raw category pointer
42 const Category* categoryPtr = category.get();
Jim Flynn6730fe92022-03-10 22:57:47 +000043 ARM_PIPE_ASSERT(categoryPtr);
Matteo Martincigh6db5f202019-09-05 12:02:04 +010044
45 // Register the category
46 m_Categories.insert(std::move(category));
47
48 return categoryPtr;
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +010049}
50
Matteo Martincigh6db5f202019-09-05 12:02:04 +010051const Device* CounterDirectory::RegisterDevice(const std::string& deviceName,
52 uint16_t cores,
Jim Flynndecd08b2022-03-13 22:35:46 +000053 const arm::pipe::Optional<std::string>& parentCategoryName)
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +010054{
Matteo Martincigh6db5f202019-09-05 12:02:04 +010055 // Check that the given device name is valid
56 if (deviceName.empty() ||
Jim Flynnbbfe6032020-07-20 16:57:44 +010057 !arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>(deviceName))
Matteo Martincigh6db5f202019-09-05 12:02:04 +010058 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +000059 throw arm::pipe::InvalidArgumentException("Trying to register a device with an invalid name");
Matteo Martincigh6db5f202019-09-05 12:02:04 +010060 }
61
62 // Check that a device with the given name is not already registered
Matteo Martincigha84edee2019-10-02 12:50:57 +010063 if (IsDeviceRegistered(deviceName))
Matteo Martincigh6db5f202019-09-05 12:02:04 +010064 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +000065 throw arm::pipe::InvalidArgumentException(fmt::format(
66 "Trying to register a device already registered (\"{}\")",
67 deviceName));
Matteo Martincigh6db5f202019-09-05 12:02:04 +010068 }
69
Matteo Martincigh6db5f202019-09-05 12:02:04 +010070 // Check that a category with the given (optional) parent category name is already registered
Matteo Martincigh6db5f202019-09-05 12:02:04 +010071 if (parentCategoryName.has_value())
72 {
73 // Get the (optional) parent category name
74 const std::string& parentCategoryNameValue = parentCategoryName.value();
75 if (parentCategoryNameValue.empty())
76 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +000077 throw arm::pipe::InvalidArgumentException(
78 fmt::format("Trying to connect a device (name: \"{}\") to an invalid "
79 "parent category (name: \"{}\")",
80 deviceName,
81 parentCategoryNameValue));
Matteo Martincigh6db5f202019-09-05 12:02:04 +010082 }
83
84 // Check that the given parent category is already registered
85 auto categoryIt = FindCategory(parentCategoryNameValue);
86 if (categoryIt == m_Categories.end())
87 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +000088 throw arm::pipe::InvalidArgumentException(
89 fmt::format("Trying to connect a device (name: \"{}\") to a parent category that "
90 "is not registered (name: \"{}\")",
91 deviceName,
92 parentCategoryNameValue));
Matteo Martincigh6db5f202019-09-05 12:02:04 +010093 }
Matteo Martincigh6db5f202019-09-05 12:02:04 +010094 }
95
96 // Get the device UID
97 uint16_t deviceUid = GetNextUid();
Matteo Martincigh6db5f202019-09-05 12:02:04 +010098
99 // Create the device
100 DevicePtr device = std::make_unique<Device>(deviceUid, deviceName, cores);
Jim Flynn6730fe92022-03-10 22:57:47 +0000101 ARM_PIPE_ASSERT(device);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100102
103 // Get the raw device pointer
104 const Device* devicePtr = device.get();
Jim Flynn6730fe92022-03-10 22:57:47 +0000105 ARM_PIPE_ASSERT(devicePtr);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100106
107 // Register the device
108 m_Devices.insert(std::make_pair(deviceUid, std::move(device)));
109
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100110 return devicePtr;
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100111}
112
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100113const CounterSet* CounterDirectory::RegisterCounterSet(const std::string& counterSetName,
114 uint16_t count,
Jim Flynndecd08b2022-03-13 22:35:46 +0000115 const arm::pipe::Optional<std::string>& parentCategoryName)
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100116{
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100117 // Check that the given counter set name is valid
118 if (counterSetName.empty() ||
Jim Flynnbbfe6032020-07-20 16:57:44 +0100119 !arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>(counterSetName))
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100120 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +0000121 throw arm::pipe::InvalidArgumentException("Trying to register a counter set with an invalid name");
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100122 }
123
124 // Check that a counter set with the given name is not already registered
Matteo Martincigha84edee2019-10-02 12:50:57 +0100125 if (IsCounterSetRegistered(counterSetName))
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100126 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +0000127 throw arm::pipe::InvalidArgumentException(
128 fmt::format("Trying to register a counter set already registered (\"{}\")", counterSetName));
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100129 }
130
131 // Peek the next UID, do not get an actual valid UID just now as we don't want to waste a good UID in case
132 // the registration fails. We'll get a proper one once we're sure that the counter set can be registered
133 uint16_t counterSetUidPeek = GetNextUid(true);
134
135 // Check that a category with the given (optional) parent category name is already registered
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100136 if (parentCategoryName.has_value())
137 {
138 // Get the (optional) parent category name
139 const std::string& parentCategoryNameValue = parentCategoryName.value();
140 if (parentCategoryNameValue.empty())
141 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +0000142 throw arm::pipe::InvalidArgumentException(
143 fmt::format("Trying to connect a counter set (UID: {}) to an invalid "
Jan Eilers156113c2020-09-09 19:11:16 +0100144 "parent category (name: \"{}\")",
145 counterSetUidPeek,
146 parentCategoryNameValue));
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100147 }
148
149 // Check that the given parent category is already registered
150 auto it = FindCategory(parentCategoryNameValue);
151 if (it == m_Categories.end())
152 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +0000153 throw arm::pipe::InvalidArgumentException(
154 fmt::format("Trying to connect a counter set (UID: {}) to a parent category "
155 "that is not registered (name: \"{}\")",
156 counterSetUidPeek,
157 parentCategoryNameValue));
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100158 }
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100159 }
160
161 // Get the counter set UID
162 uint16_t counterSetUid = GetNextUid();
Jim Flynn6730fe92022-03-10 22:57:47 +0000163 ARM_PIPE_ASSERT(counterSetUid == counterSetUidPeek);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100164
165 // Create the counter set
166 CounterSetPtr counterSet = std::make_unique<CounterSet>(counterSetUid, counterSetName, count);
Jim Flynn6730fe92022-03-10 22:57:47 +0000167 ARM_PIPE_ASSERT(counterSet);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100168
169 // Get the raw counter set pointer
170 const CounterSet* counterSetPtr = counterSet.get();
Jim Flynn6730fe92022-03-10 22:57:47 +0000171 ARM_PIPE_ASSERT(counterSetPtr);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100172
173 // Register the counter set
174 m_CounterSets.insert(std::make_pair(counterSetUid, std::move(counterSet)));
175
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100176 return counterSetPtr;
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100177}
178
Jim Flynn4a962112022-03-13 20:18:58 +0000179const Counter* CounterDirectory::RegisterCounter(const std::string& applicationName,
Keith Davise394bd92019-12-02 15:12:19 +0000180 const uint16_t uid,
181 const std::string& parentCategoryName,
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100182 uint16_t counterClass,
183 uint16_t interpolation,
184 double multiplier,
185 const std::string& name,
186 const std::string& description,
Jim Flynndecd08b2022-03-13 22:35:46 +0000187 const arm::pipe::Optional<std::string>& units,
188 const arm::pipe::Optional<uint16_t>& numberOfCores,
189 const arm::pipe::Optional<uint16_t>& deviceUid,
190 const arm::pipe::Optional<uint16_t>& counterSetUid)
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100191{
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100192 // Check that the given parent category name is valid
193 if (parentCategoryName.empty() ||
Jim Flynnbbfe6032020-07-20 16:57:44 +0100194 !arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>(parentCategoryName))
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100195 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +0000196 throw arm::pipe::InvalidArgumentException("Trying to register a counter with an invalid parent category name");
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100197 }
198
199 // Check that the given class is valid
200 if (counterClass != 0 && counterClass != 1)
201 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +0000202 throw arm::pipe::InvalidArgumentException("Trying to register a counter with an invalid class");
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100203 }
204
205 // Check that the given interpolation is valid
206 if (interpolation != 0 && interpolation != 1)
207 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +0000208 throw arm::pipe::InvalidArgumentException("Trying to register a counter with an invalid interpolation");
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100209 }
210
211 // Check that the given multiplier is valid
212 if (multiplier == .0f)
213 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +0000214 throw arm::pipe::InvalidArgumentException("Trying to register a counter with an invalid multiplier");
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100215 }
216
217 // Check that the given name is valid
218 if (name.empty() ||
Jim Flynnbbfe6032020-07-20 16:57:44 +0100219 !arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>(name))
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100220 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +0000221 throw arm::pipe::InvalidArgumentException("Trying to register a counter with an invalid name");
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100222 }
223
224 // Check that the given description is valid
225 if (description.empty() ||
Jim Flynnbbfe6032020-07-20 16:57:44 +0100226 !arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceCharPolicy>(description))
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100227 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +0000228 throw arm::pipe::InvalidArgumentException("Trying to register a counter with an invalid description");
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100229 }
230
231 // Check that the given units are valid
232 if (units.has_value()
Jim Flynnbbfe6032020-07-20 16:57:44 +0100233 && !arm::pipe::IsValidSwTraceString<arm::pipe::SwTraceNameCharPolicy>(units.value()))
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100234 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +0000235 throw arm::pipe::InvalidArgumentException("Trying to register a counter with a invalid units");
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100236 }
237
238 // Check that the given parent category is registered
239 auto categoryIt = FindCategory(parentCategoryName);
240 if (categoryIt == m_Categories.end())
241 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +0000242 throw arm::pipe::InvalidArgumentException(
243 fmt::format("Trying to connect a counter to a category that is not registered (name: \"{}\")",
244 parentCategoryName));
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100245 }
246
247 // Get the parent category
248 const CategoryPtr& parentCategory = *categoryIt;
Jim Flynn6730fe92022-03-10 22:57:47 +0000249 ARM_PIPE_ASSERT(parentCategory);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100250
251 // Check that a counter with the given name is not already registered within the parent category
252 const std::vector<uint16_t>& parentCategoryCounters = parentCategory->m_Counters;
253 for (uint16_t parentCategoryCounterUid : parentCategoryCounters)
254 {
255 const Counter* parentCategoryCounter = GetCounter(parentCategoryCounterUid);
Jim Flynn6730fe92022-03-10 22:57:47 +0000256 ARM_PIPE_ASSERT(parentCategoryCounter);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100257
258 if (parentCategoryCounter->m_Name == name)
259 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +0000260 throw arm::pipe::InvalidArgumentException(
261 fmt::format("Trying to register a counter to category \"{}\" with a name that "
262 "is already used within that category (name: \"{}\")",
263 parentCategoryName,
264 name));
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100265 }
266 }
267
268 // Check that a counter set with the given (optional) UID is already registered
269 uint16_t counterSetUidValue = counterSetUid.has_value() ? counterSetUid.value() : 0;
270 if (counterSetUidValue > 0)
271 {
272 // Check that the (optional) counter set is already registered
Matteo Martincigha84edee2019-10-02 12:50:57 +0100273 if (!IsCounterSetRegistered(counterSetUidValue))
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100274 {
275 throw InvalidArgumentException(
Jan Eilers156113c2020-09-09 19:11:16 +0100276 fmt::format("Trying to connect a counter to a counter set that is "
277 "not registered (counter set UID: {})",
278 counterSetUidValue));
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100279 }
280 }
281
282 // Get the number of cores (this call may throw)
283 uint16_t deviceUidValue = deviceUid.has_value() ? deviceUid.value() : 0;
Sadik Armagan4c998992020-02-25 12:44:44 +0000284 uint16_t deviceCores = GetNumberOfCores(numberOfCores, deviceUidValue);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100285
286 // Get the counter UIDs and calculate the max counter UID
Keith Davise394bd92019-12-02 15:12:19 +0000287 std::vector<uint16_t> counterUids = GetNextCounterUids(uid, deviceCores);
Jim Flynn6730fe92022-03-10 22:57:47 +0000288 ARM_PIPE_ASSERT(!counterUids.empty());
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100289 uint16_t maxCounterUid = deviceCores <= 1 ? counterUids.front() : counterUids.back();
290
291 // Get the counter units
292 const std::string unitsValue = units.has_value() ? units.value() : "";
293
294 // Create the counter
Jim Flynn4a962112022-03-13 20:18:58 +0000295 CounterPtr counter = std::make_shared<Counter>(applicationName,
Keith Davise394bd92019-12-02 15:12:19 +0000296 counterUids.front(),
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100297 maxCounterUid,
298 counterClass,
299 interpolation,
300 multiplier,
301 name,
302 description,
303 unitsValue,
304 deviceUidValue,
305 counterSetUidValue);
Jim Flynn6730fe92022-03-10 22:57:47 +0000306 ARM_PIPE_ASSERT(counter);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100307
308 // Get the raw counter pointer
309 const Counter* counterPtr = counter.get();
Jim Flynn6730fe92022-03-10 22:57:47 +0000310 ARM_PIPE_ASSERT(counterPtr);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100311
312 // Process multiple counters if necessary
313 for (uint16_t counterUid : counterUids)
314 {
315 // Connect the counter to the parent category
316 parentCategory->m_Counters.push_back(counterUid);
317
318 // Register the counter
319 m_Counters.insert(std::make_pair(counterUid, counter));
320 }
321
322 return counterPtr;
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100323}
324
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100325const Category* CounterDirectory::GetCategory(const std::string& categoryName) const
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100326{
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100327 auto it = FindCategory(categoryName);
328 if (it == m_Categories.end())
329 {
330 return nullptr;
331 }
332
333 const Category* category = it->get();
Jim Flynn6730fe92022-03-10 22:57:47 +0000334 ARM_PIPE_ASSERT(category);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100335
336 return category;
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100337}
338
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100339const Device* CounterDirectory::GetDevice(uint16_t deviceUid) const
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100340{
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100341 auto it = FindDevice(deviceUid);
342 if (it == m_Devices.end())
343 {
344 return nullptr;
345 }
346
347 const Device* device = it->second.get();
Jim Flynn6730fe92022-03-10 22:57:47 +0000348 ARM_PIPE_ASSERT(device);
349 ARM_PIPE_ASSERT(device->m_Uid == deviceUid);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100350
351 return device;
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100352}
353
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100354const CounterSet* CounterDirectory::GetCounterSet(uint16_t counterSetUid) const
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100355{
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100356 auto it = FindCounterSet(counterSetUid);
357 if (it == m_CounterSets.end())
358 {
359 return nullptr;
360 }
361
362 const CounterSet* counterSet = it->second.get();
Jim Flynn6730fe92022-03-10 22:57:47 +0000363 ARM_PIPE_ASSERT(counterSet);
364 ARM_PIPE_ASSERT(counterSet->m_Uid == counterSetUid);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100365
366 return counterSet;
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100367}
368
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100369const Counter* CounterDirectory::GetCounter(uint16_t counterUid) const
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100370{
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100371 auto it = FindCounter(counterUid);
372 if (it == m_Counters.end())
373 {
374 return nullptr;
375 }
376
377 const Counter* counter = it->second.get();
Jim Flynn6730fe92022-03-10 22:57:47 +0000378 ARM_PIPE_ASSERT(counter);
379 ARM_PIPE_ASSERT(counter->m_Uid <= counterUid);
380 ARM_PIPE_ASSERT(counter->m_Uid <= counter->m_MaxCounterUid);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100381
382 return counter;
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100383}
384
Matteo Martincigha84edee2019-10-02 12:50:57 +0100385bool CounterDirectory::IsCategoryRegistered(const std::string& categoryName) const
386{
387 auto it = FindCategory(categoryName);
388
389 return it != m_Categories.end();
390}
391
392bool CounterDirectory::IsDeviceRegistered(uint16_t deviceUid) const
393{
394 auto it = FindDevice(deviceUid);
395
396 return it != m_Devices.end();
397}
398
399bool CounterDirectory::IsDeviceRegistered(const std::string& deviceName) const
400{
401 auto it = FindDevice(deviceName);
402
403 return it != m_Devices.end();
404}
405
406bool CounterDirectory::IsCounterSetRegistered(uint16_t counterSetUid) const
407{
408 auto it = FindCounterSet(counterSetUid);
409
410 return it != m_CounterSets.end();
411}
412
413bool CounterDirectory::IsCounterSetRegistered(const std::string& counterSetName) const
414{
415 auto it = FindCounterSet(counterSetName);
416
417 return it != m_CounterSets.end();
418}
419
420bool CounterDirectory::IsCounterRegistered(uint16_t counterUid) const
421{
422 auto it = FindCounter(counterUid);
423
424 return it != m_Counters.end();
425}
426
427bool CounterDirectory::IsCounterRegistered(const std::string& counterName) const
428{
429 auto it = FindCounter(counterName);
430
431 return it != m_Counters.end();
432}
433
434void CounterDirectory::Clear()
435{
436 // Clear all the counter directory contents
437 m_Categories.clear();
438 m_Devices.clear();
439 m_CounterSets.clear();
440 m_Counters.clear();
441}
442
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100443CategoriesIt CounterDirectory::FindCategory(const std::string& categoryName) const
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100444{
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100445 return std::find_if(m_Categories.begin(), m_Categories.end(), [&categoryName](const CategoryPtr& category)
446 {
Jim Flynn6730fe92022-03-10 22:57:47 +0000447 ARM_PIPE_ASSERT(category);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100448
449 return category->m_Name == categoryName;
450 });
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100451}
452
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100453DevicesIt CounterDirectory::FindDevice(uint16_t deviceUid) const
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100454{
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100455 return m_Devices.find(deviceUid);
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100456}
457
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100458DevicesIt CounterDirectory::FindDevice(const std::string& deviceName) const
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100459{
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100460 return std::find_if(m_Devices.begin(), m_Devices.end(), [&deviceName](const auto& pair)
461 {
Jim Flynn6730fe92022-03-10 22:57:47 +0000462 ARM_PIPE_ASSERT(pair.second);
463 ARM_PIPE_ASSERT(pair.second->m_Uid == pair.first);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100464
465 return pair.second->m_Name == deviceName;
466 });
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100467}
468
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100469CounterSetsIt CounterDirectory::FindCounterSet(uint16_t counterSetUid) const
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100470{
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100471 return m_CounterSets.find(counterSetUid);
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100472}
473
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100474CounterSetsIt CounterDirectory::FindCounterSet(const std::string& counterSetName) const
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100475{
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100476 return std::find_if(m_CounterSets.begin(), m_CounterSets.end(), [&counterSetName](const auto& pair)
477 {
Jim Flynn6730fe92022-03-10 22:57:47 +0000478 ARM_PIPE_ASSERT(pair.second);
479 ARM_PIPE_ASSERT(pair.second->m_Uid == pair.first);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100480
481 return pair.second->m_Name == counterSetName;
482 });
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100483}
484
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100485CountersIt CounterDirectory::FindCounter(uint16_t counterUid) const
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100486{
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100487 return m_Counters.find(counterUid);
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100488}
489
Matteo Martincigha84edee2019-10-02 12:50:57 +0100490CountersIt CounterDirectory::FindCounter(const std::string& counterName) const
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100491{
Matteo Martincigha84edee2019-10-02 12:50:57 +0100492 return std::find_if(m_Counters.begin(), m_Counters.end(), [&counterName](const auto& pair)
493 {
Jim Flynn6730fe92022-03-10 22:57:47 +0000494 ARM_PIPE_ASSERT(pair.second);
495 ARM_PIPE_ASSERT(pair.first >= pair.second->m_Uid && pair.first <= pair.second->m_MaxCounterUid);
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100496
Matteo Martincigha84edee2019-10-02 12:50:57 +0100497 return pair.second->m_Name == counterName;
498 });
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100499}
500
Jim Flynndecd08b2022-03-13 22:35:46 +0000501uint16_t CounterDirectory::GetNumberOfCores(const arm::pipe::Optional<uint16_t>& numberOfCores,
Sadik Armagan4c998992020-02-25 12:44:44 +0000502 uint16_t deviceUid)
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100503{
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100504 // To get the number of cores, apply the following rules:
505 //
506 // 1. If numberOfCores is set then take it as the deviceCores value
507 // 2. If numberOfCores is not set then check to see if this counter is directly associated with a device,
508 // if so then that devices number of cores is taken as the deviceCores value
Sadik Armagan4c998992020-02-25 12:44:44 +0000509 // 3. If none of the above holds then set deviceCores to zero
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100510
511 // 1. If numberOfCores is set then take it as the deviceCores value
512 if (numberOfCores.has_value())
513 {
514 // Get the number of cores
515 return numberOfCores.value();
516 }
517
518 // 2. If numberOfCores is not set then check to see if this counter is directly associated with a device,
519 // if so then that devices number of cores is taken as the deviceCores value
520 if (deviceUid > 0)
521 {
522 // Check that the (optional) device is already registered
523 auto deviceIt = FindDevice(deviceUid);
524 if (deviceIt == m_Devices.end())
525 {
Jim Flynnf9db3ef2022-03-08 21:23:44 +0000526 throw arm::pipe::InvalidArgumentException(
527 fmt::format("Trying to connect a counter to a device that is not registered (device UID {})",
528 deviceUid));
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100529 }
530
531 // Get the associated device
532 const DevicePtr& device = deviceIt->second;
Jim Flynn6730fe92022-03-10 22:57:47 +0000533 ARM_PIPE_ASSERT(device);
534
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100535
536 // Get the number of cores of the associated device
537 return device->m_Cores;
538 }
539
Sadik Armagan4c998992020-02-25 12:44:44 +0000540 // 3. If none of the above holds then set deviceCores to zero
Matteo Martincigh6db5f202019-09-05 12:02:04 +0100541 return 0;
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100542}
543
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000544} // namespace pipe
Aron Virginas-Tar4e5fc1f2019-08-22 18:10:52 +0100545
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000546} // namespace arm