aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/AllocatorWrapper.cpp66
-rw-r--r--src/common/AllocatorWrapper.h81
-rw-r--r--src/common/IContext.h151
-rw-r--r--src/common/IOperator.cpp73
-rw-r--r--src/common/IOperator.h137
-rw-r--r--src/common/IQueue.h100
-rw-r--r--src/common/ITensorV2.cpp41
-rw-r--r--src/common/ITensorV2.h139
-rw-r--r--src/common/TensorPack.cpp74
-rw-r--r--src/common/TensorPack.h131
-rw-r--r--src/common/Types.h62
-rw-r--r--src/common/cpuinfo/CpuInfo.cpp561
-rw-r--r--src/common/cpuinfo/CpuInfo.h140
-rw-r--r--src/common/cpuinfo/CpuIsaInfo.cpp167
-rw-r--r--src/common/cpuinfo/CpuIsaInfo.h84
-rw-r--r--src/common/cpuinfo/CpuModel.cpp203
-rw-r--r--src/common/cpuinfo/CpuModel.h71
-rw-r--r--src/common/utils/LegacySupport.cpp162
-rw-r--r--src/common/utils/LegacySupport.h60
-rw-r--r--src/common/utils/Log.h233
-rw-r--r--src/common/utils/Macros.h37
-rw-r--r--src/common/utils/Object.h64
-rw-r--r--src/common/utils/Utils.h82
-rw-r--r--src/common/utils/Validate.h41
24 files changed, 2960 insertions, 0 deletions
diff --git a/src/common/AllocatorWrapper.cpp b/src/common/AllocatorWrapper.cpp
new file mode 100644
index 0000000000..28d81a9fa4
--- /dev/null
+++ b/src/common/AllocatorWrapper.cpp
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+#include "src/common/AllocatorWrapper.h"
+
+#include "arm_compute/core/Error.h"
+
+namespace arm_compute
+{
+AllocatorWrapper::AllocatorWrapper(const AclAllocator &backing_allocator) noexcept
+ : _backing_allocator(backing_allocator)
+{
+}
+
+void *AllocatorWrapper::alloc(size_t size)
+{
+ ARM_COMPUTE_ERROR_ON(_backing_allocator.alloc == nullptr);
+ return _backing_allocator.alloc(_backing_allocator.user_data, size);
+}
+
+void AllocatorWrapper::free(void *ptr)
+{
+ ARM_COMPUTE_ERROR_ON(_backing_allocator.free == nullptr);
+ _backing_allocator.free(_backing_allocator.user_data, ptr);
+}
+
+void *AllocatorWrapper::aligned_alloc(size_t size, size_t alignment)
+{
+ ARM_COMPUTE_ERROR_ON(_backing_allocator.aligned_alloc == nullptr);
+ return _backing_allocator.aligned_alloc(_backing_allocator.user_data, size, alignment);
+}
+
+void AllocatorWrapper::aligned_free(void *ptr)
+{
+ ARM_COMPUTE_ERROR_ON(_backing_allocator.aligned_free == nullptr);
+ _backing_allocator.aligned_free(_backing_allocator.user_data, ptr);
+}
+
+void AllocatorWrapper::set_user_data(void *user_data)
+{
+ if (user_data != nullptr)
+ {
+ _backing_allocator.user_data = user_data;
+ }
+}
+} // namespace arm_compute
diff --git a/src/common/AllocatorWrapper.h b/src/common/AllocatorWrapper.h
new file mode 100644
index 0000000000..bbf70a2cb1
--- /dev/null
+++ b/src/common/AllocatorWrapper.h
@@ -0,0 +1,81 @@
+/*
+ * 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_ALLOCATORWRAPPER_H
+#define SRC_COMMON_ALLOCATORWRAPPER_H
+
+#include "arm_compute/AclTypes.h"
+
+namespace arm_compute
+{
+/** Default malloc allocator implementation */
+class AllocatorWrapper final
+{
+public:
+ /** Default Constructor
+ *
+ * @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 &operator=(const AllocatorWrapper &) noexcept = delete;
+ AllocatorWrapper &operator=(AllocatorWrapper &&other) noexcept = default;
+ /** Allocate a chunk of memory of a given size in bytes
+ *
+ * @param[in] size Size of memory to allocate in bytes
+ *
+ * @return A pointer to the allocated memory if successful else nullptr
+ */
+ void *alloc(size_t size);
+ /** Free an allocated memory block
+ *
+ * @param[in] ptr Pointer to allocated memory
+ */
+ void free(void *ptr);
+ /** Allocate a chunk of memory of a given size in bytes,
+ * while honoring a given alignment requirement
+ *
+ * @param[in] size Size of memory to allocate in bytes
+ * @param[in] alignment Alignment requirements
+ *
+ * @return A pointer to the allocated memory if successful else nullptr
+ */
+ void *aligned_alloc(size_t size, size_t alignment);
+ /** Free an aligned memory block
+ *
+ * @param[in] ptr Pointer to the memory to release
+ */
+ void aligned_free(void *ptr);
+ /** Set user data to be used by the allocator
+ *
+ * @param[in] user_data User data to be used by the allocator
+ */
+ void set_user_data(void *user_data);
+
+private:
+ AclAllocator _backing_allocator;
+};
+} // namespace arm_compute
+
+#endif /* SRC_COMMON_ALLOCATORWRAPPER_H */
diff --git a/src/common/IContext.h b/src/common/IContext.h
new file mode 100644
index 0000000000..a221e5db61
--- /dev/null
+++ b/src/common/IContext.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2021,2023 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_ICONTEXT_H
+#define SRC_COMMON_ICONTEXT_H
+
+#include "src/common/Types.h"
+#include "src/common/utils/Log.h"
+#include "src/common/utils/Object.h"
+
+#include <atomic>
+#include <tuple>
+
+struct AclContext_
+{
+ arm_compute::detail::Header header{arm_compute::detail::ObjectType::Context, nullptr};
+
+protected:
+ AclContext_() = default;
+ ~AclContext_() = default;
+};
+
+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)
+ {
+ }
+ /** Virtual Destructor */
+ virtual ~IContext()
+ {
+ header.type = detail::ObjectType::Invalid;
+ };
+ /** Target type accessor
+ *
+ * @return Target that the context is associated with
+ */
+ Target type() const
+ {
+ 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
+ */
+ int refcount() const
+ {
+ return _refcount;
+ }
+ /** Checks if an object is valid
+ *
+ * @return True if sucessful otherwise false
+ */
+ bool is_valid() const
+ {
+ return header.type == detail::ObjectType::Context;
+ }
+ /** Create a tensor object
+ *
+ * @param[in] desc Descriptor to use
+ * @param[in] allocate Flag to allocate tensor
+ *
+ * @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 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 */
+ mutable std::atomic<int> _refcount; /**< Reference counter */
+};
+
+/** Extract internal representation of a Context
+ *
+ * @param[in] ctx Opaque context pointer
+ *
+ * @return The internal representation as an IContext
+ */
+inline IContext *get_internal(AclContext ctx)
+{
+ return static_cast<IContext *>(ctx);
+}
+
+namespace detail
+{
+/** Check if an internal context is valid
+ *
+ * @param[in] ctx Internal context to check
+ *
+ * @return A status code
+ */
+inline StatusCode validate_internal_context(const IContext *ctx)
+{
+ if (ctx == nullptr || !ctx->is_valid())
+ {
+ ARM_COMPUTE_LOG_ERROR_ACL("Invalid context object");
+ return StatusCode::InvalidArgument;
+ }
+ return StatusCode::Success;
+}
+} // namespace detail
+} // namespace arm_compute
+#endif /* SRC_COMMON_ICONTEXT_H */
diff --git a/src/common/IOperator.cpp b/src/common/IOperator.cpp
new file mode 100644
index 0000000000..90e3473814
--- /dev/null
+++ b/src/common/IOperator.cpp
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+#include "src/common/IOperator.h"
+
+#include "src/common/utils/Validate.h"
+
+namespace arm_compute
+{
+#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)
+{
+ 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
+{
+ return _op->workspace();
+}
+#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
new file mode 100644
index 0000000000..60745d206e
--- /dev/null
+++ b/src/common/IQueue.h
@@ -0,0 +1,100 @@
+/*
+ * 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_IQUEUE_H_
+#define SRC_COMMON_IQUEUE_H_
+
+#include "src/common/IContext.h"
+
+struct AclQueue_
+{
+ arm_compute::detail::Header header{arm_compute::detail::ObjectType::Queue, nullptr};
+
+protected:
+ AclQueue_() = default;
+ ~AclQueue_() = default;
+};
+
+namespace arm_compute
+{
+/** Base class specifying the queue interface */
+class IQueue : public AclQueue_
+{
+public:
+ /** Explict Operator Constructor
+ *
+ * @param[in] ctx Context to be used by the operator
+ */
+ explicit IQueue(IContext *ctx)
+ {
+ this->header.ctx = ctx;
+ this->header.ctx->inc_ref();
+ }
+ /** Destructor */
+ virtual ~IQueue()
+ {
+ this->header.ctx->dec_ref();
+ this->header.type = detail::ObjectType::Invalid;
+ };
+ /** Checks if a queue is valid
+ *
+ * @return True if successful otherwise false
+ */
+ bool is_valid() const
+ {
+ return this->header.type == detail::ObjectType::Queue;
+ };
+ virtual StatusCode finish() = 0;
+};
+
+/** Extract internal representation of a Queue
+ *
+ * @param[in] queue Opaque queue pointer
+ *
+ * @return The internal representation as an IQueue
+ */
+inline IQueue *get_internal(AclQueue queue)
+{
+ return static_cast<IQueue *>(queue);
+}
+
+namespace detail
+{
+/** Check if an internal queue is valid
+ *
+ * @param[in] queue Internal queue to check
+ *
+ * @return A status code
+ */
+inline StatusCode validate_internal_queue(const IQueue *queue)
+{
+ if (queue == nullptr || !queue->is_valid())
+ {
+ ARM_COMPUTE_LOG_ERROR_ACL("[IQueue]: Invalid queue object");
+ return StatusCode::InvalidArgument;
+ }
+ return StatusCode::Success;
+}
+} // namespace detail
+} // namespace arm_compute
+#endif /* SRC_COMMON_IQUEUE_H_ */
diff --git a/src/common/ITensorV2.cpp b/src/common/ITensorV2.cpp
new file mode 100644
index 0000000000..bf3d963926
--- /dev/null
+++ b/src/common/ITensorV2.cpp
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+#include "src/common/ITensorV2.h"
+
+#include "arm_compute/core/TensorInfo.h"
+
+#include "src/common/utils/LegacySupport.h"
+
+namespace arm_compute
+{
+size_t ITensorV2::get_size() const
+{
+ return tensor()->info()->total_size();
+}
+
+AclTensorDescriptor ITensorV2::get_descriptor() const
+{
+ return detail::convert_to_descriptor(*tensor()->info());
+}
+} // namespace arm_compute
diff --git a/src/common/ITensorV2.h b/src/common/ITensorV2.h
new file mode 100644
index 0000000000..903bfad66a
--- /dev/null
+++ b/src/common/ITensorV2.h
@@ -0,0 +1,139 @@
+/*
+ * 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_ITENSOR_H_
+#define SRC_COMMON_ITENSOR_H_
+
+#include "src/common/IContext.h"
+#include "src/common/utils/Validate.h"
+
+struct AclTensor_
+{
+ arm_compute::detail::Header header{arm_compute::detail::ObjectType::Tensor, nullptr};
+
+protected:
+ AclTensor_() = default;
+ ~AclTensor_() = default;
+};
+
+namespace arm_compute
+{
+// Forward declaration
+class ITensor;
+
+/** Base class specifying the tensor interface */
+class ITensorV2 : public AclTensor_
+{
+public:
+ /** Explict Operator Constructor
+ *
+ * @param[in] ctx Context to be used by the operator
+ */
+ explicit ITensorV2(IContext *ctx) : AclTensor_()
+ {
+ ARM_COMPUTE_ASSERT_NOT_NULLPTR(ctx);
+ this->header.ctx = ctx;
+ this->header.ctx->inc_ref();
+ }
+ /** Destructor */
+ virtual ~ITensorV2()
+ {
+ this->header.ctx->dec_ref();
+ this->header.type = detail::ObjectType::Invalid;
+ };
+ /** Checks if a queue is valid
+ *
+ * @return True if successful otherwise false
+ */
+ bool is_valid() const
+ {
+ return this->header.type == detail::ObjectType::Tensor;
+ };
+ /** Map tensor to a host pointer
+ *
+ * @return A pointer to the underlying backing memory if successful else nullptr
+ */
+ virtual void *map() = 0;
+ /** Unmap tensor
+ *
+ * @return AclStatus A status cod
+ */
+ virtual StatusCode unmap() = 0;
+ /** Import external memory handle
+ *
+ * @param[in] handle Memory to import
+ * @param[in] type Type of imported memory
+ *
+ * @return Status code
+ */
+ virtual StatusCode import(void *handle, ImportMemoryType type) = 0;
+ /** Get the legacy tensor object
+ *
+ * @return The legacy underlying tensor object
+ */
+ virtual arm_compute::ITensor *tensor() const = 0;
+ /** Get the size of the tensor in byte
+ *
+ * @note The size isn't based on allocated memory, but based on information in its descriptor (dimensions, data type, etc.).
+ *
+ * @return The size of the tensor in byte
+ */
+ size_t get_size() const;
+ /** Get the descriptor of this tensor
+ *
+ * @return The descriptor describing the characteristics of this tensor
+ */
+ AclTensorDescriptor get_descriptor() const;
+};
+
+/** Extract internal representation of a Tensor
+ *
+ * @param[in] tensor Opaque tensor pointer
+ *
+ * @return The internal representation as an ITensor
+ */
+inline ITensorV2 *get_internal(AclTensor tensor)
+{
+ return static_cast<ITensorV2 *>(tensor);
+}
+
+namespace detail
+{
+/** Check if an internal tensor is valid
+ *
+ * @param[in] tensor Internal tensor to check
+ *
+ * @return A status code
+ */
+inline StatusCode validate_internal_tensor(const ITensorV2 *tensor)
+{
+ if (tensor == nullptr || !tensor->is_valid())
+ {
+ ARM_COMPUTE_LOG_ERROR_ACL("[ITensorV2]: Invalid tensor object");
+ return StatusCode::InvalidArgument;
+ }
+ return StatusCode::Success;
+}
+} // namespace detail
+} // namespace arm_compute
+#endif /* SRC_COMMON_ITENSOR_H_ */
diff --git a/src/common/TensorPack.cpp b/src/common/TensorPack.cpp
new file mode 100644
index 0000000000..b51fc0bdd8
--- /dev/null
+++ b/src/common/TensorPack.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+#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()
+{
+ ARM_COMPUTE_ASSERT_NOT_NULLPTR(ctx);
+ this->header.ctx = ctx;
+ this->header.ctx->inc_ref();
+}
+
+TensorPack::~TensorPack()
+{
+ this->header.ctx->dec_ref();
+ this->header.type = detail::ObjectType::Invalid;
+}
+
+AclStatus TensorPack::add_tensor(ITensorV2 *tensor, int32_t slot_id)
+{
+ _pack.add_tensor(slot_id, tensor->tensor());
+ return AclStatus::AclSuccess;
+}
+
+size_t TensorPack::size() const
+{
+ return _pack.size();
+}
+
+bool TensorPack::empty() const
+{
+ return _pack.empty();
+}
+
+bool TensorPack::is_valid() const
+{
+ return this->header.type == detail::ObjectType::TensorPack;
+}
+
+arm_compute::ITensor *TensorPack::get_tensor(int32_t slot_id)
+{
+ return _pack.get_tensor(slot_id);
+}
+
+arm_compute::ITensorPack &TensorPack::get_tensor_pack()
+{
+ return _pack;
+}
+} // namespace arm_compute
diff --git a/src/common/TensorPack.h b/src/common/TensorPack.h
new file mode 100644
index 0000000000..b3d1624dae
--- /dev/null
+++ b/src/common/TensorPack.h
@@ -0,0 +1,131 @@
+/*
+ * 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_ITENSORPACK_H_
+#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};
+
+protected:
+ AclTensorPack_() = default;
+ ~AclTensorPack_() = default;
+};
+
+namespace arm_compute
+{
+// Forward declaration
+class ITensor;
+class ITensorV2;
+
+/** Tensor packing service
+ *
+ * Class is responsible for creating and managing a collection of tensors.
+ * Tensor packs can be passed to operators to be part of the mutable data of the execution.
+ */
+class TensorPack : public AclTensorPack_
+{
+public:
+ /** Constructor
+ *
+ * @param[in] ctx Context to be used
+ */
+ explicit TensorPack(IContext *ctx);
+ /** Destructor */
+ ~TensorPack();
+ /** Add tensor to the pack
+ *
+ * @param[in] tensor Tensor to add
+ * @param[in] slot_id Slot identification in respect to the operator of the tensor to add
+ *
+ * @return Status code
+ */
+ AclStatus add_tensor(ITensorV2 *tensor, int32_t slot_id);
+ /** Pack size accessor
+ *
+ * @return Number of tensors registered to the pack
+ */
+ size_t size() const;
+ /** Checks if pack is empty
+ *
+ * @return True if empty else false
+ */
+ bool empty() const;
+ /** Checks if an object is valid
+ *
+ * @return True if valid else false
+ */
+ bool is_valid() const;
+ /** Get tensor of a given id from the pac
+ *
+ * @param[in] slot_id Slot identification of tensor to extract
+ *
+ * @return The pointer to the tensor if exist and is non-const else nullptr
+ */
+ arm_compute::ITensor *get_tensor(int32_t slot_id);
+ /** Get legacy tensor pack
+ *
+ * @return Legacy tensor pack
+ */
+ arm_compute::ITensorPack &get_tensor_pack();
+
+private:
+ arm_compute::ITensorPack _pack; /**< Pack that currently redirects to the existing TensorPack */
+};
+
+/** Extract internal representation of a TensoPack
+ *
+ * @param[in] pack Opaque tensor pack pointer
+ *
+ * @return The internal representation as an TensorPack
+ */
+inline TensorPack *get_internal(AclTensorPack pack)
+{
+ return static_cast<TensorPack *>(pack);
+}
+
+namespace detail
+{
+/** Check if an internal TensorPack is valid
+ *
+ * @param[in] pack Internal tensor pack to check
+ *
+ * @return A status code
+ */
+inline StatusCode validate_internal_pack(const TensorPack *pack)
+{
+ if (pack == nullptr || !pack->is_valid())
+ {
+ ARM_COMPUTE_LOG_ERROR_ACL("[TensorPack]: Invalid tensor pack object");
+ return StatusCode::InvalidArgument;
+ }
+ return StatusCode::Success;
+}
+} // namespace detail
+} // namespace arm_compute
+#endif /* SRC_COMMON_ITENSORPACK_H_ */
diff --git a/src/common/Types.h b/src/common/Types.h
new file mode 100644
index 0000000000..25ee32353a
--- /dev/null
+++ b/src/common/Types.h
@@ -0,0 +1,62 @@
+/*
+ * 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_TYPES_H_
+#define SRC_COMMON_TYPES_H_
+
+#include "arm_compute/AclDescriptors.h"
+#include "arm_compute/AclTypes.h"
+
+namespace arm_compute
+{
+enum class StatusCode
+{
+ Success = AclSuccess,
+ RuntimeError = AclRuntimeError,
+ OutOfMemory = AclOutOfMemory,
+ Unimplemented = AclUnimplemented,
+ UnsupportedTarget = AclUnsupportedTarget,
+ InvalidTarget = AclInvalidTarget,
+ InvalidArgument = AclInvalidArgument,
+ UnsupportedConfig = AclUnsupportedConfig,
+ InvalidObjectState = AclInvalidObjectState,
+};
+
+enum class Target
+{
+ Cpu = AclTarget::AclCpu,
+ GpuOcl = AclTarget::AclGpuOcl,
+};
+
+enum class ExecutionMode
+{
+ FastRerun = AclPreferFastRerun,
+ FastStart = AclPreferFastStart,
+};
+
+enum class ImportMemoryType
+{
+ HostPtr = AclImportMemoryType::AclHostPtr
+};
+} // namespace arm_compute
+#endif /* SRC_COMMON_TYPES_H_ */
diff --git a/src/common/cpuinfo/CpuInfo.cpp b/src/common/cpuinfo/CpuInfo.cpp
new file mode 100644
index 0000000000..92ba5223c9
--- /dev/null
+++ b/src/common/cpuinfo/CpuInfo.cpp
@@ -0,0 +1,561 @@
+/*
+ * Copyright (c) 2021-2024 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.
+ */
+#include "src/common/cpuinfo/CpuInfo.h"
+
+#include "arm_compute/core/Error.h"
+#include "arm_compute/core/Log.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(_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>
+#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(_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
+ *
+ * @return std::vector<uint32_t> A list of the MIDR of each core
+ */
+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)
+ {
+ 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())
+ {
+ std::string line;
+ if (bool(getline(file, line)))
+ {
+ cpus.emplace_back(support::cpp11::stoul(line, nullptr, support::cpp11::NumericBase::BASE_16));
+ }
+ }
+ }
+ return cpus;
+}
+
+/** Extract MIDR by parsing the /proc/cpuinfo meta-data
+ *
+ * @param[in] max_num_cpus Maximum number of possible CPUs
+ *
+ * @return std::vector<uint32_t> A list of the MIDR of each core
+ */
+std::vector<uint32_t> midr_from_proc_cpuinfo(int max_num_cpus)
+{
+ std::vector<uint32_t> cpus;
+
+ regex_t proc_regex;
+ regex_t imp_regex;
+ regex_t var_regex;
+ regex_t part_regex;
+ regex_t rev_regex;
+
+ memset(&proc_regex, 0, sizeof(regex_t));
+ memset(&imp_regex, 0, sizeof(regex_t));
+ memset(&var_regex, 0, sizeof(regex_t));
+ memset(&part_regex, 0, sizeof(regex_t));
+ memset(&rev_regex, 0, sizeof(regex_t));
+
+ int ret_status = 0;
+ // If "long-form" cpuinfo is present, parse that to populate models.
+ ret_status |= regcomp(&proc_regex, R"(^processor.*([[:digit:]]+)$)", REG_EXTENDED);
+ ret_status |= regcomp(&imp_regex, R"(^CPU implementer.*0x(..)$)", REG_EXTENDED);
+ ret_status |= regcomp(&var_regex, R"(^CPU variant.*0x(.)$)", REG_EXTENDED);
+ ret_status |= regcomp(&part_regex, R"(^CPU part.*0x(...)$)", REG_EXTENDED);
+ ret_status |= regcomp(&rev_regex, R"(^CPU revision.*([[:digit:]]+)$)", REG_EXTENDED);
+ ARM_COMPUTE_UNUSED(ret_status);
+ ARM_COMPUTE_ERROR_ON_MSG(ret_status != 0, "Regex compilation failed.");
+
+ std::ifstream file("/proc/cpuinfo", std::ios::in);
+ if (file.is_open())
+ {
+ std::string line;
+ int midr = 0;
+ int curcpu = -1;
+
+ 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)
+ {
+ 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)
+ {
+ // Matched a new CPU ID without any description of the previous one - looks like old format.
+ return {};
+ }
+
+ 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!");
+ }
+
+ midr = 0;
+ curcpu = newcpu;
+
+ continue;
+ }
+
+ ret_status = regexec(&imp_regex, line.c_str(), 2, match.data(), 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);
+ midr |= (impv << 24);
+
+ continue;
+ }
+
+ ret_status = regexec(&var_regex, line.c_str(), 2, match.data(), 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);
+ midr |= (varv << 20);
+
+ continue;
+ }
+
+ ret_status = regexec(&part_regex, line.c_str(), 2, match.data(), 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);
+ midr |= (partv << 4);
+
+ continue;
+ }
+
+ ret_status = regexec(&rev_regex, line.c_str(), 2, match.data(), 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);
+ midr |= (regv);
+ midr |= (0xf << 16);
+
+ continue;
+ }
+ }
+
+ 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!");
+ }
+ }
+
+ // Free allocated memory
+ regfree(&proc_regex);
+ regfree(&imp_regex);
+ regfree(&var_regex);
+ regfree(&part_regex);
+ regfree(&rev_regex);
+
+ return cpus;
+}
+
+/** Get the maximim number of CPUs in the system by parsing /sys/devices/system/cpu/present
+ *
+ * @return int Maximum number of CPUs
+ */
+int get_max_cpus()
+{
+ int max_cpus = 1;
+ std::ifstream CPUspresent;
+ CPUspresent.open("/sys/devices/system/cpu/present", std::ios::in);
+ bool success = false;
+
+ if (CPUspresent.is_open())
+ {
+ std::string 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
+ * max valid ID, we just need to find the last valid
+ * delimiter ('-' or ',') and parse the integer immediately after that.
+ */
+ auto startfrom = line.begin();
+
+ for (auto i = line.begin(); i < line.end(); ++i)
+ {
+ if (*i == '-' || *i == ',')
+ {
+ startfrom = i + 1;
+ }
+ }
+
+ line.erase(line.begin(), startfrom);
+
+ max_cpus = support::cpp11::stoi(line, nullptr) + 1;
+ success = true;
+ }
+ }
+
+ // Return std::thread::hardware_concurrency() as a fallback.
+ if (!success)
+ {
+ max_cpus = std::thread::hardware_concurrency();
+ }
+ return max_cpus;
+}
+
+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::build()
+{
+#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)
+ {
+ cpus_midr = midr_from_cpuid(max_cpus);
+ }
+ if (cpus_midr.empty())
+ {
+ cpus_midr = midr_from_proc_cpuinfo(max_cpus);
+ }
+ if (cpus_midr.empty())
+ {
+ cpus_midr.resize(max_cpus, 0);
+ }
+
+ // Populate isa (Assume homogeneous ISA specification)
+ CpuIsaInfo isa = init_cpu_isa_from_hwcaps(hwcaps, hwcaps2, cpus_midr.back());
+
+ // Convert midr to models
+ std::vector<CpuModel> cpus_model;
+ std::transform(std::begin(cpus_midr), std::end(cpus_midr), std::back_inserter(cpus_model),
+ [](uint32_t midr) -> CpuModel { return midr_to_model(midr); });
+
+ CpuInfo info(isa, cpus_model);
+ return info;
+
+#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, 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)
+ {
+ svefr0 = get_sve_feature_reg();
+ }
+
+ 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;
+#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;
+#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())
+ {
+ return _cpus[cpuid];
+ }
+ return CpuModel::GENERIC;
+}
+
+CpuModel CpuInfo::cpu_model() const
+{
+#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(__OpenBSD__) || (!defined(__arm__) && !defined(__aarch64__)) */
+ return cpu_model(sched_getcpu());
+#endif /* defined(BARE_METAL) || defined(__APPLE__) || defined(__OpenBSD__) || (!defined(__arm__) && !defined(__aarch64__)) */
+}
+
+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) && !defined(_WIN64) && !defined(ARM_COMPUTE_DISABLE_THREADS_HINT)
+ std::vector<std::string> cpus;
+ cpus.reserve(64);
+
+ // CPU part regex
+ regex_t cpu_part_rgx;
+ memset(&cpu_part_rgx, 0, sizeof(regex_t));
+ int ret_status = regcomp(&cpu_part_rgx, R"(.*CPU part.+/?\:[[:space:]]+([[:alnum:]]+).*)", REG_EXTENDED);
+ ARM_COMPUTE_UNUSED(ret_status);
+ ARM_COMPUTE_ERROR_ON_MSG(ret_status != 0, "Regex compilation failed.");
+
+ // Read cpuinfo and get occurrence of each core
+ std::ifstream cpuinfo_file("/proc/cpuinfo", std::ios::in);
+ if (cpuinfo_file.is_open())
+ {
+ std::string 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)
+ {
+ cpus.emplace_back(line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so)));
+ }
+ }
+ }
+ regfree(&cpu_part_rgx);
+
+ // Get min number of threads
+ std::sort(std::begin(cpus), std::end(cpus));
+ 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)
+ {
+ cpus_freq[cpu]++;
+ }
+
+ uint32_t vmin = cpus.size() + 1;
+ for (const auto &cpu_freq : cpus_freq)
+ {
+ vmin = std::min(vmin, cpu_freq.second);
+ }
+ return vmin;
+ };
+
+ // Set thread hint
+ num_threads_hint = cpus.empty() ? std::thread::hardware_concurrency() : least_frequent_cpu_occurences(cpus);
+#endif /* !defined(BARE_METAL) && !defined(_WIN64) && !defined(ARM_COMPUTE_DISABLE_THREADS_HINT) */
+
+ return num_threads_hint;
+}
+} // namespace cpuinfo
+} // namespace arm_compute
diff --git a/src/common/cpuinfo/CpuInfo.h b/src/common/cpuinfo/CpuInfo.h
new file mode 100644
index 0000000000..506830aa81
--- /dev/null
+++ b/src/common/cpuinfo/CpuInfo.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2021-2022, 2024 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 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"
+
+#include <string>
+#include <vector>
+
+namespace arm_compute
+{
+namespace cpuinfo
+{
+/** Aggregate class that contains CPU related information
+ *
+ * Contains information about the numbers of the CPUs, the model of each CPU,
+ * ISA related information and more
+ *
+ * @note We can safely assume that the ISA is common between different clusters of cores
+ */
+class CpuInfo
+{
+public:
+ /** Default constructor */
+ CpuInfo() = default;
+ /** Construct a new Cpu Info object
+ *
+ * @param[in] isa ISA capabilities information
+ * @param[in] cpus CPU models information
+ */
+ CpuInfo(CpuIsaInfo isa, std::vector<CpuModel> cpus);
+ /** CpuInfo builder function from system related information
+ *
+ * @return CpuInfo A populated CpuInfo structure
+ */
+ static CpuInfo build();
+
+public:
+ bool has_neon() const
+ {
+ return _isa.neon;
+ }
+ bool has_sve() const
+ {
+ return _isa.sve;
+ }
+ bool has_sve2() const
+ {
+ return _isa.sve2;
+ }
+ bool has_sme() const
+ {
+ return _isa.sme;
+ }
+ bool has_sme2() const
+ {
+ return _isa.sme2;
+ }
+ bool has_fp16() const
+ {
+ return _isa.fp16;
+ }
+ bool has_bf16() const
+ {
+ return _isa.bf16;
+ }
+ bool has_svebf16() const
+ {
+ return _isa.svebf16;
+ }
+ bool has_dotprod() const
+ {
+ return _isa.dot;
+ }
+ 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;
+ }
+ const std::vector<CpuModel> &cpus() const
+ {
+ 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{};
+ std::vector<CpuModel> _cpus{};
+};
+
+/** Some systems have both big and small cores, this fuction computes the minimum number of cores
+ * that are exactly the same on the system. To maximize performance the library attempts to process
+ * workloads concurrently using as many threads as big cores are available on the system.
+ *
+ * @return The minumum number of common cores.
+ */
+uint32_t num_threads_hint();
+} // namespace cpuinfo
+} // namespace arm_compute
+#endif // ACL_SRC_COMMON_CPUINFO_CPUINFO_H
diff --git a/src/common/cpuinfo/CpuIsaInfo.cpp b/src/common/cpuinfo/CpuIsaInfo.cpp
new file mode 100644
index 0000000000..c9e39b9a08
--- /dev/null
+++ b/src/common/cpuinfo/CpuIsaInfo.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2021-2022, 2024 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.
+ */
+#include "src/common/cpuinfo/CpuIsaInfo.h"
+
+#include "arm_compute/core/Error.h"
+
+#include "src/common/cpuinfo/CpuModel.h"
+
+/* Arm Feature flags */
+#define ARM_COMPUTE_CPU_FEATURE_HWCAP_HALF (1 << 1)
+#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_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_SME (1 << 23)
+
+namespace arm_compute
+{
+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);
+ 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
+ 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
+ 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
+ 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)
+{
+ ARM_COMPUTE_UNUSED(isa, hwcaps, hwcaps2);
+}
+#endif /* defined(__aarch64__) */
+
+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
+ 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
+ isa.fp16 = is_supported(pfr0, 16);
+ isa.bf16 = is_supported(isar1, 44);
+ isa.svebf16 = is_supported(svefr0, 20);
+
+ // Instruction extensions
+ 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 allow-listed models in case of problematic kernels
+ *
+ * @param[in, out] isa ISA to update
+ * @param[in] model CPU model type
+ */
+void allowlisted_model_features(CpuIsaInfo &isa, CpuModel model)
+{
+ if (isa.dot == false)
+ {
+ isa.dot = model_supports_dot(model);
+ }
+ if (isa.fp16 == false)
+ {
+ isa.fp16 = model_supports_fp16(model);
+ }
+}
+} // namespace
+
+CpuIsaInfo init_cpu_isa_from_hwcaps(uint32_t hwcaps, uint32_t hwcaps2, uint32_t midr)
+{
+ CpuIsaInfo isa;
+
+ decode_hwcaps(isa, hwcaps, hwcaps2);
+
+ const CpuModel model = midr_to_model(midr);
+ allowlisted_model_features(isa, model);
+
+ return isa;
+}
+
+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, pfr1, svefr0);
+
+ const CpuModel model = midr_to_model(midr);
+ allowlisted_model_features(isa, model);
+
+ return isa;
+}
+} // namespace cpuinfo
+} // namespace arm_compute
diff --git a/src/common/cpuinfo/CpuIsaInfo.h b/src/common/cpuinfo/CpuIsaInfo.h
new file mode 100644
index 0000000000..9d6bc07b67
--- /dev/null
+++ b/src/common/cpuinfo/CpuIsaInfo.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2021-2022 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_CPUISAINFO_H
+#define SRC_COMMON_CPUINFO_CPUISAINFO_H
+
+#include <cstdint>
+
+namespace arm_compute
+{
+namespace cpuinfo
+{
+/** CPU ISA (Instruction Set Architecture) information
+ *
+ * Contains ISA related information around the Arm architecture
+ */
+struct CpuIsaInfo
+{
+ /* SIMD extension support */
+ 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 svebf16{false};
+
+ /* Instruction support */
+ bool dot{false};
+ bool i8mm{false};
+ bool svei8mm{false};
+ bool svef32mm{false};
+};
+
+/** Identify ISA related information through system information
+ *
+ * @param[in] hwcaps HWCAPS feature information
+ * @param[in] hwcaps2 HWCAPS2 feature information
+ * @param[in] midr MIDR value
+ *
+ * @return CpuIsaInfo A populated ISA feature structure
+ */
+CpuIsaInfo init_cpu_isa_from_hwcaps(uint32_t hwcaps, uint32_t hwcaps2, uint32_t midr);
+
+/** Identify ISA related information through register information
+ *
+ * @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] 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 pfr1, uint64_t svefr0, uint64_t midr);
+} // namespace cpuinfo
+} // namespace arm_compute
+
+#endif /* SRC_COMMON_CPUINFO_CPUISAINFO_H */
diff --git a/src/common/cpuinfo/CpuModel.cpp b/src/common/cpuinfo/CpuModel.cpp
new file mode 100644
index 0000000000..8c3f8a8faf
--- /dev/null
+++ b/src/common/cpuinfo/CpuModel.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2021-2023 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.
+ */
+#include "src/common/cpuinfo/CpuModel.h"
+
+namespace arm_compute
+{
+namespace cpuinfo
+{
+std::string cpu_model_to_string(CpuModel model)
+{
+ switch (model)
+ {
+#define X(MODEL) \
+ case CpuModel::MODEL: \
+ return #MODEL;
+ ARM_COMPUTE_CPU_MODEL_LIST
+#undef X
+ default:
+ {
+ return std::string("GENERIC");
+ }
+ };
+}
+
+bool model_supports_fp16(CpuModel model)
+{
+ switch (model)
+ {
+ case CpuModel::GENERIC_FP16:
+ case CpuModel::GENERIC_FP16_DOT:
+ case CpuModel::A55r1:
+ case CpuModel::A510:
+ case CpuModel::X1:
+ case CpuModel::V1:
+ case CpuModel::A64FX:
+ case CpuModel::N1:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool model_supports_dot(CpuModel model)
+{
+ switch (model)
+ {
+ case CpuModel::GENERIC_FP16_DOT:
+ case CpuModel::A55r1:
+ case CpuModel::A510:
+ case CpuModel::X1:
+ case CpuModel::V1:
+ case CpuModel::N1:
+ return true;
+ default:
+ return false;
+ }
+}
+
+CpuModel midr_to_model(uint32_t midr)
+{
+ CpuModel model = CpuModel::GENERIC;
+
+ // Unpack variant and CPU ID
+ const int implementer = (midr >> 24) & 0xFF;
+ const int variant = (midr >> 20) & 0xF;
+ const int cpunum = (midr >> 4) & 0xFFF;
+
+ // Only CPUs we have code paths for are detected. All other CPUs can be safely classed as "GENERIC"
+ if (implementer == 0x41) // Arm CPUs
+ {
+ switch (cpunum)
+ {
+ case 0xd03: // A53
+ case 0xd04: // A35
+ model = CpuModel::A53;
+ break;
+ case 0xd05: // A55
+ if (variant != 0)
+ {
+ model = CpuModel::A55r1;
+ }
+ else
+ {
+ model = CpuModel::A55r0;
+ }
+ break;
+ case 0xd09: // A73
+ model = CpuModel::A73;
+ break;
+ case 0xd0a: // A75
+ if (variant != 0)
+ {
+ model = CpuModel::GENERIC_FP16_DOT;
+ }
+ else
+ {
+ model = CpuModel::GENERIC_FP16;
+ }
+ break;
+ case 0xd0c: // N1
+ model = CpuModel::N1;
+ break;
+ case 0xd06: // A65
+ case 0xd0b: // A76
+ case 0xd0d: // A77
+ case 0xd0e: // A76AE
+ case 0xd41: // A78
+ case 0xd42: // A78AE
+ 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: // 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)
+ {
+ switch (cpunum)
+ {
+ case 0xd40: // A76
+ model = CpuModel::GENERIC_FP16_DOT;
+ break;
+ default:
+ model = CpuModel::GENERIC;
+ break;
+ }
+ }
+ else if (implementer == 0x51)
+ {
+ switch (cpunum)
+ {
+ case 0x800: // A73
+ model = CpuModel::A73;
+ break;
+ case 0x801: // A53
+ model = CpuModel::A53;
+ break;
+ case 0x803: // A55r0
+ model = CpuModel::A55r0;
+ break;
+ case 0x804: // A76
+ model = CpuModel::GENERIC_FP16_DOT;
+ break;
+ case 0x805: // A55r1
+ model = CpuModel::A55r1;
+ break;
+ default:
+ model = CpuModel::GENERIC;
+ break;
+ }
+ }
+
+ return model;
+}
+} // namespace cpuinfo
+} // namespace arm_compute
diff --git a/src/common/cpuinfo/CpuModel.h b/src/common/cpuinfo/CpuModel.h
new file mode 100644
index 0000000000..3b9d9e3494
--- /dev/null
+++ b/src/common/cpuinfo/CpuModel.h
@@ -0,0 +1,71 @@
+/*
+ * 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_CPUMODEL_H
+#define SRC_COMMON_CPUINFO_CPUMODEL_H
+
+#include "arm_compute/core/CPP/CPPTypes.h"
+
+#include <cstdint>
+#include <string>
+
+namespace arm_compute
+{
+namespace cpuinfo
+{
+using CpuModel = arm_compute::CPUModel;
+
+/** Convert a CPU model value to a string
+ *
+ * @param model CpuModel value to be converted
+ *
+ * @return String representing the corresponding CpuModel
+ */
+std::string cpu_model_to_string(CpuModel model);
+
+/** Extract the model type from the MIDR value
+ *
+ * @param[in] midr MIDR information
+ *
+ * @return CpuModel a mapped CPU model
+ */
+CpuModel midr_to_model(uint32_t midr);
+
+/** Check if a model supports half-precision floating point arithmetic
+ *
+ * @note This is used in case of old kernel configurations where some capabilities are not exposed.
+ *
+ * @param[in] model Model to check for allowlisted capabilities
+ */
+bool model_supports_fp16(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 allowlisted capabilities
+ */
+bool model_supports_dot(CpuModel model);
+} // namespace cpuinfo
+} // namespace arm_compute
+#endif /* SRC_COMMON_CPUINFO_CPUMODEL_H */
diff --git a/src/common/utils/LegacySupport.cpp b/src/common/utils/LegacySupport.cpp
new file mode 100644
index 0000000000..102644227e
--- /dev/null
+++ b/src/common/utils/LegacySupport.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2021, 2023 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.
+ */
+#include "src/common/utils/LegacySupport.h"
+
+#include "arm_compute/function_info/ActivationLayerInfo.h"
+
+namespace arm_compute
+{
+namespace detail
+{
+namespace
+{
+DataType convert_to_legacy_data_type(AclDataType data_type)
+{
+ switch (data_type)
+ {
+ case AclDataType::AclFloat32:
+ return DataType::F32;
+ case AclDataType::AclFloat16:
+ return DataType::F16;
+ case AclDataType::AclBFloat16:
+ return DataType::BFLOAT16;
+ default:
+ return DataType::UNKNOWN;
+ }
+}
+
+AclDataType convert_to_c_data_type(DataType data_type)
+{
+ switch (data_type)
+ {
+ case DataType::F32:
+ return AclDataType::AclFloat32;
+ case DataType::F16:
+ return AclDataType::AclFloat16;
+ case DataType::BFLOAT16:
+ return AclDataType::AclBFloat16;
+ default:
+ return AclDataType::AclDataTypeUnknown;
+ }
+}
+
+TensorShape create_legacy_tensor_shape(int32_t ndims, int32_t *shape)
+{
+ TensorShape legacy_shape{};
+ for (int32_t d = 0; d < ndims; ++d)
+ {
+ legacy_shape.set(d, shape[d], false);
+ }
+ return legacy_shape;
+}
+int32_t *create_tensor_shape_array(const TensorInfo &info)
+{
+ const auto num_dims = info.num_dimensions();
+ if (num_dims <= 0)
+ {
+ return nullptr;
+ }
+
+ int32_t *shape_array = new int32_t[num_dims];
+
+ for (size_t d = 0; d < num_dims; ++d)
+ {
+ shape_array[d] = info.tensor_shape()[d];
+ }
+
+ return shape_array;
+}
+} // namespace
+
+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));
+ 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};
+ 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
new file mode 100644
index 0000000000..05a70fc2c6
--- /dev/null
+++ b/src/common/utils/LegacySupport.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021, 2023 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_LEGACY_SUPPORT_H
+#define SRC_COMMON_LEGACY_SUPPORT_H
+
+#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
+{
+namespace detail
+{
+/** Convert a descriptor to a legacy format one
+ *
+ * @param[in] desc Descriptor to convert
+ *
+ * @return Legacy tensor meta-data
+ */
+TensorInfo convert_to_legacy_tensor_info(const AclTensorDescriptor &desc);
+/** Convert a legacy tensor meta-data to a descriptor
+ *
+ * @param[in] info Legacy tensor meta-data
+ *
+ * @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
+
+#endif /* SRC_COMMON_LEGACY_SUPPORT_H */
diff --git a/src/common/utils/Log.h b/src/common/utils/Log.h
new file mode 100644
index 0000000000..6ebfed366e
--- /dev/null
+++ b/src/common/utils/Log.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2021,2023 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_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"
+
+#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)
+
+/** Log a message to the logger
+ *
+ * @param[in] log_level Logging level
+ * @param[in] msg Message to log
+ */
+#define ARM_COMPUTE_LOG_MSG_ACL(log_level, msg) \
+ do \
+ { \
+ ARM_COMPUTE_CREATE_ACL_LOGGER(); \
+ ARM_COMPUTE_LOG_MSG("ComputeLibrary", log_level, msg); \
+ } while (false)
+
+/** Log a message with format to the logger
+ *
+ * @param[in] log_level Logging level
+ * @param[in] fmt String format (printf style)
+ * @param[in] ... Message arguments
+ */
+#define ARM_COMPUTE_LOG_MSG_WITH_FORMAT_ACL(log_level, fmt, ...) \
+ do \
+ { \
+ ARM_COMPUTE_CREATE_ACL_LOGGER(); \
+ ARM_COMPUTE_LOG_MSG_WITH_FORMAT("ComputeLibrary", log_level, fmt, __VA_ARGS__); \
+ } while (false)
+
+/** Log an error message to the logger
+ *
+ * @param[in] msg Message to log
+ */
+#define ARM_COMPUTE_LOG_ERROR_ACL(msg) \
+ do \
+ { \
+ ARM_COMPUTE_CREATE_ACL_LOGGER(); \
+ ARM_COMPUTE_LOG_MSG("ComputeLibrary", arm_compute::logging::LogLevel::ERROR, msg); \
+ } while (false)
+
+/** Log an error message to the logger with function name before the message
+ *
+ * @param[in] msg Message to log
+ */
+#define ARM_COMPUTE_LOG_ERROR_WITH_FUNCNAME_ACL(msg) \
+ do \
+ { \
+ ARM_COMPUTE_CREATE_ACL_LOGGER(); \
+ ARM_COMPUTE_LOG_MSG_WITH_FUNCNAME("ComputeLibrary", arm_compute::logging::LogLevel::ERROR, msg); \
+ } 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
new file mode 100644
index 0000000000..35f7e759d3
--- /dev/null
+++ b/src/common/utils/Macros.h
@@ -0,0 +1,37 @@
+/*
+ * 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_MACROS_H_
+#define SRC_COMMON_MACROS_H_
+
+#include "src/common/utils/Utils.h"
+
+#define ARM_COMPUTE_RETURN_CENUM_ON_FAILURE(status) \
+ { \
+ if (status != arm_compute::StatusCode::Success) \
+ { \
+ return arm_compute::utils::as_cenum<AclStatus>(status); \
+ } \
+ }
+
+#endif /* SRC_COMMON_MACROS_H_ */
diff --git a/src/common/utils/Object.h b/src/common/utils/Object.h
new file mode 100644
index 0000000000..b73de8e430
--- /dev/null
+++ b/src/common/utils/Object.h
@@ -0,0 +1,64 @@
+/*
+ * 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_OBJECT_H_
+#define SRC_COMMON_OBJECT_H_
+
+#include <cstdint>
+
+namespace arm_compute
+{
+// Forward declarations
+class IContext;
+
+namespace detail
+{
+/**< Object type enumerations */
+enum class ObjectType : uint32_t
+{
+ Context = 1,
+ Queue = 2,
+ Tensor = 3,
+ TensorPack = 4,
+ Operator = 5,
+ Invalid = 0x56DEAD78
+};
+
+/**< API Header meta-data construct used by all opaque constructs */
+struct Header
+{
+ /** Constructor
+ *
+ * @param[in] type_ Object identification type
+ * @param[in] ctx_ Context to reference
+ */
+ Header(ObjectType type_, IContext *ctx_) noexcept : type(type_), ctx(ctx_)
+ {
+ }
+
+ ObjectType type{ObjectType::Invalid};
+ IContext *ctx{nullptr};
+};
+} // namespace detail
+} // namespace arm_compute
+#endif /* SRC_COMMON_OBJECT_H_ */
diff --git a/src/common/utils/Utils.h b/src/common/utils/Utils.h
new file mode 100644
index 0000000000..33fe6c0e81
--- /dev/null
+++ b/src/common/utils/Utils.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2021,2023 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_UTILS_H
+#define SRC_COMMON_UTILS_H
+
+#include <algorithm>
+#include <initializer_list>
+#include <type_traits>
+
+namespace arm_compute
+{
+namespace utils
+{
+/** Convert a strongly typed enum to an old plain c enum
+ *
+ * @tparam E Plain old C enum
+ * @tparam SE Strongly typed resulting enum
+ *
+ * @param[in] v Value to convert
+ *
+ * @return A corresponding plain old C enumeration
+ */
+template <typename E, typename SE>
+constexpr E as_cenum(const SE v) noexcept
+{
+ return static_cast<E>(static_cast<std::underlying_type_t<SE>>(v));
+}
+
+/** Convert plain old enumeration to a strongly typed enum
+ *
+ * @tparam SE Strongly typed resulting enum
+ * @tparam E Plain old C enum
+ *
+ * @param[in] val Value to convert
+ *
+ * @return A corresponding strongly typed enumeration
+ */
+template <typename SE, typename E>
+constexpr SE as_enum(const E val) noexcept
+{
+ return static_cast<SE>(val);
+}
+
+/** Check if the given value is in the given enum value list
+ *
+ * @tparam E The type of the enum
+ *
+ * @param[in] check Value to check
+ * @param[in] list List of enum values to check against
+ *
+ * @return True if the given value is found in the list
+ */
+template <typename E>
+bool is_in(E check, std::initializer_list<E> list)
+{
+ return std::any_of(list.begin(), list.end(), [&check](E e) { return check == e; });
+}
+} // namespace utils
+} // namespace arm_compute
+
+#endif /* SRC_COMMON_UTILS_H */
diff --git a/src/common/utils/Validate.h b/src/common/utils/Validate.h
new file mode 100644
index 0000000000..97819c619f
--- /dev/null
+++ b/src/common/utils/Validate.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2020-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_CORE_COMMON_VALIDATE_H
+#define SRC_CORE_COMMON_VALIDATE_H
+
+#if defined(ARM_COMPUTE_ASSERTS_ENABLED)
+
+#include <cassert>
+
+#define ARM_COMPUTE_ASSERT(cond) assert(cond)
+#define ARM_COMPUTE_ASSERT_NOT_NULLPTR(ptr) assert((ptr) != nullptr)
+
+#else /* defined(ARM_COMPUTE_ASSERTS_ENABLED) */
+
+#define ARM_COMPUTE_ASSERT(cond)
+#define ARM_COMPUTE_ASSERT_NOT_NULLPTR(ptr)
+
+#endif /* defined(ARM_COMPUTE_ASSERTS_ENABLED) */
+#endif /* SRC_CORE_COMMON_VALIDATE_H */