blob: 8514091432e767e2eebaa10ab3d679f6a37290c9 [file] [log] [blame]
Colm Donelana21620d2019-10-11 13:09:49 +01001//
Jim Flynnbbfe6032020-07-20 16:57:44 +01002// Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
Colm Donelana21620d2019-10-11 13:09:49 +01003// SPDX-License-Identifier: MIT
4//
Matteo Martincigh65984272019-10-17 13:26:21 +01005
Colm Donelana21620d2019-10-11 13:09:49 +01006#include "GatordMockService.hpp"
7
Jim Flynnbbfe6032020-07-20 16:57:44 +01008#include <common/include/Assert.hpp>
9#include <common/include/CommandHandlerRegistry.hpp>
10#include <common/include/CommonProfilingUtils.hpp>
11#include <common/include/PacketVersionResolver.hpp>
12#include <common/include/NetworkSockets.hpp>
Narumol Prangnawarat627cbb42020-04-07 12:25:05 +010013
Colm Donelana21620d2019-10-11 13:09:49 +010014#include <cerrno>
Colm Donelana21620d2019-10-11 13:09:49 +010015#include <iostream>
Colm Donelana21620d2019-10-11 13:09:49 +010016#include <string>
Rob Hughes25b74362020-01-13 11:14:59 +000017
Colm Donelana21620d2019-10-11 13:09:49 +010018namespace armnn
19{
20
21namespace gatordmock
22{
23
Colm Donelana21620d2019-10-11 13:09:49 +010024void GatordMockService::SendConnectionAck()
25{
26 if (m_EchoPackets)
27 {
28 std::cout << "Sending connection acknowledgement." << std::endl;
29 }
30 // The connection ack packet is an empty data packet with packetId == 1.
Finn Williams2ed809c2020-04-20 21:21:07 +010031 m_BasePipeServer.get()->SendPacket(0, 1, nullptr, 0);
Colm Donelana21620d2019-10-11 13:09:49 +010032}
33
Finn Williams15db7452019-10-15 14:22:13 +010034void GatordMockService::SendRequestCounterDir()
35{
36 if (m_EchoPackets)
37 {
38 std::cout << "Sending connection acknowledgement." << std::endl;
39 }
Keith Davis33ed2212020-03-30 10:43:41 +010040 // The request counter directory packet is an empty data packet with packetId == 3.
Finn Williams2ed809c2020-04-20 21:21:07 +010041 m_BasePipeServer.get()->SendPacket(0, 3, nullptr, 0);
Finn Williams15db7452019-10-15 14:22:13 +010042}
43
Keith Davis33ed2212020-03-30 10:43:41 +010044void GatordMockService::SendActivateTimelinePacket()
45{
46 if (m_EchoPackets)
47 {
48 std::cout << "Sending activate timeline packet." << std::endl;
49 }
50 // The activate timeline packet is an empty data packet with packetId == 6.
Finn Williams2ed809c2020-04-20 21:21:07 +010051 m_BasePipeServer.get()->SendPacket(0, 6, nullptr, 0);
Keith Davis33ed2212020-03-30 10:43:41 +010052}
53
54void GatordMockService::SendDeactivateTimelinePacket()
55{
56 if (m_EchoPackets)
57 {
58 std::cout << "Sending deactivate timeline packet." << std::endl;
59 }
60 // The deactivate timeline packet is an empty data packet with packetId == 7.
Finn Williams2ed809c2020-04-20 21:21:07 +010061 m_BasePipeServer.get()->SendPacket(0, 7, nullptr, 0);
Keith Davis33ed2212020-03-30 10:43:41 +010062}
63
Colm Donelana21620d2019-10-11 13:09:49 +010064bool GatordMockService::LaunchReceivingThread()
65{
66 if (m_EchoPackets)
67 {
68 std::cout << "Launching receiving thread." << std::endl;
69 }
70 // At this point we want to make the socket non blocking.
Finn Williams2ed809c2020-04-20 21:21:07 +010071 if (!m_BasePipeServer.get()->SetNonBlocking())
Colm Donelana21620d2019-10-11 13:09:49 +010072 {
Finn Williams2ed809c2020-04-20 21:21:07 +010073 m_BasePipeServer.get()->Close();
Colm Donelana21620d2019-10-11 13:09:49 +010074 std::cerr << "Failed to set socket as non blocking: " << strerror(errno) << std::endl;
75 return false;
76 }
Finn Williams2ed809c2020-04-20 21:21:07 +010077 m_ListeningThread = std::thread(&GatordMockService::ReceiveLoop, this);
Colm Donelana21620d2019-10-11 13:09:49 +010078 return true;
79}
80
81void GatordMockService::WaitForReceivingThread()
82{
Colm Donelan02705242019-11-14 14:19:07 +000083 // The receiving thread may already have died.
84 if (m_CloseReceivingThread != true)
85 {
86 m_CloseReceivingThread.store(true);
87 }
Colm Donelana21620d2019-10-11 13:09:49 +010088 // Check that the receiving thread is running
89 if (m_ListeningThread.joinable())
90 {
91 // Wait for the receiving thread to complete operations
92 m_ListeningThread.join();
93 }
Keith Davis33ed2212020-03-30 10:43:41 +010094
95 if(m_EchoPackets)
96 {
97 m_TimelineDecoder.print();
98 }
Colm Donelana21620d2019-10-11 13:09:49 +010099}
100
Finn Williams2ed809c2020-04-20 21:21:07 +0100101bool GatordMockService::WaitForStreamMetaData()
102{
103 return m_BasePipeServer->WaitForStreamMetaData();
104}
105
Colm Donelanb682d842019-10-16 12:24:20 +0100106void GatordMockService::SendPeriodicCounterSelectionList(uint32_t period, std::vector<uint16_t> counters)
Colm Donelana21620d2019-10-11 13:09:49 +0100107{
Colm Donelanb682d842019-10-16 12:24:20 +0100108 // The packet body consists of a UINT32 representing the period following by zero or more
109 // UINT16's representing counter UID's. If the list is empty it implies all counters are to
110 // be disabled.
Colm Donelana21620d2019-10-11 13:09:49 +0100111
Colm Donelanb682d842019-10-16 12:24:20 +0100112 if (m_EchoPackets)
Colm Donelana21620d2019-10-11 13:09:49 +0100113 {
Colm Donelanb682d842019-10-16 12:24:20 +0100114 std::cout << "SendPeriodicCounterSelectionList: Period=" << std::dec << period << "uSec" << std::endl;
115 std::cout << "List length=" << counters.size() << std::endl;
Colm Donelanb682d842019-10-16 12:24:20 +0100116 }
117 // Start by calculating the length of the packet body in bytes. This will be at least 4.
118 uint32_t dataLength = static_cast<uint32_t>(4 + (counters.size() * 2));
119
120 std::unique_ptr<unsigned char[]> uniqueData = std::make_unique<unsigned char[]>(dataLength);
121 unsigned char* data = reinterpret_cast<unsigned char*>(uniqueData.get());
122
123 uint32_t offset = 0;
Jim Flynnbbfe6032020-07-20 16:57:44 +0100124 arm::pipe::WriteUint32(data, offset, period);
Colm Donelanb682d842019-10-16 12:24:20 +0100125 offset += 4;
126 for (std::vector<uint16_t>::iterator it = counters.begin(); it != counters.end(); ++it)
127 {
Jim Flynnbbfe6032020-07-20 16:57:44 +0100128 arm::pipe::WriteUint16(data, offset, *it);
Colm Donelanb682d842019-10-16 12:24:20 +0100129 offset += 2;
Colm Donelana21620d2019-10-11 13:09:49 +0100130 }
131
Colm Donelanb682d842019-10-16 12:24:20 +0100132 // Send the packet.
Finn Williams2ed809c2020-04-20 21:21:07 +0100133 m_BasePipeServer.get()->SendPacket(0, 4, data, dataLength);
Colm Donelanb682d842019-10-16 12:24:20 +0100134 // There will be an echo response packet sitting in the receive thread. PeriodicCounterSelectionResponseHandler
135 // should deal with it.
Colm Donelana21620d2019-10-11 13:09:49 +0100136}
137
Rob Hughes25b74362020-01-13 11:14:59 +0000138void GatordMockService::WaitCommand(uint32_t timeout)
Colm Donelana21620d2019-10-11 13:09:49 +0100139{
Colm Donelan02705242019-11-14 14:19:07 +0000140 // Wait for a maximum of timeout microseconds or if the receive thread has closed.
141 // There is a certain level of rounding involved in this timing.
Rob Hughes25b74362020-01-13 11:14:59 +0000142 uint32_t iterations = timeout / 1000;
Colm Donelan02705242019-11-14 14:19:07 +0000143 std::cout << std::dec << "Wait command with timeout of " << timeout << " iterations = " << iterations << std::endl;
Rob Hughes25b74362020-01-13 11:14:59 +0000144 uint32_t count = 0;
Colm Donelan02705242019-11-14 14:19:07 +0000145 while ((this->ReceiveThreadRunning() && (count < iterations)))
146 {
147 std::this_thread::sleep_for(std::chrono::microseconds(1000));
148 ++count;
149 }
Colm Donelana21620d2019-10-11 13:09:49 +0100150 if (m_EchoPackets)
151 {
152 std::cout << std::dec << "Wait command with timeout of " << timeout << " microseconds completed. " << std::endl;
153 }
154}
155
Finn Williams2ed809c2020-04-20 21:21:07 +0100156void GatordMockService::ReceiveLoop()
Colm Donelana21620d2019-10-11 13:09:49 +0100157{
158 m_CloseReceivingThread.store(false);
159 while (!m_CloseReceivingThread.load())
160 {
161 try
162 {
Jim Flynnbbfe6032020-07-20 16:57:44 +0100163 arm::pipe::Packet packet = m_BasePipeServer.get()->WaitForPacket(500);
Finn Williams2ed809c2020-04-20 21:21:07 +0100164
Jim Flynnbbfe6032020-07-20 16:57:44 +0100165 arm::pipe::PacketVersionResolver packetVersionResolver;
Finn Williams2ed809c2020-04-20 21:21:07 +0100166
Jim Flynnbbfe6032020-07-20 16:57:44 +0100167 arm::pipe::Version version =
Finn Williams2ed809c2020-04-20 21:21:07 +0100168 packetVersionResolver.ResolvePacketVersion(packet.GetPacketFamily(), packet.GetPacketId());
169
Jim Flynnbbfe6032020-07-20 16:57:44 +0100170 arm::pipe::CommandHandlerFunctor* commandHandlerFunctor = m_HandlerRegistry.GetFunctor(
Finn Williams2ed809c2020-04-20 21:21:07 +0100171 packet.GetPacketFamily(),
172 packet.GetPacketId(),
173 version.GetEncodedValue());
174
175
176
Jim Flynnbbfe6032020-07-20 16:57:44 +0100177 ARM_PIPE_ASSERT(commandHandlerFunctor);
Finn Williams2ed809c2020-04-20 21:21:07 +0100178 commandHandlerFunctor->operator()(packet);
Colm Donelana21620d2019-10-11 13:09:49 +0100179 }
Jim Flynnbbfe6032020-07-20 16:57:44 +0100180 catch (const arm::pipe::TimeoutException&)
Colm Donelana21620d2019-10-11 13:09:49 +0100181 {
182 // In this case we ignore timeouts and and keep trying to receive.
183 }
Jim Flynnbbfe6032020-07-20 16:57:44 +0100184 catch (const arm::pipe::InvalidArgumentException& e)
Colm Donelanb682d842019-10-16 12:24:20 +0100185 {
186 // We couldn't find a functor to handle the packet?
187 std::cerr << "Packet received that could not be processed: " << e.what() << std::endl;
188 }
Jim Flynnbbfe6032020-07-20 16:57:44 +0100189 catch (const arm::pipe::ProfilingException& e)
Colm Donelanb682d842019-10-16 12:24:20 +0100190 {
191 // A runtime exception occurred which means we must exit the loop.
192 std::cerr << "Receive thread closing: " << e.what() << std::endl;
193 m_CloseReceivingThread.store(true);
194 }
Colm Donelana21620d2019-10-11 13:09:49 +0100195 }
196}
197
Colm Donelanb682d842019-10-16 12:24:20 +0100198} // namespace gatordmock
Colm Donelana21620d2019-10-11 13:09:49 +0100199
Colm Donelanb682d842019-10-16 12:24:20 +0100200} // namespace armnn