aboutsummaryrefslogtreecommitdiff
path: root/src/profiling/FileOnlyProfilingConnection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/profiling/FileOnlyProfilingConnection.cpp')
-rw-r--r--src/profiling/FileOnlyProfilingConnection.cpp216
1 files changed, 216 insertions, 0 deletions
diff --git a/src/profiling/FileOnlyProfilingConnection.cpp b/src/profiling/FileOnlyProfilingConnection.cpp
new file mode 100644
index 0000000000..b32ae49911
--- /dev/null
+++ b/src/profiling/FileOnlyProfilingConnection.cpp
@@ -0,0 +1,216 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "FileOnlyProfilingConnection.hpp"
+#include "PacketVersionResolver.hpp"
+
+#include <armnn/Exceptions.hpp>
+
+#include <boost/numeric/conversion/cast.hpp>
+#include <iostream>
+#include <thread>
+
+namespace armnn
+{
+
+namespace profiling
+{
+
+FileOnlyProfilingConnection::~FileOnlyProfilingConnection()
+{
+ Close();
+}
+
+bool FileOnlyProfilingConnection::IsOpen() const
+{
+ // This type of connection is always open.
+ return true;
+}
+
+void FileOnlyProfilingConnection::Close()
+{
+ // Dump any unread packets out of the queue.
+ for (unsigned int i = 0; i < m_PacketQueue.size(); i++)
+ {
+ m_PacketQueue.pop();
+ }
+}
+
+bool FileOnlyProfilingConnection::WaitForStreamMeta(const unsigned char* buffer, uint32_t length)
+{
+ // The first word, stream_metadata_identifer, should always be 0.
+ if (ToUint32(buffer, TargetEndianness::BeWire) != 0)
+ {
+ Fail("Protocol error. The stream_metadata_identifer was not 0.");
+ }
+
+ // Before we interpret the length we need to read the pipe_magic word to determine endianness.
+ if (ToUint32(buffer + 8, TargetEndianness::BeWire) == PIPE_MAGIC)
+ {
+ m_Endianness = TargetEndianness::BeWire;
+ }
+ else if (ToUint32(buffer + 8, TargetEndianness::LeWire) == PIPE_MAGIC)
+ {
+ m_Endianness = TargetEndianness::LeWire;
+ }
+ else
+ {
+ Fail("Protocol read error. Unable to read PIPE_MAGIC value.");
+ }
+ return true;
+}
+
+void FileOnlyProfilingConnection::SendConnectionAck()
+{
+ if (!m_QuietOp)
+ {
+ std::cout << "Sending connection acknowledgement." << std::endl;
+ }
+ std::unique_ptr<unsigned char[]> uniqueNullPtr = nullptr;
+ m_PacketQueue.push(Packet(0x10000, 0, uniqueNullPtr));
+}
+
+bool FileOnlyProfilingConnection::SendCounterSelectionPacket()
+{
+ uint32_t uint16_t_size = sizeof(uint16_t);
+ uint32_t uint32_t_size = sizeof(uint32_t);
+
+ uint32_t offset = 0;
+ uint32_t bodySize = uint32_t_size + boost::numeric_cast<uint32_t>(m_IdList.size()) * uint16_t_size;
+
+ auto uniqueData = std::make_unique<unsigned char[]>(bodySize);
+ unsigned char* data = reinterpret_cast<unsigned char*>(uniqueData.get());
+
+ // Copy capturePeriod
+ WriteUint32(data, offset, m_Options.m_CapturePeriod);
+
+ // Copy m_IdList
+ offset += uint32_t_size;
+ for (const uint16_t& id : m_IdList)
+ {
+ WriteUint16(data, offset, id);
+ offset += uint16_t_size;
+ }
+
+ m_PacketQueue.push(Packet(0x40000, bodySize, uniqueData));
+
+ return true;
+}
+
+bool FileOnlyProfilingConnection::WritePacket(const unsigned char* buffer, uint32_t length)
+{
+ BOOST_ASSERT(buffer);
+
+ // Read Header and determine case
+ uint32_t outgoingHeaderAsWords[2];
+ PackageActivity packageActivity = GetPackageActivity(buffer, outgoingHeaderAsWords);
+
+ switch (packageActivity)
+ {
+ case PackageActivity::StreamMetaData:
+ {
+ if (!WaitForStreamMeta(buffer, length))
+ {
+ return EXIT_FAILURE;
+ }
+
+ SendConnectionAck();
+ break;
+ }
+ case PackageActivity::CounterDirectory:
+ {
+ std::unique_ptr<unsigned char[]> uniqueCounterData = std::make_unique<unsigned char[]>(length - 8);
+
+ std::memcpy(uniqueCounterData.get(), buffer + 8, length - 8);
+
+ Packet directoryPacket(outgoingHeaderAsWords[0], length - 8, uniqueCounterData);
+
+ armnn::profiling::PacketVersionResolver packetVersionResolver;
+ DirectoryCaptureCommandHandler directoryCaptureCommandHandler(
+ 0, 2, packetVersionResolver.ResolvePacketVersion(0, 2).GetEncodedValue());
+ directoryCaptureCommandHandler.operator()(directoryPacket);
+ const ICounterDirectory& counterDirectory = directoryCaptureCommandHandler.GetCounterDirectory();
+ for (auto& category : counterDirectory.GetCategories())
+ {
+ // Remember we need to translate the Uid's from our CounterDirectory instance to the parent one.
+ std::vector<uint16_t> translatedCounters;
+ for (auto const& copyUid : category->m_Counters)
+ {
+ translatedCounters.emplace_back(directoryCaptureCommandHandler.TranslateUIDCopyToOriginal(copyUid));
+ }
+ m_IdList.insert(std::end(m_IdList), std::begin(translatedCounters), std::end(translatedCounters));
+ }
+ SendCounterSelectionPacket();
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ return true;
+}
+
+Packet FileOnlyProfilingConnection::ReadPacket(uint32_t timeout)
+{
+ uint16_t loopCount = 10;
+ uint32_t timeoutFraction = timeout / loopCount;
+ while (m_PacketQueue.empty())
+ {
+ std::this_thread::sleep_for(std::chrono::milliseconds(timeoutFraction));
+ --loopCount;
+ if ((loopCount) == 0)
+ {
+ throw armnn::TimeoutException("Thread has timed out as per requested time limit");
+ }
+ }
+ Packet returnedPacket = std::move(m_PacketQueue.front());
+ m_PacketQueue.pop();
+ return returnedPacket;
+}
+
+PackageActivity FileOnlyProfilingConnection::GetPackageActivity(const unsigned char* buffer, uint32_t headerAsWords[2])
+{
+ headerAsWords[0] = ToUint32(buffer, m_Endianness);
+ headerAsWords[1] = ToUint32(buffer + 4, m_Endianness);
+ if (headerAsWords[0] == 0x20000) // Packet family = 0 Packet Id = 2
+ {
+ return PackageActivity::CounterDirectory;
+ }
+ else if (headerAsWords[0] == 0) // Packet family = 0 Packet Id = 0
+ {
+ return PackageActivity::StreamMetaData;
+ }
+ else
+ {
+ return PackageActivity::Unknown;
+ }
+}
+
+uint32_t FileOnlyProfilingConnection::ToUint32(const unsigned char* data, TargetEndianness endianness)
+{
+ // Extract the first 4 bytes starting at data and push them into a 32bit integer based on the
+ // specified endianness.
+ if (endianness == TargetEndianness::BeWire)
+ {
+ return static_cast<uint32_t>(data[0]) << 24 | static_cast<uint32_t>(data[1]) << 16 |
+ static_cast<uint32_t>(data[2]) << 8 | static_cast<uint32_t>(data[3]);
+ }
+ else
+ {
+ return static_cast<uint32_t>(data[3]) << 24 | static_cast<uint32_t>(data[2]) << 16 |
+ static_cast<uint32_t>(data[1]) << 8 | static_cast<uint32_t>(data[0]);
+ }
+}
+
+void FileOnlyProfilingConnection::Fail(const std::string& errorMessage)
+{
+ Close();
+ throw RuntimeException(errorMessage);
+}
+
+} // namespace profiling
+
+} // namespace armnn