aboutsummaryrefslogtreecommitdiff
path: root/profiling/common
diff options
context:
space:
mode:
authorJim Flynn <jim.flynn@arm.com>2020-07-20 16:57:44 +0100
committerJim Flynn <jim.flynn@arm.com>2020-07-29 15:35:15 +0100
commitbbfe603e5ae42317a2b67d713d00882bea341c88 (patch)
tree8d8a78d6836384fb92fb9741c865443624dfec68 /profiling/common
parenta9c2ce123a6a5a68728d040a0323c482bbe46903 (diff)
downloadarmnn-bbfe603e5ae42317a2b67d713d00882bea341c88.tar.gz
IVGCVSW-5166 Pull out the common and server side code into standalone libraries
Change-Id: I180f84c493a9b2be4b93b25d312ebdd9e71b1735 Signed-off-by: Jim Flynn <jim.flynn@arm.com>
Diffstat (limited to 'profiling/common')
-rw-r--r--profiling/common/include/Assert.hpp24
-rw-r--r--profiling/common/include/CommandHandlerFunctor.hpp42
-rw-r--r--profiling/common/include/CommandHandlerKey.hpp41
-rw-r--r--profiling/common/include/CommandHandlerRegistry.hpp49
-rw-r--r--profiling/common/include/CommonProfilingUtils.hpp38
-rw-r--r--profiling/common/include/Constants.hpp10
-rw-r--r--profiling/common/include/Conversion.hpp43
-rw-r--r--profiling/common/include/EncodeVersion.hpp83
-rw-r--r--profiling/common/include/IgnoreUnused.hpp18
-rw-r--r--profiling/common/include/Logging.hpp182
-rw-r--r--profiling/common/include/NetworkSockets.hpp19
-rw-r--r--profiling/common/include/NumericCast.hpp128
-rw-r--r--profiling/common/include/Packet.hpp14
-rw-r--r--profiling/common/include/PacketVersionResolver.hpp50
-rw-r--r--profiling/common/include/ProfilingException.hpp63
-rw-r--r--profiling/common/include/SocketConnectionException.hpp27
-rw-r--r--profiling/common/include/SwTrace.hpp139
-rw-r--r--profiling/common/include/WindowsWrapper.hpp30
-rw-r--r--profiling/common/src/CMakeLists.txt30
-rw-r--r--profiling/common/src/CommandHandlerFunctor.cpp31
-rw-r--r--profiling/common/src/CommandHandlerKey.cpp77
-rw-r--r--profiling/common/src/CommandHandlerRegistry.cpp61
-rw-r--r--profiling/common/src/CommonProfilingUtils.cpp145
-rw-r--r--profiling/common/src/NetworkSockets.cpp51
-rw-r--r--profiling/common/src/PacketVersionResolver.cpp71
-rw-r--r--profiling/common/src/SwTrace.cpp128
26 files changed, 1544 insertions, 50 deletions
diff --git a/profiling/common/include/Assert.hpp b/profiling/common/include/Assert.hpp
new file mode 100644
index 0000000000..c6e8bc49d4
--- /dev/null
+++ b/profiling/common/include/Assert.hpp
@@ -0,0 +1,24 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <cassert>
+
+namespace arm
+{
+
+namespace pipe
+{
+
+#ifndef NDEBUG
+# define ARM_PIPE_ASSERT(COND) assert(COND)
+# define ARM_PIPE_ASSERT_MSG(COND, MSG) assert((COND) && MSG)
+#else
+# define ARM_PIPE_ASSERT(COND)
+# define ARM_PIPE_ASSERT_MSG(COND, MSG)
+#endif
+} // namespace pipe
+} //namespace arm \ No newline at end of file
diff --git a/profiling/common/include/CommandHandlerFunctor.hpp b/profiling/common/include/CommandHandlerFunctor.hpp
new file mode 100644
index 0000000000..9827aa05ba
--- /dev/null
+++ b/profiling/common/include/CommandHandlerFunctor.hpp
@@ -0,0 +1,42 @@
+//
+// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <Packet.hpp>
+#include <cstdint>
+
+namespace arm
+{
+
+namespace pipe
+{
+
+class CommandHandlerFunctor
+{
+public:
+ CommandHandlerFunctor(uint32_t familyId, uint32_t packetId, uint32_t version)
+ : m_FamilyId(familyId),
+ m_PacketId(packetId)
+ , m_Version(version)
+ {}
+
+ uint32_t GetFamilyId() const;
+ uint32_t GetPacketId() const;
+ uint32_t GetVersion() const;
+
+ virtual void operator()(const Packet& packet) = 0;
+
+ virtual ~CommandHandlerFunctor() {}
+
+private:
+ uint32_t m_FamilyId;
+ uint32_t m_PacketId;
+ uint32_t m_Version;
+};
+
+} // namespace pipe
+
+} // namespace arm
diff --git a/profiling/common/include/CommandHandlerKey.hpp b/profiling/common/include/CommandHandlerKey.hpp
new file mode 100644
index 0000000000..f45b5bef14
--- /dev/null
+++ b/profiling/common/include/CommandHandlerKey.hpp
@@ -0,0 +1,41 @@
+//
+// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <cstdint>
+
+namespace arm
+{
+
+namespace pipe
+{
+
+class CommandHandlerKey
+{
+public:
+ CommandHandlerKey(uint32_t familyId, uint32_t packetId, uint32_t version)
+ : m_FamilyId(familyId), m_PacketId(packetId), m_Version(version) {};
+
+ uint32_t GetFamilyId() const;
+ uint32_t GetPacketId() const;
+ uint32_t GetVersion() const;
+
+ bool operator< (const CommandHandlerKey& rhs) const;
+ bool operator> (const CommandHandlerKey& rhs) const;
+ bool operator<=(const CommandHandlerKey& rhs) const;
+ bool operator>=(const CommandHandlerKey& rhs) const;
+ bool operator==(const CommandHandlerKey& rhs) const;
+ bool operator!=(const CommandHandlerKey& rhs) const;
+
+private:
+ uint32_t m_FamilyId;
+ uint32_t m_PacketId;
+ uint32_t m_Version;
+};
+
+} // namespace pipe
+
+} // namespace arm
diff --git a/profiling/common/include/CommandHandlerRegistry.hpp b/profiling/common/include/CommandHandlerRegistry.hpp
new file mode 100644
index 0000000000..5a5d879996
--- /dev/null
+++ b/profiling/common/include/CommandHandlerRegistry.hpp
@@ -0,0 +1,49 @@
+//
+// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "CommandHandlerFunctor.hpp"
+#include "CommandHandlerKey.hpp"
+
+#include <functional>
+#include <unordered_map>
+
+namespace arm
+{
+
+namespace pipe
+{
+
+struct CommandHandlerHash
+{
+ std::size_t operator() (const CommandHandlerKey& commandHandlerKey) const
+ {
+ std::size_t seed = 0;
+ std::hash<uint32_t> hasher;
+ seed ^= hasher(commandHandlerKey.GetPacketId()) + 0x9e3779b9 + (seed<<6) + (seed>>2);
+ seed ^= hasher(commandHandlerKey.GetVersion()) + 0x9e3779b9 + (seed<<6) + (seed>>2);
+ return seed;
+ }
+};
+
+class CommandHandlerRegistry
+{
+public:
+ CommandHandlerRegistry() = default;
+
+ void RegisterFunctor(CommandHandlerFunctor* functor, uint32_t familyId, uint32_t packetId, uint32_t version);
+
+ void RegisterFunctor(CommandHandlerFunctor* functor);
+
+ CommandHandlerFunctor* GetFunctor(uint32_t familyId, uint32_t packetId, uint32_t version) const;
+
+private:
+ std::unordered_map<CommandHandlerKey, CommandHandlerFunctor*, CommandHandlerHash> registry;
+};
+
+} // namespace pipe
+
+} // namespace arm
diff --git a/profiling/common/include/CommonProfilingUtils.hpp b/profiling/common/include/CommonProfilingUtils.hpp
new file mode 100644
index 0000000000..68fe6bb8ca
--- /dev/null
+++ b/profiling/common/include/CommonProfilingUtils.hpp
@@ -0,0 +1,38 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#pragma once
+
+#include <cstdint>
+#include <string>
+
+namespace arm
+{
+
+namespace pipe
+{
+void ReadBytes(const unsigned char* buffer, unsigned int offset, unsigned int valueSize, uint8_t outValue[]);
+
+uint64_t ReadUint64(unsigned const char* buffer, unsigned int offset);
+
+uint32_t ReadUint32(unsigned const char* buffer, unsigned int offset);
+
+uint16_t ReadUint16(unsigned const char* buffer, unsigned int offset);
+
+uint8_t ReadUint8(unsigned const char* buffer, unsigned int offset);
+
+void WriteBytes(unsigned char* buffer, unsigned int offset, const void* value, unsigned int valueSize);
+
+void WriteUint64(unsigned char* buffer, unsigned int offset, uint64_t value);
+
+void WriteUint32(unsigned char* buffer, unsigned int offset, uint32_t value);
+
+void WriteUint16(unsigned char* buffer, unsigned int offset, uint16_t value);
+
+void WriteUint8(unsigned char* buffer, unsigned int offset, uint8_t value);
+
+std::string CentreAlignFormatting(const std::string& stringToPass, const int spacingWidth);
+
+} // namespace pipe
+} // namespace arm \ No newline at end of file
diff --git a/profiling/common/include/Constants.hpp b/profiling/common/include/Constants.hpp
index 52e0e487a8..01bfe795c2 100644
--- a/profiling/common/include/Constants.hpp
+++ b/profiling/common/include/Constants.hpp
@@ -1,10 +1,14 @@
//
-// Copyright © 2020 Arm Ltd. All rights reserved.
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#pragma once
-namespace armnnProfiling
+namespace arm
+{
+
+namespace pipe
{
static const unsigned int PIPE_MAGIC = 0x45495434;
-} \ No newline at end of file
+} // namespace pipe
+} // namespace arm \ No newline at end of file
diff --git a/profiling/common/include/Conversion.hpp b/profiling/common/include/Conversion.hpp
new file mode 100644
index 0000000000..0a3eb0c0d6
--- /dev/null
+++ b/profiling/common/include/Conversion.hpp
@@ -0,0 +1,43 @@
+//
+// Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#if __GNUC__
+# define ARM_PIPE_NO_CONVERSION_WARN_BEGIN \
+ _Pragma("GCC diagnostic push") \
+ _Pragma("GCC diagnostic ignored \"-Wconversion\"") \
+ _Pragma("GCC diagnostic ignored \"-Wsign-conversion\"")
+
+# define ARM_PIPE_NO_CONVERSION_WARN_END \
+ _Pragma("GCC diagnostic pop")
+
+#elif __clang__
+# define ARM_PIPE_NO_CONVERSION_WARN_BEGIN \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Wconversion\"") \
+ _Pragma("clang diagnostic ignored \"-Wsign-conversion\"")
+
+# define ARM_PIPE_NO_CONVERSION_WARN_END \
+ _Pragma("clang diagnostic pop")
+
+#elif defined (_MSC_VER)
+# define ARM_PIPE_NO_CONVERSION_WARN_BEGIN \
+ __pragma(warning( push )) \
+ __pragma(warning(disable : 4101)) \
+ __pragma(warning(disable : 4267))
+
+# define ARM_PIPE_NO_CONVERSION_WARN_END \
+ __pragma(warning( pop ))
+
+#else
+# define ARM_PIPE_NO_CONVERSION_WARN_BEGIN
+# define ARM_PIPE_NO_CONVERSION_WARN_END
+#endif
+
+#define ARM_PIPE_SUPRESS_CONVERSION_WARNING(func) \
+ARM_PIPE_NO_CONVERSION_WARN_BEGIN \
+func; \
+ARM_PIPE_NO_CONVERSION_WARN_END
diff --git a/profiling/common/include/EncodeVersion.hpp b/profiling/common/include/EncodeVersion.hpp
new file mode 100644
index 0000000000..9257b22cfc
--- /dev/null
+++ b/profiling/common/include/EncodeVersion.hpp
@@ -0,0 +1,83 @@
+//
+// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include <ostream>
+#include <sstream>
+
+namespace arm
+{
+
+namespace pipe
+{
+
+constexpr inline uint32_t EncodeVersion(uint32_t major, uint32_t minor, uint32_t patch)
+{
+ return (major << 22) | (minor << 12) | patch;
+}
+
+// Encodes a semantic version https://semver.org/ into a 32 bit integer in the following fashion
+//
+// bits 22:31 major: Unsigned 10-bit integer. Major component of the schema version number.
+// bits 12:21 minor: Unsigned 10-bit integer. Minor component of the schema version number.
+// bits 0:11 patch: Unsigned 12-bit integer. Patch component of the schema version number.
+//
+class Version
+{
+public:
+ Version(uint32_t encodedValue)
+ {
+ m_Major = (encodedValue >> 22) & 1023;
+ m_Minor = (encodedValue >> 12) & 1023;
+ m_Patch = encodedValue & 4095;
+ }
+
+ Version(uint32_t major, uint32_t minor, uint32_t patch) :
+ m_Major(major),
+ m_Minor(minor),
+ m_Patch(patch)
+ {}
+
+ uint32_t GetEncodedValue()
+ {
+ return EncodeVersion(m_Major, m_Minor, m_Patch);
+ }
+
+ uint32_t GetMajor() { return m_Major; }
+ uint32_t GetMinor() { return m_Minor; }
+ uint32_t GetPatch() { return m_Patch; }
+
+ bool operator==(const Version& other) const
+ {
+ return m_Major == other.m_Major && m_Minor == other.m_Minor && m_Patch == other.m_Patch;
+ }
+
+ std::string ToString() const
+ {
+ constexpr char separator = '.';
+
+ std::stringstream stringStream;
+ stringStream << m_Major << separator << m_Minor << separator << m_Patch;
+
+ return stringStream.str();
+ }
+
+private:
+ uint32_t m_Major;
+ uint32_t m_Minor;
+ uint32_t m_Patch;
+};
+
+inline std::ostream& operator<<(std::ostream& os, const Version& version)
+{
+ os << version.ToString();
+ return os;
+}
+
+} // namespace pipe
+
+} // namespace arm
diff --git a/profiling/common/include/IgnoreUnused.hpp b/profiling/common/include/IgnoreUnused.hpp
new file mode 100644
index 0000000000..fad40d33d4
--- /dev/null
+++ b/profiling/common/include/IgnoreUnused.hpp
@@ -0,0 +1,18 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+namespace arm
+{
+
+namespace pipe
+{
+// Utility function to selectively silence unused variable compiler warnings
+
+template<typename ... Ts>
+inline void IgnoreUnused(Ts&&...){}
+} //namespace pipe
+} //namespace arm \ No newline at end of file
diff --git a/profiling/common/include/Logging.hpp b/profiling/common/include/Logging.hpp
new file mode 100644
index 0000000000..a31c2aaa7b
--- /dev/null
+++ b/profiling/common/include/Logging.hpp
@@ -0,0 +1,182 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <vector>
+
+namespace arm
+{
+
+namespace pipe
+{
+
+enum class LogSeverity
+{
+ Trace,
+ Debug,
+ Info,
+ Warning,
+ Error,
+ Fatal
+};
+
+inline std::string LevelToString(LogSeverity level)
+{
+ switch(level)
+ {
+ case LogSeverity::Trace:
+ return "Trace";
+ case LogSeverity::Debug:
+ return "Debug";
+ case LogSeverity::Info:
+ return "Info";
+ case LogSeverity::Warning:
+ return "Warning";
+ case LogSeverity::Error:
+ return "Error";
+ case LogSeverity::Fatal:
+ return "Fatal";
+ default:
+ return "Log";
+ }
+}
+
+class LogSink
+{
+public:
+ virtual ~LogSink(){};
+
+ virtual void Consume(const std::string&) = 0;
+private:
+
+};
+
+class StandardOutputSink : public LogSink
+{
+public:
+ void Consume(const std::string& s) override
+ {
+ std::cout << s << std::endl;
+ }
+};
+
+struct ScopedRecord
+{
+ ScopedRecord(const std::vector<std::shared_ptr<LogSink>>& sinks, LogSeverity level, bool enabled)
+ : m_LogSinks(sinks)
+ , m_Enabled(enabled)
+ {
+ if (enabled)
+ {
+ m_Os << LevelToString(level) << ": ";
+ }
+ }
+
+ ~ScopedRecord()
+ {
+ if (m_Enabled)
+ {
+ for (auto sink : m_LogSinks)
+ {
+ if (sink)
+ {
+ sink->Consume(m_Os.str());
+ }
+ }
+ }
+ }
+
+ ScopedRecord(const ScopedRecord&) = delete;
+ ScopedRecord& operator=(const ScopedRecord&) = delete;
+ ScopedRecord& operator=(ScopedRecord&&) = delete;
+
+ ScopedRecord(ScopedRecord&& other) = default;
+
+ template<typename Streamable>
+ ScopedRecord& operator<<(const Streamable& s)
+ {
+ if (m_Enabled)
+ {
+ m_Os << s;
+ }
+ return (*this);
+ }
+
+private:
+ const std::vector<std::shared_ptr<LogSink>>& m_LogSinks;
+ std::ostringstream m_Os;
+ bool m_Enabled;
+};
+
+template<LogSeverity Level>
+class SimpleLogger
+{
+public:
+ SimpleLogger()
+ : m_Sinks{std::make_shared<StandardOutputSink>()}
+ , m_Enable(true)
+ {
+ }
+
+ static SimpleLogger& Get()
+ {
+ static SimpleLogger<Level> logger;
+ return logger;
+ }
+
+ void Enable(bool enable = true)
+ {
+ m_Enable = enable;
+ }
+
+ ScopedRecord StartNewRecord()
+ {
+ ScopedRecord record(m_Sinks, Level, m_Enable);
+ return record;
+ }
+
+ void RemoveAllSinks()
+ {
+ m_Sinks.clear();
+ }
+
+ void AddSink(std::shared_ptr<LogSink> sink)
+ {
+ m_Sinks.push_back(sink);
+ }
+private:
+ std::vector<std::shared_ptr<LogSink>> m_Sinks;
+ bool m_Enable;
+};
+
+void SetLogFilter(LogSeverity level);
+
+void SetAllLoggingSinks(bool standardOut, bool debugOut, bool coloured);
+
+enum class BoostLogSeverityMapping
+{
+ trace,
+ debug,
+ info,
+ warning,
+ error,
+ fatal
+};
+
+constexpr LogSeverity ConvertLogSeverity(BoostLogSeverityMapping severity)
+{
+ return static_cast<LogSeverity>(severity);
+}
+
+
+#define ARM_PIPE_LOG(severity) \
+ arm::pipe::SimpleLogger<ConvertLogSeverity(arm::pipe::BoostLogSeverityMapping::severity)>::Get().StartNewRecord()
+
+} // namespace pipe
+} // namespace arm
diff --git a/profiling/common/include/NetworkSockets.hpp b/profiling/common/include/NetworkSockets.hpp
index 05a45ae90b..29575cdcd6 100644
--- a/profiling/common/include/NetworkSockets.hpp
+++ b/profiling/common/include/NetworkSockets.hpp
@@ -19,11 +19,14 @@
#include <WindowsWrapper.hpp>
#include <winsock2.h>
#include <afunix.h>
+#elif defined(__MINGW32__)
+#include <WindowsWrapper.hpp>
+#include <winsock2.h>
#endif
-namespace armnnUtils
+namespace arm
{
-namespace Sockets
+namespace pipe
{
#if defined(__unix__)
@@ -45,6 +48,14 @@ using nfds_t = int;
using socklen_t = int;
#define SOCK_CLOEXEC 0
+#elif defined(__MINGW32__)
+
+using Socket = SOCKET;
+using PollFd = WSAPOLLFD;
+using nfds_t = int;
+using socklen_t = int;
+#define SOCK_CLOEXEC 0
+
#endif
/// Performs any required one-time setup.
@@ -64,5 +75,5 @@ int Poll(PollFd* fds, nfds_t numFds, int timeout);
Socket Accept(Socket s, sockaddr* addr, socklen_t* addrlen, int flags);
-}
-}
+} // namespace arm
+} // namespace pipe
diff --git a/profiling/common/include/NumericCast.hpp b/profiling/common/include/NumericCast.hpp
new file mode 100644
index 0000000000..069f9514fe
--- /dev/null
+++ b/profiling/common/include/NumericCast.hpp
@@ -0,0 +1,128 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "Assert.hpp"
+
+#include <type_traits>
+#include <limits>
+
+namespace arm
+{
+
+namespace pipe
+{
+
+#if !defined(NDEBUG) || defined(ARM_PIPE_NUMERIC_CAST_TESTABLE)
+#define ENABLE_NUMERIC_CAST_CHECKS 1
+#else
+#define ENABLE_NUMERIC_CAST_CHECKS 0
+#endif
+
+#if defined(ARM_PIPE_NUMERIC_CAST_TESTABLE)
+# define ARM_PIPE_NUMERIC_CAST_CHECK(cond, msg) ConditionalThrow<std::bad_cast>(cond)
+#else
+# define ARM_PIPE_NUMERIC_CAST_CHECK(cond, msg) ARM_PIPE_ASSERT_MSG(cond, msg)
+#endif
+
+template<typename Dest, typename Source>
+typename std::enable_if_t<
+ std::is_unsigned<Source>::value &&
+ std::is_unsigned<Dest>::value
+ , Dest>
+numeric_cast(Source source)
+{
+#if ENABLE_NUMERIC_CAST_CHECKS
+ if (source > std::numeric_limits<Dest>::max())
+ {
+ ARM_PIPE_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting unsigned type to "
+ "narrower unsigned type. Overflow detected.");
+ }
+#endif // ENABLE_NUMERIC_CAST_CHECKS
+
+ return static_cast<Dest>(source);
+}
+
+template<typename Dest, typename Source>
+typename std::enable_if_t<
+ std::is_signed<Source>::value &&
+ std::is_signed<Dest>::value
+ , Dest>
+numeric_cast(Source source)
+{
+ static_assert(!std::is_floating_point<Source>::value && !std::is_floating_point<Dest>::value,
+ "numeric_cast doesn't cast float.");
+
+#if ENABLE_NUMERIC_CAST_CHECKS
+ if (source > std::numeric_limits<Dest>::max())
+ {
+ ARM_PIPE_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting signed type to narrower signed type. "
+ "Overflow detected.");
+ }
+
+ if (source < std::numeric_limits<Dest>::lowest())
+ {
+ ARM_PIPE_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting signed type to narrower signed type. "
+ "Underflow detected.");
+ }
+#endif // ENABLE_NUMERIC_CAST_CHECKS
+
+ return static_cast<Dest>(source);
+}
+
+// numeric cast from unsigned to signed checked for narrowing overflows
+template<typename Dest, typename Source>
+typename std::enable_if_t<
+ std::is_signed<Dest>::value &&
+ std::is_unsigned<Source>::value
+ , Dest>
+numeric_cast(Source sValue)
+{
+ static_assert(!std::is_floating_point<Dest>::value, "numeric_cast doesn't cast to float.");
+
+#if ENABLE_NUMERIC_CAST_CHECKS
+ if (sValue > static_cast< typename std::make_unsigned<Dest>::type >(std::numeric_limits<Dest>::max()))
+ {
+ ARM_PIPE_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting unsigned type to signed type. "
+ "Overflow detected.");
+ }
+#endif // ENABLE_NUMERIC_CAST_CHECKS
+
+ return static_cast<Dest>(sValue);
+}
+
+// numeric cast from signed to unsigned checked for underflows and narrowing overflows
+template<typename Dest, typename Source>
+typename std::enable_if_t<
+ std::is_unsigned<Dest>::value &&
+ std::is_signed<Source>::value
+ , Dest>
+numeric_cast(Source sValue)
+{
+ static_assert(!std::is_floating_point<Source>::value && !std::is_floating_point<Dest>::value,
+ "numeric_cast doesn't cast floats.");
+
+#if ENABLE_NUMERIC_CAST_CHECKS
+ if (sValue < 0)
+ {
+ ARM_PIPE_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting negative value to unsigned type. "
+ "Underflow detected.");
+ }
+
+ if (static_cast< typename std::make_unsigned<Source>::type >(sValue) > std::numeric_limits<Dest>::max())
+ {
+ ARM_PIPE_NUMERIC_CAST_CHECK(false, "numeric_cast failed casting signed type to unsigned type. "
+ "Overflow detected.");
+ }
+
+#endif // ENABLE_NUMERIC_CAST_CHECKS
+ return static_cast<Dest>(sValue);
+}
+
+#undef ENABLE_NUMERIC_CAST_CHECKS
+
+} // namespace pipe
+} // namespace arm
diff --git a/profiling/common/include/Packet.hpp b/profiling/common/include/Packet.hpp
index 23c3124bad..d8fa2709e2 100644
--- a/profiling/common/include/Packet.hpp
+++ b/profiling/common/include/Packet.hpp
@@ -1,18 +1,18 @@
//
-// Copyright © 2017 Arm Ltd. All rights reserved.
+// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#pragma once
-#include <armnn/Exceptions.hpp>
+#include "ProfilingException.hpp"
#include <memory>
-namespace armnn
+namespace arm
{
-namespace profiling
+namespace pipe
{
class Packet
@@ -45,7 +45,7 @@ public:
if (length == 0 && m_Data != nullptr)
{
- throw armnn::InvalidArgumentException("Data should be null when length is zero");
+ throw arm::pipe::InvalidArgumentException("Data should be null when length is zero");
}
}
@@ -86,6 +86,6 @@ private:
std::unique_ptr<unsigned char[]> m_Data;
};
-} // namespace profiling
+} // namespace pipe
-} // namespace armnn
+} // namespace arm
diff --git a/profiling/common/include/PacketVersionResolver.hpp b/profiling/common/include/PacketVersionResolver.hpp
new file mode 100644
index 0000000000..0ec7d2aca4
--- /dev/null
+++ b/profiling/common/include/PacketVersionResolver.hpp
@@ -0,0 +1,50 @@
+//
+// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "EncodeVersion.hpp"
+
+namespace arm
+{
+
+namespace pipe
+{
+
+class PacketKey final
+{
+public:
+ PacketKey(uint32_t familyId, uint32_t packetId) : m_FamilyId(familyId), m_PacketId(packetId) {}
+
+ uint32_t GetFamilyId() { return m_FamilyId; }
+ uint32_t GetPacketId() { return m_PacketId; }
+
+ bool operator< (const PacketKey& rhs) const;
+ bool operator> (const PacketKey& rhs) const;
+ bool operator<=(const PacketKey& rhs) const;
+ bool operator>=(const PacketKey& rhs) const;
+ bool operator==(const PacketKey& rhs) const;
+ bool operator!=(const PacketKey& rhs) const;
+
+private:
+ uint32_t m_FamilyId;
+ uint32_t m_PacketId;
+};
+
+static const PacketKey ActivateTimeLinePacket(0 , 6);
+static const PacketKey DeactivateTimeLinePacket(0 , 7);
+
+class PacketVersionResolver final
+{
+public:
+ PacketVersionResolver() = default;
+ ~PacketVersionResolver() = default;
+
+ Version ResolvePacketVersion(uint32_t familyId, uint32_t packetId) const;
+};
+
+} // namespace pipe
+
+} // namespace arm
diff --git a/profiling/common/include/ProfilingException.hpp b/profiling/common/include/ProfilingException.hpp
index 532c2d49f7..abdc0dc025 100644
--- a/profiling/common/include/ProfilingException.hpp
+++ b/profiling/common/include/ProfilingException.hpp
@@ -1,29 +1,82 @@
//
-// Copyright © 2020 Arm Ltd. All rights reserved.
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#pragma once
#include <stdexcept>
#include <string>
+#include <sstream>
-namespace armnnProfiling
+namespace arm
{
+namespace pipe
+{
+
+struct Location
+{
+ const char* m_Function;
+ const char* m_File;
+ unsigned int m_Line;
+
+ Location(const char* func,
+ const char* file,
+ unsigned int line)
+ : m_Function{func}
+ , m_File{file}
+ , m_Line{line}
+ {
+ }
+
+ std::string AsString() const
+ {
+ std::stringstream ss;
+ ss << " at function " << m_Function
+ << " [" << m_File << ':' << m_Line << "]";
+ return ss.str();
+ }
+
+ std::string FileLine() const
+ {
+ std::stringstream ss;
+ ss << " [" << m_File << ':' << m_Line << "]";
+ return ss.str();
+ }
+};
+
/// General Exception class for Profiling code
class ProfilingException : public std::exception
{
public:
explicit ProfilingException(const std::string& message) : m_Message(message) {};
+ explicit ProfilingException(const std::string& message,
+ const Location& location) : m_Message(message + location.AsString()) {};
+
/// @return - Error message of ProfilingException
- virtual const char* what() const noexcept override
+ virtual const char *what() const noexcept override
{
- return m_Message.c_str();
+ return m_Message.c_str();
}
private:
std::string m_Message;
};
-} // namespace armnnProfiling
+class TimeoutException : public ProfilingException
+{
+public:
+ using ProfilingException::ProfilingException;
+};
+
+class InvalidArgumentException : public ProfilingException
+{
+public:
+ using ProfilingException::ProfilingException;
+};
+
+} // namespace pipe
+} // namespace arm
+
+#define LOCATION() arm::pipe::Location(__func__, __FILE__, __LINE__)
diff --git a/profiling/common/include/SocketConnectionException.hpp b/profiling/common/include/SocketConnectionException.hpp
index d18dcc37e4..42b8d9d67e 100644
--- a/profiling/common/include/SocketConnectionException.hpp
+++ b/profiling/common/include/SocketConnectionException.hpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2020 Arm Ltd. All rights reserved.
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#pragma once
@@ -10,30 +10,31 @@
#include "NetworkSockets.hpp"
-namespace armnnProfiling
+namespace arm
+{
+
+namespace pipe
{
/// Socket Connection Exception for profiling
class SocketConnectionException : public std::exception
{
public:
- explicit SocketConnectionException(const std::string& message, armnnUtils::Sockets::Socket socket)
- : m_Message(message), m_Socket(socket), m_ErrNo(-1)
- {};
+ explicit SocketConnectionException(const std::string &message, arm::pipe::Socket socket)
+ : m_Message(message), m_Socket(socket), m_ErrNo(-1) {};
- explicit SocketConnectionException(const std::string& message, armnnUtils::Sockets::Socket socket, int errNo)
- : m_Message(message), m_Socket(socket), m_ErrNo(errNo)
- {};
+ explicit SocketConnectionException(const std::string &message, arm::pipe::Socket socket, int errNo)
+ : m_Message(message), m_Socket(socket), m_ErrNo(errNo) {};
/// @return - Error message of SocketProfilingConnection
- virtual const char* what() const noexcept override
+ virtual const char *what() const noexcept override
{
return m_Message.c_str();
}
/// @return - Socket File Descriptor of SocketProfilingConnection
/// or '-1', an invalid file descriptor
- armnnUtils::Sockets::Socket GetSocketFd() const noexcept
+ arm::pipe::Socket GetSocketFd() const noexcept
{
return m_Socket;
}
@@ -46,8 +47,8 @@ public:
private:
std::string m_Message;
- armnnUtils::Sockets::Socket m_Socket;
+ arm::pipe::Socket m_Socket;
int m_ErrNo;
};
-
-} // namespace armnnProfiling
+} // namespace pipe
+} // namespace arm
diff --git a/profiling/common/include/SwTrace.hpp b/profiling/common/include/SwTrace.hpp
new file mode 100644
index 0000000000..5abc59b1a8
--- /dev/null
+++ b/profiling/common/include/SwTrace.hpp
@@ -0,0 +1,139 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "NumericCast.hpp"
+
+#include <algorithm>
+#include <cstring>
+#include <string>
+#include <vector>
+
+namespace arm
+{
+
+namespace pipe
+{
+
+struct SwTraceHeader
+{
+ uint8_t m_StreamVersion;
+ uint8_t m_PointerBytes;
+ uint8_t m_ThreadIdBytes;
+};
+
+struct SwTraceMessage
+{
+ uint32_t m_Id;
+ std::string m_Name;
+ std::string m_UiName;
+ std::vector<char> m_ArgTypes;
+ std::vector<std::string> m_ArgNames;
+};
+
+struct SwTraceCharPolicy
+{
+ static bool IsValidChar(unsigned char c)
+ {
+ // Check that the given character has ASCII 7-bit encoding
+ return c < 128;
+ }
+};
+
+struct SwTraceNameCharPolicy
+{
+ static bool IsValidChar(unsigned char c)
+ {
+ // Check that the given character has ASCII 7-bit encoding, alpha-numeric and underscore only
+ return c < 128 && (std::isalnum(c) || c == '_');
+ }
+};
+
+struct SwTraceTypeCharPolicy
+{
+ static bool IsValidChar(unsigned char c)
+ {
+ // Check that the given character is among the allowed ones
+ switch (c)
+ {
+ case '@':
+ case 't':
+ case 'i':
+ case 'I':
+ case 'l':
+ case 'L':
+ case 'F':
+ case 'p':
+ case 's':
+ return true; // Valid char
+ default:
+ return false; // Invalid char
+ }
+ }
+};
+
+template <typename SwTracePolicy>
+bool IsValidSwTraceString(const std::string& s)
+{
+ // Check that all the characters in the given string conform to the given policy
+ return std::all_of(s.begin(), s.end(), [](unsigned char c) { return SwTracePolicy::IsValidChar(c); });
+}
+
+template <typename SwTracePolicy>
+bool StringToSwTraceString(const std::string& s, std::vector<uint32_t>& outputBuffer)
+{
+ // Converts the given string to an SWTrace "string" (i.e. a string of "chars"), and writes it into
+ // the given buffer including the null-terminator. It also pads it to the next uint32_t if necessary
+
+ // Clear the output buffer
+ outputBuffer.clear();
+
+ // Check that the given string is a valid SWTrace "string" (i.e. a string of "chars")
+ if (!IsValidSwTraceString<SwTracePolicy>(s))
+ {
+ return false;
+ }
+
+ // Prepare the output buffer
+ size_t s_size = s.size() + 1; // The size of the string (in chars) plus the null-terminator
+ size_t uint32_t_size = sizeof(uint32_t);
+ // Output buffer size = StringLength (32 bit) + amount of complete 32bit words that fit into the string
+ // + an additional 32bit word if there are remaining chars to complete the string
+ // (The rest of the 32bit word is then filled with the NULL terminator)
+ size_t outBufferSize = 1 + (s_size / uint32_t_size) + (s_size % uint32_t_size != 0 ? 1 : 0);
+ outputBuffer.resize(outBufferSize, '\0');
+
+ // Write the SWTrace string to the output buffer
+ outputBuffer[0] = numeric_cast<uint32_t>(s_size);
+ std::memcpy(outputBuffer.data() + 1, s.data(), s_size);
+
+ return true;
+}
+
+template <typename SwTracePolicy,
+ typename SwTraceBuffer = std::vector<uint32_t>>
+bool ConvertDirectoryComponent(const std::string& directoryComponent, SwTraceBuffer& swTraceBuffer)
+{
+ // Convert the directory component using the given policy
+ SwTraceBuffer tempSwTraceBuffer;
+ bool result = StringToSwTraceString<SwTracePolicy>(directoryComponent, tempSwTraceBuffer);
+ if (!result)
+ {
+ return false;
+ }
+
+ swTraceBuffer.insert(swTraceBuffer.end(), tempSwTraceBuffer.begin(), tempSwTraceBuffer.end());
+
+ return true;
+}
+
+uint32_t CalculateSizeOfPaddedSwString(const std::string& str);
+
+SwTraceMessage ReadSwTraceMessage(const unsigned char*, unsigned int&, const unsigned int& packetLength);
+
+} // namespace pipe
+
+} // namespace arm
diff --git a/profiling/common/include/WindowsWrapper.hpp b/profiling/common/include/WindowsWrapper.hpp
new file mode 100644
index 0000000000..d75fdc857a
--- /dev/null
+++ b/profiling/common/include/WindowsWrapper.hpp
@@ -0,0 +1,30 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+// This header brings in the Win32 API header, with some small modifications applied to prevent clashes with our code.
+
+#if defined(_MSC_VER)
+
+#define NOMINMAX // Prevent definition of min/max macros that interfere with std::min/max
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+// Windows.h defines some names that we don't need and interfere with some of our definition
+#undef TIME_MS // Instrument.hpp
+#undef CreateEvent // ITimelineDecoder.hpp
+
+#endif
+
+#if defined(__MINGW32__)
+
+#define NOMINMAX // Prevent definition of min/max macros that interfere with std::min/max
+#define WIN32_LEAN_AND_MEAN
+#define WINVER 0x0A00
+#define _WIN32_WINNT 0x0A00
+#include <windows.h>
+// Windows.h defines some names that we don't need and interfere with some of our definition
+#undef TIME_MS // Instrument.hpp
+#undef CreateEvent // ITimelineDecoder.hpp
+
+#endif
diff --git a/profiling/common/src/CMakeLists.txt b/profiling/common/src/CMakeLists.txt
new file mode 100644
index 0000000000..9505fb8869
--- /dev/null
+++ b/profiling/common/src/CMakeLists.txt
@@ -0,0 +1,30 @@
+#
+# Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+# SPDX-License-Identifier: MIT
+#
+
+if(BUILD_TIMELINE_DECODER)
+ set(pipeCommon_sources)
+ list(APPEND pipeCommon_sources
+ CommandHandlerFunctor.cpp
+ CommandHandlerKey.cpp
+ CommandHandlerRegistry.cpp
+ CommonProfilingUtils.cpp
+ NetworkSockets.cpp
+ PacketVersionResolver.cpp
+ SwTrace.cpp)
+
+ include_directories(${PROJECT_SOURCE_DIR}/profiling/common/include)
+ include_directories(${PROJECT_SOURCE_DIR}/common/include)
+
+ if(BUILD_UNIT_TESTS)
+ include_directories(${PROJECT_SOURCE_DIR}/src/profiling
+ ${PROJECT_SOURCE_DIR}/src/armnnUtils)
+ target_include_directories(UnitTests PRIVATE ${PROJECT_SOURCE_DIR}/profiling/common/include)
+ endif()
+
+ # will only build a static version of this common code
+ # to simplify the build. No extra .so file to deploy to boards etc.
+ add_library_ex(pipeCommon STATIC ${pipeCommon_sources})
+
+endif()
diff --git a/profiling/common/src/CommandHandlerFunctor.cpp b/profiling/common/src/CommandHandlerFunctor.cpp
new file mode 100644
index 0000000000..ea24cfb34e
--- /dev/null
+++ b/profiling/common/src/CommandHandlerFunctor.cpp
@@ -0,0 +1,31 @@
+//
+// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "CommandHandlerFunctor.hpp"
+
+namespace arm
+{
+
+namespace pipe
+{
+
+uint32_t CommandHandlerFunctor::GetFamilyId() const
+{
+ return m_FamilyId;
+}
+
+uint32_t CommandHandlerFunctor::GetPacketId() const
+{
+ return m_PacketId;
+}
+
+uint32_t CommandHandlerFunctor::GetVersion() const
+{
+ return m_Version;
+}
+
+} // namespace pipe
+
+} // namespace arm
diff --git a/profiling/common/src/CommandHandlerKey.cpp b/profiling/common/src/CommandHandlerKey.cpp
new file mode 100644
index 0000000000..98e4567348
--- /dev/null
+++ b/profiling/common/src/CommandHandlerKey.cpp
@@ -0,0 +1,77 @@
+//
+// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "CommandHandlerKey.hpp"
+
+namespace arm
+{
+
+namespace pipe
+{
+
+uint32_t CommandHandlerKey::GetFamilyId() const
+{
+ return m_FamilyId;
+}
+
+uint32_t CommandHandlerKey::GetPacketId() const
+{
+ return m_PacketId;
+}
+
+uint32_t CommandHandlerKey::GetVersion() const
+{
+ return m_Version;
+}
+
+bool CommandHandlerKey::operator<(const CommandHandlerKey& rhs) const
+{
+ bool result = true;
+ if (m_FamilyId == rhs.m_FamilyId)
+ {
+ if (m_PacketId == rhs.m_PacketId)
+ {
+ result = m_Version < rhs.m_Version;
+ }
+ else if (m_PacketId > rhs.m_PacketId)
+ {
+ result = false;
+ }
+ }
+ else if (m_FamilyId > rhs.m_FamilyId)
+ {
+ result = false;
+ }
+ return result;
+}
+
+bool CommandHandlerKey::operator>(const CommandHandlerKey& rhs) const
+{
+ return rhs < *this;
+}
+
+bool CommandHandlerKey::operator<=(const CommandHandlerKey& rhs) const
+{
+ return !(*this > rhs);
+}
+
+bool CommandHandlerKey::operator>=(const CommandHandlerKey& rhs) const
+{
+ return !(*this < rhs);
+}
+
+bool CommandHandlerKey::operator==(const CommandHandlerKey& rhs) const
+{
+ return m_FamilyId == rhs.m_FamilyId && m_PacketId == rhs.m_PacketId && m_Version == rhs.m_Version;
+}
+
+bool CommandHandlerKey::operator!=(const CommandHandlerKey& rhs) const
+{
+ return !(*this == rhs);
+}
+
+} // namespace pipe
+
+} // namespace arm
diff --git a/profiling/common/src/CommandHandlerRegistry.cpp b/profiling/common/src/CommandHandlerRegistry.cpp
new file mode 100644
index 0000000000..324737eda5
--- /dev/null
+++ b/profiling/common/src/CommandHandlerRegistry.cpp
@@ -0,0 +1,61 @@
+//
+// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+
+#include <common/include/Assert.hpp>
+#include <common/include/CommandHandlerRegistry.hpp>
+
+#include <sstream>
+
+namespace arm
+{
+
+namespace pipe
+{
+
+void CommandHandlerRegistry::RegisterFunctor(CommandHandlerFunctor* functor,
+ uint32_t familyId,
+ uint32_t packetId,
+ uint32_t version)
+{
+ ARM_PIPE_ASSERT_MSG(functor, "Provided functor should not be a nullptr");
+
+ CommandHandlerKey key(familyId, packetId, version);
+ registry[key] = functor;
+}
+
+void CommandHandlerRegistry::RegisterFunctor(CommandHandlerFunctor* functor)
+{
+ ARM_PIPE_ASSERT_MSG(functor, "Provided functor should not be a nullptr");
+
+ RegisterFunctor(functor, functor->GetFamilyId(), functor->GetPacketId(), functor->GetVersion());
+}
+
+CommandHandlerFunctor* CommandHandlerRegistry::GetFunctor(uint32_t familyId,uint32_t packetId, uint32_t version) const
+{
+ CommandHandlerKey key(familyId, packetId, version);
+
+ // Check that the requested key exists
+ if (registry.find(key) == registry.end())
+ {
+ std::stringstream ss;
+ ss << "Functor with requested PacketId=" << packetId << " and Version=" << version << " does not exist";
+ throw ProfilingException(ss.str());
+ }
+
+ CommandHandlerFunctor* commandHandlerFunctor = registry.at(key);
+ if (commandHandlerFunctor == nullptr)
+ {
+ std::stringstream ss;
+ ss << "Invalid functor registered for PacketId=" << packetId << " and Version=" << version;
+ throw ProfilingException(ss.str());
+ }
+
+ return commandHandlerFunctor;
+}
+
+} // namespace pipe
+
+} // namespace arm
diff --git a/profiling/common/src/CommonProfilingUtils.cpp b/profiling/common/src/CommonProfilingUtils.cpp
new file mode 100644
index 0000000000..fe98e0aaa9
--- /dev/null
+++ b/profiling/common/src/CommonProfilingUtils.cpp
@@ -0,0 +1,145 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include <common/include/Assert.hpp>
+#include <common/include/CommonProfilingUtils.hpp>
+
+#include <sstream>
+
+namespace arm
+{
+
+namespace pipe
+{
+void ReadBytes(const unsigned char* buffer, unsigned int offset, unsigned int valueSize, uint8_t outValue[])
+{
+ ARM_PIPE_ASSERT(buffer);
+ ARM_PIPE_ASSERT(outValue);
+
+ for (unsigned int i = 0; i < valueSize; i++, offset++)
+ {
+ outValue[i] = static_cast<uint8_t>(buffer[offset]);
+ }
+}
+
+uint64_t ReadUint64(const unsigned char* buffer, unsigned int offset)
+{
+ ARM_PIPE_ASSERT(buffer);
+
+ uint64_t value = 0;
+ value = static_cast<uint64_t>(buffer[offset]);
+ value |= static_cast<uint64_t>(buffer[offset + 1]) << 8;
+ value |= static_cast<uint64_t>(buffer[offset + 2]) << 16;
+ value |= static_cast<uint64_t>(buffer[offset + 3]) << 24;
+ value |= static_cast<uint64_t>(buffer[offset + 4]) << 32;
+ value |= static_cast<uint64_t>(buffer[offset + 5]) << 40;
+ value |= static_cast<uint64_t>(buffer[offset + 6]) << 48;
+ value |= static_cast<uint64_t>(buffer[offset + 7]) << 56;
+
+ return value;
+}
+
+uint32_t ReadUint32(const unsigned char* buffer, unsigned int offset)
+{
+ ARM_PIPE_ASSERT(buffer);
+
+ uint32_t value = 0;
+ value = static_cast<uint32_t>(buffer[offset]);
+ value |= static_cast<uint32_t>(buffer[offset + 1]) << 8;
+ value |= static_cast<uint32_t>(buffer[offset + 2]) << 16;
+ value |= static_cast<uint32_t>(buffer[offset + 3]) << 24;
+ return value;
+}
+
+uint16_t ReadUint16(const unsigned char* buffer, unsigned int offset)
+{
+ ARM_PIPE_ASSERT(buffer);
+
+ uint32_t value = 0;
+ value = static_cast<uint32_t>(buffer[offset]);
+ value |= static_cast<uint32_t>(buffer[offset + 1]) << 8;
+ return static_cast<uint16_t>(value);
+}
+
+uint8_t ReadUint8(const unsigned char* buffer, unsigned int offset)
+{
+ ARM_PIPE_ASSERT(buffer);
+
+ return buffer[offset];
+}
+
+void WriteBytes(unsigned char* buffer, unsigned int offset, const void* value, unsigned int valueSize)
+{
+ ARM_PIPE_ASSERT(buffer);
+ ARM_PIPE_ASSERT(value);
+
+ for (unsigned int i = 0; i < valueSize; i++, offset++)
+ {
+ buffer[offset] = *(reinterpret_cast<const unsigned char*>(value) + i);
+ }
+}
+
+void WriteUint64(unsigned char* buffer, unsigned int offset, uint64_t value)
+{
+ ARM_PIPE_ASSERT(buffer);
+
+ buffer[offset] = static_cast<unsigned char>(value & 0xFF);
+ buffer[offset + 1] = static_cast<unsigned char>((value >> 8) & 0xFF);
+ buffer[offset + 2] = static_cast<unsigned char>((value >> 16) & 0xFF);
+ buffer[offset + 3] = static_cast<unsigned char>((value >> 24) & 0xFF);
+ buffer[offset + 4] = static_cast<unsigned char>((value >> 32) & 0xFF);
+ buffer[offset + 5] = static_cast<unsigned char>((value >> 40) & 0xFF);
+ buffer[offset + 6] = static_cast<unsigned char>((value >> 48) & 0xFF);
+ buffer[offset + 7] = static_cast<unsigned char>((value >> 56) & 0xFF);
+}
+
+void WriteUint32(unsigned char* buffer, unsigned int offset, uint32_t value)
+{
+ ARM_PIPE_ASSERT(buffer);
+
+ buffer[offset] = static_cast<unsigned char>(value & 0xFF);
+ buffer[offset + 1] = static_cast<unsigned char>((value >> 8) & 0xFF);
+ buffer[offset + 2] = static_cast<unsigned char>((value >> 16) & 0xFF);
+ buffer[offset + 3] = static_cast<unsigned char>((value >> 24) & 0xFF);
+}
+
+void WriteUint16(unsigned char* buffer, unsigned int offset, uint16_t value)
+{
+ ARM_PIPE_ASSERT(buffer);
+
+ buffer[offset] = static_cast<unsigned char>(value & 0xFF);
+ buffer[offset + 1] = static_cast<unsigned char>((value >> 8) & 0xFF);
+}
+
+void WriteUint8(unsigned char* buffer, unsigned int offset, uint8_t value)
+{
+ ARM_PIPE_ASSERT(buffer);
+
+ buffer[offset] = static_cast<unsigned char>(value);
+}
+
+std::string CentreAlignFormatting(const std::string& stringToPass, const int spacingWidth)
+{
+ std::stringstream outputStream, centrePadding;
+ int padding = spacingWidth - static_cast<int>(stringToPass.size());
+
+ for (int i = 0; i < padding / 2; ++i)
+ {
+ centrePadding << " ";
+ }
+
+ outputStream << centrePadding.str() << stringToPass << centrePadding.str();
+
+ if (padding > 0 && padding %2 != 0)
+ {
+ outputStream << " ";
+ }
+
+ return outputStream.str();
+}
+
+
+} // namespace pipe
+} // namespace arm \ No newline at end of file
diff --git a/profiling/common/src/NetworkSockets.cpp b/profiling/common/src/NetworkSockets.cpp
index 7f47c79b31..2a656552f1 100644
--- a/profiling/common/src/NetworkSockets.cpp
+++ b/profiling/common/src/NetworkSockets.cpp
@@ -1,27 +1,35 @@
//
-// Copyright © 2020 Arm Ltd. All rights reserved.
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
-#include "common/include/NetworkSockets.hpp"
+#include <common/include/NetworkSockets.hpp>
#if defined(__unix__) || defined(__APPLE__)
#include <unistd.h>
#include <fcntl.h>
-#include <armnn/Conversion.hpp>
+#include <common/include/Conversion.hpp>
+#endif
+
+#if defined(__APPLE__) || defined(_MSC_VER) || defined(__MINGW32__)
+#include <common/include/IgnoreUnused.hpp>
+#endif
+#if defined(__MINGW32__)
+#include <common/include/Conversion.hpp>
+#include <common/include/NumericCast.hpp>
#endif
-namespace armnnUtils
+namespace arm
{
-namespace Sockets
+namespace pipe
{
bool Initialize()
{
#if defined(__unix__) || defined(__APPLE__)
return true;
-#elif defined(_MSC_VER)
+#elif defined(_MSC_VER) || defined(__MINGW32__)
WSADATA wsaData;
return WSAStartup(MAKEWORD(2, 2), &wsaData) == 0;
#endif
@@ -31,7 +39,7 @@ int Close(Socket s)
{
#if defined(__unix__) || defined(__APPLE__)
return close(s);
-#elif defined(_MSC_VER)
+#elif defined(_MSC_VER) || defined(__MINGW32__)
return closesocket(s);
#endif
}
@@ -45,6 +53,9 @@ bool SetNonBlocking(Socket s)
#elif defined(_MSC_VER)
u_long mode = 1;
return ioctlsocket(s, FIONBIO, &mode) == 0;
+#elif defined(__MINGW32__)
+ u_long mode = 1;
+ return ioctlsocket(s, arm::pipe::numeric_cast<long>(FIONBIO), &mode) == 0;
#endif
}
@@ -53,7 +64,7 @@ long Write(Socket s, const void* buf, size_t len)
{
#if defined(__unix__) || defined(__APPLE__)
return write(s, buf, len);
-#elif defined(_MSC_VER)
+#elif defined(_MSC_VER) || defined(__MINGW32__)
return send(s, static_cast<const char*>(buf), static_cast<int>(len), 0);
#endif
}
@@ -63,7 +74,7 @@ long Read(Socket s, void* buf, size_t len)
{
#if defined(__unix__) || defined(__APPLE__)
return read(s, buf, len);
-#elif defined(_MSC_VER)
+#elif defined(_MSC_VER) || defined(__MINGW32__)
return recv(s, static_cast<char*>(buf), static_cast<int>(len), 0);
#endif
}
@@ -71,11 +82,13 @@ long Read(Socket s, void* buf, size_t len)
int Ioctl(Socket s, unsigned long int cmd, void* arg)
{
#if defined(__unix__) || defined(__APPLE__)
- ARMNN_NO_CONVERSION_WARN_BEGIN
+ ARM_PIPE_NO_CONVERSION_WARN_BEGIN
return ioctl(s, static_cast<int>(cmd), arg);
- ARMNN_NO_CONVERSION_WARN_END
-#elif defined(_MSC_VER)
+ ARM_PIPE_NO_CONVERSION_WARN_END
+#elif defined(_MSC_VER) || defined(__MINGW32__)
+ ARM_PIPE_NO_CONVERSION_WARN_BEGIN
return ioctlsocket(s, cmd, static_cast<u_long*>(arg));
+ ARM_PIPE_NO_CONVERSION_WARN_END
#endif
}
@@ -84,22 +97,24 @@ int Poll(PollFd* fds, nfds_t numFds, int timeout)
{
#if defined(__unix__) || defined(__APPLE__)
return poll(fds, numFds, timeout);
-#elif defined(_MSC_VER)
- return WSAPoll(fds, numFds, timeout);
+#elif defined(_MSC_VER) || defined(__MINGW32__)
+ return WSAPoll(fds, arm::pipe::numeric_cast<unsigned long>(numFds), timeout);
#endif
}
-armnnUtils::Sockets::Socket Accept(Socket s, sockaddr* addr, socklen_t* addrlen, int flags)
+arm::pipe::Socket Accept(Socket s, sockaddr* addr, socklen_t* addrlen, int flags)
{
#if defined(__unix__)
return accept4(s, addr, addrlen, flags);
#elif defined(__APPLE__)
+ IgnoreUnused(flags);
return accept(s, addr, addrlen);
-#elif defined(_MSC_VER)
+#elif defined(_MSC_VER) || defined(__MINGW32__)
+ IgnoreUnused(flags);
return accept(s, addr, reinterpret_cast<int*>(addrlen));
#endif
}
-}
-}
+} // pipe
+} // arm
diff --git a/profiling/common/src/PacketVersionResolver.cpp b/profiling/common/src/PacketVersionResolver.cpp
new file mode 100644
index 0000000000..25d92b0c5d
--- /dev/null
+++ b/profiling/common/src/PacketVersionResolver.cpp
@@ -0,0 +1,71 @@
+//
+// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include <common/include/PacketVersionResolver.hpp>
+
+namespace arm
+{
+
+namespace pipe
+{
+
+bool PacketKey::operator<(const PacketKey& rhs) const
+{
+ bool result = true;
+ if (m_FamilyId == rhs.m_FamilyId)
+ {
+ result = m_PacketId < rhs.m_PacketId;
+ }
+ else if (m_FamilyId > rhs.m_FamilyId)
+ {
+ result = false;
+ }
+ return result;
+}
+
+bool PacketKey::operator>(const PacketKey& rhs) const
+{
+ return rhs < *this;
+}
+
+bool PacketKey::operator<=(const PacketKey& rhs) const
+{
+ return !(*this > rhs);
+}
+
+bool PacketKey::operator>=(const PacketKey& rhs) const
+{
+ return !(*this < rhs);
+}
+
+bool PacketKey::operator==(const PacketKey& rhs) const
+{
+ return m_FamilyId == rhs.m_FamilyId && m_PacketId == rhs.m_PacketId;
+}
+
+bool PacketKey::operator!=(const PacketKey& rhs) const
+{
+ return !(*this == rhs);
+}
+
+Version PacketVersionResolver::ResolvePacketVersion(uint32_t familyId, uint32_t packetId) const
+{
+ const PacketKey packetKey(familyId, packetId);
+
+ if( packetKey == ActivateTimeLinePacket )
+ {
+ return Version(1, 1, 0);
+ }
+ if( packetKey == DeactivateTimeLinePacket )
+ {
+ return Version(1, 1, 0);
+ }
+
+ return Version(1, 0, 0);
+}
+
+} // namespace pipe
+
+} // namespace arm
diff --git a/profiling/common/src/SwTrace.cpp b/profiling/common/src/SwTrace.cpp
new file mode 100644
index 0000000000..5860d8cf06
--- /dev/null
+++ b/profiling/common/src/SwTrace.cpp
@@ -0,0 +1,128 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include <common/include/CommonProfilingUtils.hpp>
+#include <common/include/NumericCast.hpp>
+#include <common/include/ProfilingException.hpp>
+#include <common/include/SwTrace.hpp>
+
+#include <sstream>
+
+namespace arm
+{
+
+namespace pipe
+{
+
+// Calculate the actual length an SwString will be including the terminating null character
+// padding to bring it to the next uint32_t boundary but minus the leading uint32_t encoding
+// the size to allow the offset to be correctly updated when decoding a binary packet.
+uint32_t CalculateSizeOfPaddedSwString(const std::string& str)
+{
+ std::vector<uint32_t> swTraceString;
+ StringToSwTraceString<SwTraceCharPolicy>(str, swTraceString);
+ unsigned int uint32_t_size = sizeof(uint32_t);
+ uint32_t size = (numeric_cast<uint32_t>(swTraceString.size()) - 1) * uint32_t_size;
+ return size;
+}
+
+// Read TimelineMessageDirectoryPacket from given IPacketBuffer and offset
+SwTraceMessage ReadSwTraceMessage(const unsigned char* packetBuffer,
+ unsigned int& offset,
+ const unsigned int& packetLength)
+{
+ ARM_PIPE_ASSERT(packetBuffer);
+
+ unsigned int uint32_t_size = sizeof(uint32_t);
+
+ SwTraceMessage swTraceMessage;
+
+ // Read the decl_id
+ uint32_t readDeclId = ReadUint32(packetBuffer, offset);
+ swTraceMessage.m_Id = readDeclId;
+
+ // SWTrace "namestring" format
+ // length of the string (first 4 bytes) + string + null terminator
+
+ // Check the decl_name
+ offset += uint32_t_size;
+ uint32_t swTraceDeclNameLength = ReadUint32(packetBuffer, offset);
+
+ if (swTraceDeclNameLength == 0 || swTraceDeclNameLength > packetLength)
+ {
+ throw arm::pipe::ProfilingException("Error swTraceDeclNameLength is an invalid size", LOCATION());
+ }
+
+ offset += uint32_t_size;
+ std::vector<unsigned char> swTraceStringBuffer(swTraceDeclNameLength - 1);
+ std::memcpy(swTraceStringBuffer.data(),
+ packetBuffer + offset, swTraceStringBuffer.size());
+
+ swTraceMessage.m_Name.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // name
+
+ // Check the ui_name
+ offset += CalculateSizeOfPaddedSwString(swTraceMessage.m_Name);
+ uint32_t swTraceUINameLength = ReadUint32(packetBuffer, offset);
+
+ if (swTraceUINameLength == 0 || swTraceUINameLength > packetLength)
+ {
+ throw arm::pipe::ProfilingException("Error swTraceUINameLength is an invalid size", LOCATION());
+ }
+
+ offset += uint32_t_size;
+ swTraceStringBuffer.resize(swTraceUINameLength - 1);
+ std::memcpy(swTraceStringBuffer.data(),
+ packetBuffer + offset, swTraceStringBuffer.size());
+
+ swTraceMessage.m_UiName.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // ui_name
+
+ // Check arg_types
+ offset += CalculateSizeOfPaddedSwString(swTraceMessage.m_UiName);
+ uint32_t swTraceArgTypesLength = ReadUint32(packetBuffer, offset);
+
+ if (swTraceArgTypesLength == 0 || swTraceArgTypesLength > packetLength)
+ {
+ throw arm::pipe::ProfilingException("Error swTraceArgTypesLength is an invalid size", LOCATION());
+ }
+
+ offset += uint32_t_size;
+ swTraceStringBuffer.resize(swTraceArgTypesLength - 1);
+ std::memcpy(swTraceStringBuffer.data(),
+ packetBuffer + offset, swTraceStringBuffer.size());
+
+ swTraceMessage.m_ArgTypes.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // arg_types
+
+ std::string swTraceString(swTraceStringBuffer.begin(), swTraceStringBuffer.end());
+
+ // Check arg_names
+ offset += CalculateSizeOfPaddedSwString(swTraceString);
+ uint32_t swTraceArgNamesLength = ReadUint32(packetBuffer, offset);
+
+ if (swTraceArgNamesLength == 0 || swTraceArgNamesLength > packetLength)
+ {
+ throw arm::pipe::ProfilingException("Error swTraceArgNamesLength is an invalid size", LOCATION());
+ }
+
+ offset += uint32_t_size;
+ swTraceStringBuffer.resize(swTraceArgNamesLength - 1);
+ std::memcpy(swTraceStringBuffer.data(),
+ packetBuffer + offset, swTraceStringBuffer.size());
+
+ swTraceString.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end());
+ std::stringstream stringStream(swTraceString);
+ std::string argName;
+ while (std::getline(stringStream, argName, ','))
+ {
+ swTraceMessage.m_ArgNames.push_back(argName);
+ }
+
+ offset += CalculateSizeOfPaddedSwString(swTraceString);
+
+ return swTraceMessage;
+}
+
+} // namespace pipe
+
+} // namespace arm