blob: c7fc7b84ace81f57f980833c553cbeb8d76dc949 [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>
Sadik Armagan3896b472020-02-10 12:24:15 +00009#include <SendThread.hpp>
Matteo Martincigh24e8f922019-09-19 11:57:46 +010010#include <ProfilingUtils.hpp>
Matteo Martincighe8485382019-10-10 14:08:21 +010011#include <IProfilingConnectionFactory.hpp>
Ferran Balaguer1b941722019-08-28 16:57:18 +010012
13#include <armnn/Exceptions.hpp>
Matteo Martincigh24e8f922019-09-19 11:57:46 +010014#include <armnn/Optional.hpp>
15#include <armnn/Conversion.hpp>
Ferran Balaguer1b941722019-08-28 16:57:18 +010016
Matteo Martincighd0613b52019-10-09 16:47:04 +010017#include <boost/assert.hpp>
Derek Lambertif143fba2020-01-02 13:50:57 +000018#include <boost/core/ignore_unused.hpp>
Matteo Martincigh24e8f922019-09-19 11:57:46 +010019#include <boost/numeric/conversion/cast.hpp>
Ferran Balaguer1b941722019-08-28 16:57:18 +010020
Sadik Armagan3896b472020-02-10 12:24:15 +000021#include <atomic>
22#include <condition_variable>
23#include <mutex>
24#include <thread>
25
Matteo Martincigh24e8f922019-09-19 11:57:46 +010026namespace armnn
27{
Ferran Balaguer1b941722019-08-28 16:57:18 +010028
Matteo Martincigh24e8f922019-09-19 11:57:46 +010029namespace profiling
30{
Matteo Martincighd0613b52019-10-09 16:47:04 +010031
Matteo Martincigh24e8f922019-09-19 11:57:46 +010032class MockProfilingConnection : public IProfilingConnection
33{
34public:
35 MockProfilingConnection()
36 : m_IsOpen(true)
Matteo Martincigh54fb9572019-10-02 12:50:57 +010037 , m_WrittenData()
38 , m_Packet()
Matteo Martincigh24e8f922019-09-19 11:57:46 +010039 {}
40
Finn Williams09ad6f92019-12-19 17:05:18 +000041 enum class PacketType
42 {
43 StreamMetaData,
44 ConnectionAcknowledge,
45 CounterDirectory,
46 ReqCounterDirectory,
47 PeriodicCounterSelection,
48 PerJobCounterSelection,
49 TimelineMessageDirectory,
50 PeriodicCounterCapture,
51 Unknown
52 };
53
Matteo Martincighd0613b52019-10-09 16:47:04 +010054 bool IsOpen() const override
55 {
56 std::lock_guard<std::mutex> lock(m_Mutex);
Matteo Martincigh24e8f922019-09-19 11:57:46 +010057
Matteo Martincighd0613b52019-10-09 16:47:04 +010058 return m_IsOpen;
59 }
60
61 void Close() override
62 {
63 std::lock_guard<std::mutex> lock(m_Mutex);
64
65 m_IsOpen = false;
66 }
Matteo Martincigh24e8f922019-09-19 11:57:46 +010067
68 bool WritePacket(const unsigned char* buffer, uint32_t length) override
69 {
Matteo Martincigh5d737fb2019-10-07 13:05:13 +010070 if (buffer == nullptr || length == 0)
71 {
72 return false;
73 }
Matteo Martincigh24e8f922019-09-19 11:57:46 +010074
Finn Williams09ad6f92019-12-19 17:05:18 +000075 uint32_t header = ReadUint32(buffer, 0);
76
77 uint32_t packetFamily = (header >> 26);
78 uint32_t packetId = ((header >> 16) & 1023);
79
80 PacketType packetType;
81
82 switch (packetFamily)
83 {
84 case 0:
85 packetType = packetId < 6 ? PacketType(packetId) : PacketType::Unknown;
86 break;
87 case 1:
88 packetType = packetId == 0 ? PacketType::TimelineMessageDirectory : PacketType::Unknown;
89 break;
90 case 3:
91 packetType = packetId == 0 ? PacketType::PeriodicCounterCapture : PacketType::Unknown;
92 break;
93 default:
94 packetType = PacketType::Unknown;
95 }
96
Matteo Martincighd0613b52019-10-09 16:47:04 +010097 std::lock_guard<std::mutex> lock(m_Mutex);
98
Finn Williams09ad6f92019-12-19 17:05:18 +000099 m_WrittenData.push_back({ packetType, length });
Matteo Martincigh5d737fb2019-10-07 13:05:13 +0100100 return true;
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +0100101 }
Finn Williams09ad6f92019-12-19 17:05:18 +0000102
103 long CheckForPacket(const std::pair<PacketType, uint32_t> packetInfo)
104 {
105 std::lock_guard<std::mutex> lock(m_Mutex);
106
107 if(packetInfo.second != 0)
108 {
109 return std::count(m_WrittenData.begin(), m_WrittenData.end(), packetInfo);
110 }
111 else
112 {
113 return std::count_if(m_WrittenData.begin(), m_WrittenData.end(),
114 [&packetInfo](const std::pair<PacketType, uint32_t> pair) { return packetInfo.first == pair.first; });
115 }
116 }
117
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100118 bool WritePacket(Packet&& packet)
119 {
Matteo Martincighd0613b52019-10-09 16:47:04 +0100120 std::lock_guard<std::mutex> lock(m_Mutex);
121
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100122 m_Packet = std::move(packet);
123 return true;
124 }
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +0100125
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100126 Packet ReadPacket(uint32_t timeout) override
127 {
Derek Lamberti1dd75b32019-12-10 21:23:23 +0000128 boost::ignore_unused(timeout);
129
Colm Donelan2ba48d22019-11-29 09:10:59 +0000130 // Simulate a delay in the reading process. The default timeout is way too long.
131 std::this_thread::sleep_for(std::chrono::milliseconds(5));
Matteo Martincighd0613b52019-10-09 16:47:04 +0100132 std::lock_guard<std::mutex> lock(m_Mutex);
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100133 return std::move(m_Packet);
134 }
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +0100135
Finn Williams09ad6f92019-12-19 17:05:18 +0000136 unsigned long GetWrittenDataSize()
Matteo Martincighd0613b52019-10-09 16:47:04 +0100137 {
138 std::lock_guard<std::mutex> lock(m_Mutex);
Matteo Martincigh5d737fb2019-10-07 13:05:13 +0100139
Finn Williams09ad6f92019-12-19 17:05:18 +0000140 return m_WrittenData.size();
Colm Donelan2ba48d22019-11-29 09:10:59 +0000141 }
142
Matteo Martincighd0613b52019-10-09 16:47:04 +0100143 void Clear()
144 {
145 std::lock_guard<std::mutex> lock(m_Mutex);
146
147 m_WrittenData.clear();
148 }
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +0100149
150private:
151 bool m_IsOpen;
Finn Williams09ad6f92019-12-19 17:05:18 +0000152 std::vector<std::pair<PacketType, uint32_t>> m_WrittenData;
Matteo Martincigh54fb9572019-10-02 12:50:57 +0100153 Packet m_Packet;
Matteo Martincighd0613b52019-10-09 16:47:04 +0100154 mutable std::mutex m_Mutex;
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +0100155};
156
Matteo Martincighe8485382019-10-10 14:08:21 +0100157class MockProfilingConnectionFactory : public IProfilingConnectionFactory
158{
159public:
160 IProfilingConnectionPtr GetProfilingConnection(const ExternalProfilingOptions& options) const override
161 {
Derek Lamberti1dd75b32019-12-10 21:23:23 +0000162 boost::ignore_unused(options);
Matteo Martincighe8485382019-10-10 14:08:21 +0100163 return std::make_unique<MockProfilingConnection>();
164 }
165};
166
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100167class MockPacketBuffer : public IPacketBuffer
Ferran Balaguer1b941722019-08-28 16:57:18 +0100168{
169public:
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100170 MockPacketBuffer(unsigned int maxSize)
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100171 : m_MaxSize(maxSize)
172 , m_Size(0)
173 , m_Data(std::make_unique<unsigned char[]>(m_MaxSize))
174 {}
Ferran Balaguer1b941722019-08-28 16:57:18 +0100175
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100176 ~MockPacketBuffer() {}
177
Matteo Martincigh76c50d82019-11-21 12:10:42 +0000178 const unsigned char* GetReadableData() const override { return m_Data.get(); }
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100179
180 unsigned int GetSize() const override { return m_Size; }
181
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100182 void MarkRead() override { m_Size = 0; }
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100183
184 void Commit(unsigned int size) override { m_Size = size; }
185
186 void Release() override { m_Size = 0; }
187
188 unsigned char* GetWritableData() override { return m_Data.get(); }
189
190private:
191 unsigned int m_MaxSize;
192 unsigned int m_Size;
193 std::unique_ptr<unsigned char[]> m_Data;
194};
195
196class MockBufferManager : public IBufferManager
197{
198public:
199 MockBufferManager(unsigned int size)
200 : m_BufferSize(size),
201 m_Buffer(std::make_unique<MockPacketBuffer>(size)) {}
202
203 ~MockBufferManager() {}
204
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000205 IPacketBufferPtr Reserve(unsigned int requestedSize, unsigned int& reservedSize) override
Ferran Balaguer1b941722019-08-28 16:57:18 +0100206 {
207 if (requestedSize > m_BufferSize)
208 {
209 reservedSize = m_BufferSize;
210 }
211 else
212 {
213 reservedSize = requestedSize;
214 }
215
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100216 return std::move(m_Buffer);
Ferran Balaguer1b941722019-08-28 16:57:18 +0100217 }
218
Sadik Armagan3896b472020-02-10 12:24:15 +0000219 void Commit(IPacketBufferPtr& packetBuffer, unsigned int size, bool notifyConsumer = true) override
Ferran Balaguer1b941722019-08-28 16:57:18 +0100220 {
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100221 packetBuffer->Commit(size);
222 m_Buffer = std::move(packetBuffer);
Sadik Armagan3896b472020-02-10 12:24:15 +0000223
224 if (notifyConsumer)
225 {
226 FlushReadList();
227 }
Ferran Balaguer1b941722019-08-28 16:57:18 +0100228 }
229
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000230 IPacketBufferPtr GetReadableBuffer() override
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100231 {
232 return std::move(m_Buffer);
233 }
234
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000235 void Release(IPacketBufferPtr& packetBuffer) override
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100236 {
237 packetBuffer->Release();
238 m_Buffer = std::move(packetBuffer);
239 }
240
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000241 void MarkRead(IPacketBufferPtr& packetBuffer) override
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100242 {
243 packetBuffer->MarkRead();
244 m_Buffer = std::move(packetBuffer);
245 }
Ferran Balaguer1b941722019-08-28 16:57:18 +0100246
Sadik Armagan3896b472020-02-10 12:24:15 +0000247 void SetConsumer(IConsumer* consumer) override
248 {
249 if (consumer != nullptr)
250 {
251 m_Consumer = consumer;
252 }
253 }
254
255 void FlushReadList() override
256 {
257 // notify consumer that packet is ready to read
258 if (m_Consumer != nullptr)
259 {
260 m_Consumer->SetReadyToRead();
261 }
262 }
263
Ferran Balaguer1b941722019-08-28 16:57:18 +0100264private:
265 unsigned int m_BufferSize;
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000266 IPacketBufferPtr m_Buffer;
Sadik Armagan3896b472020-02-10 12:24:15 +0000267 IConsumer* m_Consumer = nullptr;
Ferran Balaguer1b941722019-08-28 16:57:18 +0100268};
269
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100270class MockStreamCounterBuffer : public IBufferManager
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100271{
272public:
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100273 MockStreamCounterBuffer(unsigned int maxBufferSize = 4096)
274 : m_MaxBufferSize(maxBufferSize)
275 , m_BufferList()
276 , m_CommittedSize(0)
277 , m_ReadableSize(0)
278 , m_ReadSize(0)
279 {}
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100280 ~MockStreamCounterBuffer() {}
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100281
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100282 IPacketBufferPtr Reserve(unsigned int requestedSize, unsigned int& reservedSize) override
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100283 {
Matteo Martincighd0613b52019-10-09 16:47:04 +0100284 std::lock_guard<std::mutex> lock(m_Mutex);
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100285
286 reservedSize = 0;
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100287 if (requestedSize > m_MaxBufferSize)
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +0100288 {
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100289 throw armnn::InvalidArgumentException("The maximum buffer size that can be requested is [" +
290 std::to_string(m_MaxBufferSize) + "] bytes");
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +0100291 }
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100292 reservedSize = requestedSize;
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100293 return std::make_unique<MockPacketBuffer>(requestedSize);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100294 }
295
Sadik Armagan3896b472020-02-10 12:24:15 +0000296 void Commit(IPacketBufferPtr& packetBuffer, unsigned int size, bool notifyConsumer = true) override
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100297 {
Matteo Martincighd0613b52019-10-09 16:47:04 +0100298 std::lock_guard<std::mutex> lock(m_Mutex);
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100299
300 packetBuffer->Commit(size);
301 m_BufferList.push_back(std::move(packetBuffer));
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100302 m_CommittedSize += size;
Sadik Armagan3896b472020-02-10 12:24:15 +0000303
304 if (notifyConsumer)
305 {
306 FlushReadList();
307 }
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100308 }
309
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100310 void Release(IPacketBufferPtr& packetBuffer) override
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100311 {
Matteo Martincighd0613b52019-10-09 16:47:04 +0100312 std::lock_guard<std::mutex> lock(m_Mutex);
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100313
314 packetBuffer->Release();
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100315 }
316
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100317 IPacketBufferPtr GetReadableBuffer() override
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100318 {
Matteo Martincighd0613b52019-10-09 16:47:04 +0100319 std::lock_guard<std::mutex> lock(m_Mutex);
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100320
321 if (m_BufferList.empty())
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100322 {
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100323 return nullptr;
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100324 }
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100325 IPacketBufferPtr buffer = std::move(m_BufferList.back());
326 m_BufferList.pop_back();
327 m_ReadableSize += buffer->GetSize();
328 return buffer;
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100329 }
330
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100331 void MarkRead(IPacketBufferPtr& packetBuffer) override
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100332 {
Matteo Martincighd0613b52019-10-09 16:47:04 +0100333 std::lock_guard<std::mutex> lock(m_Mutex);
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100334
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100335 m_ReadSize += packetBuffer->GetSize();
336 packetBuffer->MarkRead();
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100337 }
338
Sadik Armagan3896b472020-02-10 12:24:15 +0000339 void SetConsumer(IConsumer* consumer) override
340 {
341 if (consumer != nullptr)
342 {
343 m_Consumer = consumer;
344 }
345 }
346
347 void FlushReadList() override
348 {
349 // notify consumer that packet is ready to read
350 if (m_Consumer != nullptr)
351 {
352 m_Consumer->SetReadyToRead();
353 }
354 }
355
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100356 unsigned int GetCommittedSize() const { return m_CommittedSize; }
357 unsigned int GetReadableSize() const { return m_ReadableSize; }
358 unsigned int GetReadSize() const { return m_ReadSize; }
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100359
360private:
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100361 // The maximum buffer size when creating a new buffer
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100362 unsigned int m_MaxBufferSize;
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100363
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100364 // A list of buffers
365 std::vector<IPacketBufferPtr> m_BufferList;
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100366
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100367 // The mutex to synchronize this mock's methods
368 std::mutex m_Mutex;
369
370 // The total size of the buffers that has been committed for reading
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100371 unsigned int m_CommittedSize;
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100372
Matteo Martincigh61d6f732019-10-03 11:21:18 +0100373 // The total size of the buffers that can be read
374 unsigned int m_ReadableSize;
375
376 // The total size of the buffers that has already been read
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100377 unsigned int m_ReadSize;
Sadik Armagan3896b472020-02-10 12:24:15 +0000378
379 // Consumer thread to notify packet is ready to read
380 IConsumer* m_Consumer = nullptr;
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100381};
382
Ferran Balaguer1b941722019-08-28 16:57:18 +0100383class MockSendCounterPacket : public ISendCounterPacket
384{
385public:
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100386 MockSendCounterPacket(IBufferManager& sendBuffer) : m_BufferManager(sendBuffer) {}
Ferran Balaguer1b941722019-08-28 16:57:18 +0100387
388 void SendStreamMetaDataPacket() override
389 {
390 std::string message("SendStreamMetaDataPacket");
391 unsigned int reserved = 0;
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000392 IPacketBufferPtr buffer = m_BufferManager.Reserve(1024, reserved);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100393 memcpy(buffer->GetWritableData(), message.c_str(), static_cast<unsigned int>(message.size()) + 1);
Sadik Armagan3896b472020-02-10 12:24:15 +0000394 m_BufferManager.Commit(buffer, reserved, false);
Ferran Balaguer1b941722019-08-28 16:57:18 +0100395 }
396
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100397 void SendCounterDirectoryPacket(const ICounterDirectory& counterDirectory) override
Ferran Balaguer1b941722019-08-28 16:57:18 +0100398 {
Derek Lamberti1dd75b32019-12-10 21:23:23 +0000399 boost::ignore_unused(counterDirectory);
400
Ferran Balaguer1b941722019-08-28 16:57:18 +0100401 std::string message("SendCounterDirectoryPacket");
402 unsigned int reserved = 0;
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000403 IPacketBufferPtr buffer = m_BufferManager.Reserve(1024, reserved);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100404 memcpy(buffer->GetWritableData(), message.c_str(), static_cast<unsigned int>(message.size()) + 1);
405 m_BufferManager.Commit(buffer, reserved);
Ferran Balaguer1b941722019-08-28 16:57:18 +0100406 }
407
408 void SendPeriodicCounterCapturePacket(uint64_t timestamp,
409 const std::vector<std::pair<uint16_t, uint32_t>>& values) override
410 {
Derek Lamberti1dd75b32019-12-10 21:23:23 +0000411 boost::ignore_unused(timestamp, values);
412
Ferran Balaguer1b941722019-08-28 16:57:18 +0100413 std::string message("SendPeriodicCounterCapturePacket");
414 unsigned int reserved = 0;
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000415 IPacketBufferPtr buffer = m_BufferManager.Reserve(1024, reserved);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100416 memcpy(buffer->GetWritableData(), message.c_str(), static_cast<unsigned int>(message.size()) + 1);
417 m_BufferManager.Commit(buffer, reserved);
Ferran Balaguer1b941722019-08-28 16:57:18 +0100418 }
419
420 void SendPeriodicCounterSelectionPacket(uint32_t capturePeriod,
421 const std::vector<uint16_t>& selectedCounterIds) override
422 {
Derek Lamberti1dd75b32019-12-10 21:23:23 +0000423 boost::ignore_unused(capturePeriod, selectedCounterIds);
424
Ferran Balaguer1b941722019-08-28 16:57:18 +0100425 std::string message("SendPeriodicCounterSelectionPacket");
426 unsigned int reserved = 0;
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000427 IPacketBufferPtr buffer = m_BufferManager.Reserve(1024, reserved);
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100428 memcpy(buffer->GetWritableData(), message.c_str(), static_cast<unsigned int>(message.size()) + 1);
429 m_BufferManager.Commit(buffer, reserved);
Ferran Balaguer1b941722019-08-28 16:57:18 +0100430 }
431
Ferran Balaguer1b941722019-08-28 16:57:18 +0100432private:
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100433 IBufferManager& m_BufferManager;
Ferran Balaguer1b941722019-08-28 16:57:18 +0100434};
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100435
436class MockCounterDirectory : public ICounterDirectory
437{
438public:
439 MockCounterDirectory() = default;
440 ~MockCounterDirectory() = default;
441
442 // Register profiling objects
443 const Category* RegisterCategory(const std::string& categoryName,
444 const armnn::Optional<uint16_t>& deviceUid = armnn::EmptyOptional(),
445 const armnn::Optional<uint16_t>& counterSetUid = armnn::EmptyOptional())
446 {
447 // Get the device UID
448 uint16_t deviceUidValue = deviceUid.has_value() ? deviceUid.value() : 0;
449
450 // Get the counter set UID
451 uint16_t counterSetUidValue = counterSetUid.has_value() ? counterSetUid.value() : 0;
452
453 // Create the category
454 CategoryPtr category = std::make_unique<Category>(categoryName, deviceUidValue, counterSetUidValue);
455 BOOST_ASSERT(category);
456
457 // Get the raw category pointer
458 const Category* categoryPtr = category.get();
459 BOOST_ASSERT(categoryPtr);
460
461 // Register the category
462 m_Categories.insert(std::move(category));
463
464 return categoryPtr;
465 }
466
467 const Device* RegisterDevice(const std::string& deviceName,
468 uint16_t cores = 0,
469 const armnn::Optional<std::string>& parentCategoryName = armnn::EmptyOptional())
470 {
471 // Get the device UID
472 uint16_t deviceUid = GetNextUid();
473
474 // Create the device
475 DevicePtr device = std::make_unique<Device>(deviceUid, deviceName, cores);
476 BOOST_ASSERT(device);
477
478 // Get the raw device pointer
479 const Device* devicePtr = device.get();
480 BOOST_ASSERT(devicePtr);
481
482 // Register the device
483 m_Devices.insert(std::make_pair(deviceUid, std::move(device)));
484
485 // Connect the counter set to the parent category, if required
486 if (parentCategoryName.has_value())
487 {
488 // Set the counter set UID in the parent category
489 Category* parentCategory = const_cast<Category*>(GetCategory(parentCategoryName.value()));
490 BOOST_ASSERT(parentCategory);
491 parentCategory->m_DeviceUid = deviceUid;
492 }
493
494 return devicePtr;
495 }
496
497 const CounterSet* RegisterCounterSet(
498 const std::string& counterSetName,
499 uint16_t count = 0,
500 const armnn::Optional<std::string>& parentCategoryName = armnn::EmptyOptional())
501 {
502 // Get the counter set UID
503 uint16_t counterSetUid = GetNextUid();
504
505 // Create the counter set
506 CounterSetPtr counterSet = std::make_unique<CounterSet>(counterSetUid, counterSetName, count);
507 BOOST_ASSERT(counterSet);
508
509 // Get the raw counter set pointer
510 const CounterSet* counterSetPtr = counterSet.get();
511 BOOST_ASSERT(counterSetPtr);
512
513 // Register the counter set
514 m_CounterSets.insert(std::make_pair(counterSetUid, std::move(counterSet)));
515
516 // Connect the counter set to the parent category, if required
517 if (parentCategoryName.has_value())
518 {
519 // Set the counter set UID in the parent category
520 Category* parentCategory = const_cast<Category*>(GetCategory(parentCategoryName.value()));
521 BOOST_ASSERT(parentCategory);
522 parentCategory->m_CounterSetUid = counterSetUid;
523 }
524
525 return counterSetPtr;
526 }
527
Keith Davise394bd92019-12-02 15:12:19 +0000528 const Counter* RegisterCounter(const BackendId& backendId,
529 const uint16_t uid,
530 const std::string& parentCategoryName,
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100531 uint16_t counterClass,
532 uint16_t interpolation,
533 double multiplier,
534 const std::string& name,
535 const std::string& description,
536 const armnn::Optional<std::string>& units = armnn::EmptyOptional(),
537 const armnn::Optional<uint16_t>& numberOfCores = armnn::EmptyOptional(),
538 const armnn::Optional<uint16_t>& deviceUid = armnn::EmptyOptional(),
539 const armnn::Optional<uint16_t>& counterSetUid = armnn::EmptyOptional())
540 {
Derek Lambertif143fba2020-01-02 13:50:57 +0000541 boost::ignore_unused(backendId);
542
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100543 // Get the number of cores from the argument only
544 uint16_t deviceCores = numberOfCores.has_value() ? numberOfCores.value() : 0;
545
546 // Get the device UID
547 uint16_t deviceUidValue = deviceUid.has_value() ? deviceUid.value() : 0;
548
549 // Get the counter set UID
550 uint16_t counterSetUidValue = counterSetUid.has_value() ? counterSetUid.value() : 0;
551
552 // Get the counter UIDs and calculate the max counter UID
Keith Davise394bd92019-12-02 15:12:19 +0000553 std::vector<uint16_t> counterUids = GetNextCounterUids(uid, deviceCores);
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100554 BOOST_ASSERT(!counterUids.empty());
555 uint16_t maxCounterUid = deviceCores <= 1 ? counterUids.front() : counterUids.back();
556
557 // Get the counter units
558 const std::string unitsValue = units.has_value() ? units.value() : "";
559
560 // Create the counter
Keith Davise394bd92019-12-02 15:12:19 +0000561 CounterPtr counter = std::make_shared<Counter>(armnn::profiling::BACKEND_ID,
562 counterUids.front(),
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100563 maxCounterUid,
564 counterClass,
565 interpolation,
566 multiplier,
567 name,
568 description,
569 unitsValue,
570 deviceUidValue,
571 counterSetUidValue);
572 BOOST_ASSERT(counter);
573
574 // Get the raw counter pointer
575 const Counter* counterPtr = counter.get();
576 BOOST_ASSERT(counterPtr);
577
578 // Process multiple counters if necessary
579 for (uint16_t counterUid : counterUids)
580 {
581 // Connect the counter to the parent category
582 Category* parentCategory = const_cast<Category*>(GetCategory(parentCategoryName));
583 BOOST_ASSERT(parentCategory);
584 parentCategory->m_Counters.push_back(counterUid);
585
586 // Register the counter
587 m_Counters.insert(std::make_pair(counterUid, counter));
588 }
589
590 return counterPtr;
591 }
592
593 // Getters for counts
594 uint16_t GetCategoryCount() const override { return boost::numeric_cast<uint16_t>(m_Categories.size()); }
595 uint16_t GetDeviceCount() const override { return boost::numeric_cast<uint16_t>(m_Devices.size()); }
596 uint16_t GetCounterSetCount() const override { return boost::numeric_cast<uint16_t>(m_CounterSets.size()); }
597 uint16_t GetCounterCount() const override { return boost::numeric_cast<uint16_t>(m_Counters.size()); }
598
599 // Getters for collections
600 const Categories& GetCategories() const override { return m_Categories; }
601 const Devices& GetDevices() const override { return m_Devices; }
602 const CounterSets& GetCounterSets() const override { return m_CounterSets; }
603 const Counters& GetCounters() const override { return m_Counters; }
604
605 // Getters for profiling objects
606 const Category* GetCategory(const std::string& name) const override
607 {
608 auto it = std::find_if(m_Categories.begin(), m_Categories.end(), [&name](const CategoryPtr& category)
609 {
610 BOOST_ASSERT(category);
611
612 return category->m_Name == name;
613 });
614
615 if (it == m_Categories.end())
616 {
617 return nullptr;
618 }
619
620 return it->get();
621 }
622
623 const Device* GetDevice(uint16_t uid) const override
624 {
Derek Lamberti1dd75b32019-12-10 21:23:23 +0000625 boost::ignore_unused(uid);
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100626 return nullptr; // Not used by the unit tests
627 }
628
629 const CounterSet* GetCounterSet(uint16_t uid) const override
630 {
Derek Lamberti1dd75b32019-12-10 21:23:23 +0000631 boost::ignore_unused(uid);
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100632 return nullptr; // Not used by the unit tests
633 }
634
635 const Counter* GetCounter(uint16_t uid) const override
636 {
Derek Lamberti1dd75b32019-12-10 21:23:23 +0000637 boost::ignore_unused(uid);
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100638 return nullptr; // Not used by the unit tests
639 }
640
641private:
642 Categories m_Categories;
643 Devices m_Devices;
644 CounterSets m_CounterSets;
645 Counters m_Counters;
646};
647
648class SendCounterPacketTest : public SendCounterPacket
649{
650public:
Sadik Armagan3896b472020-02-10 12:24:15 +0000651 SendCounterPacketTest(IBufferManager& buffer)
652 : SendCounterPacket(buffer)
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100653 {}
654
655 bool CreateDeviceRecordTest(const DevicePtr& device,
656 DeviceRecord& deviceRecord,
657 std::string& errorMessage)
658 {
659 return CreateDeviceRecord(device, deviceRecord, errorMessage);
660 }
661
662 bool CreateCounterSetRecordTest(const CounterSetPtr& counterSet,
663 CounterSetRecord& counterSetRecord,
664 std::string& errorMessage)
665 {
666 return CreateCounterSetRecord(counterSet, counterSetRecord, errorMessage);
667 }
668
669 bool CreateEventRecordTest(const CounterPtr& counter,
670 EventRecord& eventRecord,
671 std::string& errorMessage)
672 {
673 return CreateEventRecord(counter, eventRecord, errorMessage);
674 }
675
676 bool CreateCategoryRecordTest(const CategoryPtr& category,
677 const Counters& counters,
678 CategoryRecord& categoryRecord,
679 std::string& errorMessage)
680 {
681 return CreateCategoryRecord(category, counters, categoryRecord, errorMessage);
682 }
683};
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100684
685} // namespace profiling
686
687} // namespace armnn