blob: 4d517e5829c5a177ccf40328d9e69b4b4efe0620 [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#pragma once
7
Matteo Martincigh24e8f922019-09-19 11:57:46 +01008#include <SendCounterPacket.hpp>
9#include <ProfilingUtils.hpp>
Matteo Martincighe8485382019-10-10 14:08:21 +010010#include <IProfilingConnectionFactory.hpp>
Ferran Balaguer1b941722019-08-28 16:57:18 +010011
12#include <armnn/Exceptions.hpp>
Matteo Martincigh24e8f922019-09-19 11:57:46 +010013#include <armnn/Optional.hpp>
14#include <armnn/Conversion.hpp>
Ferran Balaguer1b941722019-08-28 16:57:18 +010015
Matteo Martincighd0613b52019-10-09 16:47:04 +010016#include <boost/assert.hpp>
Derek Lambertif143fba2020-01-02 13:50:57 +000017#include <boost/core/ignore_unused.hpp>
Matteo Martincigh24e8f922019-09-19 11:57:46 +010018#include <boost/numeric/conversion/cast.hpp>
Ferran Balaguer1b941722019-08-28 16:57:18 +010019
Matteo Martincigh24e8f922019-09-19 11:57:46 +010020namespace armnn
21{
Ferran Balaguer1b941722019-08-28 16:57:18 +010022
Matteo Martincigh24e8f922019-09-19 11:57:46 +010023namespace profiling
24{
Matteo Martincighd0613b52019-10-09 16:47:04 +010025
Matteo Martincigh24e8f922019-09-19 11:57:46 +010026class MockProfilingConnection : public IProfilingConnection
27{
28public:
29 MockProfilingConnection()
30 : m_IsOpen(true)
Matteo Martincigh54fb9572019-10-02 12:50:57 +010031 , m_WrittenData()
32 , m_Packet()
Matteo Martincigh24e8f922019-09-19 11:57:46 +010033 {}
34
Finn Williams09ad6f92019-12-19 17:05:18 +000035 enum class PacketType
36 {
37 StreamMetaData,
38 ConnectionAcknowledge,
39 CounterDirectory,
40 ReqCounterDirectory,
41 PeriodicCounterSelection,
42 PerJobCounterSelection,
43 TimelineMessageDirectory,
44 PeriodicCounterCapture,
45 Unknown
46 };
47
Matteo Martincighd0613b52019-10-09 16:47:04 +010048 bool IsOpen() const override
49 {
50 std::lock_guard<std::mutex> lock(m_Mutex);
Matteo Martincigh24e8f922019-09-19 11:57:46 +010051
Matteo Martincighd0613b52019-10-09 16:47:04 +010052 return m_IsOpen;
53 }
54
55 void Close() override
56 {
57 std::lock_guard<std::mutex> lock(m_Mutex);
58
59 m_IsOpen = false;
60 }
Matteo Martincigh24e8f922019-09-19 11:57:46 +010061
62 bool WritePacket(const unsigned char* buffer, uint32_t length) override
63 {
Matteo Martincigh5d737fb2019-10-07 13:05:13 +010064 if (buffer == nullptr || length == 0)
65 {
66 return false;
67 }
Matteo Martincigh24e8f922019-09-19 11:57:46 +010068
Finn Williams09ad6f92019-12-19 17:05:18 +000069 uint32_t header = ReadUint32(buffer, 0);
70
71 uint32_t packetFamily = (header >> 26);
72 uint32_t packetId = ((header >> 16) & 1023);
73
74 PacketType packetType;
75
76 switch (packetFamily)
77 {
78 case 0:
79 packetType = packetId < 6 ? PacketType(packetId) : PacketType::Unknown;
80 break;
81 case 1:
82 packetType = packetId == 0 ? PacketType::TimelineMessageDirectory : PacketType::Unknown;
83 break;
84 case 3:
85 packetType = packetId == 0 ? PacketType::PeriodicCounterCapture : PacketType::Unknown;
86 break;
87 default:
88 packetType = PacketType::Unknown;
89 }
90
Matteo Martincighd0613b52019-10-09 16:47:04 +010091 std::lock_guard<std::mutex> lock(m_Mutex);
92
Finn Williams09ad6f92019-12-19 17:05:18 +000093 m_WrittenData.push_back({ packetType, length });
Matteo Martincigh5d737fb2019-10-07 13:05:13 +010094 return true;
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +010095 }
Finn Williams09ad6f92019-12-19 17:05:18 +000096
97 long CheckForPacket(const std::pair<PacketType, uint32_t> packetInfo)
98 {
99 std::lock_guard<std::mutex> lock(m_Mutex);
100
101 if(packetInfo.second != 0)
102 {
103 return std::count(m_WrittenData.begin(), m_WrittenData.end(), packetInfo);
104 }
105 else
106 {
107 return std::count_if(m_WrittenData.begin(), m_WrittenData.end(),
108 [&packetInfo](const std::pair<PacketType, uint32_t> pair) { return packetInfo.first == pair.first; });
109 }
110 }
111
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100112 bool WritePacket(Packet&& packet)
113 {
Matteo Martincighd0613b52019-10-09 16:47:04 +0100114 std::lock_guard<std::mutex> lock(m_Mutex);
115
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100116 m_Packet = std::move(packet);
117 return true;
118 }
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +0100119
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100120 Packet ReadPacket(uint32_t timeout) override
121 {
Derek Lamberti1dd75b32019-12-10 21:23:23 +0000122 boost::ignore_unused(timeout);
123
Colm Donelan2ba48d22019-11-29 09:10:59 +0000124 // Simulate a delay in the reading process. The default timeout is way too long.
125 std::this_thread::sleep_for(std::chrono::milliseconds(5));
Matteo Martincighd0613b52019-10-09 16:47:04 +0100126 std::lock_guard<std::mutex> lock(m_Mutex);
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100127 return std::move(m_Packet);
128 }
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +0100129
Finn Williams09ad6f92019-12-19 17:05:18 +0000130 unsigned long GetWrittenDataSize()
Matteo Martincighd0613b52019-10-09 16:47:04 +0100131 {
132 std::lock_guard<std::mutex> lock(m_Mutex);
Matteo Martincigh5d737fb2019-10-07 13:05:13 +0100133
Finn Williams09ad6f92019-12-19 17:05:18 +0000134 return m_WrittenData.size();
Colm Donelan2ba48d22019-11-29 09:10:59 +0000135 }
136
Matteo Martincighd0613b52019-10-09 16:47:04 +0100137 void Clear()
138 {
139 std::lock_guard<std::mutex> lock(m_Mutex);
140
141 m_WrittenData.clear();
142 }
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +0100143
144private:
145 bool m_IsOpen;
Finn Williams09ad6f92019-12-19 17:05:18 +0000146 std::vector<std::pair<PacketType, uint32_t>> m_WrittenData;
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100147 Packet m_Packet;
Matteo Martincighd0613b52019-10-09 16:47:04 +0100148 mutable std::mutex m_Mutex;
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +0100149};
150
Matteo Martincighe8485382019-10-10 14:08:21 +0100151class MockProfilingConnectionFactory : public IProfilingConnectionFactory
152{
153public:
154 IProfilingConnectionPtr GetProfilingConnection(const ExternalProfilingOptions& options) const override
155 {
Derek Lamberti1dd75b32019-12-10 21:23:23 +0000156 boost::ignore_unused(options);
Matteo Martincighe8485382019-10-10 14:08:21 +0100157 return std::make_unique<MockProfilingConnection>();
158 }
159};
160
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100161class MockPacketBuffer : public IPacketBuffer
Ferran Balaguer1b941722019-08-28 16:57:18 +0100162{
163public:
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100164 MockPacketBuffer(unsigned int maxSize)
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100165 : m_MaxSize(maxSize)
166 , m_Size(0)
167 , m_Data(std::make_unique<unsigned char[]>(m_MaxSize))
168 {}
Ferran Balaguer1b941722019-08-28 16:57:18 +0100169
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100170 ~MockPacketBuffer() {}
171
Matteo Martincigh76c50d82019-11-21 12:10:42 +0000172 const unsigned char* GetReadableData() const override { return m_Data.get(); }
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100173
174 unsigned int GetSize() const override { return m_Size; }
175
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100176 void MarkRead() override { m_Size = 0; }
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100177
178 void Commit(unsigned int size) override { m_Size = size; }
179
180 void Release() override { m_Size = 0; }
181
182 unsigned char* GetWritableData() override { return m_Data.get(); }
183
184private:
185 unsigned int m_MaxSize;
186 unsigned int m_Size;
187 std::unique_ptr<unsigned char[]> m_Data;
188};
189
190class MockBufferManager : public IBufferManager
191{
192public:
193 MockBufferManager(unsigned int size)
194 : m_BufferSize(size),
195 m_Buffer(std::make_unique<MockPacketBuffer>(size)) {}
196
197 ~MockBufferManager() {}
198
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000199 IPacketBufferPtr Reserve(unsigned int requestedSize, unsigned int& reservedSize) override
Ferran Balaguer1b941722019-08-28 16:57:18 +0100200 {
201 if (requestedSize > m_BufferSize)
202 {
203 reservedSize = m_BufferSize;
204 }
205 else
206 {
207 reservedSize = requestedSize;
208 }
209
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100210 return std::move(m_Buffer);
Ferran Balaguer1b941722019-08-28 16:57:18 +0100211 }
212
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000213 void Commit(IPacketBufferPtr& packetBuffer, unsigned int size) override
Ferran Balaguer1b941722019-08-28 16:57:18 +0100214 {
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100215 packetBuffer->Commit(size);
216 m_Buffer = std::move(packetBuffer);
Ferran Balaguer1b941722019-08-28 16:57:18 +0100217 }
218
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000219 IPacketBufferPtr GetReadableBuffer() override
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100220 {
221 return std::move(m_Buffer);
222 }
223
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000224 void Release(IPacketBufferPtr& packetBuffer) override
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100225 {
226 packetBuffer->Release();
227 m_Buffer = std::move(packetBuffer);
228 }
229
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000230 void MarkRead(IPacketBufferPtr& packetBuffer) override
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100231 {
232 packetBuffer->MarkRead();
233 m_Buffer = std::move(packetBuffer);
234 }
Ferran Balaguer1b941722019-08-28 16:57:18 +0100235
236private:
237 unsigned int m_BufferSize;
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000238 IPacketBufferPtr m_Buffer;
Ferran Balaguer1b941722019-08-28 16:57:18 +0100239};
240
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100241class MockStreamCounterBuffer : public IBufferManager
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100242{
243public:
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100244 MockStreamCounterBuffer(unsigned int maxBufferSize = 4096)
245 : m_MaxBufferSize(maxBufferSize)
246 , m_BufferList()
247 , m_CommittedSize(0)
248 , m_ReadableSize(0)
249 , m_ReadSize(0)
250 {}
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100251 ~MockStreamCounterBuffer() {}
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100252
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100253 IPacketBufferPtr Reserve(unsigned int requestedSize, unsigned int& reservedSize) override
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100254 {
Matteo Martincighd0613b52019-10-09 16:47:04 +0100255 std::lock_guard<std::mutex> lock(m_Mutex);
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100256
257 reservedSize = 0;
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100258 if (requestedSize > m_MaxBufferSize)
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +0100259 {
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100260 throw armnn::InvalidArgumentException("The maximum buffer size that can be requested is [" +
261 std::to_string(m_MaxBufferSize) + "] bytes");
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +0100262 }
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100263 reservedSize = requestedSize;
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100264 return std::make_unique<MockPacketBuffer>(requestedSize);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100265 }
266
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100267 void Commit(IPacketBufferPtr& packetBuffer, unsigned int size) override
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100268 {
Matteo Martincighd0613b52019-10-09 16:47:04 +0100269 std::lock_guard<std::mutex> lock(m_Mutex);
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100270
271 packetBuffer->Commit(size);
272 m_BufferList.push_back(std::move(packetBuffer));
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100273 m_CommittedSize += size;
274 }
275
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100276 void Release(IPacketBufferPtr& packetBuffer) override
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100277 {
Matteo Martincighd0613b52019-10-09 16:47:04 +0100278 std::lock_guard<std::mutex> lock(m_Mutex);
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100279
280 packetBuffer->Release();
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100281 }
282
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100283 IPacketBufferPtr GetReadableBuffer() override
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100284 {
Matteo Martincighd0613b52019-10-09 16:47:04 +0100285 std::lock_guard<std::mutex> lock(m_Mutex);
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100286
287 if (m_BufferList.empty())
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100288 {
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100289 return nullptr;
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100290 }
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100291 IPacketBufferPtr buffer = std::move(m_BufferList.back());
292 m_BufferList.pop_back();
293 m_ReadableSize += buffer->GetSize();
294 return buffer;
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100295 }
296
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100297 void MarkRead(IPacketBufferPtr& packetBuffer) override
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100298 {
Matteo Martincighd0613b52019-10-09 16:47:04 +0100299 std::lock_guard<std::mutex> lock(m_Mutex);
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100300
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100301 m_ReadSize += packetBuffer->GetSize();
302 packetBuffer->MarkRead();
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100303 }
304
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100305 unsigned int GetCommittedSize() const { return m_CommittedSize; }
306 unsigned int GetReadableSize() const { return m_ReadableSize; }
307 unsigned int GetReadSize() const { return m_ReadSize; }
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100308
309private:
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100310 // The maximum buffer size when creating a new buffer
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100311 unsigned int m_MaxBufferSize;
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100312
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100313 // A list of buffers
314 std::vector<IPacketBufferPtr> m_BufferList;
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100315
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100316 // The mutex to synchronize this mock's methods
317 std::mutex m_Mutex;
318
319 // The total size of the buffers that has been committed for reading
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100320 unsigned int m_CommittedSize;
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100321
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100322 // The total size of the buffers that can be read
323 unsigned int m_ReadableSize;
324
325 // The total size of the buffers that has already been read
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100326 unsigned int m_ReadSize;
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100327};
328
Ferran Balaguer1b941722019-08-28 16:57:18 +0100329class MockSendCounterPacket : public ISendCounterPacket
330{
331public:
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100332 MockSendCounterPacket(IBufferManager& sendBuffer) : m_BufferManager(sendBuffer) {}
Ferran Balaguer1b941722019-08-28 16:57:18 +0100333
334 void SendStreamMetaDataPacket() override
335 {
336 std::string message("SendStreamMetaDataPacket");
337 unsigned int reserved = 0;
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000338 IPacketBufferPtr buffer = m_BufferManager.Reserve(1024, reserved);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100339 memcpy(buffer->GetWritableData(), message.c_str(), static_cast<unsigned int>(message.size()) + 1);
340 m_BufferManager.Commit(buffer, reserved);
Ferran Balaguer1b941722019-08-28 16:57:18 +0100341 }
342
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100343 void SendCounterDirectoryPacket(const ICounterDirectory& counterDirectory) override
Ferran Balaguer1b941722019-08-28 16:57:18 +0100344 {
Derek Lamberti1dd75b32019-12-10 21:23:23 +0000345 boost::ignore_unused(counterDirectory);
346
Ferran Balaguer1b941722019-08-28 16:57:18 +0100347 std::string message("SendCounterDirectoryPacket");
348 unsigned int reserved = 0;
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000349 IPacketBufferPtr buffer = m_BufferManager.Reserve(1024, reserved);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100350 memcpy(buffer->GetWritableData(), message.c_str(), static_cast<unsigned int>(message.size()) + 1);
351 m_BufferManager.Commit(buffer, reserved);
Ferran Balaguer1b941722019-08-28 16:57:18 +0100352 }
353
354 void SendPeriodicCounterCapturePacket(uint64_t timestamp,
355 const std::vector<std::pair<uint16_t, uint32_t>>& values) override
356 {
Derek Lamberti1dd75b32019-12-10 21:23:23 +0000357 boost::ignore_unused(timestamp, values);
358
Ferran Balaguer1b941722019-08-28 16:57:18 +0100359 std::string message("SendPeriodicCounterCapturePacket");
360 unsigned int reserved = 0;
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000361 IPacketBufferPtr buffer = m_BufferManager.Reserve(1024, reserved);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100362 memcpy(buffer->GetWritableData(), message.c_str(), static_cast<unsigned int>(message.size()) + 1);
363 m_BufferManager.Commit(buffer, reserved);
Ferran Balaguer1b941722019-08-28 16:57:18 +0100364 }
365
366 void SendPeriodicCounterSelectionPacket(uint32_t capturePeriod,
367 const std::vector<uint16_t>& selectedCounterIds) override
368 {
Derek Lamberti1dd75b32019-12-10 21:23:23 +0000369 boost::ignore_unused(capturePeriod, selectedCounterIds);
370
Ferran Balaguer1b941722019-08-28 16:57:18 +0100371 std::string message("SendPeriodicCounterSelectionPacket");
372 unsigned int reserved = 0;
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000373 IPacketBufferPtr buffer = m_BufferManager.Reserve(1024, reserved);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100374 memcpy(buffer->GetWritableData(), message.c_str(), static_cast<unsigned int>(message.size()) + 1);
375 m_BufferManager.Commit(buffer, reserved);
Ferran Balaguer1b941722019-08-28 16:57:18 +0100376 }
377
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100378 void SetReadyToRead() override {}
Ferran Balaguer1b941722019-08-28 16:57:18 +0100379
380private:
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100381 IBufferManager& m_BufferManager;
Ferran Balaguer1b941722019-08-28 16:57:18 +0100382};
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100383
384class MockCounterDirectory : public ICounterDirectory
385{
386public:
387 MockCounterDirectory() = default;
388 ~MockCounterDirectory() = default;
389
390 // Register profiling objects
391 const Category* RegisterCategory(const std::string& categoryName,
392 const armnn::Optional<uint16_t>& deviceUid = armnn::EmptyOptional(),
393 const armnn::Optional<uint16_t>& counterSetUid = armnn::EmptyOptional())
394 {
395 // Get the device UID
396 uint16_t deviceUidValue = deviceUid.has_value() ? deviceUid.value() : 0;
397
398 // Get the counter set UID
399 uint16_t counterSetUidValue = counterSetUid.has_value() ? counterSetUid.value() : 0;
400
401 // Create the category
402 CategoryPtr category = std::make_unique<Category>(categoryName, deviceUidValue, counterSetUidValue);
403 BOOST_ASSERT(category);
404
405 // Get the raw category pointer
406 const Category* categoryPtr = category.get();
407 BOOST_ASSERT(categoryPtr);
408
409 // Register the category
410 m_Categories.insert(std::move(category));
411
412 return categoryPtr;
413 }
414
415 const Device* RegisterDevice(const std::string& deviceName,
416 uint16_t cores = 0,
417 const armnn::Optional<std::string>& parentCategoryName = armnn::EmptyOptional())
418 {
419 // Get the device UID
420 uint16_t deviceUid = GetNextUid();
421
422 // Create the device
423 DevicePtr device = std::make_unique<Device>(deviceUid, deviceName, cores);
424 BOOST_ASSERT(device);
425
426 // Get the raw device pointer
427 const Device* devicePtr = device.get();
428 BOOST_ASSERT(devicePtr);
429
430 // Register the device
431 m_Devices.insert(std::make_pair(deviceUid, std::move(device)));
432
433 // Connect the counter set to the parent category, if required
434 if (parentCategoryName.has_value())
435 {
436 // Set the counter set UID in the parent category
437 Category* parentCategory = const_cast<Category*>(GetCategory(parentCategoryName.value()));
438 BOOST_ASSERT(parentCategory);
439 parentCategory->m_DeviceUid = deviceUid;
440 }
441
442 return devicePtr;
443 }
444
445 const CounterSet* RegisterCounterSet(
446 const std::string& counterSetName,
447 uint16_t count = 0,
448 const armnn::Optional<std::string>& parentCategoryName = armnn::EmptyOptional())
449 {
450 // Get the counter set UID
451 uint16_t counterSetUid = GetNextUid();
452
453 // Create the counter set
454 CounterSetPtr counterSet = std::make_unique<CounterSet>(counterSetUid, counterSetName, count);
455 BOOST_ASSERT(counterSet);
456
457 // Get the raw counter set pointer
458 const CounterSet* counterSetPtr = counterSet.get();
459 BOOST_ASSERT(counterSetPtr);
460
461 // Register the counter set
462 m_CounterSets.insert(std::make_pair(counterSetUid, std::move(counterSet)));
463
464 // Connect the counter set to the parent category, if required
465 if (parentCategoryName.has_value())
466 {
467 // Set the counter set UID in the parent category
468 Category* parentCategory = const_cast<Category*>(GetCategory(parentCategoryName.value()));
469 BOOST_ASSERT(parentCategory);
470 parentCategory->m_CounterSetUid = counterSetUid;
471 }
472
473 return counterSetPtr;
474 }
475
Keith Davise394bd92019-12-02 15:12:19 +0000476 const Counter* RegisterCounter(const BackendId& backendId,
477 const uint16_t uid,
478 const std::string& parentCategoryName,
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100479 uint16_t counterClass,
480 uint16_t interpolation,
481 double multiplier,
482 const std::string& name,
483 const std::string& description,
484 const armnn::Optional<std::string>& units = armnn::EmptyOptional(),
485 const armnn::Optional<uint16_t>& numberOfCores = armnn::EmptyOptional(),
486 const armnn::Optional<uint16_t>& deviceUid = armnn::EmptyOptional(),
487 const armnn::Optional<uint16_t>& counterSetUid = armnn::EmptyOptional())
488 {
Derek Lambertif143fba2020-01-02 13:50:57 +0000489 boost::ignore_unused(backendId);
490
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100491 // Get the number of cores from the argument only
492 uint16_t deviceCores = numberOfCores.has_value() ? numberOfCores.value() : 0;
493
494 // Get the device UID
495 uint16_t deviceUidValue = deviceUid.has_value() ? deviceUid.value() : 0;
496
497 // Get the counter set UID
498 uint16_t counterSetUidValue = counterSetUid.has_value() ? counterSetUid.value() : 0;
499
500 // Get the counter UIDs and calculate the max counter UID
Keith Davise394bd92019-12-02 15:12:19 +0000501 std::vector<uint16_t> counterUids = GetNextCounterUids(uid, deviceCores);
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100502 BOOST_ASSERT(!counterUids.empty());
503 uint16_t maxCounterUid = deviceCores <= 1 ? counterUids.front() : counterUids.back();
504
505 // Get the counter units
506 const std::string unitsValue = units.has_value() ? units.value() : "";
507
508 // Create the counter
Keith Davise394bd92019-12-02 15:12:19 +0000509 CounterPtr counter = std::make_shared<Counter>(armnn::profiling::BACKEND_ID,
510 counterUids.front(),
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100511 maxCounterUid,
512 counterClass,
513 interpolation,
514 multiplier,
515 name,
516 description,
517 unitsValue,
518 deviceUidValue,
519 counterSetUidValue);
520 BOOST_ASSERT(counter);
521
522 // Get the raw counter pointer
523 const Counter* counterPtr = counter.get();
524 BOOST_ASSERT(counterPtr);
525
526 // Process multiple counters if necessary
527 for (uint16_t counterUid : counterUids)
528 {
529 // Connect the counter to the parent category
530 Category* parentCategory = const_cast<Category*>(GetCategory(parentCategoryName));
531 BOOST_ASSERT(parentCategory);
532 parentCategory->m_Counters.push_back(counterUid);
533
534 // Register the counter
535 m_Counters.insert(std::make_pair(counterUid, counter));
536 }
537
538 return counterPtr;
539 }
540
541 // Getters for counts
542 uint16_t GetCategoryCount() const override { return boost::numeric_cast<uint16_t>(m_Categories.size()); }
543 uint16_t GetDeviceCount() const override { return boost::numeric_cast<uint16_t>(m_Devices.size()); }
544 uint16_t GetCounterSetCount() const override { return boost::numeric_cast<uint16_t>(m_CounterSets.size()); }
545 uint16_t GetCounterCount() const override { return boost::numeric_cast<uint16_t>(m_Counters.size()); }
546
547 // Getters for collections
548 const Categories& GetCategories() const override { return m_Categories; }
549 const Devices& GetDevices() const override { return m_Devices; }
550 const CounterSets& GetCounterSets() const override { return m_CounterSets; }
551 const Counters& GetCounters() const override { return m_Counters; }
552
553 // Getters for profiling objects
554 const Category* GetCategory(const std::string& name) const override
555 {
556 auto it = std::find_if(m_Categories.begin(), m_Categories.end(), [&name](const CategoryPtr& category)
557 {
558 BOOST_ASSERT(category);
559
560 return category->m_Name == name;
561 });
562
563 if (it == m_Categories.end())
564 {
565 return nullptr;
566 }
567
568 return it->get();
569 }
570
571 const Device* GetDevice(uint16_t uid) const override
572 {
Derek Lamberti1dd75b32019-12-10 21:23:23 +0000573 boost::ignore_unused(uid);
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100574 return nullptr; // Not used by the unit tests
575 }
576
577 const CounterSet* GetCounterSet(uint16_t uid) const override
578 {
Derek Lamberti1dd75b32019-12-10 21:23:23 +0000579 boost::ignore_unused(uid);
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100580 return nullptr; // Not used by the unit tests
581 }
582
583 const Counter* GetCounter(uint16_t uid) const override
584 {
Derek Lamberti1dd75b32019-12-10 21:23:23 +0000585 boost::ignore_unused(uid);
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100586 return nullptr; // Not used by the unit tests
587 }
588
589private:
590 Categories m_Categories;
591 Devices m_Devices;
592 CounterSets m_CounterSets;
593 Counters m_Counters;
594};
595
596class SendCounterPacketTest : public SendCounterPacket
597{
598public:
Matteo Martincigh5d737fb2019-10-07 13:05:13 +0100599 SendCounterPacketTest(ProfilingStateMachine& profilingStateMachine, IBufferManager& buffer)
600 : SendCounterPacket(profilingStateMachine, buffer)
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100601 {}
602
603 bool CreateDeviceRecordTest(const DevicePtr& device,
604 DeviceRecord& deviceRecord,
605 std::string& errorMessage)
606 {
607 return CreateDeviceRecord(device, deviceRecord, errorMessage);
608 }
609
610 bool CreateCounterSetRecordTest(const CounterSetPtr& counterSet,
611 CounterSetRecord& counterSetRecord,
612 std::string& errorMessage)
613 {
614 return CreateCounterSetRecord(counterSet, counterSetRecord, errorMessage);
615 }
616
617 bool CreateEventRecordTest(const CounterPtr& counter,
618 EventRecord& eventRecord,
619 std::string& errorMessage)
620 {
621 return CreateEventRecord(counter, eventRecord, errorMessage);
622 }
623
624 bool CreateCategoryRecordTest(const CategoryPtr& category,
625 const Counters& counters,
626 CategoryRecord& categoryRecord,
627 std::string& errorMessage)
628 {
629 return CreateCategoryRecord(category, counters, categoryRecord, errorMessage);
630 }
631};
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100632
633} // namespace profiling
634
635} // namespace armnn