Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 1 | // |
| 2 | // Copyright © 2019 Arm Ltd. All rights reserved. |
| 3 | // SPDX-License-Identifier: MIT |
| 4 | // |
Matteo Martincigh | 6598427 | 2019-10-17 13:26:21 +0100 | [diff] [blame] | 5 | |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 6 | #include "GatordMockService.hpp" |
| 7 | |
Matteo Martincigh | 6598427 | 2019-10-17 13:26:21 +0100 | [diff] [blame] | 8 | #include <CommandHandlerRegistry.hpp> |
Keith Davis | 3201eea | 2019-10-24 17:30:41 +0100 | [diff] [blame] | 9 | #include <PacketVersionResolver.hpp> |
| 10 | #include <ProfilingUtils.hpp> |
Rob Hughes | 25b7436 | 2020-01-13 11:14:59 +0000 | [diff] [blame] | 11 | #include <NetworkSockets.hpp> |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 12 | |
Narumol Prangnawarat | 627cbb4 | 2020-04-07 12:25:05 +0100 | [diff] [blame] | 13 | #include <armnn/utility/Assert.hpp> |
| 14 | |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 15 | #include <cerrno> |
Colm Donelan | b682d84 | 2019-10-16 12:24:20 +0100 | [diff] [blame] | 16 | #include <iomanip> |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 17 | #include <iostream> |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 18 | #include <string> |
Rob Hughes | 25b7436 | 2020-01-13 11:14:59 +0000 | [diff] [blame] | 19 | |
| 20 | using namespace armnnUtils; |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 21 | |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 22 | namespace armnn |
| 23 | { |
| 24 | |
| 25 | namespace gatordmock |
| 26 | { |
| 27 | |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 28 | void GatordMockService::SendConnectionAck() |
| 29 | { |
| 30 | if (m_EchoPackets) |
| 31 | { |
| 32 | std::cout << "Sending connection acknowledgement." << std::endl; |
| 33 | } |
| 34 | // The connection ack packet is an empty data packet with packetId == 1. |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame^] | 35 | m_BasePipeServer.get()->SendPacket(0, 1, nullptr, 0); |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 36 | } |
| 37 | |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 38 | void GatordMockService::SendRequestCounterDir() |
| 39 | { |
| 40 | if (m_EchoPackets) |
| 41 | { |
| 42 | std::cout << "Sending connection acknowledgement." << std::endl; |
| 43 | } |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 44 | // The request counter directory packet is an empty data packet with packetId == 3. |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame^] | 45 | m_BasePipeServer.get()->SendPacket(0, 3, nullptr, 0); |
Finn Williams | 15db745 | 2019-10-15 14:22:13 +0100 | [diff] [blame] | 46 | } |
| 47 | |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 48 | void GatordMockService::SendActivateTimelinePacket() |
| 49 | { |
| 50 | if (m_EchoPackets) |
| 51 | { |
| 52 | std::cout << "Sending activate timeline packet." << std::endl; |
| 53 | } |
| 54 | // The activate timeline packet is an empty data packet with packetId == 6. |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame^] | 55 | m_BasePipeServer.get()->SendPacket(0, 6, nullptr, 0); |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 56 | } |
| 57 | |
| 58 | void GatordMockService::SendDeactivateTimelinePacket() |
| 59 | { |
| 60 | if (m_EchoPackets) |
| 61 | { |
| 62 | std::cout << "Sending deactivate timeline packet." << std::endl; |
| 63 | } |
| 64 | // The deactivate timeline packet is an empty data packet with packetId == 7. |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame^] | 65 | m_BasePipeServer.get()->SendPacket(0, 7, nullptr, 0); |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 66 | } |
| 67 | |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 68 | bool GatordMockService::LaunchReceivingThread() |
| 69 | { |
| 70 | if (m_EchoPackets) |
| 71 | { |
| 72 | std::cout << "Launching receiving thread." << std::endl; |
| 73 | } |
| 74 | // At this point we want to make the socket non blocking. |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame^] | 75 | if (!m_BasePipeServer.get()->SetNonBlocking()) |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 76 | { |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame^] | 77 | m_BasePipeServer.get()->Close(); |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 78 | std::cerr << "Failed to set socket as non blocking: " << strerror(errno) << std::endl; |
| 79 | return false; |
| 80 | } |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame^] | 81 | m_ListeningThread = std::thread(&GatordMockService::ReceiveLoop, this); |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 82 | return true; |
| 83 | } |
| 84 | |
| 85 | void GatordMockService::WaitForReceivingThread() |
| 86 | { |
Colm Donelan | 0270524 | 2019-11-14 14:19:07 +0000 | [diff] [blame] | 87 | // The receiving thread may already have died. |
| 88 | if (m_CloseReceivingThread != true) |
| 89 | { |
| 90 | m_CloseReceivingThread.store(true); |
| 91 | } |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 92 | // Check that the receiving thread is running |
| 93 | if (m_ListeningThread.joinable()) |
| 94 | { |
| 95 | // Wait for the receiving thread to complete operations |
| 96 | m_ListeningThread.join(); |
| 97 | } |
Keith Davis | 33ed221 | 2020-03-30 10:43:41 +0100 | [diff] [blame] | 98 | |
| 99 | if(m_EchoPackets) |
| 100 | { |
| 101 | m_TimelineDecoder.print(); |
| 102 | } |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 103 | } |
| 104 | |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame^] | 105 | bool GatordMockService::WaitForStreamMetaData() |
| 106 | { |
| 107 | return m_BasePipeServer->WaitForStreamMetaData(); |
| 108 | } |
| 109 | |
Colm Donelan | b682d84 | 2019-10-16 12:24:20 +0100 | [diff] [blame] | 110 | void GatordMockService::SendPeriodicCounterSelectionList(uint32_t period, std::vector<uint16_t> counters) |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 111 | { |
Colm Donelan | b682d84 | 2019-10-16 12:24:20 +0100 | [diff] [blame] | 112 | // The packet body consists of a UINT32 representing the period following by zero or more |
| 113 | // UINT16's representing counter UID's. If the list is empty it implies all counters are to |
| 114 | // be disabled. |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 115 | |
Colm Donelan | b682d84 | 2019-10-16 12:24:20 +0100 | [diff] [blame] | 116 | if (m_EchoPackets) |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 117 | { |
Colm Donelan | b682d84 | 2019-10-16 12:24:20 +0100 | [diff] [blame] | 118 | std::cout << "SendPeriodicCounterSelectionList: Period=" << std::dec << period << "uSec" << std::endl; |
| 119 | std::cout << "List length=" << counters.size() << std::endl; |
Colm Donelan | b682d84 | 2019-10-16 12:24:20 +0100 | [diff] [blame] | 120 | } |
| 121 | // Start by calculating the length of the packet body in bytes. This will be at least 4. |
| 122 | uint32_t dataLength = static_cast<uint32_t>(4 + (counters.size() * 2)); |
| 123 | |
| 124 | std::unique_ptr<unsigned char[]> uniqueData = std::make_unique<unsigned char[]>(dataLength); |
| 125 | unsigned char* data = reinterpret_cast<unsigned char*>(uniqueData.get()); |
| 126 | |
| 127 | uint32_t offset = 0; |
| 128 | profiling::WriteUint32(data, offset, period); |
| 129 | offset += 4; |
| 130 | for (std::vector<uint16_t>::iterator it = counters.begin(); it != counters.end(); ++it) |
| 131 | { |
| 132 | profiling::WriteUint16(data, offset, *it); |
| 133 | offset += 2; |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 134 | } |
| 135 | |
Colm Donelan | b682d84 | 2019-10-16 12:24:20 +0100 | [diff] [blame] | 136 | // Send the packet. |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame^] | 137 | m_BasePipeServer.get()->SendPacket(0, 4, data, dataLength); |
Colm Donelan | b682d84 | 2019-10-16 12:24:20 +0100 | [diff] [blame] | 138 | // There will be an echo response packet sitting in the receive thread. PeriodicCounterSelectionResponseHandler |
| 139 | // should deal with it. |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 140 | } |
| 141 | |
Rob Hughes | 25b7436 | 2020-01-13 11:14:59 +0000 | [diff] [blame] | 142 | void GatordMockService::WaitCommand(uint32_t timeout) |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 143 | { |
Colm Donelan | 0270524 | 2019-11-14 14:19:07 +0000 | [diff] [blame] | 144 | // Wait for a maximum of timeout microseconds or if the receive thread has closed. |
| 145 | // There is a certain level of rounding involved in this timing. |
Rob Hughes | 25b7436 | 2020-01-13 11:14:59 +0000 | [diff] [blame] | 146 | uint32_t iterations = timeout / 1000; |
Colm Donelan | 0270524 | 2019-11-14 14:19:07 +0000 | [diff] [blame] | 147 | std::cout << std::dec << "Wait command with timeout of " << timeout << " iterations = " << iterations << std::endl; |
Rob Hughes | 25b7436 | 2020-01-13 11:14:59 +0000 | [diff] [blame] | 148 | uint32_t count = 0; |
Colm Donelan | 0270524 | 2019-11-14 14:19:07 +0000 | [diff] [blame] | 149 | while ((this->ReceiveThreadRunning() && (count < iterations))) |
| 150 | { |
| 151 | std::this_thread::sleep_for(std::chrono::microseconds(1000)); |
| 152 | ++count; |
| 153 | } |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 154 | if (m_EchoPackets) |
| 155 | { |
| 156 | std::cout << std::dec << "Wait command with timeout of " << timeout << " microseconds completed. " << std::endl; |
| 157 | } |
| 158 | } |
| 159 | |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame^] | 160 | void GatordMockService::ReceiveLoop() |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 161 | { |
| 162 | m_CloseReceivingThread.store(false); |
| 163 | while (!m_CloseReceivingThread.load()) |
| 164 | { |
| 165 | try |
| 166 | { |
Finn Williams | 2ed809c | 2020-04-20 21:21:07 +0100 | [diff] [blame^] | 167 | profiling::Packet packet = m_BasePipeServer.get()->WaitForPacket(500); |
| 168 | |
| 169 | profiling::PacketVersionResolver packetVersionResolver; |
| 170 | |
| 171 | profiling::Version version = |
| 172 | packetVersionResolver.ResolvePacketVersion(packet.GetPacketFamily(), packet.GetPacketId()); |
| 173 | |
| 174 | profiling::CommandHandlerFunctor* commandHandlerFunctor = m_HandlerRegistry.GetFunctor( |
| 175 | packet.GetPacketFamily(), |
| 176 | packet.GetPacketId(), |
| 177 | version.GetEncodedValue()); |
| 178 | |
| 179 | |
| 180 | |
| 181 | ARMNN_ASSERT(commandHandlerFunctor); |
| 182 | commandHandlerFunctor->operator()(packet); |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 183 | } |
Jammy Zhou | d80cc0c | 2019-10-21 16:44:40 +0800 | [diff] [blame] | 184 | catch (const armnn::TimeoutException&) |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 185 | { |
| 186 | // In this case we ignore timeouts and and keep trying to receive. |
| 187 | } |
Keith Davis | 3201eea | 2019-10-24 17:30:41 +0100 | [diff] [blame] | 188 | catch (const armnn::InvalidArgumentException& e) |
Colm Donelan | b682d84 | 2019-10-16 12:24:20 +0100 | [diff] [blame] | 189 | { |
| 190 | // We couldn't find a functor to handle the packet? |
| 191 | std::cerr << "Packet received that could not be processed: " << e.what() << std::endl; |
| 192 | } |
Keith Davis | 3201eea | 2019-10-24 17:30:41 +0100 | [diff] [blame] | 193 | catch (const armnn::RuntimeException& e) |
Colm Donelan | b682d84 | 2019-10-16 12:24:20 +0100 | [diff] [blame] | 194 | { |
| 195 | // A runtime exception occurred which means we must exit the loop. |
| 196 | std::cerr << "Receive thread closing: " << e.what() << std::endl; |
| 197 | m_CloseReceivingThread.store(true); |
| 198 | } |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 199 | } |
| 200 | } |
| 201 | |
Colm Donelan | b682d84 | 2019-10-16 12:24:20 +0100 | [diff] [blame] | 202 | } // namespace gatordmock |
Colm Donelan | a21620d | 2019-10-11 13:09:49 +0100 | [diff] [blame] | 203 | |
Colm Donelan | b682d84 | 2019-10-16 12:24:20 +0100 | [diff] [blame] | 204 | } // namespace armnn |