aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/AllocatorWrapper.cpp3
-rw-r--r--src/common/AllocatorWrapper.h6
-rw-r--r--src/common/IContext.h25
-rw-r--r--src/common/IOperator.cpp (renamed from src/common/cpuinfo/target/CpuInfoSveUtils.cpp)53
-rw-r--r--src/common/IOperator.h137
-rw-r--r--src/common/IQueue.h4
-rw-r--r--src/common/ITensorV2.cpp4
-rw-r--r--src/common/ITensorV2.h7
-rw-r--r--src/common/TensorPack.cpp4
-rw-r--r--src/common/TensorPack.h5
-rw-r--r--src/common/Types.h1
-rw-r--r--src/common/cpuinfo/CpuInfo.cpp266
-rw-r--r--src/common/cpuinfo/CpuInfo.h43
-rw-r--r--src/common/cpuinfo/CpuIsaInfo.cpp159
-rw-r--r--src/common/cpuinfo/CpuIsaInfo.h28
-rw-r--r--src/common/cpuinfo/CpuModel.cpp83
-rw-r--r--src/common/cpuinfo/CpuModel.h16
-rw-r--r--src/common/cpuinfo/target/CpuInfoSveUtils.h40
-rw-r--r--src/common/utils/LegacySupport.cpp81
-rw-r--r--src/common/utils/LegacySupport.h11
-rw-r--r--src/common/utils/Log.h176
-rw-r--r--src/common/utils/Macros.h2
-rw-r--r--src/common/utils/Object.h8
-rw-r--r--src/common/utils/Utils.h9
-rw-r--r--src/common/utils/Validate.h2
25 files changed, 833 insertions, 340 deletions
diff --git a/src/common/AllocatorWrapper.cpp b/src/common/AllocatorWrapper.cpp
index 7b5bb34433..28d81a9fa4 100644
--- a/src/common/AllocatorWrapper.cpp
+++ b/src/common/AllocatorWrapper.cpp
@@ -22,6 +22,7 @@
* SOFTWARE.
*/
#include "src/common/AllocatorWrapper.h"
+
#include "arm_compute/core/Error.h"
namespace arm_compute
@@ -57,7 +58,7 @@ void AllocatorWrapper::aligned_free(void *ptr)
void AllocatorWrapper::set_user_data(void *user_data)
{
- if(user_data != nullptr)
+ if (user_data != nullptr)
{
_backing_allocator.user_data = user_data;
}
diff --git a/src/common/AllocatorWrapper.h b/src/common/AllocatorWrapper.h
index 5e1f138f16..bbf70a2cb1 100644
--- a/src/common/AllocatorWrapper.h
+++ b/src/common/AllocatorWrapper.h
@@ -37,8 +37,8 @@ public:
* @param[in] backing_allocator Backing memory allocator to be used
*/
AllocatorWrapper(const AclAllocator &backing_allocator) noexcept;
- AllocatorWrapper(const AllocatorWrapper &) noexcept = default;
- AllocatorWrapper(AllocatorWrapper &&) noexcept = default;
+ AllocatorWrapper(const AllocatorWrapper &) noexcept = default;
+ AllocatorWrapper(AllocatorWrapper &&) noexcept = default;
AllocatorWrapper &operator=(const AllocatorWrapper &) noexcept = delete;
AllocatorWrapper &operator=(AllocatorWrapper &&other) noexcept = default;
/** Allocate a chunk of memory of a given size in bytes
@@ -78,4 +78,4 @@ private:
};
} // namespace arm_compute
-#endif /* SRC_COMMON_ALLOCATORWRAPPER_H */ \ No newline at end of file
+#endif /* SRC_COMMON_ALLOCATORWRAPPER_H */
diff --git a/src/common/IContext.h b/src/common/IContext.h
index 31f39da06d..a221e5db61 100644
--- a/src/common/IContext.h
+++ b/src/common/IContext.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Arm Limited.
+ * Copyright (c) 2021,2023 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -29,10 +29,11 @@
#include "src/common/utils/Object.h"
#include <atomic>
+#include <tuple>
struct AclContext_
{
- arm_compute::detail::Header header{ arm_compute::detail::ObjectType::Context, nullptr };
+ arm_compute::detail::Header header{arm_compute::detail::ObjectType::Context, nullptr};
protected:
AclContext_() = default;
@@ -44,22 +45,20 @@ namespace arm_compute
// Forward declarations
class ITensorV2;
class IQueue;
+class IOperator;
/**< Context interface */
class IContext : public AclContext_
{
public:
- IContext(Target target)
- : AclContext_(), _target(target), _refcount(0)
+ IContext(Target target) : AclContext_(), _target(target), _refcount(0)
{
}
-
/** Virtual Destructor */
virtual ~IContext()
{
header.type = detail::ObjectType::Invalid;
};
-
/** Target type accessor
*
* @return Target that the context is associated with
@@ -68,19 +67,16 @@ public:
{
return _target;
}
-
/** Increment context refcount */
void inc_ref() const
{
++_refcount;
}
-
/** Decrement context refcount */
void dec_ref() const
{
--_refcount;
}
-
/** Reference counter accessor
*
* @return The number of references pointing to this object
@@ -89,7 +85,6 @@ public:
{
return _refcount;
}
-
/** Checks if an object is valid
*
* @return True if sucessful otherwise false
@@ -98,7 +93,6 @@ public:
{
return header.type == detail::ObjectType::Context;
}
-
/** Create a tensor object
*
* @param[in] desc Descriptor to use
@@ -107,14 +101,17 @@ public:
* @return A pointer to the created tensor object
*/
virtual ITensorV2 *create_tensor(const AclTensorDescriptor &desc, bool allocate) = 0;
-
/** Create a queue object
*
* @param[in] options Queue options to be used
*
* @return A pointer to the created queue object
*/
- virtual IQueue *create_queue(const AclQueueOptions *options) = 0;
+ virtual IQueue *create_queue(const AclQueueOptions *options) = 0;
+ virtual std::tuple<IOperator *, StatusCode> create_activation(const AclTensorDescriptor &src,
+ const AclTensorDescriptor &dst,
+ const AclActivationDescriptor &act,
+ bool is_validate) = 0;
private:
Target _target; /**< Target type of context */
@@ -142,7 +139,7 @@ namespace detail
*/
inline StatusCode validate_internal_context(const IContext *ctx)
{
- if(ctx == nullptr || !ctx->is_valid())
+ if (ctx == nullptr || !ctx->is_valid())
{
ARM_COMPUTE_LOG_ERROR_ACL("Invalid context object");
return StatusCode::InvalidArgument;
diff --git a/src/common/cpuinfo/target/CpuInfoSveUtils.cpp b/src/common/IOperator.cpp
index 750a1b01d1..90e3473814 100644
--- a/src/common/cpuinfo/target/CpuInfoSveUtils.cpp
+++ b/src/common/IOperator.cpp
@@ -21,20 +21,53 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-#include "src/common/cpuinfo/target/CpuInfoSveUtils.h"
+#include "src/common/IOperator.h"
+
+#include "src/common/utils/Validate.h"
namespace arm_compute
{
-namespace cpuinfo
+#ifndef DOXYGEN_SKIP_THIS
+IOperator::IOperator(IContext *ctx) : AclOperator_()
+{
+ ARM_COMPUTE_ASSERT_NOT_NULLPTR(ctx);
+ this->header.ctx = ctx;
+ this->header.ctx->inc_ref();
+}
+
+IOperator::~IOperator()
+{
+ this->header.ctx->dec_ref();
+ this->header.type = detail::ObjectType::Invalid;
+}
+
+bool IOperator::is_valid() const
+{
+ return this->header.type == detail::ObjectType::Operator;
+}
+
+StatusCode IOperator::run(ITensorPack &tensors)
+{
+ _op->run(tensors);
+ return StatusCode::Success;
+}
+
+StatusCode IOperator::run(IQueue &queue, ITensorPack &tensors)
{
-uint64_t get_sve_feature_reg()
+ ARM_COMPUTE_UNUSED(queue);
+ _op->run(tensors);
+ return StatusCode::Success;
+}
+
+StatusCode IOperator::prepare(ITensorPack &tensors)
+{
+ _op->prepare(tensors);
+ return StatusCode::Success;
+}
+
+MemoryRequirements IOperator::workspace() const
{
- uint64_t reg = 0;
-#if defined(ENABLE_SVE)
- __asm __volatile("MRS %0, ID_AA64ZFR0_EL1"
- : "=r"(reg));
-#endif /* defined(DENABLE_SVE) */
- return reg;
+ return _op->workspace();
}
-} // namespace cpuinfo
+#endif /* DOXYGEN_SKIP_THIS */
} // namespace arm_compute
diff --git a/src/common/IOperator.h b/src/common/IOperator.h
new file mode 100644
index 0000000000..e86e11fe25
--- /dev/null
+++ b/src/common/IOperator.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2021 Arm Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef SRC_COMMON_IOPERATOR_H_
+#define SRC_COMMON_IOPERATOR_H_
+
+#include "src/common/IContext.h"
+#include "src/common/IQueue.h"
+
+// TODO: Remove when all functions have been ported
+#include "arm_compute/core/experimental/Types.h"
+#include "arm_compute/runtime/IOperator.h"
+
+#include "src/common/utils/Validate.h"
+
+#include <vector>
+
+struct AclOperator_
+{
+ arm_compute::detail::Header header{arm_compute::detail::ObjectType::Operator, nullptr};
+
+protected:
+ AclOperator_() = default;
+ ~AclOperator_() = default;
+};
+
+namespace arm_compute
+{
+// Forward declarations
+class ITensorPack;
+namespace experimental
+{
+class IOperator;
+} // namespace experimental
+
+using MemoryRequirements = experimental::MemoryRequirements;
+
+/** Base class specifying the operator interface */
+class IOperator : public AclOperator_
+{
+public:
+ /** Explict Operator Constructor
+ *
+ * @param[in] ctx Context to be used by the operator
+ */
+ explicit IOperator(IContext *ctx);
+ /** Destructor */
+ virtual ~IOperator();
+ /** Checks if an operator is valid
+ *
+ * @return True if successful otherwise false
+ */
+ bool is_valid() const;
+ /** Run the kernels contained in the function
+ *
+ * @param[in] queue Queue to use
+ * @param[in] tensors Vector that contains the tensors to operate on
+ */
+ virtual StatusCode run(IQueue &queue, ITensorPack &tensors);
+ /** Run the kernels contained in the function
+ *
+ * @param[in] tensors Vector that contains the tensors to operate on
+ */
+ virtual StatusCode run(ITensorPack &tensors);
+ /** Prepare the operator for execution
+ *
+ * Any one off pre-processing step required by the function is handled here
+ *
+ * @param[in] tensors Vector that contains the preparation tensors.
+ *
+ * @note Prepare stage might not need all the function's buffers' backing memory to be available in order to execute
+ */
+ virtual StatusCode prepare(ITensorPack &tensors);
+ /** Return the memory requirements required by the workspace
+ */
+ virtual MemoryRequirements workspace() const;
+
+ void set_internal_operator(std::unique_ptr<experimental::IOperator> op)
+ {
+ _op = std::move(op);
+ }
+
+private:
+ std::unique_ptr<experimental::IOperator> _op{nullptr};
+};
+
+/** Extract internal representation of an Operator
+ *
+ * @param[in] op Opaque operator pointer
+ *
+ * @return The internal representation as an IOperator
+ */
+inline IOperator *get_internal(AclOperator op)
+{
+ return static_cast<IOperator *>(op);
+}
+
+namespace detail
+{
+/** Check if an internal operator is valid
+ *
+ * @param[in] op Internal operator to check
+ *
+ * @return A status code
+ */
+inline StatusCode validate_internal_operator(const IOperator *op)
+{
+ if (op == nullptr || !op->is_valid())
+ {
+ ARM_COMPUTE_LOG_ERROR_ACL("[IOperator]: Invalid operator object");
+ return StatusCode::InvalidArgument;
+ }
+ return StatusCode::Success;
+}
+} // namespace detail
+} // namespace arm_compute
+#endif /* SRC_COMMON_IOPERATOR_H_ */
diff --git a/src/common/IQueue.h b/src/common/IQueue.h
index 6a0cbc75da..60745d206e 100644
--- a/src/common/IQueue.h
+++ b/src/common/IQueue.h
@@ -28,7 +28,7 @@
struct AclQueue_
{
- arm_compute::detail::Header header{ arm_compute::detail::ObjectType::Queue, nullptr };
+ arm_compute::detail::Header header{arm_compute::detail::ObjectType::Queue, nullptr};
protected:
AclQueue_() = default;
@@ -88,7 +88,7 @@ namespace detail
*/
inline StatusCode validate_internal_queue(const IQueue *queue)
{
- if(queue == nullptr || !queue->is_valid())
+ if (queue == nullptr || !queue->is_valid())
{
ARM_COMPUTE_LOG_ERROR_ACL("[IQueue]: Invalid queue object");
return StatusCode::InvalidArgument;
diff --git a/src/common/ITensorV2.cpp b/src/common/ITensorV2.cpp
index 39bf1c6fb3..bf3d963926 100644
--- a/src/common/ITensorV2.cpp
+++ b/src/common/ITensorV2.cpp
@@ -22,7 +22,9 @@
* SOFTWARE.
*/
#include "src/common/ITensorV2.h"
+
#include "arm_compute/core/TensorInfo.h"
+
#include "src/common/utils/LegacySupport.h"
namespace arm_compute
@@ -36,4 +38,4 @@ AclTensorDescriptor ITensorV2::get_descriptor() const
{
return detail::convert_to_descriptor(*tensor()->info());
}
-} // namespace arm_compute \ No newline at end of file
+} // namespace arm_compute
diff --git a/src/common/ITensorV2.h b/src/common/ITensorV2.h
index 965aacea23..903bfad66a 100644
--- a/src/common/ITensorV2.h
+++ b/src/common/ITensorV2.h
@@ -29,7 +29,7 @@
struct AclTensor_
{
- arm_compute::detail::Header header{ arm_compute::detail::ObjectType::Tensor, nullptr };
+ arm_compute::detail::Header header{arm_compute::detail::ObjectType::Tensor, nullptr};
protected:
AclTensor_() = default;
@@ -49,8 +49,7 @@ public:
*
* @param[in] ctx Context to be used by the operator
*/
- explicit ITensorV2(IContext *ctx)
- : AclTensor_()
+ explicit ITensorV2(IContext *ctx) : AclTensor_()
{
ARM_COMPUTE_ASSERT_NOT_NULLPTR(ctx);
this->header.ctx = ctx;
@@ -128,7 +127,7 @@ namespace detail
*/
inline StatusCode validate_internal_tensor(const ITensorV2 *tensor)
{
- if(tensor == nullptr || !tensor->is_valid())
+ if (tensor == nullptr || !tensor->is_valid())
{
ARM_COMPUTE_LOG_ERROR_ACL("[ITensorV2]: Invalid tensor object");
return StatusCode::InvalidArgument;
diff --git a/src/common/TensorPack.cpp b/src/common/TensorPack.cpp
index 6c2c7f9622..b51fc0bdd8 100644
--- a/src/common/TensorPack.cpp
+++ b/src/common/TensorPack.cpp
@@ -22,13 +22,13 @@
* SOFTWARE.
*/
#include "src/common/TensorPack.h"
+
#include "src/common/ITensorV2.h"
#include "src/common/utils/Validate.h"
namespace arm_compute
{
-TensorPack::TensorPack(IContext *ctx)
- : AclTensorPack_(), _pack()
+TensorPack::TensorPack(IContext *ctx) : AclTensorPack_(), _pack()
{
ARM_COMPUTE_ASSERT_NOT_NULLPTR(ctx);
this->header.ctx = ctx;
diff --git a/src/common/TensorPack.h b/src/common/TensorPack.h
index f330eee740..b3d1624dae 100644
--- a/src/common/TensorPack.h
+++ b/src/common/TensorPack.h
@@ -25,11 +25,12 @@
#define SRC_COMMON_ITENSORPACK_H_
#include "arm_compute/core/ITensorPack.h"
+
#include "src/common/IContext.h"
struct AclTensorPack_
{
- arm_compute::detail::Header header{ arm_compute::detail::ObjectType::TensorPack, nullptr };
+ arm_compute::detail::Header header{arm_compute::detail::ObjectType::TensorPack, nullptr};
protected:
AclTensorPack_() = default;
@@ -118,7 +119,7 @@ namespace detail
*/
inline StatusCode validate_internal_pack(const TensorPack *pack)
{
- if(pack == nullptr || !pack->is_valid())
+ if (pack == nullptr || !pack->is_valid())
{
ARM_COMPUTE_LOG_ERROR_ACL("[TensorPack]: Invalid tensor pack object");
return StatusCode::InvalidArgument;
diff --git a/src/common/Types.h b/src/common/Types.h
index ba07b51d55..25ee32353a 100644
--- a/src/common/Types.h
+++ b/src/common/Types.h
@@ -24,6 +24,7 @@
#ifndef SRC_COMMON_TYPES_H_
#define SRC_COMMON_TYPES_H_
+#include "arm_compute/AclDescriptors.h"
#include "arm_compute/AclTypes.h"
namespace arm_compute
diff --git a/src/common/cpuinfo/CpuInfo.cpp b/src/common/cpuinfo/CpuInfo.cpp
index 436e7ea803..92ba5223c9 100644
--- a/src/common/cpuinfo/CpuInfo.cpp
+++ b/src/common/cpuinfo/CpuInfo.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Arm Limited.
+ * Copyright (c) 2021-2024 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -25,37 +25,46 @@
#include "arm_compute/core/Error.h"
#include "arm_compute/core/Log.h"
-#include "src/common/cpuinfo/target/CpuInfoSveUtils.h"
+
#include "support/StringSupport.h"
#include "support/ToolchainSupport.h"
+#include <map>
#include <sstream>
#if !defined(BARE_METAL)
#include <algorithm>
#include <cstring>
#include <fstream>
+#if !defined(_WIN64)
#include <regex.h> /* C++ std::regex takes up a lot of space in the standalone builds */
#include <sched.h>
+#endif /* !defined(_WIN64) */
+
#include <thread>
#include <unordered_map>
#endif /* !defined(BARE_METAL) */
-#if !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__))
+#if !defined(_WIN64)
+#if !defined(BARE_METAL) && !defined(__APPLE__) && !defined(__OpenBSD__) && (defined(__arm__) || defined(__aarch64__))
#include <asm/hwcap.h> /* Get HWCAP bits from asm/hwcap.h */
#include <sys/auxv.h>
-#endif /* !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__)) */
-
-#define ARM_COMPUTE_CPU_FEATURE_HWCAP_CPUID (1 << 11)
-#define ARM_COMPUTE_GET_FEATURE_REG(var, freg) __asm __volatile("MRS %0, " #freg \
- : "=r"(var))
+#elif defined(__APPLE__) && defined(__aarch64__)
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#endif /* defined(__APPLE__) && defined(__aarch64__)) */
+#endif /* !defined(BARE_METAL) && !defined(__APPLE__) && !defined(__OpenBSD__) && (defined(__arm__) || defined(__aarch64__)) */
+
+#define ARM_COMPUTE_CPU_FEATURE_HWCAP_CPUID (1 << 11)
+#define ARM_COMPUTE_GET_FEATURE_REG(var, freg) __asm __volatile("MRS %0, " #freg : "=r"(var))
namespace arm_compute
{
namespace cpuinfo
{
namespace
{
-#if !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__))
+#if !defined(_WIN64) && !defined(BARE_METAL) && !defined(__APPLE__) && !defined(__OpenBSD__) && \
+ (defined(__arm__) || defined(__aarch64__))
/** Extract MIDR using CPUID information that are exposed to user-space
*
* @param[in] max_num_cpus Maximum number of possible CPUs
@@ -65,15 +74,15 @@ namespace
std::vector<uint32_t> midr_from_cpuid(uint32_t max_num_cpus)
{
std::vector<uint32_t> cpus;
- for(unsigned int i = 0; i < max_num_cpus; ++i)
+ for (unsigned int i = 0; i < max_num_cpus; ++i)
{
std::stringstream str;
str << "/sys/devices/system/cpu/cpu" << i << "/regs/identification/midr_el1";
std::ifstream file(str.str(), std::ios::in);
- if(file.is_open())
+ if (file.is_open())
{
std::string line;
- if(bool(getline(file, line)))
+ if (bool(getline(file, line)))
{
cpus.emplace_back(support::cpp11::stoul(line, nullptr, support::cpp11::NumericBase::BASE_16));
}
@@ -115,34 +124,35 @@ std::vector<uint32_t> midr_from_proc_cpuinfo(int max_num_cpus)
ARM_COMPUTE_ERROR_ON_MSG(ret_status != 0, "Regex compilation failed.");
std::ifstream file("/proc/cpuinfo", std::ios::in);
- if(file.is_open())
+ if (file.is_open())
{
std::string line;
int midr = 0;
int curcpu = -1;
- while(bool(getline(file, line)))
+ while (bool(getline(file, line)))
{
std::array<regmatch_t, 2> match;
ret_status = regexec(&proc_regex, line.c_str(), 2, match.data(), 0);
- if(ret_status == 0)
+ if (ret_status == 0)
{
std::string id = line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so));
int newcpu = support::cpp11::stoi(id, nullptr);
- if(curcpu >= 0 && midr == 0)
+ if (curcpu >= 0 && midr == 0)
{
// Matched a new CPU ID without any description of the previous one - looks like old format.
return {};
}
- if(curcpu >= 0 && curcpu < max_num_cpus)
+ if (curcpu >= 0 && curcpu < max_num_cpus)
{
cpus.emplace_back(midr);
}
else
{
- ARM_COMPUTE_LOG_INFO_MSG_CORE("Trying to populate a core id with id greater than the expected number of cores!");
+ ARM_COMPUTE_LOG_INFO_MSG_CORE(
+ "Trying to populate a core id with id greater than the expected number of cores!");
}
midr = 0;
@@ -152,7 +162,7 @@ std::vector<uint32_t> midr_from_proc_cpuinfo(int max_num_cpus)
}
ret_status = regexec(&imp_regex, line.c_str(), 2, match.data(), 0);
- if(ret_status == 0)
+ if (ret_status == 0)
{
std::string subexp = line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so));
int impv = support::cpp11::stoi(subexp, nullptr, support::cpp11::NumericBase::BASE_16);
@@ -162,7 +172,7 @@ std::vector<uint32_t> midr_from_proc_cpuinfo(int max_num_cpus)
}
ret_status = regexec(&var_regex, line.c_str(), 2, match.data(), 0);
- if(ret_status == 0)
+ if (ret_status == 0)
{
std::string subexp = line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so));
int varv = support::cpp11::stoi(subexp, nullptr, support::cpp11::NumericBase::BASE_16);
@@ -172,7 +182,7 @@ std::vector<uint32_t> midr_from_proc_cpuinfo(int max_num_cpus)
}
ret_status = regexec(&part_regex, line.c_str(), 2, match.data(), 0);
- if(ret_status == 0)
+ if (ret_status == 0)
{
std::string subexp = line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so));
int partv = support::cpp11::stoi(subexp, nullptr, support::cpp11::NumericBase::BASE_16);
@@ -182,7 +192,7 @@ std::vector<uint32_t> midr_from_proc_cpuinfo(int max_num_cpus)
}
ret_status = regexec(&rev_regex, line.c_str(), 2, match.data(), 0);
- if(ret_status == 0)
+ if (ret_status == 0)
{
std::string subexp = line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so));
int regv = support::cpp11::stoi(subexp, nullptr);
@@ -193,13 +203,14 @@ std::vector<uint32_t> midr_from_proc_cpuinfo(int max_num_cpus)
}
}
- if(curcpu >= 0 && curcpu < max_num_cpus)
+ if (curcpu >= 0 && curcpu < max_num_cpus)
{
cpus.emplace_back(midr);
}
else
{
- ARM_COMPUTE_LOG_INFO_MSG_CORE("Trying to populate a core id with id greater than the expected number of cores!");
+ ARM_COMPUTE_LOG_INFO_MSG_CORE(
+ "Trying to populate a core id with id greater than the expected number of cores!");
}
}
@@ -224,11 +235,11 @@ int get_max_cpus()
CPUspresent.open("/sys/devices/system/cpu/present", std::ios::in);
bool success = false;
- if(CPUspresent.is_open())
+ if (CPUspresent.is_open())
{
std::string line;
- if(bool(getline(CPUspresent, line)))
+ if (bool(getline(CPUspresent, line)))
{
/* The content of this file is a list of ranges or single values, e.g.
* 0-5, or 1-3,5,7 or similar. As we are interested in the
@@ -237,9 +248,9 @@ int get_max_cpus()
*/
auto startfrom = line.begin();
- for(auto i = line.begin(); i < line.end(); ++i)
+ for (auto i = line.begin(); i < line.end(); ++i)
{
- if(*i == '-' || *i == ',')
+ if (*i == '-' || *i == ',')
{
startfrom = i + 1;
}
@@ -253,38 +264,145 @@ int get_max_cpus()
}
// Return std::thread::hardware_concurrency() as a fallback.
- if(!success)
+ if (!success)
{
max_cpus = std::thread::hardware_concurrency();
}
return max_cpus;
}
-#endif /* !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__)) */
+
+const static std::map<std::string, std::vector<uint32_t>> known_configurations_with_little_cores = {
+ {"xiaomi14-pro", {379, 379, 923, 923, 923, 867, 867, 1024}}};
+
+const static std::map<std::string, uint32_t> number_of_cores_to_use = {{"xiaomi14-pro", 6}};
+
+#if defined(__ANDROID__)
+std::vector<uint32_t> get_cpu_capacities()
+{
+ std::vector<uint32_t> cpu_capacities;
+ for (int i = 0; i < get_max_cpus(); ++i)
+ {
+ std::stringstream str;
+ str << "/sys/devices/system/cpu/cpu" << i << "/cpu_capacity";
+ std::ifstream file(str.str(), std::ios::in);
+ if (file.is_open())
+ {
+ std::string line;
+ if (bool(getline(file, line)))
+ {
+ cpu_capacities.emplace_back(support::cpp11::stoul(line));
+ }
+ }
+ }
+
+ return cpu_capacities;
+}
+
+uint32_t not_little_num_cpus_internal()
+{
+ std::vector<uint32_t> cpus_all = get_cpu_capacities();
+ std::vector<uint32_t> cpus_not_little;
+
+ for (auto &it : known_configurations_with_little_cores)
+ {
+ if (it.second == cpus_all)
+ {
+ return number_of_cores_to_use.find(it.first)->second;
+ }
+ }
+
+ std::vector<uint32_t>::iterator result = std::max_element(cpus_all.begin(), cpus_all.end());
+ uint32_t max_capacity = *result;
+ uint32_t threshold = max_capacity / 2;
+ for (unsigned int i = 0; i < cpus_all.size(); i++)
+ {
+ if (!(cpus_all[i] < threshold))
+ {
+ cpus_not_little.emplace_back(cpus_all[i]);
+ }
+ }
+ return cpus_not_little.size();
+}
+
+bool has_little_mid_big_internal()
+{
+ std::vector<uint32_t> cpus_all = get_cpu_capacities();
+ std::vector<uint32_t> cpus_not_little;
+
+ for (auto &it : known_configurations_with_little_cores)
+ {
+ if (it.second == cpus_all)
+ {
+ return true;
+ }
+ }
+ std::sort(cpus_all.begin(), cpus_all.end());
+ std::vector<uint32_t>::iterator ip;
+ ip = std::unique(cpus_all.begin(), cpus_all.end());
+ cpus_all.resize(std::distance(cpus_all.begin(), ip));
+
+ if (cpus_all.size() == 3)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+#endif /* defined(__ANDROID__) */
+#elif defined(__aarch64__) && \
+ defined(__APPLE__) /* !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__)) */
+/** Query features through sysctlbyname
+ *
+ * @return int value queried
+ */
+int get_hw_capability(const std::string &cap)
+{
+ int64_t result(0);
+ size_t size = sizeof(result);
+ sysctlbyname(cap.c_str(), &result, &size, NULL, 0);
+ return result;
+}
+#endif /* !defined(BARE_METAL) && !defined(__APPLE__) && !defined(__OpenBSD__) && (defined(__arm__) || defined(__aarch64__)) */
+
+#if defined(BARE_METAL) && defined(__aarch64__)
+uint64_t get_sve_feature_reg()
+{
+ uint64_t svefr0 = 0;
+ __asm __volatile(".inst 0xd5380483 // mrs x3, ID_AA64ZFR0_EL1\n"
+ "MOV %0, X3"
+ : "=r"(svefr0)
+ :
+ : "x3");
+ return svefr0;
+}
+#endif /* defined(BARE_METAL) && defined(__aarch64__) */
} // namespace
-CpuInfo::CpuInfo(CpuIsaInfo isa, std::vector<CpuModel> cpus)
- : _isa(std::move(isa)), _cpus(std::move(cpus))
+CpuInfo::CpuInfo(CpuIsaInfo isa, std::vector<CpuModel> cpus) : _isa(std::move(isa)), _cpus(std::move(cpus))
{
}
CpuInfo CpuInfo::build()
{
-#if !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__))
+#if !defined(_WIN64) && !defined(BARE_METAL) && !defined(__APPLE__) && !defined(__OpenBSD__) && \
+ (defined(__arm__) || defined(__aarch64__))
const uint32_t hwcaps = getauxval(AT_HWCAP);
const uint32_t hwcaps2 = getauxval(AT_HWCAP2);
const uint32_t max_cpus = get_max_cpus();
// Populate midr values
std::vector<uint32_t> cpus_midr;
- if(hwcaps & ARM_COMPUTE_CPU_FEATURE_HWCAP_CPUID)
+ if (hwcaps & ARM_COMPUTE_CPU_FEATURE_HWCAP_CPUID)
{
cpus_midr = midr_from_cpuid(max_cpus);
}
- if(cpus_midr.empty())
+ if (cpus_midr.empty())
{
cpus_midr = midr_from_proc_cpuinfo(max_cpus);
}
- if(cpus_midr.empty())
+ if (cpus_midr.empty())
{
cpus_midr.resize(max_cpus, 0);
}
@@ -300,32 +418,51 @@ CpuInfo CpuInfo::build()
CpuInfo info(isa, cpus_model);
return info;
-#elif(BARE_METAL) && defined(__aarch64__) /* !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__)) */
+#elif (BARE_METAL) && \
+ defined( \
+ __aarch64__) /* !defined(BARE_METAL) && !defined(__APPLE__) && !defined(__OpenBSD__) && (defined(__arm__) || defined(__aarch64__)) */
// Assume single CPU in bare metal mode. Just read the ID register and feature bits directly.
- uint64_t isar0 = 0, isar1 = 0, pfr0 = 0, svefr0 = 0, midr = 0;
+ uint64_t isar0 = 0, isar1 = 0, pfr0 = 0, pfr1 = 0, svefr0 = 0, midr = 0;
ARM_COMPUTE_GET_FEATURE_REG(isar0, ID_AA64ISAR0_EL1);
ARM_COMPUTE_GET_FEATURE_REG(isar1, ID_AA64ISAR1_EL1);
ARM_COMPUTE_GET_FEATURE_REG(pfr0, ID_AA64PFR0_EL1);
+ ARM_COMPUTE_GET_FEATURE_REG(pfr1, ID_AA64PFR1_EL1);
ARM_COMPUTE_GET_FEATURE_REG(midr, MIDR_EL1);
- if((pfr0 >> 32) & 0xf)
+ if ((pfr0 >> 32) & 0xf)
{
svefr0 = get_sve_feature_reg();
}
- CpuIsaInfo isa = init_cpu_isa_from_regs(isar0, isar1, pfr0, svefr0, midr);
+ CpuIsaInfo isa = init_cpu_isa_from_regs(isar0, isar1, pfr0, pfr1, svefr0, midr);
std::vector<CpuModel> cpus_model(1, midr_to_model(midr));
CpuInfo info(isa, cpus_model);
return info;
-#else /* #elif(BARE_METAL) && defined(__aarch64__) */
- CpuInfo info(CpuIsaInfo(), { CpuModel::GENERIC });
+#elif defined(__aarch64__) && defined(__APPLE__) /* #elif(BARE_METAL) && defined(__aarch64__) */
+ int ncpus = get_hw_capability("hw.perflevel0.logicalcpu");
+ CpuIsaInfo isainfo;
+ std::vector<CpuModel> cpus_model(ncpus);
+ isainfo.neon = get_hw_capability("hw.optional.neon");
+ isainfo.fp16 = get_hw_capability("hw.optional.neon_fp16");
+ isainfo.dot = get_hw_capability("hw.optional.arm.FEAT_DotProd");
+ isainfo.bf16 = get_hw_capability("hw.optional.arm.FEAT_BF16");
+ isainfo.i8mm = get_hw_capability("hw.optional.arm.FEAT_I8MM");
+ CpuInfo info(isainfo, cpus_model);
return info;
-#endif /* !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__)) */
+#elif defined(__aarch64__) && defined(_WIN64) /* #elif defined(__aarch64__) && defined(__APPLE__) */
+ CpuIsaInfo isainfo;
+ isainfo.neon = true;
+ CpuInfo info(isainfo, {CpuModel::GENERIC});
+ return info;
+#else /* #elif defined(__aarch64__) && defined(_WIN64) */
+ CpuInfo info(CpuIsaInfo(), {CpuModel::GENERIC});
+ return info;
+#endif /* !defined(BARE_METAL) && !defined(__APPLE__) && !defined(__OpenBSD__) && (defined(__arm__) || defined(__aarch64__)) */
}
CpuModel CpuInfo::cpu_model(uint32_t cpuid) const
{
- if(cpuid < _cpus.size())
+ if (cpuid < _cpus.size())
{
return _cpus[cpuid];
}
@@ -334,11 +471,12 @@ CpuModel CpuInfo::cpu_model(uint32_t cpuid) const
CpuModel CpuInfo::cpu_model() const
{
-#if defined(BARE_METAL) || defined(__APPLE__) || (!defined(__arm__) && !defined(__aarch64__))
+#if defined(_WIN64) || defined(BARE_METAL) || defined(__APPLE__) || defined(__OpenBSD__) || \
+ (!defined(__arm__) && !defined(__aarch64__))
return cpu_model(0);
-#else /* defined(BARE_METAL) || defined(__APPLE__) || (!defined(__arm__) && !defined(__aarch64__)) */
+#else /* defined(BARE_METAL) || defined(__APPLE__) || defined(__OpenBSD__) || (!defined(__arm__) && !defined(__aarch64__)) */
return cpu_model(sched_getcpu());
-#endif /* defined(BARE_METAL) || defined(__APPLE__) || (!defined(__arm__) && !defined(__aarch64__)) */
+#endif /* defined(BARE_METAL) || defined(__APPLE__) || defined(__OpenBSD__) || (!defined(__arm__) && !defined(__aarch64__)) */
}
uint32_t CpuInfo::num_cpus() const
@@ -346,11 +484,29 @@ uint32_t CpuInfo::num_cpus() const
return _cpus.size();
}
+uint32_t CpuInfo::not_little_num_cpus() const
+{
+#if defined(__ANDROID__)
+ return not_little_num_cpus_internal();
+#else /* defined(__ANDROID__) */
+ return num_cpus();
+#endif /* defined(__ANDROID__) */
+}
+
+bool CpuInfo::has_little_mid_big() const
+{
+#if defined(__ANDROID__)
+ return has_little_mid_big_internal();
+#else /* defined(__ANDROID__) */
+ return false;
+#endif /* defined(__ANDROID__) */
+}
+
uint32_t num_threads_hint()
{
unsigned int num_threads_hint = 1;
-#if !defined(BARE_METAL)
+#if !defined(BARE_METAL) && !defined(_WIN64) && !defined(ARM_COMPUTE_DISABLE_THREADS_HINT)
std::vector<std::string> cpus;
cpus.reserve(64);
@@ -363,13 +519,13 @@ uint32_t num_threads_hint()
// Read cpuinfo and get occurrence of each core
std::ifstream cpuinfo_file("/proc/cpuinfo", std::ios::in);
- if(cpuinfo_file.is_open())
+ if (cpuinfo_file.is_open())
{
std::string line;
- while(bool(getline(cpuinfo_file, line)))
+ while (bool(getline(cpuinfo_file, line)))
{
std::array<regmatch_t, 2> match;
- if(regexec(&cpu_part_rgx, line.c_str(), 2, match.data(), 0) == 0)
+ if (regexec(&cpu_part_rgx, line.c_str(), 2, match.data(), 0) == 0)
{
cpus.emplace_back(line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so)));
}
@@ -382,13 +538,13 @@ uint32_t num_threads_hint()
auto least_frequent_cpu_occurences = [](const std::vector<std::string> &cpus) -> uint32_t
{
std::unordered_map<std::string, uint32_t> cpus_freq;
- for(const auto &cpu : cpus)
+ for (const auto &cpu : cpus)
{
cpus_freq[cpu]++;
}
uint32_t vmin = cpus.size() + 1;
- for(const auto &cpu_freq : cpus_freq)
+ for (const auto &cpu_freq : cpus_freq)
{
vmin = std::min(vmin, cpu_freq.second);
}
@@ -397,9 +553,9 @@ uint32_t num_threads_hint()
// Set thread hint
num_threads_hint = cpus.empty() ? std::thread::hardware_concurrency() : least_frequent_cpu_occurences(cpus);
-#endif /* !defined(BARE_METAL) */
+#endif /* !defined(BARE_METAL) && !defined(_WIN64) && !defined(ARM_COMPUTE_DISABLE_THREADS_HINT) */
return num_threads_hint;
}
} // namespace cpuinfo
-} // namespace arm_compute \ No newline at end of file
+} // namespace arm_compute
diff --git a/src/common/cpuinfo/CpuInfo.h b/src/common/cpuinfo/CpuInfo.h
index f3056d2faf..506830aa81 100644
--- a/src/common/cpuinfo/CpuInfo.h
+++ b/src/common/cpuinfo/CpuInfo.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Arm Limited.
+ * Copyright (c) 2021-2022, 2024 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -21,8 +21,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-#ifndef SRC_COMMON_CPUINFO_H
-#define SRC_COMMON_CPUINFO_H
+#ifndef ACL_SRC_COMMON_CPUINFO_CPUINFO_H
+#define ACL_SRC_COMMON_CPUINFO_CPUINFO_H
#include "src/common/cpuinfo/CpuIsaInfo.h"
#include "src/common/cpuinfo/CpuModel.h"
@@ -71,6 +71,14 @@ public:
{
return _isa.sve2;
}
+ bool has_sme() const
+ {
+ return _isa.sme;
+ }
+ bool has_sme2() const
+ {
+ return _isa.sme2;
+ }
bool has_fp16() const
{
return _isa.fp16;
@@ -79,22 +87,41 @@ public:
{
return _isa.bf16;
}
+ bool has_svebf16() const
+ {
+ return _isa.svebf16;
+ }
bool has_dotprod() const
{
return _isa.dot;
}
- bool has_immla() const
+ bool has_i8mm() const
+ {
+ return _isa.i8mm;
+ }
+ bool has_svei8mm() const
+ {
+ return _isa.svei8mm;
+ }
+ bool has_svef32mm() const
+ {
+ return _isa.svef32mm;
+ }
+
+ const CpuIsaInfo &isa() const
{
- return _isa.immla;
+ return _isa;
}
- bool has_fmmla() const
+ const std::vector<CpuModel> &cpus() const
{
- return _isa.fmmla;
+ return _cpus;
}
CpuModel cpu_model(uint32_t cpuid) const;
CpuModel cpu_model() const;
uint32_t num_cpus() const;
+ uint32_t not_little_num_cpus() const;
+ bool has_little_mid_big() const;
private:
CpuIsaInfo _isa{};
@@ -110,4 +137,4 @@ private:
uint32_t num_threads_hint();
} // namespace cpuinfo
} // namespace arm_compute
-#endif /* SRC_COMMON_CPUINFO_H */
+#endif // ACL_SRC_COMMON_CPUINFO_CPUINFO_H
diff --git a/src/common/cpuinfo/CpuIsaInfo.cpp b/src/common/cpuinfo/CpuIsaInfo.cpp
index d99f9aec29..c9e39b9a08 100644
--- a/src/common/cpuinfo/CpuIsaInfo.cpp
+++ b/src/common/cpuinfo/CpuIsaInfo.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Arm Limited.
+ * Copyright (c) 2021-2022, 2024 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -24,6 +24,7 @@
#include "src/common/cpuinfo/CpuIsaInfo.h"
#include "arm_compute/core/Error.h"
+
#include "src/common/cpuinfo/CpuModel.h"
/* Arm Feature flags */
@@ -31,17 +32,18 @@
#define ARM_COMPUTE_CPU_FEATURE_HWCAP_NEON (1 << 12)
/* Arm64 Feature flags */
-#define ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMD (1 << 1)
-#define ARM_COMPUTE_CPU_FEATURE_HWCAP_FPHP (1 << 9)
-#define ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDHP (1 << 10)
-#define ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDDP (1 << 20)
-#define ARM_COMPUTE_CPU_FEATURE_HWCAP_SVE (1 << 22)
-#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVE2 (1 << 1)
-#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEI8MM (1 << 9)
+#define ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMD (1 << 1)
+#define ARM_COMPUTE_CPU_FEATURE_HWCAP_FPHP (1 << 9)
+#define ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDHP (1 << 10)
+#define ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDDP (1 << 20)
+#define ARM_COMPUTE_CPU_FEATURE_HWCAP_SVE (1 << 22)
+#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVE2 (1 << 1)
+#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEI8MM (1 << 9)
#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEF32MM (1 << 10)
-#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEBF16 (1 << 12)
-#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_I8MM (1 << 13)
-#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_BF16 (1 << 14)
+#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEBF16 (1 << 12)
+#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_I8MM (1 << 13)
+#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_BF16 (1 << 14)
+#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SME (1 << 23)
namespace arm_compute
{
@@ -49,61 +51,40 @@ namespace cpuinfo
{
namespace
{
+inline bool is_feature_supported(uint64_t features, uint64_t feature_mask)
+{
+ return (features & feature_mask);
+}
+
#if defined(__arm__)
void decode_hwcaps(CpuIsaInfo &isa, const uint32_t hwcaps, const uint32_t hwcaps2)
{
ARM_COMPUTE_UNUSED(hwcaps2);
-
- if(hwcaps & ARM_COMPUTE_CPU_FEATURE_HWCAP_HALF)
- {
- isa.fp16 = true;
- }
- if(hwcaps & ARM_COMPUTE_CPU_FEATURE_HWCAP_NEON)
- {
- isa.neon = true;
- }
+ isa.fp16 = false;
+ isa.neon = is_feature_supported(hwcaps, ARM_COMPUTE_CPU_FEATURE_HWCAP_NEON);
}
#elif defined(__aarch64__)
void decode_hwcaps(CpuIsaInfo &isa, const uint32_t hwcaps, const uint32_t hwcaps2)
{
// High-level SIMD support
- if(hwcaps & ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMD)
- {
- isa.neon = true;
- }
- if(hwcaps & ARM_COMPUTE_CPU_FEATURE_HWCAP_SVE)
- {
- isa.sve = true;
- }
- if(hwcaps2 & ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVE2)
- {
- isa.sve2 = true;
- }
+ isa.neon = is_feature_supported(hwcaps, ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMD);
+ isa.sve = is_feature_supported(hwcaps, ARM_COMPUTE_CPU_FEATURE_HWCAP_SVE);
+ isa.sve2 = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVE2);
+
+ // Detection of SME from type HWCAP2 in the auxillary vector
+ isa.sme = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_SME);
+ isa.sme2 = isa.sme; // Needs to be set properly
// Data-type support
- const uint32_t fp16_support_mask = ARM_COMPUTE_CPU_FEATURE_HWCAP_FPHP | ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDHP;
- if(hwcaps & fp16_support_mask)
- {
- isa.fp16 = true;
- }
- if(hwcaps2 & ARM_COMPUTE_CPU_FEATURE_HWCAP2_BF16)
- {
- isa.bf16 = true;
- }
+ isa.fp16 = is_feature_supported(hwcaps, ARM_COMPUTE_CPU_FEATURE_HWCAP_FPHP | ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDHP);
+ isa.bf16 = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_BF16);
+ isa.svebf16 = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEBF16);
// Instruction extensions
- if(hwcaps & ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDDP)
- {
- isa.dot = true;
- }
- if(hwcaps2 & ARM_COMPUTE_CPU_FEATURE_HWCAP2_I8MM)
- {
- isa.immla = true;
- }
- if(hwcaps2 & ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEF32MM)
- {
- isa.fmmla = true;
- }
+ isa.dot = is_feature_supported(hwcaps, ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDDP);
+ isa.i8mm = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_I8MM);
+ isa.svei8mm = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEI8MM);
+ isa.svef32mm = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEF32MM);
}
#else /* defined(__aarch64__) */
void decode_hwcaps(CpuIsaInfo &isa, const uint32_t hwcaps, const uint32_t hwcaps2)
@@ -112,62 +93,49 @@ void decode_hwcaps(CpuIsaInfo &isa, const uint32_t hwcaps, const uint32_t hwcaps
}
#endif /* defined(__aarch64__) */
-void decode_regs(CpuIsaInfo &isa, const uint64_t isar0, const uint64_t isar1, const uint64_t pfr0, const uint64_t svefr0)
+void decode_regs(CpuIsaInfo &isa,
+ const uint64_t isar0,
+ const uint64_t isar1,
+ const uint64_t pfr0,
+ const uint64_t pfr1,
+ const uint64_t svefr0)
{
+ auto is_supported = [](uint64_t feature_reg, uint8_t feature_pos) -> bool
+ { return ((feature_reg >> feature_pos) & 0xf); };
+
// High-level SIMD support
- if((pfr0 >> 32) & 0xf)
- {
- isa.sve = true;
- }
- if(svefr0 & 0xf)
- {
- isa.sve2 = true;
- }
+ isa.sve = is_supported(pfr0, 32);
+ isa.sve2 = is_supported(svefr0, 0);
+ isa.sme = is_supported(pfr1, 24);
+ isa.sme2 = (((pfr1 >> 24) & 0xf) > 1);
// Data-type support
- if((pfr0 >> 16) & 0xf)
- {
- isa.fp16 = true;
- }
- if((isar1 >> 44) & 0xf)
- {
- isa.bf16 = true;
- }
+ isa.fp16 = is_supported(pfr0, 16);
+ isa.bf16 = is_supported(isar1, 44);
+ isa.svebf16 = is_supported(svefr0, 20);
// Instruction extensions
- if((isar0 >> 44) & 0xf)
- {
- isa.dot = true;
- }
- if((isar1 >> 48) & 0xf)
- {
- isa.immla = true;
- }
- if((svefr0 >> 52) & 0xf)
- {
- isa.fmmla = true;
- }
+ isa.dot = is_supported(isar0, 44);
+ isa.i8mm = is_supported(isar1, 48);
+ isa.svei8mm = is_supported(svefr0, 44);
+ isa.svef32mm = is_supported(svefr0, 52);
}
-/** Handle features from whitelisted models in case of problematic kernels
+/** Handle features from allow-listed models in case of problematic kernels
*
* @param[in, out] isa ISA to update
* @param[in] model CPU model type
*/
-void whitelisted_model_features(CpuIsaInfo &isa, CpuModel model)
+void allowlisted_model_features(CpuIsaInfo &isa, CpuModel model)
{
- if(isa.dot == false)
+ if (isa.dot == false)
{
isa.dot = model_supports_dot(model);
}
- if(isa.fp16 == false)
+ if (isa.fp16 == false)
{
isa.fp16 = model_supports_fp16(model);
}
- if(isa.sve == false)
- {
- isa.sve = model_supports_sve(model);
- }
}
} // namespace
@@ -178,21 +146,22 @@ CpuIsaInfo init_cpu_isa_from_hwcaps(uint32_t hwcaps, uint32_t hwcaps2, uint32_t
decode_hwcaps(isa, hwcaps, hwcaps2);
const CpuModel model = midr_to_model(midr);
- whitelisted_model_features(isa, model);
+ allowlisted_model_features(isa, model);
return isa;
}
-CpuIsaInfo init_cpu_isa_from_regs(uint64_t isar0, uint64_t isar1, uint64_t pfr0, uint64_t svefr0, uint64_t midr)
+CpuIsaInfo
+init_cpu_isa_from_regs(uint64_t isar0, uint64_t isar1, uint64_t pfr0, uint64_t pfr1, uint64_t svefr0, uint64_t midr)
{
CpuIsaInfo isa;
- decode_regs(isa, isar0, isar1, pfr0, svefr0);
+ decode_regs(isa, isar0, isar1, pfr0, pfr1, svefr0);
const CpuModel model = midr_to_model(midr);
- whitelisted_model_features(isa, model);
+ allowlisted_model_features(isa, model);
return isa;
}
} // namespace cpuinfo
-} // namespace arm_compute \ No newline at end of file
+} // namespace arm_compute
diff --git a/src/common/cpuinfo/CpuIsaInfo.h b/src/common/cpuinfo/CpuIsaInfo.h
index 1125f766dd..9d6bc07b67 100644
--- a/src/common/cpuinfo/CpuIsaInfo.h
+++ b/src/common/cpuinfo/CpuIsaInfo.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Arm Limited.
+ * Copyright (c) 2021-2022 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -37,18 +37,22 @@ namespace cpuinfo
struct CpuIsaInfo
{
/* SIMD extension support */
- bool neon{ false };
- bool sve{ false };
- bool sve2{ false };
+ bool neon{false};
+ bool sve{false};
+ bool sve2{false};
+ bool sme{false};
+ bool sme2{false};
/* Data-type extensions support */
- bool fp16{ false };
- bool bf16{ false };
+ bool fp16{false};
+ bool bf16{false};
+ bool svebf16{false};
/* Instruction support */
- bool dot{ false };
- bool immla{ false };
- bool fmmla{ false };
+ bool dot{false};
+ bool i8mm{false};
+ bool svei8mm{false};
+ bool svef32mm{false};
};
/** Identify ISA related information through system information
@@ -65,13 +69,15 @@ CpuIsaInfo init_cpu_isa_from_hwcaps(uint32_t hwcaps, uint32_t hwcaps2, uint32_t
*
* @param[in] isar0 Value of Instruction Set Attribute Register 0 (ID_AA64ISAR0_EL1)
* @param[in] isar1 Value of Instruction Set Attribute Register 1 (ID_AA64ISAR1_EL1)
- * @param[in] pfr0 Value of Processor Feature Register 0 (ID_AA64PFR0_EL1)
+ * @param[in] pfr0 Value of Processor Feature Register 0 (ID_AA64PFR0_EL1)
+ * @param[in] pfr1 Value of Processor Feature Register 1 (ID_AA64PFR1_EL1)
* @param[in] svefr0 Value of SVE feature ID register 0 (ID_AA64ZFR0_EL1)
* @param[in] midr Value of Main ID Register (MIDR)
*
* @return CpuIsaInfo A populated ISA feature structure
*/
-CpuIsaInfo init_cpu_isa_from_regs(uint64_t isar0, uint64_t isar1, uint64_t pfr0, uint64_t svefr0, uint64_t midr);
+CpuIsaInfo
+init_cpu_isa_from_regs(uint64_t isar0, uint64_t isar1, uint64_t pfr0, uint64_t pfr1, uint64_t svefr0, uint64_t midr);
} // namespace cpuinfo
} // namespace arm_compute
diff --git a/src/common/cpuinfo/CpuModel.cpp b/src/common/cpuinfo/CpuModel.cpp
index 9f4d5d1433..8c3f8a8faf 100644
--- a/src/common/cpuinfo/CpuModel.cpp
+++ b/src/common/cpuinfo/CpuModel.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Arm Limited.
+ * Copyright (c) 2021-2023 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -29,12 +29,12 @@ namespace cpuinfo
{
std::string cpu_model_to_string(CpuModel model)
{
- switch(model)
+ switch (model)
{
#define X(MODEL) \
-case CpuModel::MODEL: \
- return #MODEL;
- ARM_COMPUTE_CPU_MODEL_LIST
+ case CpuModel::MODEL: \
+ return #MODEL;
+ ARM_COMPUTE_CPU_MODEL_LIST
#undef X
default:
{
@@ -45,13 +45,16 @@ case CpuModel::MODEL: \
bool model_supports_fp16(CpuModel model)
{
- switch(model)
+ switch (model)
{
case CpuModel::GENERIC_FP16:
case CpuModel::GENERIC_FP16_DOT:
case CpuModel::A55r1:
+ case CpuModel::A510:
case CpuModel::X1:
- case CpuModel::KLEIN:
+ case CpuModel::V1:
+ case CpuModel::A64FX:
+ case CpuModel::N1:
return true;
default:
return false;
@@ -60,23 +63,14 @@ bool model_supports_fp16(CpuModel model)
bool model_supports_dot(CpuModel model)
{
- switch(model)
+ switch (model)
{
case CpuModel::GENERIC_FP16_DOT:
case CpuModel::A55r1:
+ case CpuModel::A510:
case CpuModel::X1:
- case CpuModel::KLEIN:
- return true;
- default:
- return false;
- }
-}
-
-bool model_supports_sve(CpuModel model)
-{
- switch(model)
- {
- case CpuModel::KLEIN:
+ case CpuModel::V1:
+ case CpuModel::N1:
return true;
default:
return false;
@@ -92,17 +86,17 @@ CpuModel midr_to_model(uint32_t midr)
const int variant = (midr >> 20) & 0xF;
const int cpunum = (midr >> 4) & 0xFFF;
- if(implementer == 0x41) // Arm CPUs
+ // Only CPUs we have code paths for are detected. All other CPUs can be safely classed as "GENERIC"
+ if (implementer == 0x41) // Arm CPUs
{
- // Only CPUs we have code paths for are detected. All other CPUs can be safely classed as "GENERIC"
- switch(cpunum)
+ switch (cpunum)
{
case 0xd03: // A53
case 0xd04: // A35
model = CpuModel::A53;
break;
case 0xd05: // A55
- if(variant != 0)
+ if (variant != 0)
{
model = CpuModel::A55r1;
}
@@ -115,7 +109,7 @@ CpuModel midr_to_model(uint32_t midr)
model = CpuModel::A73;
break;
case 0xd0a: // A75
- if(variant != 0)
+ if (variant != 0)
{
model = CpuModel::GENERIC_FP16_DOT;
}
@@ -124,9 +118,11 @@ CpuModel midr_to_model(uint32_t midr)
model = CpuModel::GENERIC_FP16;
}
break;
+ case 0xd0c: // N1
+ model = CpuModel::N1;
+ break;
case 0xd06: // A65
case 0xd0b: // A76
- case 0xd0c: // N1
case 0xd0d: // A77
case 0xd0e: // A76AE
case 0xd41: // A78
@@ -134,21 +130,39 @@ CpuModel midr_to_model(uint32_t midr)
case 0xd4a: // E1
model = CpuModel::GENERIC_FP16_DOT;
break;
+ case 0xd40: // V1
+ model = CpuModel::V1;
+ break;
case 0xd44: // X1
model = CpuModel::X1;
break;
- case 0xd46:
- model = CpuModel::KLEIN;
+ case 0xd46: // A510
+ case 0xd80: // A520
+ model = CpuModel::A510;
+ break;
+ case 0xd15: // R82
+ model = CpuModel::A55r1;
+ break;
+ default:
+ model = CpuModel::GENERIC;
+ break;
+ }
+ }
+ else if (implementer == 0x46)
+ {
+ switch (cpunum)
+ {
+ case 0x001: // A64FX
+ model = CpuModel::A64FX;
break;
default:
model = CpuModel::GENERIC;
break;
}
}
- else if(implementer == 0x48)
+ else if (implementer == 0x48)
{
- // Only CPUs we have code paths for are detected. All other CPUs can be safely classed as "GENERIC"
- switch(cpunum)
+ switch (cpunum)
{
case 0xd40: // A76
model = CpuModel::GENERIC_FP16_DOT;
@@ -158,10 +172,9 @@ CpuModel midr_to_model(uint32_t midr)
break;
}
}
- else if(implementer == 0x51)
+ else if (implementer == 0x51)
{
- // Only CPUs we have code paths for are detected. All other CPUs can be safely classed as "GENERIC"
- switch(cpunum)
+ switch (cpunum)
{
case 0x800: // A73
model = CpuModel::A73;
@@ -187,4 +200,4 @@ CpuModel midr_to_model(uint32_t midr)
return model;
}
} // namespace cpuinfo
-} // namespace arm_compute \ No newline at end of file
+} // namespace arm_compute
diff --git a/src/common/cpuinfo/CpuModel.h b/src/common/cpuinfo/CpuModel.h
index 071efc4b3f..3b9d9e3494 100644
--- a/src/common/cpuinfo/CpuModel.h
+++ b/src/common/cpuinfo/CpuModel.h
@@ -24,11 +24,11 @@
#ifndef SRC_COMMON_CPUINFO_CPUMODEL_H
#define SRC_COMMON_CPUINFO_CPUMODEL_H
+#include "arm_compute/core/CPP/CPPTypes.h"
+
#include <cstdint>
#include <string>
-#include "arm_compute/core/CPP/CPPTypes.h"
-
namespace arm_compute
{
namespace cpuinfo
@@ -55,23 +55,15 @@ CpuModel midr_to_model(uint32_t midr);
*
* @note This is used in case of old kernel configurations where some capabilities are not exposed.
*
- * @param[in] model Model to check for whitelisted capabilities
+ * @param[in] model Model to check for allowlisted capabilities
*/
bool model_supports_fp16(CpuModel model);
-/** Check if a model supports SVE
- *
- * @note This is used in case of old kernel configurations where some capabilities are not exposed.
- *
- * @param[in] model Model to check for whitelisted capabilities
- */
-bool model_supports_sve(CpuModel model);
-
/** Check if a model supports dot product
*
* @note This is used in case of old kernel configurations where some capabilities are not exposed.
*
- * @param[in] model Model to check for whitelisted capabilities
+ * @param[in] model Model to check for allowlisted capabilities
*/
bool model_supports_dot(CpuModel model);
} // namespace cpuinfo
diff --git a/src/common/cpuinfo/target/CpuInfoSveUtils.h b/src/common/cpuinfo/target/CpuInfoSveUtils.h
deleted file mode 100644
index 73862b131c..0000000000
--- a/src/common/cpuinfo/target/CpuInfoSveUtils.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2021 Arm Limited.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#ifndef SRC_COMMON_CPUINFO_TARGET_CPUINFO_SVE_UTILS_H
-#define SRC_COMMON_CPUINFO_TARGET_CPUINFO_SVE_UTILS_H
-
-#include <cstdint>
-
-namespace arm_compute
-{
-namespace cpuinfo
-{
-/** Returns the contents of the SVE feature register (ID_AA64ZFR0_EL1)
- *
- * @return uint64_t The value of the register
- */
-uint64_t get_sve_feature_reg();
-} // namespace cpuinfo
-} // namespace arm_compute
-#endif /* SRC_COMMON_CPUINFO_CPUISAINFO_H */
diff --git a/src/common/utils/LegacySupport.cpp b/src/common/utils/LegacySupport.cpp
index 569b2abd89..102644227e 100644
--- a/src/common/utils/LegacySupport.cpp
+++ b/src/common/utils/LegacySupport.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Arm Limited.
+ * Copyright (c) 2021, 2023 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -23,6 +23,8 @@
*/
#include "src/common/utils/LegacySupport.h"
+#include "arm_compute/function_info/ActivationLayerInfo.h"
+
namespace arm_compute
{
namespace detail
@@ -31,7 +33,7 @@ namespace
{
DataType convert_to_legacy_data_type(AclDataType data_type)
{
- switch(data_type)
+ switch (data_type)
{
case AclDataType::AclFloat32:
return DataType::F32;
@@ -46,7 +48,7 @@ DataType convert_to_legacy_data_type(AclDataType data_type)
AclDataType convert_to_c_data_type(DataType data_type)
{
- switch(data_type)
+ switch (data_type)
{
case DataType::F32:
return AclDataType::AclFloat32;
@@ -62,7 +64,7 @@ AclDataType convert_to_c_data_type(DataType data_type)
TensorShape create_legacy_tensor_shape(int32_t ndims, int32_t *shape)
{
TensorShape legacy_shape{};
- for(int32_t d = 0; d < ndims; ++d)
+ for (int32_t d = 0; d < ndims; ++d)
{
legacy_shape.set(d, shape[d], false);
}
@@ -71,14 +73,14 @@ TensorShape create_legacy_tensor_shape(int32_t ndims, int32_t *shape)
int32_t *create_tensor_shape_array(const TensorInfo &info)
{
const auto num_dims = info.num_dimensions();
- if(num_dims <= 0)
+ if (num_dims <= 0)
{
return nullptr;
}
int32_t *shape_array = new int32_t[num_dims];
- for(size_t d = 0; d < num_dims; ++d)
+ for (size_t d = 0; d < num_dims; ++d)
{
shape_array[d] = info.tensor_shape()[d];
}
@@ -90,22 +92,71 @@ int32_t *create_tensor_shape_array(const TensorInfo &info)
TensorInfo convert_to_legacy_tensor_info(const AclTensorDescriptor &desc)
{
TensorInfo legacy_desc;
- legacy_desc.init(create_legacy_tensor_shape(desc.ndims, desc.shape), 1, convert_to_legacy_data_type(desc.data_type));
+ legacy_desc.init(create_legacy_tensor_shape(desc.ndims, desc.shape), 1,
+ convert_to_legacy_data_type(desc.data_type));
return legacy_desc;
}
AclTensorDescriptor convert_to_descriptor(const TensorInfo &info)
{
const auto num_dims = info.num_dimensions();
- AclTensorDescriptor desc
- {
- static_cast<int32_t>(num_dims),
- create_tensor_shape_array(info),
- convert_to_c_data_type(info.data_type()),
- nullptr,
- 0
- };
+ AclTensorDescriptor desc{static_cast<int32_t>(num_dims), create_tensor_shape_array(info),
+ convert_to_c_data_type(info.data_type()), nullptr, 0};
return desc;
}
+
+ActivationLayerInfo convert_to_activation_info(const AclActivationDescriptor &desc)
+{
+ ActivationLayerInfo::ActivationFunction act;
+ switch (desc.type)
+ {
+ case AclActivationType::AclIdentity:
+ act = ActivationLayerInfo::ActivationFunction::IDENTITY;
+ break;
+ case AclActivationType::AclLogistic:
+ act = ActivationLayerInfo::ActivationFunction::LOGISTIC;
+ break;
+ case AclActivationType::AclTanh:
+ act = ActivationLayerInfo::ActivationFunction::TANH;
+ break;
+ case AclActivationType::AclRelu:
+ act = ActivationLayerInfo::ActivationFunction::RELU;
+ break;
+ case AclActivationType::AclBoundedRelu:
+ act = ActivationLayerInfo::ActivationFunction::BOUNDED_RELU;
+ break;
+ case AclActivationType::AclLuBoundedRelu:
+ act = ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU;
+ break;
+ case AclActivationType::AclLeakyRelu:
+ act = ActivationLayerInfo::ActivationFunction::LEAKY_RELU;
+ break;
+ case AclActivationType::AclSoftRelu:
+ act = ActivationLayerInfo::ActivationFunction::SOFT_RELU;
+ break;
+ case AclActivationType::AclElu:
+ act = ActivationLayerInfo::ActivationFunction::ELU;
+ break;
+ case AclActivationType::AclAbs:
+ act = ActivationLayerInfo::ActivationFunction::ABS;
+ break;
+ case AclActivationType::AclSquare:
+ act = ActivationLayerInfo::ActivationFunction::SQUARE;
+ break;
+ case AclActivationType::AclSqrt:
+ act = ActivationLayerInfo::ActivationFunction::SQRT;
+ break;
+ case AclActivationType::AclLinear:
+ act = ActivationLayerInfo::ActivationFunction::LINEAR;
+ break;
+ case AclActivationType::AclHardSwish:
+ act = ActivationLayerInfo::ActivationFunction::HARD_SWISH;
+ break;
+ default:
+ return ActivationLayerInfo();
+ }
+
+ return ActivationLayerInfo(act, desc.a, desc.b);
+}
} // namespace detail
} // namespace arm_compute
diff --git a/src/common/utils/LegacySupport.h b/src/common/utils/LegacySupport.h
index c2cc1bc182..05a70fc2c6 100644
--- a/src/common/utils/LegacySupport.h
+++ b/src/common/utils/LegacySupport.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Arm Limited.
+ * Copyright (c) 2021, 2023 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -26,6 +26,8 @@
#include "arm_compute/Acl.h"
#include "arm_compute/core/TensorInfo.h"
+#include "arm_compute/core/Types.h"
+#include "arm_compute/function_info/ActivationLayerInfo.h"
namespace arm_compute
{
@@ -45,6 +47,13 @@ TensorInfo convert_to_legacy_tensor_info(const AclTensorDescriptor &desc);
* @return A converted descriptor
*/
AclTensorDescriptor convert_to_descriptor(const TensorInfo &info);
+/** Convert an AclActivation descriptor to an internal one
+ *
+ * @param[in] desc Descriptor to convert
+ *
+ * @return Legacy tensor meta-data
+ */
+ActivationLayerInfo convert_to_activation_info(const AclActivationDescriptor &desc);
} // namespace detail
} // namespace arm_compute
diff --git a/src/common/utils/Log.h b/src/common/utils/Log.h
index 496ee74a16..6ebfed366e 100644
--- a/src/common/utils/Log.h
+++ b/src/common/utils/Log.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Arm Limited.
+ * Copyright (c) 2021,2023 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -24,25 +24,37 @@
#ifndef SRC_COMMON_LOG_H
#define SRC_COMMON_LOG_H
+#ifndef ARM_COMPUTE_LOGGING_ENABLED
+
+#define ARM_COMPUTE_CREATE_ACL_LOGGER()
+#define ARM_COMPUTE_LOG_MSG_ACL(log_level, msg)
+#define ARM_COMPUTE_LOG_MSG_WITH_FORMAT_ACL(log_level, fmt, ...)
+#define ARM_COMPUTE_LOG_ERROR_ACL(msg)
+#define ARM_COMPUTE_LOG_ERROR_WITH_FUNCNAME_ACL(msg)
+#define ARM_COMPUTE_LOG_INFO_WITH_FUNCNAME_ACL(msg)
+#define ARM_COMPUTE_LOG_PARAMS(...)
+
+#else /* ARM_COMPUTE_LOGGING_ENABLED */
+
#include "arm_compute/core/Error.h"
#include "arm_compute/core/utils/logging/Macros.h"
-#ifdef ARM_COMPUTE_LOGGING_ENABLED
+#include "utils/TypePrinter.h"
+
/** Create a logger
*
* @note It will eventually create all default loggers in don't exist
*/
-#define ARM_COMPUTE_CREATE_ACL_LOGGER() \
- do \
- { \
- if(arm_compute::logging::LoggerRegistry::get().logger("ComputeLibrary") == nullptr) \
- { \
- arm_compute::logging::LoggerRegistry::get().create_logger("ComputeLibrary", arm_compute::logging::LogLevel::INFO); \
- } \
- } while(false)
-#else /* ARM_COMPUTE_LOGGING_ENABLED */
-#define ARM_COMPUTE_CREATE_ACL_LOGGER()
-#endif /* ARM_COMPUTE_LOGGING_ENABLED */
+#define ARM_COMPUTE_CREATE_ACL_LOGGER() \
+ do \
+ { \
+ if (arm_compute::logging::LoggerRegistry::get().logger("ComputeLibrary") == nullptr) \
+ { \
+ arm_compute::logging::LoggerRegistry::get().create_logger("ComputeLibrary", \
+ arm_compute::logging::LogLevel::INFO); \
+ } \
+ } while (false)
+
/** Log a message to the logger
*
* @param[in] log_level Logging level
@@ -53,7 +65,8 @@
{ \
ARM_COMPUTE_CREATE_ACL_LOGGER(); \
ARM_COMPUTE_LOG_MSG("ComputeLibrary", log_level, msg); \
- } while(false)
+ } while (false)
+
/** Log a message with format to the logger
*
* @param[in] log_level Logging level
@@ -65,7 +78,8 @@
{ \
ARM_COMPUTE_CREATE_ACL_LOGGER(); \
ARM_COMPUTE_LOG_MSG_WITH_FORMAT("ComputeLibrary", log_level, fmt, __VA_ARGS__); \
- } while(false)
+ } while (false)
+
/** Log an error message to the logger
*
* @param[in] msg Message to log
@@ -75,7 +89,7 @@
{ \
ARM_COMPUTE_CREATE_ACL_LOGGER(); \
ARM_COMPUTE_LOG_MSG("ComputeLibrary", arm_compute::logging::LogLevel::ERROR, msg); \
- } while(false)
+ } while (false)
/** Log an error message to the logger with function name before the message
*
@@ -86,6 +100,134 @@
{ \
ARM_COMPUTE_CREATE_ACL_LOGGER(); \
ARM_COMPUTE_LOG_MSG_WITH_FUNCNAME("ComputeLibrary", arm_compute::logging::LogLevel::ERROR, msg); \
- } while(false)
+ } while (false)
+
+/** Log an information message to the logger with function name before the message
+ *
+ * @param[in] msg Message to log
+ */
+#define ARM_COMPUTE_LOG_INFO_WITH_FUNCNAME_ACL(msg) \
+ do \
+ { \
+ ARM_COMPUTE_CREATE_ACL_LOGGER(); \
+ ARM_COMPUTE_LOG_MSG_WITH_FUNCNAME("ComputeLibrary", arm_compute::logging::LogLevel::INFO, msg); \
+ } while (false)
+/** Function template specialization for the out of bound element at index = tuple_size
+ *
+ * @param[in,out] data_registry Reference to the input parameters data in a string format
+ * @param[in] in_params_tuple Tuple of different input data types
+ */
+template <std::size_t Index, typename... Tp>
+inline typename std::enable_if<Index == sizeof...(Tp), void>::type
+logParamsImpl(std::vector<std::string> &data_registry, const std::tuple<Tp...> &in_params_tuple)
+{
+ // Because it is out of bound index so do nothing
+ ARM_COMPUTE_UNUSED(data_registry);
+ ARM_COMPUTE_UNUSED(in_params_tuple);
+}
+
+/** Function template to iterate over all input parameters tuple at compile time:
+ *
+ * @param[in,out] data_registry Reference to a vector of input parameters data in a string format
+ * @param[in] in_params_tuple Constant reference to a tuple of different input data types
+ */
+template <std::size_t Index, typename... Tp>
+ inline typename std::enable_if <
+ Index<sizeof...(Tp), void>::type logParamsImpl(std::vector<std::string> &data_registry,
+ const std::tuple<Tp...> &in_params_tuple)
+{
+ data_registry.push_back(arm_compute::to_string(std::get<Index>(in_params_tuple)));
+ // Unfold the next tuple element
+ logParamsImpl<Index + 1, Tp...>(data_registry, in_params_tuple);
+}
+
+/** Function Template with variable number of inputs to collect all the passed parameters from
+ * the logging macro ARM_COMPUTE_LOG_PARAMS(...)
+ *
+ * @param[in] ...ins The input parameters in the variadic template, taken by universal references Ts.. &&, (not by value)
+ * to avoid detecting T as an abstract data type when passing any of these parameters as an L-value
+ * reference to an abstract type.
+ *
+ * @return Vector of the parameters' data in a string format
+ */
+template <typename... Ts>
+const std::vector<std::string> logParams(Ts &&...ins)
+{
+ std::vector<std::string> data_registry{};
+ std::tuple<Ts...> in_params_tuple{ins...};
+
+ // Start logging the tuple elements, starting from 0 to tuple_size-1
+ logParamsImpl<0>(data_registry, in_params_tuple);
+ return data_registry;
+}
+
+/** Inline function to parse the input parameters string passed from strignizing of the variadic macro input
+ * #__VA_ARGS__.
+ * It is Inline to avoid the redefinition of this function each time this header is included
+ *
+ * @param[in] in_params_str Constant reference to a string consists of the names of the input parameters provided
+ * as:ARM_COMPUTE_LOG_PARAMS(src0, src1) the params_names = "src0, src1"
+ *
+ * @return Vector of strings containing all the names of the input parameters
+ */
+inline const std::vector<std::string> getParamsNames(const std::string &in_params_str)
+{
+ std::stringstream ss(in_params_str);
+
+ // Vector containing all the names of the input parameters
+ std::vector<std::string> names;
+ std::string temp;
+
+ // Usually the input parameters string would be name of parameters separated
+ // by ',' e.g. "src0, src1, policy"
+ while (std::getline(ss, temp, ','))
+ {
+ names.push_back(temp);
+ }
+ for (auto &name : names)
+ {
+ // Totally get rid of white space characters
+ name.erase(std::remove(name.begin(), name.end(), ' '), name.end());
+ }
+ return names;
+}
+
+/** It constructs the log message to be displayed by the logger by writing each parameter name and its
+ * corresponding data info string.
+ *
+ * @param[in] params_names Constant reference to a string consists of the the input parameters' names
+ * provided e.g.: ARM_COMPUTE_LOG_PARAMS(src0, src1) then params_names = "src0, src1"
+ * @param[in] data_registry Constant reference to a registry of all parameters' data in string format,
+ * stringnized by arm_compute::to_string()
+ *
+ * @return Log message string to be displayed
+ */
+inline const std::string constructDataLog(const std::vector<std::string> &params_names,
+ const std::vector<std::string> &data_registry)
+{
+ std::string dataLog = "\n ";
+ ARM_COMPUTE_ERROR_ON(params_names.size() != data_registry.size());
+ for (uint8_t i = 0; i < params_names.size(); ++i)
+ {
+ dataLog += params_names[i] + ": " + data_registry.at(i) + "\n ";
+ }
+
+ return dataLog;
+}
+
+/** Macro for logging input Parameters from any function.
+ * It detects the input parameters names, and their corresponding values before stringizing them using
+ * the overloaded arm_compute::to_string() type printer. Finally, displayed using the printer configured
+ * in the logger.
+ *
+ * @param[in] ... Input parameters
+ */
+#define ARM_COMPUTE_LOG_PARAMS(...) \
+ do \
+ { \
+ ARM_COMPUTE_LOG_INFO_WITH_FUNCNAME_ACL( \
+ constructDataLog(getParamsNames(#__VA_ARGS__), logParams(__VA_ARGS__))); \
+ } while (false)
+#endif /* ARM_COMPUTE_LOGGING_ENABLED */
#endif /* SRC_COMMON_LOG_H */
diff --git a/src/common/utils/Macros.h b/src/common/utils/Macros.h
index 2e44ea599e..35f7e759d3 100644
--- a/src/common/utils/Macros.h
+++ b/src/common/utils/Macros.h
@@ -28,7 +28,7 @@
#define ARM_COMPUTE_RETURN_CENUM_ON_FAILURE(status) \
{ \
- if(status != arm_compute::StatusCode::Success) \
+ if (status != arm_compute::StatusCode::Success) \
{ \
return arm_compute::utils::as_cenum<AclStatus>(status); \
} \
diff --git a/src/common/utils/Object.h b/src/common/utils/Object.h
index 1f194737d4..b73de8e430 100644
--- a/src/common/utils/Object.h
+++ b/src/common/utils/Object.h
@@ -52,14 +52,12 @@ struct Header
* @param[in] type_ Object identification type
* @param[in] ctx_ Context to reference
*/
- Header(ObjectType type_, IContext *ctx_) noexcept
- : type(type_),
- ctx(ctx_)
+ Header(ObjectType type_, IContext *ctx_) noexcept : type(type_), ctx(ctx_)
{
}
- ObjectType type{ ObjectType::Invalid };
- IContext *ctx{ nullptr };
+ ObjectType type{ObjectType::Invalid};
+ IContext *ctx{nullptr};
};
} // namespace detail
} // namespace arm_compute
diff --git a/src/common/utils/Utils.h b/src/common/utils/Utils.h
index 79f4f39c47..33fe6c0e81 100644
--- a/src/common/utils/Utils.h
+++ b/src/common/utils/Utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Arm Limited.
+ * Copyright (c) 2021,2023 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -24,6 +24,8 @@
#ifndef SRC_COMMON_UTILS_H
#define SRC_COMMON_UTILS_H
+#include <algorithm>
+#include <initializer_list>
#include <type_traits>
namespace arm_compute
@@ -72,10 +74,7 @@ constexpr SE as_enum(const E val) noexcept
template <typename E>
bool is_in(E check, std::initializer_list<E> list)
{
- return std::any_of(std::cbegin(list), std::cend(list), [&check](E e)
- {
- return check == e;
- });
+ return std::any_of(list.begin(), list.end(), [&check](E e) { return check == e; });
}
} // namespace utils
} // namespace arm_compute
diff --git a/src/common/utils/Validate.h b/src/common/utils/Validate.h
index 4e8807273a..97819c619f 100644
--- a/src/common/utils/Validate.h
+++ b/src/common/utils/Validate.h
@@ -29,7 +29,7 @@
#include <cassert>
-#define ARM_COMPUTE_ASSERT(cond) assert(cond)
+#define ARM_COMPUTE_ASSERT(cond) assert(cond)
#define ARM_COMPUTE_ASSERT_NOT_NULLPTR(ptr) assert((ptr) != nullptr)
#else /* defined(ARM_COMPUTE_ASSERTS_ENABLED) */