blob: fff26d435b8a140daa01cb0c756660bb15ea42f3 [file] [log] [blame]
Aron Virginas-Tardfa14772019-09-24 18:24:47 +01001//
Jim Flynnbbfe6032020-07-20 16:57:44 +01002// Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
Aron Virginas-Tardfa14772019-09-24 18:24:47 +01003// SPDX-License-Identifier: MIT
4//
5
6#include "ProfilingConnectionDumpToFileDecorator.hpp"
7
8#include <armnn/Exceptions.hpp>
Matthew Sloyan371b70e2020-09-11 10:14:57 +01009#include <armnn/utility/NumericCast.hpp>
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010010
11#include <fstream>
12
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000013namespace arm
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010014{
15
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000016namespace pipe
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010017{
18
19ProfilingConnectionDumpToFileDecorator::ProfilingConnectionDumpToFileDecorator(
20 std::unique_ptr<IProfilingConnection> connection,
Jim Flynn4c9ed1d2022-01-23 23:57:20 +000021 const ProfilingOptions& options,
Keith Davisb10e0812019-10-17 09:52:50 +010022 bool ignoreFailures)
23 : m_Connection(std::move(connection))
24 , m_Options(options)
25 , m_IgnoreFileErrors(ignoreFailures)
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010026{
27 if (!m_Connection)
28 {
29 throw InvalidArgumentException("Connection cannot be nullptr");
30 }
31}
32
33ProfilingConnectionDumpToFileDecorator::~ProfilingConnectionDumpToFileDecorator()
34{
35 Close();
36}
37
Matteo Martincigh54fb9572019-10-02 12:50:57 +010038bool ProfilingConnectionDumpToFileDecorator::IsOpen() const
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010039{
40 return m_Connection->IsOpen();
41}
42
43void ProfilingConnectionDumpToFileDecorator::Close()
44{
Keith Davis3201eea2019-10-24 17:30:41 +010045 m_IncomingDumpFileStream.flush();
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010046 m_IncomingDumpFileStream.close();
Keith Davis3201eea2019-10-24 17:30:41 +010047 m_OutgoingDumpFileStream.flush();
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010048 m_OutgoingDumpFileStream.close();
49 m_Connection->Close();
50}
51
52bool ProfilingConnectionDumpToFileDecorator::WritePacket(const unsigned char* buffer, uint32_t length)
53{
54 bool success = true;
Keith Davisb10e0812019-10-17 09:52:50 +010055 if (!m_Options.m_OutgoingCaptureFile.empty())
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010056 {
Matteo Martincigh67ef2a52019-10-10 13:29:02 +010057 success &= DumpOutgoingToFile(buffer, length);
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010058 }
59 success &= m_Connection->WritePacket(buffer, length);
60 return success;
61}
62
Jim Flynnbbfe6032020-07-20 16:57:44 +010063arm::pipe::Packet ProfilingConnectionDumpToFileDecorator::ReadPacket(uint32_t timeout)
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010064{
Jim Flynnbbfe6032020-07-20 16:57:44 +010065 arm::pipe::Packet packet = m_Connection->ReadPacket(timeout);
Keith Davisb10e0812019-10-17 09:52:50 +010066 if (!m_Options.m_IncomingCaptureFile.empty())
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010067 {
68 DumpIncomingToFile(packet);
69 }
70 return packet;
71}
72
73bool ProfilingConnectionDumpToFileDecorator::OpenIncomingDumpFile()
74{
Keith Davisb10e0812019-10-17 09:52:50 +010075 m_IncomingDumpFileStream.open(m_Options.m_IncomingCaptureFile, std::ios::out | std::ios::binary);
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010076 return m_IncomingDumpFileStream.is_open();
77}
78
79bool ProfilingConnectionDumpToFileDecorator::OpenOutgoingDumpFile()
80{
Keith Davisb10e0812019-10-17 09:52:50 +010081 m_OutgoingDumpFileStream.open(m_Options.m_OutgoingCaptureFile, std::ios::out | std::ios::binary);
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010082 return m_OutgoingDumpFileStream.is_open();
83}
84
85
86/// Dumps incoming data into the file specified by m_Settings.m_IncomingDumpFileName.
87/// If m_IgnoreFileErrors is set to true in m_Settings, write errors will be ignored,
88/// i.e. the method will not throw an exception if it encounters an error while trying
89/// to write the data into the specified file.
90/// @param packet data packet to write
91/// @return nothing
Jim Flynnbbfe6032020-07-20 16:57:44 +010092void ProfilingConnectionDumpToFileDecorator::DumpIncomingToFile(const arm::pipe::Packet& packet)
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010093{
94 bool success = true;
95 if (!m_IncomingDumpFileStream.is_open())
96 {
97 // attempt to open dump file
98 success &= OpenIncomingDumpFile();
Keith Davisb10e0812019-10-17 09:52:50 +010099 if (!(success || m_IgnoreFileErrors))
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100100 {
Keith Davisb10e0812019-10-17 09:52:50 +0100101 Fail("Failed to open \"" + m_Options.m_IncomingCaptureFile + "\" for writing");
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100102 }
103 }
104
105 // attempt to write binary data from packet
Aron Virginas-Taraab82c52019-09-30 14:21:26 +0100106 const unsigned int header = packet.GetHeader();
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100107 const unsigned int packetLength = packet.GetLength();
108
109 m_IncomingDumpFileStream.write(reinterpret_cast<const char*>(&header), sizeof header);
110 m_IncomingDumpFileStream.write(reinterpret_cast<const char*>(&packetLength), sizeof packetLength);
Matteo Martincigh67ef2a52019-10-10 13:29:02 +0100111 m_IncomingDumpFileStream.write(reinterpret_cast<const char*>(packet.GetData()),
Matthew Sloyan371b70e2020-09-11 10:14:57 +0100112 armnn::numeric_cast<std::streamsize>(packetLength));
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100113
114 success &= m_IncomingDumpFileStream.good();
Keith Davisb10e0812019-10-17 09:52:50 +0100115 if (!(success || m_IgnoreFileErrors))
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100116 {
117 Fail("Error writing incoming packet of " + std::to_string(packetLength) + " bytes");
118 }
119}
120
121/// Dumps outgoing data into the file specified by m_Settings.m_OutgoingDumpFileName.
122/// If m_IgnoreFileErrors is set to true in m_Settings, write errors will be ignored,
123/// i.e. the method will not throw an exception if it encounters an error while trying
124/// to write the data into the specified file. However, the return value will still
125/// signal if the write has not been completed succesfully.
126/// @param buffer pointer to data to write
127/// @param length number of bytes to write
128/// @return true if write successful, false otherwise
Matteo Martincigh67ef2a52019-10-10 13:29:02 +0100129bool ProfilingConnectionDumpToFileDecorator::DumpOutgoingToFile(const unsigned char* buffer, uint32_t length)
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100130{
131 bool success = true;
132 if (!m_OutgoingDumpFileStream.is_open())
133 {
134 // attempt to open dump file
135 success &= OpenOutgoingDumpFile();
Keith Davisb10e0812019-10-17 09:52:50 +0100136 if (!(success || m_IgnoreFileErrors))
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100137 {
Keith Davisb10e0812019-10-17 09:52:50 +0100138 Fail("Failed to open \"" + m_Options.m_OutgoingCaptureFile + "\" for writing");
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100139 }
140 }
141
142 // attempt to write binary data
Matteo Martincigh67ef2a52019-10-10 13:29:02 +0100143 m_OutgoingDumpFileStream.write(reinterpret_cast<const char*>(buffer),
Matthew Sloyan371b70e2020-09-11 10:14:57 +0100144 armnn::numeric_cast<std::streamsize>(length));
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100145 success &= m_OutgoingDumpFileStream.good();
Keith Davisb10e0812019-10-17 09:52:50 +0100146 if (!(success || m_IgnoreFileErrors))
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100147 {
148 Fail("Error writing outgoing packet of " + std::to_string(length) + " bytes");
149 }
150
151 return success;
152}
153
154void ProfilingConnectionDumpToFileDecorator::Fail(const std::string& errorMessage)
155{
156 Close();
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000157 throw armnn::RuntimeException(errorMessage);
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100158}
159
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000160} // namespace pipe
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100161
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000162} // namespace arm