diff options
Diffstat (limited to 'profiling/common/include')
18 files changed, 968 insertions, 32 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 |