aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp8
-rw-r--r--SConscript8
-rw-r--r--SConstruct4
-rw-r--r--arm_compute/Acl.h39
-rw-r--r--arm_compute/Acl.hpp381
-rw-r--r--arm_compute/AclEntrypoints.h68
-rw-r--r--arm_compute/AclOpenClExt.h69
-rw-r--r--arm_compute/AclTypes.h151
-rw-r--r--arm_compute/AclVersion.h56
-rw-r--r--scripts/arm_compute_library_nn_driver.go3
-rw-r--r--src/c/AclContext.cpp122
-rw-r--r--src/c/AclVersion.cpp42
-rw-r--r--src/c/cl/AclOpenClExt.cpp83
-rw-r--r--src/common/AllocatorWrapper.cpp65
-rw-r--r--src/common/AllocatorWrapper.h81
-rw-r--r--src/common/IContext.h127
-rw-r--r--src/common/Types.h56
-rw-r--r--src/common/utils/Log.h80
-rw-r--r--src/common/utils/Macros.h37
-rw-r--r--src/common/utils/Object.h65
-rw-r--r--src/common/utils/Utils.h67
-rw-r--r--src/common/utils/Validate.h (renamed from src/core/common/Validate.h)2
-rw-r--r--src/core/NEON/kernels/NELogicalKernel.cpp4
-rw-r--r--src/core/NEON/kernels/batchnormalization/impl/NEON/fp16.cpp1
-rw-r--r--src/core/NEON/kernels/batchnormalization/impl/NEON/fp32.cpp1
-rw-r--r--src/core/NEON/kernels/batchnormalization/impl/SVE/fp16.cpp1
-rw-r--r--src/core/NEON/kernels/batchnormalization/impl/SVE/fp32.cpp1
-rw-r--r--src/core/NEON/kernels/scale/impl/NEON/fp16.cpp174
-rw-r--r--src/core/NEON/kernels/scale/impl/NEON/integer.cpp293
-rw-r--r--src/core/NEON/kernels/scale/impl/NEON/list.h1
-rw-r--r--src/core/NEON/kernels/scale/impl/NEON/qasymm8_signed.cpp1
-rw-r--r--src/core/NEON/kernels/scale/impl/SVE/fp16.cpp1
-rw-r--r--src/core/NEON/kernels/scale/impl/SVE/fp32.cpp1
-rw-r--r--src/core/NEON/kernels/scale/impl/SVE/integer.cpp1
-rw-r--r--src/core/NEON/kernels/scale/impl/SVE/qasymm8.cpp1
-rw-r--r--src/core/NEON/kernels/scale/impl/SVE/qasymm8_signed.cpp1
-rw-r--r--src/core/cpu/kernels/activation/NEON/fp16.cpp1
-rw-r--r--src/core/cpu/kernels/activation/NEON/fp32.cpp1
-rw-r--r--src/core/cpu/kernels/activation/NEON/qasymm8.cpp1
-rw-r--r--src/core/cpu/kernels/activation/NEON/qasymm8_signed.cpp1
-rw-r--r--src/core/cpu/kernels/activation/NEON/qsymm16.cpp1
-rw-r--r--src/core/cpu/kernels/activation/SVE/fp16.cpp1
-rw-r--r--src/core/cpu/kernels/activation/SVE/fp32.cpp1
-rw-r--r--src/core/cpu/kernels/activation/SVE/qasymm8.cpp1
-rw-r--r--src/core/cpu/kernels/activation/SVE/qasymm8_signed.cpp1
-rw-r--r--src/core/cpu/kernels/activation/SVE/qsymm16.cpp1
-rw-r--r--src/core/cpu/kernels/floor/NEON/fp16.cpp2
-rw-r--r--src/core/cpu/kernels/floor/NEON/fp32.cpp2
-rw-r--r--src/core/gpu/cl/kernels/ClElementwiseKernel.cpp2
-rw-r--r--src/cpu/CpuContext.cpp182
-rw-r--r--src/cpu/CpuContext.h77
-rw-r--r--src/gpu/cl/ClContext.cpp74
-rw-r--r--src/gpu/cl/ClContext.h76
-rw-r--r--tests/SConscript2
-rw-r--r--tests/validation/CL/UNIT/Extensions.cpp49
-rw-r--r--tests/validation/UNIT/Version.cpp47
-rw-r--r--tests/validation/cpu/unit/Context.cpp197
-rw-r--r--tests/validation/gpu/unit/Context.cpp168
58 files changed, 2956 insertions, 28 deletions
diff --git a/Android.bp b/Android.bp
index 6d0d6b6fa6..c5980c3170 100644
--- a/Android.bp
+++ b/Android.bp
@@ -51,6 +51,10 @@ cc_library_static {
"src/core/NEON/kernels/convolution/winograd"],
export_include_dirs: [".", "./include"],
srcs: [
+ "src/c/AclContext.cpp",
+ "src/c/AclVersion.cpp",
+ "src/c/cl/AclOpenClExt.cpp",
+ "src/common/AllocatorWrapper.cpp",
"src/core/AccessWindowAutoPadding.cpp",
"src/core/AccessWindowStatic.cpp",
"src/core/AccessWindowTranspose.cpp",
@@ -342,6 +346,8 @@ cc_library_static {
"src/core/NEON/kernels/convolution/winograd/winograd_transforms/weights_4x4_3x3_fp16_fp16_integers.cpp",
"src/core/NEON/kernels/convolution/winograd/winograd_transforms/weights_4x4_3x3_fp32_fp32_integers.cpp",
"src/core/NEON/kernels/convolution/winograd/winograd_transforms/weights_6_3_fp32_fp32_integers.cpp",
+ "src/core/NEON/kernels/scale/impl/NEON/fp16.cpp",
+ "src/core/NEON/kernels/scale/impl/NEON/integer.cpp",
"src/core/NEON/kernels/scale/impl/NEON/qasymm8.cpp",
"src/core/NEON/kernels/scale/impl/NEON/qasymm8_signed.cpp",
"src/core/NEON/kernels/scale/impl/SVE/fp16.cpp",
@@ -431,6 +437,8 @@ cc_library_static {
"src/core/utils/logging/LoggerRegistry.cpp",
"src/core/utils/misc/MMappedFile.cpp",
"src/core/utils/quantization/AsymmHelpers.cpp",
+ "src/cpu/CpuContext.cpp",
+ "src/gpu/cl/ClContext.cpp",
"src/runtime/Allocator.cpp",
"src/runtime/BlobLifetimeManager.cpp",
"src/runtime/BlobMemoryPool.cpp",
diff --git a/SConscript b/SConscript
index c89abef81c..9894e30481 100644
--- a/SConscript
+++ b/SConscript
@@ -165,7 +165,6 @@ arm_compute_env.Append(CPPDEFINES = [('ARM_COMPUTE_VERSION_MAJOR', LIBRARY_VERSI
('ARM_COMPUTE_VERSION_MINOR', LIBRARY_VERSION_MINOR),
('ARM_COMPUTE_VERSION_PATCH', LIBRARY_VERSION_PATCH)])
-
# Don't allow undefined references in the libraries:
undefined_flag = '-Wl,-undefined,error' if 'macos' in arm_compute_env["os"] else '-Wl,--no-undefined'
arm_compute_env.Append(LINKFLAGS=[undefined_flag])
@@ -189,6 +188,10 @@ runtime_files = Glob('src/runtime/*.cpp')
runtime_files += Glob('src/runtime/CPP/ICPPSimpleFunction.cpp')
runtime_files += Glob('src/runtime/CPP/functions/*.cpp')
+runtime_files += Glob('src/c/*.cpp')
+runtime_files += Glob('src/common/*.cpp')
+runtime_files += Glob('src/cpu/*.cpp')
+
# CLHarrisCorners uses the Scheduler to run CPP kernels
runtime_files += Glob('src/runtime/CPP/SingleThreadScheduler.cpp')
@@ -220,6 +223,9 @@ if env['opencl']:
runtime_files += Glob('src/runtime/CL/mlgo/*.cpp')
runtime_files += Glob('src/runtime/CL/gemm_auto_heuristics/*.cpp')
+ runtime_files += Glob('src/gpu/cl/*.cpp')
+ runtime_files += Glob('src/c/cl/*.cpp')
+
graph_files += Glob('src/graph/backends/CL/*.cpp')
diff --git a/SConstruct b/SConstruct
index 8892626b90..ad9a3aca1d 100644
--- a/SConstruct
+++ b/SConstruct
@@ -340,7 +340,11 @@ if env['os'] == 'linux' and env['arch'] == 'armv7a':
if env['specs_file'] != "":
env.Append(LINKFLAGS = ['-specs='+env['specs_file']])
+if env['neon']:
+ env.Append(CPPDEFINES = ['ARM_COMPUTE_CPU_ENABLED'])
+
if env['opencl']:
+ env.Append(CPPDEFINES = ['ARM_COMPUTE_OPENCL_ENABLED'])
if env['os'] in ['bare_metal'] or env['standalone']:
print("Cannot link OpenCL statically, which is required for bare metal / standalone builds")
Exit(1)
diff --git a/arm_compute/Acl.h b/arm_compute/Acl.h
new file mode 100644
index 0000000000..6958f60bfd
--- /dev/null
+++ b/arm_compute/Acl.h
@@ -0,0 +1,39 @@
+/*
+ * 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 ARM_COMPUTE_ACL_H_
+#define ARM_COMPUTE_ACL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Core headers */
+#include "arm_compute/AclEntrypoints.h"
+#include "arm_compute/AclTypes.h"
+#include "arm_compute/AclVersion.h"
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* ARM_COMPUTE_ACL_H_ */
diff --git a/arm_compute/Acl.hpp b/arm_compute/Acl.hpp
new file mode 100644
index 0000000000..b74e65430c
--- /dev/null
+++ b/arm_compute/Acl.hpp
@@ -0,0 +1,381 @@
+/*
+ * 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 ARM_COMPUTE_ACL_HPP_
+#define ARM_COMPUTE_ACL_HPP_
+
+#include "arm_compute/Acl.h"
+
+#include <cstdlib>
+#include <memory>
+#include <string>
+
+#if defined(ARM_COMPUTE_EXCEPTIONS_ENABLED)
+#include <exception>
+#endif /* defined(ARM_COMPUTE_EXCEPTIONS_ENABLED) */
+
+// Helper Macros
+#define ARM_COMPUTE_IGNORE_UNUSED(x) (void)(x)
+
+namespace acl
+{
+// Forward declarations
+class Context;
+
+/**< Status code enum */
+enum class StatusCode
+{
+ Success = AclSuccess,
+ RuntimeError = AclRuntimeError,
+ OutOfMemory = AclOutOfMemory,
+ Unimplemented = AclUnimplemented,
+ UnsupportedTarget = AclUnsupportedTarget,
+ InvalidArgument = AclInvalidArgument,
+ InvalidTarget = AclInvalidTarget,
+ UnsupportedConfig = AclUnsupportedConfig,
+ InvalidObjectState = AclInvalidObjectState,
+};
+
+/**< Utility namespace containing helpers functions */
+namespace detail
+{
+/** Construct to handle destruction of objects
+ *
+ * @tparam T Object base type
+ */
+template <typename T>
+struct ObjectDeleter
+{
+};
+
+#define OBJECT_DELETER(obj, func) \
+ template <> \
+ struct ObjectDeleter<obj> \
+ \
+ { \
+ static inline AclStatus Destroy(obj v) \
+ { \
+ return func(v); \
+ } \
+ };
+
+OBJECT_DELETER(AclContext, AclDestroyContext)
+
+#undef OBJECT_DELETER
+
+/** 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(SE v) noexcept
+{
+ return static_cast<E>(static_cast<typename std::underlying_type<SE>::type>(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(E val) noexcept
+{
+ return static_cast<SE>(val);
+}
+
+/** Object base class for library objects
+ *
+ * Class is defining basic common interface for all the library objects
+ *
+ * @tparam T Object type to be templated on
+ */
+template <typename T>
+class ObjectBase
+{
+public:
+ /** Destructor */
+ ~ObjectBase() = default;
+ /** Copy constructor */
+ ObjectBase(const ObjectBase<T> &) = default;
+ /** Move Constructor */
+ ObjectBase(ObjectBase<T> &&) = default;
+ /** Copy assignment operator */
+ ObjectBase<T> &operator=(const ObjectBase<T> &) = default;
+ /** Move assignment operator */
+ ObjectBase<T> &operator=(ObjectBase<T> &&) = default;
+ /** Reset object value
+ *
+ * @param [in] val Value to set
+ */
+ void reset(T *val)
+ {
+ _object.reset(val, detail::ObjectDeleter<T *>::Destroy);
+ }
+ /** Access uderlying object
+ *
+ * @return Underlying object
+ */
+ const T *get() const
+ {
+ return _object.get();
+ }
+ /** Access uderlying object
+ *
+ * @return Underlying object
+ */
+ T *get()
+ {
+ return _object.get();
+ }
+
+protected:
+ /** Constructor */
+ ObjectBase() = default;
+
+protected:
+ std::shared_ptr<T> _object{ nullptr }; /**< Library object */
+};
+
+/** Equality operator for library object
+ *
+ * @tparam T Parameter to template on
+ *
+ * @param[in] lhs Left hand-side argument
+ * @param[in] rhs Right hand-side argument
+ *
+ * @return True if objects are equal, else false
+ */
+template <typename T>
+bool operator==(const ObjectBase<T> &lhs, const ObjectBase<T> &rhs)
+{
+ return lhs.get() == rhs.get();
+}
+
+/** Inequality operator for library object
+ *
+ * @tparam T Parameter to template on
+ *
+ * @param[in] lhs Left hand-side argument
+ * @param[in] rhs Right hand-side argument
+ *
+ * @return True if objects are equal, else false
+ */
+template <typename T>
+bool operator!=(const ObjectBase<T> &lhs, const ObjectBase<T> &rhs)
+{
+ return !(lhs == rhs);
+}
+} // namespace detail
+
+#if defined(ARM_COMPUTE_EXCEPTIONS_ENABLED)
+/** Status class
+ *
+ * Class is an extension of std::exception and contains the underlying
+ * status construct and an error explanatory message to be reported.
+ *
+ * @note Class is visible only when exceptions are enabled during compilation
+ */
+class Status : public std::exception
+{
+public:
+ /** Constructor
+ *
+ * @param[in] status Status returned
+ * @param[in] msg Error message to be bound with the exception
+ */
+ Status(StatusCode status, const std::string &msg)
+ : _status(status), _msg(msg)
+ {
+ }
+ /** Returns an explanatory exception message
+ *
+ * @return Status message
+ */
+ const char *what() const noexcept override
+ {
+ return _msg.c_str();
+ }
+ /** Underlying status accessor
+ *
+ * @return Status code
+ */
+ StatusCode status() const
+ {
+ return _status;
+ }
+ /** Explicit status converter
+ *
+ * @return Status code
+ */
+ explicit operator StatusCode() const
+ {
+ return _status;
+ }
+
+private:
+ StatusCode _status; /**< Status code */
+ std::string _msg; /**< Status message */
+};
+
+/** Reports an error status and throws an exception object in case of failure
+ *
+ * @note This implementation is used when exceptions are enabled during compilation
+ *
+ * @param[in] status Status to report
+ * @param[in] msg Explanatory error messaged
+ *
+ * @return Status code
+ */
+static inline StatusCode report_status(StatusCode status, const std::string &msg)
+{
+ if(status != StatusCode::Success)
+ {
+ throw Status(status, msg);
+ }
+ return status;
+}
+#else /* defined(ARM_COMPUTE_EXCEPTIONS_ENABLED) */
+/** Reports a status code
+ *
+ * @note This implementation is used when exceptions are disabled during compilation
+ * @note Message is surpressed and not reported in this case
+ *
+ * @param[in] status Status to report
+ * @param[in] msg Explanatory error messaged
+ *
+ * @return Status code
+ */
+static inline StatusCode report_status(StatusCode status, const std::string &msg)
+{
+ ARM_COMPUTE_IGNORE_UNUSED(msg);
+ return status;
+}
+#endif /* defined(ARM_COMPUTE_EXCEPTIONS_ENABLED) */
+
+/**< Target enum */
+enum class Target
+{
+ Cpu = AclCpu, /**< Cpu target that leverages SIMD */
+ GpuOcl = AclGpuOcl /**< Gpu target that leverages OpenCL */
+};
+
+/**< Available execution modes */
+enum class ExecutionMode
+{
+ FastRerun = AclPreferFastRerun, /**< Prefer minimum latency in consecutive runs, might introduce higher startup times */
+ FastStart = AclPreferFastStart, /**< Prefer minimizing startup time */
+};
+
+/** Context class
+ *
+ * Context acts as a central aggregate service for further objects created from it.
+ * It provides, internally, common facilities in order to avoid the use of global
+ * statically initialized objects that can lead to important side-effect under
+ * specific execution contexts.
+ *
+ * For example context contains allocators for object creation, for further backing memory allocation,
+ * any serialization interfaces and other modules that affect the construction of objects,
+ * like program caches for OpenCL.
+ */
+class Context : public detail::ObjectBase<AclContext_>
+{
+public:
+ /**< Context options */
+ struct Options
+ {
+ /** Default Constructor
+ *
+ * @note By default no precision loss is enabled for operators
+ * @note By default the preferred execution mode is to favor multiple consecutive reruns of an operator
+ */
+ Options() = default;
+ /** Constructor
+ *
+ * @param[in] mode Execution mode to be used
+ * @param[in] caps Capabilities to be used
+ * @param[in] enable_fast_math Allow precision loss in favor of performance
+ * @param[in] kernel_config Kernel configuration file containing construction tuning meta-data
+ * @param[in] max_compute_units Max compute units that are expected to used
+ * @param[in] allocator Allocator to be used for internal memory allocation
+ */
+ Options(ExecutionMode mode,
+ AclTargetCapabilities caps,
+ bool enable_fast_math,
+ const char *kernel_config,
+ int32_t max_compute_units,
+ AclAllocator *allocator)
+ {
+ opts.mode = detail::as_cenum<AclExecutionMode>(mode);
+ opts.capabilities = caps;
+ opts.enable_fast_math = enable_fast_math;
+ opts.kernel_config_file = kernel_config;
+ opts.max_compute_units = max_compute_units;
+ opts.allocator = allocator;
+ }
+ AclContextOptions opts{ acl_default_ctx_options };
+ };
+
+public:
+ /** Constructor
+ *
+ * @note Serves as a simpler delegate constructor
+ * @note As context options, default conservative options will be used
+ *
+ * @param[in] target Target to create context for
+ * @param[out] status Status information if requested
+ */
+ explicit Context(Target target, StatusCode *status = nullptr)
+ : Context(target, Options(), status)
+ {
+ }
+ /** Constructor
+ *
+ * @param[in] target Target to create context for
+ * @param[in] options Context construction options
+ * @param[out] status Status information if requested
+ */
+ Context(Target target, const Options &options, StatusCode *status = nullptr)
+ {
+ AclContext ctx;
+ const auto st = detail::as_enum<StatusCode>(AclCreateContext(&ctx, detail::as_cenum<AclTarget>(target), &options.opts));
+ reset(ctx);
+ report_status(st, "Failure during context creation");
+ if(status)
+ {
+ *status = st;
+ }
+ }
+};
+} // namespace acl
+#undef ARM_COMPUTE_IGNORE_UNUSED
+#endif /* ARM_COMPUTE_ACL_HPP_ */
diff --git a/arm_compute/AclEntrypoints.h b/arm_compute/AclEntrypoints.h
new file mode 100644
index 0000000000..02e072f826
--- /dev/null
+++ b/arm_compute/AclEntrypoints.h
@@ -0,0 +1,68 @@
+/*
+ * 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 ARM_COMPUTE_ACLENTRYPOINTS_H_
+#define ARM_COMPUTE_ACLENTRYPOINTS_H_
+
+#include "arm_compute/AclTypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /** __cplusplus */
+
+/** Create a context object
+ *
+ * Context is responsible for retaining internal information and work as an aggregate service mechanism
+ *
+ * @param[in, out] ctx A valid non-zero context object if no failure occurs
+ * @param[in] target Target to create the context for
+ * @param[in] options Context options to be used for all the kernels that are created under the context
+ *
+ * @return Status code
+ *
+ * Returns:
+ * - @ref AclSuccess if function was completed successfully
+ * - @ref AclOutOfMemory if there was a failure allocating memory resources
+ * - @ref AclUnsupportedTarget if the requested target is unsupported
+ * - @ref AclInvalidArgument if a given argument is invalid
+ */
+AclStatus AclCreateContext(AclContext *ctx,
+ AclTarget target,
+ const AclContextOptions *options);
+
+/** Destroy a given context object
+ *
+ * @param[in] ctx A valid context object to destroy
+ *
+ * @return Status code
+ *
+ * Returns:
+ * - @ref AclSuccess if functions was completed successfully
+ * - @ref AclInvalidArgument if the provided context is invalid
+ */
+AclStatus AclDestroyContext(AclContext ctx);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* ARM_COMPUTE_ACLENTRYPOINTS_H_ */
diff --git a/arm_compute/AclOpenClExt.h b/arm_compute/AclOpenClExt.h
new file mode 100644
index 0000000000..f71cd37299
--- /dev/null
+++ b/arm_compute/AclOpenClExt.h
@@ -0,0 +1,69 @@
+/*
+ * 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 ARM_COMPUTE_ACLOPENCLEXT_H_
+#define ARM_COMPUTE_ACLOPENCLEXT_H_
+
+#include "arm_compute/AclTypes.h"
+
+#ifndef CL_TARGET_OPENCL_VERSION
+#define CL_TARGET_OPENCL_VERSION 200
+#define CL_USE_DEPRECATED_OPENCL_1_1_APIS
+#define CL_USE_DEPRECATED_OPENCL_1_2_APIS
+#endif /* CL_TARGET_OPENCL_VERSION */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Weffc++"
+#include "include/CL/cl.h"
+#pragma GCC diagnostic pop
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/** Extract the underlying OpenCL context used by a given Compute Library context object
+ *
+ * @note @ref AclContext should be of an OpenCL backend target
+ * @note @ref AclContext refcount should be 0, meaning not used by other objects
+ *
+ * @param[in] ctx A valid non-zero context
+ * @param[out] opencl_context Underlying OpenCL context used
+ *
+ * @return Status code
+ */
+AclStatus AclGetClContext(AclContext ctx, cl_context *opencl_context);
+
+/** Set the underlying OpenCL context used by a given Compute Library context object
+ *
+ * @note @ref AclContext should be of an OpenCL backend target
+ *
+ * @param[in] ctx A valid non-zero context object
+ * @param[out] opencl_context Underlying OpenCL context to be used
+ *
+ * @return Status code
+ */
+AclStatus AclSetClContext(AclContext ctx, cl_context opencl_context);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* ARM_COMPUTE_ACLOPENCLEXT_H_ */
diff --git a/arm_compute/AclTypes.h b/arm_compute/AclTypes.h
new file mode 100644
index 0000000000..3b022b7106
--- /dev/null
+++ b/arm_compute/AclTypes.h
@@ -0,0 +1,151 @@
+/*
+ * 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 ARM_COMPUTE_ACLTYPES_H_
+#define ARM_COMPUTE_ACLTYPES_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**< Opaque Context object */
+typedef struct AclContext_ *AclContext;
+
+// Capabilities bitfield (Note: if multiple are enabled ComputeLibrary will pick the best possible)
+typedef uint64_t AclTargetCapabilities;
+
+/**< Error codes returned by the public entry-points */
+typedef enum AclStatus : int32_t
+{
+ AclSuccess = 0, /**< Call succeeded, leading to valid state for all involved objects/data */
+ AclRuntimeError = 1, /**< Call failed during execution */
+ AclOutOfMemory = 2, /**< Call failed due to failure to allocate resources */
+ AclUnimplemented = 3, /**< Call failed as requested capability is not implemented */
+ AclUnsupportedTarget = 4, /**< Call failed as an invalid backend was requested */
+ AclInvalidTarget = 5, /**< Call failed as invalid argument was passed */
+ AclInvalidArgument = 6, /**< Call failed as invalid argument was passed */
+ AclUnsupportedConfig = 7, /**< Call failed as configuration is unsupported */
+ AclInvalidObjectState = 8, /**< Call failed as an object has invalid state */
+} AclStatus;
+
+/**< Supported CPU targets */
+typedef enum AclTarget
+{
+ AclCpu = 0, /**< Cpu target that uses SIMD extensions */
+ AclGpuOcl = 1, /**< OpenCL target for GPU */
+} AclTarget;
+
+/** Execution mode types */
+typedef enum AclExecutionMode
+{
+ AclPreferFastRerun = 0, /**< Prioritize performance when multiple iterations are performed */
+ AclPreferFastStart = 1, /**< Prioritize performance when a single iterations is expected to be performed */
+} AclExecutionMode;
+
+/** Available CPU capabilities */
+typedef enum AclCpuCapabalities
+{
+ AclCpuCapabilitiesAuto = 0, /**< Automatic discovery of capabilities */
+
+ AclCpuCapabilitiesNeon = (1 << 0), /**< Enable NEON optimized paths */
+ AclCpuCapabilitiesSve = (1 << 1), /**< Enable SVE optimized paths */
+ AclCpuCapabilitiesSve2 = (1 << 2), /**< Enable SVE2 optimized paths */
+ // Reserve 3, 4, 5, 6
+
+ AclCpuCapabilitiesFp16 = (1 << 7), /**< Enable float16 data-type support */
+ AclCpuCapabilitiesBf16 = (1 << 8), /**< Enable bfloat16 data-type support */
+ // Reserve 9, 10, 11, 12
+
+ AclCpuCapabilitiesDot = (1 << 13), /**< Enable paths that use the udot/sdot instructions */
+ AclCpuCapabilitiesMmlaInt8 = (1 << 14), /**< Enable paths that use the mmla integer instructions */
+ AclCpuCapabilitiesMmlaFp = (1 << 15), /**< Enable paths that use the mmla float instructions */
+
+ AclCpuCapabilitiesAll = ~0 /**< Enable all paths */
+} AclCpuCapabalities;
+
+/**< Allocator interface that can be passed to a context */
+typedef struct AclAllocator
+{
+ /** Allocate a block of size bytes of memory.
+ *
+ * @param[in] user_data User provided data that can be used by the allocator
+ * @param[in] size Size of the allocation
+ *
+ * @return A pointer to the allocated block if successfull else NULL
+ */
+ void *(*alloc)(void *user_data, size_t size);
+ /** Release a block of size bytes of memory.
+ *
+ * @param[in] user_data User provided data that can be used by the allocator
+ * @param[in] size Size of the allocation
+ */
+ void (*free)(void *user_data, void *ptr);
+ /** Allocate a block of size bytes of memory.
+ *
+ * @param[in] user_data User provided data that can be used by the allocator
+ * @param[in] size Size of the allocation
+ *
+ * @return A pointer to the allocated block if successfull else NULL
+ */
+ void *(*aligned_alloc)(void *user_data, size_t size, size_t alignment);
+ /** Allocate a block of size bytes of memory.
+ *
+ * @param[in] user_data User provided data that can be used by the allocator
+ * @param[in] size Size of the allocation
+ */
+ void (*aligned_free)(void *user_data, void *ptr);
+
+ /**< User provided information */
+ void *user_data;
+} AclAllocator;
+
+/**< Context options */
+typedef struct AclContextOptions
+{
+ AclExecutionMode mode; /**< Execution mode to use */
+ AclTargetCapabilities capabilities; /**< Target capabilities */
+ bool enable_fast_math; /**< Allow precision loss */
+ const char *kernel_config_file; /**< Kernel cofiguration file */
+ int32_t max_compute_units; /**< Max compute units that can be used by a queue created from the context.
+ If <=0 the system will use the hw concurency insted */
+ AclAllocator *allocator; /**< Allocator to be used by all the memory internally */
+} AclContextOptions;
+
+/** Default context */
+const AclContextOptions acl_default_ctx_options =
+{
+ AclPreferFastRerun, /* mode */
+ AclCpuCapabilitiesAuto, /* capabilities */
+ false, /* enable_fast_math */
+ "default.mlgo", /* kernel_config_file */
+ -1, /* max_compute_units */
+ nullptr /* allocator */
+};
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* ARM_COMPUTE_ACLTYPES_H_ */
diff --git a/arm_compute/AclVersion.h b/arm_compute/AclVersion.h
new file mode 100644
index 0000000000..3a2f30791d
--- /dev/null
+++ b/arm_compute/AclVersion.h
@@ -0,0 +1,56 @@
+/*
+ * 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 ARM_COMPUTE_ACLVERSION_H_
+#define ARM_COMPUTE_ACLVERSION_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/** Semantic versioning information */
+typedef struct AclVersion
+{
+ int major; /**< Major version, is increased on API incompatible changes */
+ int minor; /**< Minor version, is increased on adding back-ward compatible functionality */
+ int patch; /**< Patch version, is increased when doing backward compatible fixes */
+ const char *build_info; /**< Build related information */
+} AclVersion;
+
+/**< Major version, is increased on API incompatible changes */
+#define ARM_COMPUTE_LIBRARY_VERSION_MAJOR 0
+/**< Minor version, is increased on adding back-ward compatible functionality */
+#define ARM_COMPUTE_LIBRARY_VERSION_MINOR 1
+/**< Patch version, is increased when doing backward compatible fixes */
+#define ARM_COMPUTE_LIBRARY_VERSION_PATCH 0
+
+/** Get library's version meta-data
+ *
+ * @return Version information
+ */
+const AclVersion *AclVersionInfo();
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* ARM_COMPUTE_ACLVERSION_H_ */
diff --git a/scripts/arm_compute_library_nn_driver.go b/scripts/arm_compute_library_nn_driver.go
index 61c8b992cf..8b1b80a7a7 100644
--- a/scripts/arm_compute_library_nn_driver.go
+++ b/scripts/arm_compute_library_nn_driver.go
@@ -57,6 +57,9 @@ func globalFlags(ctx android.BaseContext) []string {
}
}
+ cppflags = append(cppflags, "-ARM_COMPUTE_CPU_ENABLED")
+ cppflags = append(cppflags, "-ARM_COMPUTE_OPENCL_ENABLED")
+
return cppflags
}
diff --git a/src/c/AclContext.cpp b/src/c/AclContext.cpp
new file mode 100644
index 0000000000..e88995bcff
--- /dev/null
+++ b/src/c/AclContext.cpp
@@ -0,0 +1,122 @@
+/*
+ * 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 "arm_compute/AclEntrypoints.h"
+
+#include "src/common/IContext.h"
+#include "src/common/utils/Macros.h"
+#include "src/common/utils/Validate.h"
+
+#ifdef ARM_COMPUTE_CPU_ENABLED
+#include "src/cpu/CpuContext.h"
+#endif /* ARM_COMPUTE_CPU_ENABLED */
+
+#ifdef ARM_COMPUTE_OPENCL_ENABLED
+#include "src/gpu/cl/ClContext.h"
+#endif /* ARM_COMPUTE_OPENCL_ENABLED */
+
+namespace
+{
+template <typename ContextType>
+arm_compute::IContext *create_backend_ctx(const AclContextOptions *options)
+{
+ return new(std::nothrow) ContextType(options);
+}
+
+bool is_target_valid(AclTarget target)
+{
+ return arm_compute::utils::is_in(target, { AclCpu, AclGpuOcl });
+}
+
+bool are_context_options_valid(const AclContextOptions *options)
+{
+ ARM_COMPUTE_ASSERT_NOT_NULLPTR(options);
+ return arm_compute::utils::is_in(options->mode, { AclPreferFastRerun, AclPreferFastStart });
+}
+
+arm_compute::IContext *create_context(AclTarget target, const AclContextOptions *options)
+{
+ switch(target)
+ {
+#ifdef ARM_COMPUTE_CPU_ENABLED
+ case AclCpu:
+ return create_backend_ctx<arm_compute::cpu::CpuContext>(options);
+#endif /* ARM_COMPUTE_CPU_ENABLED */
+#ifdef ARM_COMPUTE_OPENCL_ENABLED
+ case AclGpuOcl:
+ return create_backend_ctx<arm_compute::gpu::opencl::ClContext>(options);
+#endif /* ARM_COMPUTE_OPENCL_ENABLED */
+ default:
+ return nullptr;
+ }
+ return nullptr;
+}
+} // namespace
+
+extern "C" AclStatus AclCreateContext(AclContext *ctx,
+ AclTarget target,
+ const AclContextOptions *options)
+{
+ if(!is_target_valid(target))
+ {
+ ARM_COMPUTE_LOG_ERROR_ACL("Target is invalid");
+ return AclUnsupportedTarget;
+ }
+
+ if(options != nullptr && !are_context_options_valid(options))
+ {
+ ARM_COMPUTE_LOG_ERROR_ACL("Context options are invalid");
+ return AclInvalidArgument;
+ }
+
+ auto acl_ctx = create_context(target, options);
+ if(ctx == nullptr)
+ {
+ ARM_COMPUTE_LOG_ERROR_ACL("Couldn't allocate internal resources for context creation");
+ return AclOutOfMemory;
+ }
+ *ctx = acl_ctx;
+
+ return AclSuccess;
+}
+
+extern "C" AclStatus AclDestroyContext(AclContext external_ctx)
+{
+ using namespace arm_compute;
+
+ IContext *ctx = get_internal(external_ctx);
+
+ StatusCode status = StatusCode::Success;
+ status = detail::validate_internal_context(ctx);
+ ARM_COMPUTE_RETURN_CENUM_ON_FAILURE(status);
+
+ if(ctx->refcount() != 0)
+ {
+ ARM_COMPUTE_LOG_ERROR_ACL("Context has references on it that haven't been released");
+ // TODO: Fix the refcount with callback when reaches 0
+ }
+
+ delete ctx;
+
+ return utils::as_cenum<AclStatus>(status);
+}
diff --git a/src/c/AclVersion.cpp b/src/c/AclVersion.cpp
new file mode 100644
index 0000000000..971189a6d4
--- /dev/null
+++ b/src/c/AclVersion.cpp
@@ -0,0 +1,42 @@
+/*
+ * 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 "arm_compute/AclVersion.h"
+
+namespace
+{
+constexpr AclVersion version_info
+{
+ ARM_COMPUTE_LIBRARY_VERSION_MAJOR,
+ ARM_COMPUTE_LIBRARY_VERSION_MINOR,
+ ARM_COMPUTE_LIBRARY_VERSION_PATCH,
+#ifndef DOXYGEN_SKIP_THIS
+#include "arm_compute_version.embed"
+#endif /* DOXYGEN_SKIP_THIS */
+};
+} // namespace
+
+extern "C" const AclVersion *AclVersionInfo()
+{
+ return &version_info;
+}
diff --git a/src/c/cl/AclOpenClExt.cpp b/src/c/cl/AclOpenClExt.cpp
new file mode 100644
index 0000000000..5f2bb47c16
--- /dev/null
+++ b/src/c/cl/AclOpenClExt.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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 "arm_compute/AclOpenClExt.h"
+
+#include "src/common/Types.h"
+#include "src/gpu/cl/ClContext.h"
+
+#include "support/Cast.h"
+
+extern "C" AclStatus AclGetClContext(AclContext external_ctx, cl_context *opencl_context)
+{
+ using namespace arm_compute;
+ IContext *ctx = get_internal(external_ctx);
+
+ if(detail::validate_internal_context(ctx) != StatusCode::Success)
+ {
+ return AclStatus::AclInvalidArgument;
+ }
+
+ if(ctx->type() != Target::GpuOcl)
+ {
+ return AclStatus::AclInvalidTarget;
+ }
+
+ if(opencl_context == nullptr)
+ {
+ return AclStatus::AclInvalidArgument;
+ }
+
+ *opencl_context = utils::cast::polymorphic_downcast<arm_compute::gpu::opencl::ClContext *>(ctx)->cl_ctx().get();
+
+ return AclStatus::AclSuccess;
+}
+
+extern "C" AclStatus AclSetClContext(AclContext external_ctx, cl_context opencl_context)
+{
+ using namespace arm_compute;
+ IContext *ctx = get_internal(external_ctx);
+
+ if(detail::validate_internal_context(ctx) != StatusCode::Success)
+ {
+ return AclStatus::AclInvalidArgument;
+ }
+
+ if(ctx->type() != Target::GpuOcl)
+ {
+ return AclStatus::AclInvalidTarget;
+ }
+
+ if(ctx->refcount() != 0)
+ {
+ return AclStatus::AclUnsupportedConfig;
+ }
+
+ auto cl_ctx = utils::cast::polymorphic_downcast<arm_compute::gpu::opencl::ClContext *>(ctx);
+ if(!cl_ctx->set_cl_ctx(::cl::Context(opencl_context)))
+ {
+ return AclStatus::AclRuntimeError;
+ }
+
+ return AclStatus::AclSuccess;
+} \ No newline at end of file
diff --git a/src/common/AllocatorWrapper.cpp b/src/common/AllocatorWrapper.cpp
new file mode 100644
index 0000000000..7b5bb34433
--- /dev/null
+++ b/src/common/AllocatorWrapper.cpp
@@ -0,0 +1,65 @@
+/*
+ * 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..5e1f138f16
--- /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 */ \ No newline at end of file
diff --git a/src/common/IContext.h b/src/common/IContext.h
new file mode 100644
index 0000000000..0d23abd2be
--- /dev/null
+++ b/src/common/IContext.h
@@ -0,0 +1,127 @@
+/*
+ * 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_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>
+
+struct AclContext_
+{
+ arm_compute::detail::Header header{ arm_compute::detail::ObjectType::Context, nullptr };
+
+protected:
+ AclContext_() = default;
+ ~AclContext_() = default;
+};
+
+namespace arm_compute
+{
+/**< 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;
+ }
+
+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/Types.h b/src/common/Types.h
new file mode 100644
index 0000000000..60a11b04ec
--- /dev/null
+++ b/src/common/Types.h
@@ -0,0 +1,56 @@
+/*
+ * 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/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,
+};
+} // namespace arm_compute
+#endif /* SRC_COMMON_TYPES_H_ */
diff --git a/src/common/utils/Log.h b/src/common/utils/Log.h
new file mode 100644
index 0000000000..0d6a50da92
--- /dev/null
+++ b/src/common/utils/Log.h
@@ -0,0 +1,80 @@
+/*
+ * 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_LOG_H
+#define SRC_COMMON_LOG_H
+
+#include "arm_compute/core/Error.h"
+#include "arm_compute/core/utils/logging/Macros.h"
+
+#ifdef ARM_COMPUTE_LOGGING_ENABLED
+/** Create a logger
+ *
+ * @note It will eventually create all default loggers in don't exist
+ */
+#define ARM_COMPUTE_CREATE_ACL_LOGGER() \
+ do \
+ { \
+ if(arm_compute::logging::LoggerRegistry::get().logger("ComputeLibrary") == nullptr) \
+ { \
+ arm_compute::logging::LoggerRegistry::get().create_logger("ComputeLibrary", arm_compute::logging::LogLevel::INFO); \
+ } \
+ } while(false)
+#else /* ARM_COMPUTE_LOGGING_ENABLED */
+#define ARM_COMPUTE_CREATE_ACL_LOGGER()
+#endif /* ARM_COMPUTE_LOGGING_ENABLED */
+/** 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)
+
+#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..2e44ea599e
--- /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..6f56f77d3c
--- /dev/null
+++ b/src/common/utils/Object.h
@@ -0,0 +1,65 @@
+/*
+ * 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_)
+ : 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..9602c32f62
--- /dev/null
+++ b/src/common/utils/Utils.h
@@ -0,0 +1,67 @@
+/*
+ * 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_UTILS_H
+#define SRC_COMMON_UTILS_H
+
+#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(SE v) noexcept
+{
+ return static_cast<E>(static_cast<std::underlying_type_t<SE>>(v));
+}
+/** 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(std::cbegin(list), std::cend(list), [&check](E e)
+ {
+ return check == e;
+ });
+}
+} // namespace utils
+} // namespace arm_compute
+
+#endif /* SRC_COMMON_UTILS_H */
diff --git a/src/core/common/Validate.h b/src/common/utils/Validate.h
index fa24bf5fa7..4e8807273a 100644
--- a/src/core/common/Validate.h
+++ b/src/common/utils/Validate.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Arm Limited.
+ * Copyright (c) 2020-2021 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
diff --git a/src/core/NEON/kernels/NELogicalKernel.cpp b/src/core/NEON/kernels/NELogicalKernel.cpp
index 27605e15c6..d98694ffe1 100644
--- a/src/core/NEON/kernels/NELogicalKernel.cpp
+++ b/src/core/NEON/kernels/NELogicalKernel.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Arm Limited.
+ * Copyright (c) 2020-2021 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -25,7 +25,7 @@
#include "arm_compute/core/Helpers.h"
#include "arm_compute/core/Validate.h"
-#include "src/core/common/Validate.h"
+#include "src/common/utils/Validate.h"
#include "src/core/helpers/AutoConfiguration.h"
#include "src/core/helpers/WindowHelpers.h"
diff --git a/src/core/NEON/kernels/batchnormalization/impl/NEON/fp16.cpp b/src/core/NEON/kernels/batchnormalization/impl/NEON/fp16.cpp
index 4108d79a5a..c105adac70 100644
--- a/src/core/NEON/kernels/batchnormalization/impl/NEON/fp16.cpp
+++ b/src/core/NEON/kernels/batchnormalization/impl/NEON/fp16.cpp
@@ -27,7 +27,6 @@
#include "src/core/NEON/NEMath.h"
#include "src/core/NEON/kernels/detail/NEActivationFunctionDetail.h"
#include "src/core/NEON/wrapper/wrapper.h"
-#include "src/core/common/Validate.h"
#include <arm_neon.h>
#include <cmath>
diff --git a/src/core/NEON/kernels/batchnormalization/impl/NEON/fp32.cpp b/src/core/NEON/kernels/batchnormalization/impl/NEON/fp32.cpp
index 1fdc5bd5b1..4a90a211c7 100644
--- a/src/core/NEON/kernels/batchnormalization/impl/NEON/fp32.cpp
+++ b/src/core/NEON/kernels/batchnormalization/impl/NEON/fp32.cpp
@@ -27,7 +27,6 @@
#include "src/core/NEON/NEMath.h"
#include "src/core/NEON/kernels/detail/NEActivationFunctionDetail.h"
#include "src/core/NEON/wrapper/wrapper.h"
-#include "src/core/common/Validate.h"
#include <arm_neon.h>
#include <cmath>
diff --git a/src/core/NEON/kernels/batchnormalization/impl/SVE/fp16.cpp b/src/core/NEON/kernels/batchnormalization/impl/SVE/fp16.cpp
index 5638dcef0a..3e3e81d044 100644
--- a/src/core/NEON/kernels/batchnormalization/impl/SVE/fp16.cpp
+++ b/src/core/NEON/kernels/batchnormalization/impl/SVE/fp16.cpp
@@ -25,7 +25,6 @@
#include "arm_compute/core/ITensorPack.h"
#include "arm_compute/core/Window.h"
#include "src/core/NEON/SVEMath.h"
-#include "src/core/common/Validate.h"
#include <cmath>
#include <cstddef>
diff --git a/src/core/NEON/kernels/batchnormalization/impl/SVE/fp32.cpp b/src/core/NEON/kernels/batchnormalization/impl/SVE/fp32.cpp
index 51397aca3a..b0d4cbb684 100644
--- a/src/core/NEON/kernels/batchnormalization/impl/SVE/fp32.cpp
+++ b/src/core/NEON/kernels/batchnormalization/impl/SVE/fp32.cpp
@@ -25,7 +25,6 @@
#include "arm_compute/core/ITensorPack.h"
#include "arm_compute/core/Window.h"
#include "src/core/NEON/SVEMath.h"
-#include "src/core/common/Validate.h"
#include <cmath>
#include <cstddef>
diff --git a/src/core/NEON/kernels/scale/impl/NEON/fp16.cpp b/src/core/NEON/kernels/scale/impl/NEON/fp16.cpp
new file mode 100644
index 0000000000..0ad66cab1c
--- /dev/null
+++ b/src/core/NEON/kernels/scale/impl/NEON/fp16.cpp
@@ -0,0 +1,174 @@
+/*
+ * 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 "arm_compute/core/Helpers.h"
+#include "arm_compute/core/ITensorPack.h"
+#include "arm_compute/core/Window.h"
+#include "src/core/NEON/NEMath.h"
+#include "src/core/NEON/wrapper/wrapper.h"
+#include "src/core/helpers/ScaleHelpers.h"
+#include "src/core/utils/ScaleUtils.h"
+#include "support/Rounding.h"
+
+#include <arm_neon.h>
+#include <cmath>
+#include <cstddef>
+
+#if defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(ENABLE_FP16_KERNELS)
+
+namespace arm_compute
+{
+namespace
+{
+void fp16_neon_scale_nearest(const ITensor *src, ITensor *dst, const ITensor *offsets,
+ float sampling_offset, bool align_corners, const Window &window)
+{
+ const size_t in_stride_c = src->info()->dimension(0) + src->info()->padding().left + src->info()->padding().right;
+ const size_t in_stride_w = src->info()->dimension(1) + src->info()->padding().top + src->info()->padding().bottom;
+ const size_t in_stride_wc = in_stride_w * in_stride_c;
+ const size_t in_dim_h = src->info()->dimension(2);
+
+ // Compute the ratio between source height and destination height
+ const auto hr = scale_utils::calculate_resize_ratio(in_dim_h, dst->info()->dimension(2), align_corners);
+ const auto window_start_x = static_cast<int32_t>(window.x().start());
+ const auto window_end_x = static_cast<int32_t>(window.x().end());
+ const int window_step_x = 8;
+
+ Window win(window);
+ win.set(Window::DimX, Window::Dimension(0, 1, 1));
+ Iterator out(dst, win);
+
+ const uint8_t *in_ptr_start = src->buffer() + src->info()->offset_first_element_in_bytes();
+ const unsigned int in_stride_bytes_hwc = src->info()->strides_in_bytes()[3];
+
+ execute_window_loop(win, [&](const Coordinates & id)
+ {
+ const int32_t offset = *reinterpret_cast<const int32_t *>(offsets->ptr_to_element(Coordinates(id.y(), id.z()))) * in_stride_c;
+ const auto in_hi = static_cast<int>(align_corners ? utils::rounding::round_half_away_from_zero((id.z() + sampling_offset) * hr) : std::floor((id.z() + sampling_offset) * hr));
+ const int offset_row = in_hi * in_stride_wc;
+ int32_t x = window_start_x;
+ const float16_t *in_ptr = reinterpret_cast<const float16_t *>(in_ptr_start + in_stride_bytes_hwc * id[3]);
+
+ for(; x <= window_end_x - window_step_x; x += window_step_x)
+ {
+ wrapper::vstore(reinterpret_cast<float16_t *>(out.ptr()) + x,
+ wrapper::vloadq(in_ptr + offset + offset_row + x));
+ }
+ for(; x < window_end_x; ++x)
+ {
+ *(reinterpret_cast<float16_t *>(out.ptr()) + x) = *(in_ptr + offset + offset_row + x);
+ }
+ },
+ out);
+}
+
+void fp16_neon_scale_bilinear(const ITensor *src, ITensor *dst, const ITensor *offsets, const ITensor *dx, const ITensor *dy,
+ BorderMode border_mode, PixelValue constant_border_value, float sampling_offset,
+ bool align_corners, const Window &window)
+{
+ // Compute the ratio between source height and destination height
+ const auto hr = scale_utils::calculate_resize_ratio(src->info()->dimension(2), dst->info()->dimension(2), align_corners);
+
+ Iterator out(dst, window);
+ const int in_stride_c = src->info()->dimension(0) + src->info()->padding().left + src->info()->padding().right;
+ const int in_dim_w = src->info()->dimension(1);
+ const int in_dim_h = src->info()->dimension(2);
+ const int in_stride_wc = in_stride_c * (in_dim_w + src->info()->padding().top + src->info()->padding().bottom);
+
+ // Don't increment in Y and Z direction for the input tensor
+ // A pointer to the start of this plane is needed as base for the precomputed offsets
+ Window win_in(window);
+ win_in.set(Window::DimY, Window::Dimension(0, 0, 0));
+ win_in.set(Window::DimZ, Window::Dimension(0, 0, 0));
+ Iterator in(src, win_in);
+
+ if(border_mode == BorderMode::CONSTANT)
+ {
+ using ConstType = typename std::conditional<std::is_same<float16_t, float16_t>::value, half, float16_t>::type;
+
+ const float16_t const_border_value = static_cast<float16_t>(constant_border_value.get<ConstType>());
+ execute_window_loop(window, [&](const Coordinates & id)
+ {
+ const auto offset = *reinterpret_cast<const int32_t *>(offsets->ptr_to_element(Coordinates(id.y(), id.z())));
+ const auto dx_val = *reinterpret_cast<const float *>(dx->ptr_to_element(Coordinates(id.y(), id.z())));
+ const auto dy_val = *reinterpret_cast<const float *>(dy->ptr_to_element(Coordinates(id.y(), id.z())));
+ const int32_t in_hi = std::floor((id.z() + sampling_offset) * hr - sampling_offset);
+ const float16_t *in_ptr = reinterpret_cast<const float16_t *>(in.ptr()) + offset * in_stride_c + in_hi * in_stride_wc;
+
+ const auto a00 = (0 <= offset && offset < in_dim_w && 0 <= in_hi && in_hi < in_dim_h) ? *in_ptr : const_border_value;
+ const auto a01 = (-1 <= offset && offset < in_dim_w - 1 && 0 <= in_hi && in_hi < in_dim_h) ? *(in_ptr + in_stride_c) : const_border_value;
+ const auto a10 = (0 <= offset && offset < in_dim_w && -1 <= in_hi && in_hi < in_dim_h - 1) ? *(in_ptr + in_stride_wc) : const_border_value;
+ const auto a11 = (-1 <= offset && offset < in_dim_w - 1 && -1 <= in_hi && in_hi < in_dim_h - 1) ? *(in_ptr + in_stride_c + in_stride_wc) : const_border_value;
+
+ *reinterpret_cast<float16_t *>(out.ptr()) = static_cast<float16_t>(scale_helpers::delta_bilinear(a00, a01, a10, a11, dx_val, dy_val));
+ },
+ in, out);
+ }
+ else if(border_mode == BorderMode::REPLICATE)
+ {
+ execute_window_loop(window, [&](const Coordinates & id)
+ {
+ const auto offset = *reinterpret_cast<const int32_t *>(offsets->ptr_to_element(Coordinates(id.y(), id.z())));
+ const auto dx_val = *reinterpret_cast<const float *>(dx->ptr_to_element(Coordinates(id.y(), id.z())));
+ const auto dy_val = *reinterpret_cast<const float *>(dy->ptr_to_element(Coordinates(id.y(), id.z())));
+ const int in_hi = std::floor((id.z() + sampling_offset) * hr - sampling_offset);
+
+ auto clamped_w = utility::clamp<int>(offset, 0, in_dim_w - 1);
+ auto clamped_w1 = utility::clamp<int>(offset + 1, 0, in_dim_w - 1);
+ auto clamped_h = utility::clamp<int>(in_hi, 0, in_dim_h - 1);
+ auto clamped_h1 = utility::clamp<int>(in_hi + 1, 0, in_dim_h - 1);
+
+ const auto a00 = *(reinterpret_cast<const float16_t *>(in.ptr()) + clamped_w * in_stride_c + clamped_h * in_stride_wc);
+ const auto a01 = *(reinterpret_cast<const float16_t *>(in.ptr()) + clamped_w1 * in_stride_c + clamped_h * in_stride_wc);
+ const auto a10 = *(reinterpret_cast<const float16_t *>(in.ptr()) + clamped_w * in_stride_c + clamped_h1 * in_stride_wc);
+ const auto a11 = *(reinterpret_cast<const float16_t *>(in.ptr()) + clamped_w1 * in_stride_c + clamped_h1 * in_stride_wc);
+
+ *reinterpret_cast<float16_t *>(out.ptr()) = static_cast<float16_t>(scale_helpers::delta_bilinear(a00, a01, a10, a11, dx_val, dy_val));
+ },
+ in, out);
+ }
+ else
+ {
+ ARM_COMPUTE_ERROR("Not implemented");
+ }
+}
+}
+namespace cpu
+{
+void fp16_neon_scale(const ITensor *src, ITensor *dst, const ITensor *offsets, const ITensor *dx, const ITensor *dy,
+ InterpolationPolicy policy, BorderMode border_mode, PixelValue constant_border_value, float sampling_offset,
+ bool align_corners, const Window &window)
+{
+ if(policy == InterpolationPolicy::BILINEAR)
+ {
+ fp16_neon_scale_bilinear(src, dst, offsets, dx, dy, border_mode, constant_border_value, sampling_offset, align_corners, window);
+ }
+ else if(policy == InterpolationPolicy::NEAREST_NEIGHBOR)
+ {
+ fp16_neon_scale_nearest(src, dst, offsets, sampling_offset, align_corners, window);
+ }
+}
+} // namespace cpu
+} // namespace arm_compute
+
+#endif /* defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(ENABLE_FP16_KERNELS) */ \ No newline at end of file
diff --git a/src/core/NEON/kernels/scale/impl/NEON/integer.cpp b/src/core/NEON/kernels/scale/impl/NEON/integer.cpp
new file mode 100644
index 0000000000..a2359aac94
--- /dev/null
+++ b/src/core/NEON/kernels/scale/impl/NEON/integer.cpp
@@ -0,0 +1,293 @@
+/*
+ * 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 "arm_compute/core/Helpers.h"
+#include "arm_compute/core/ITensorPack.h"
+#include "arm_compute/core/Window.h"
+#include "src/core/NEON/NEMath.h"
+#include "src/core/NEON/wrapper/wrapper.h"
+#include "src/core/helpers/ScaleHelpers.h"
+#include "src/core/utils/ScaleUtils.h"
+#include "support/Rounding.h"
+
+#include <arm_neon.h>
+#include <cmath>
+#include <cstddef>
+
+namespace arm_compute
+{
+namespace
+{
+void u8_neon_scale_nearest(const ITensor *src, ITensor *dst, const ITensor *offsets,
+ float sampling_offset, bool align_corners, const Window &window)
+{
+ const size_t in_stride_c = src->info()->dimension(0) + src->info()->padding().left + src->info()->padding().right;
+ const size_t in_stride_w = src->info()->dimension(1) + src->info()->padding().top + src->info()->padding().bottom;
+ const size_t in_stride_wc = in_stride_w * in_stride_c;
+ const size_t in_dim_h = src->info()->dimension(2);
+
+ // Compute the ratio between source height and destination height
+ const auto hr = scale_utils::calculate_resize_ratio(in_dim_h, dst->info()->dimension(2), align_corners);
+ const auto window_start_x = static_cast<int32_t>(window.x().start());
+ const auto window_end_x = static_cast<int32_t>(window.x().end());
+ const int window_step_x = 16;
+
+ Window win(window);
+ win.set(Window::DimX, Window::Dimension(0, 1, 1));
+ Iterator out(dst, win);
+
+ const uint8_t *in_ptr_start = src->buffer() + src->info()->offset_first_element_in_bytes();
+ const unsigned int in_stride_bytes_hwc = src->info()->strides_in_bytes()[3];
+
+ execute_window_loop(win, [&](const Coordinates & id)
+ {
+ const int32_t offset = *reinterpret_cast<const int32_t *>(offsets->ptr_to_element(Coordinates(id.y(), id.z()))) * in_stride_c;
+ const auto in_hi = static_cast<int>(align_corners ? utils::rounding::round_half_away_from_zero((id.z() + sampling_offset) * hr) : std::floor((id.z() + sampling_offset) * hr));
+ const int offset_row = in_hi * in_stride_wc;
+ int32_t x = window_start_x;
+ const uint8_t *in_ptr = reinterpret_cast<const uint8_t *>(in_ptr_start + in_stride_bytes_hwc * id[3]);
+
+ for(; x <= window_end_x - window_step_x; x += window_step_x)
+ {
+ wrapper::vstore(reinterpret_cast<uint8_t *>(out.ptr()) + x,
+ wrapper::vloadq(in_ptr + offset + offset_row + x));
+ }
+ for(; x < window_end_x; ++x)
+ {
+ *(reinterpret_cast<uint8_t *>(out.ptr()) + x) = *(in_ptr + offset + offset_row + x);
+ }
+ },
+ out);
+}
+
+void u8_neon_scale_bilinear(const ITensor *src, ITensor *dst, const ITensor *offsets, const ITensor *dx, const ITensor *dy,
+ BorderMode border_mode, PixelValue constant_border_value, float sampling_offset,
+ bool align_corners, const Window &window)
+{
+ // Compute the ratio between source height and destination height
+ const auto hr = scale_utils::calculate_resize_ratio(src->info()->dimension(2), dst->info()->dimension(2), align_corners);
+
+ Iterator out(dst, window);
+ const int in_stride_c = src->info()->dimension(0) + src->info()->padding().left + src->info()->padding().right;
+ const int in_dim_w = src->info()->dimension(1);
+ const int in_dim_h = src->info()->dimension(2);
+ const int in_stride_wc = in_stride_c * (in_dim_w + src->info()->padding().top + src->info()->padding().bottom);
+
+ // Don't increment in Y and Z direction for the input tensor
+ // A pointer to the start of this plane is needed as base for the precomputed offsets
+ Window win_in(window);
+ win_in.set(Window::DimY, Window::Dimension(0, 0, 0));
+ win_in.set(Window::DimZ, Window::Dimension(0, 0, 0));
+ Iterator in(src, win_in);
+
+ if(border_mode == BorderMode::CONSTANT)
+ {
+ const uint8_t const_border_value = static_cast<uint8_t>(constant_border_value.get<uint8_t>());
+ execute_window_loop(window, [&](const Coordinates & id)
+ {
+ const auto offset = *reinterpret_cast<const int32_t *>(offsets->ptr_to_element(Coordinates(id.y(), id.z())));
+ const auto dx_val = *reinterpret_cast<const float *>(dx->ptr_to_element(Coordinates(id.y(), id.z())));
+ const auto dy_val = *reinterpret_cast<const float *>(dy->ptr_to_element(Coordinates(id.y(), id.z())));
+ const int32_t in_hi = std::floor((id.z() + sampling_offset) * hr - sampling_offset);
+ const uint8_t *in_ptr = reinterpret_cast<const uint8_t *>(in.ptr()) + offset * in_stride_c + in_hi * in_stride_wc;
+
+ const auto a00 = (0 <= offset && offset < in_dim_w && 0 <= in_hi && in_hi < in_dim_h) ? *in_ptr : const_border_value;
+ const auto a01 = (-1 <= offset && offset < in_dim_w - 1 && 0 <= in_hi && in_hi < in_dim_h) ? *(in_ptr + in_stride_c) : const_border_value;
+ const auto a10 = (0 <= offset && offset < in_dim_w && -1 <= in_hi && in_hi < in_dim_h - 1) ? *(in_ptr + in_stride_wc) : const_border_value;
+ const auto a11 = (-1 <= offset && offset < in_dim_w - 1 && -1 <= in_hi && in_hi < in_dim_h - 1) ? *(in_ptr + in_stride_c + in_stride_wc) : const_border_value;
+
+ *reinterpret_cast<uint8_t *>(out.ptr()) = static_cast<uint8_t>(scale_helpers::delta_bilinear(a00, a01, a10, a11, dx_val, dy_val));
+ },
+ in, out);
+ }
+ else if(border_mode == BorderMode::REPLICATE)
+ {
+ execute_window_loop(window, [&](const Coordinates & id)
+ {
+ const auto offset = *reinterpret_cast<const int32_t *>(offsets->ptr_to_element(Coordinates(id.y(), id.z())));
+ const auto dx_val = *reinterpret_cast<const float *>(dx->ptr_to_element(Coordinates(id.y(), id.z())));
+ const auto dy_val = *reinterpret_cast<const float *>(dy->ptr_to_element(Coordinates(id.y(), id.z())));
+ const int in_hi = std::floor((id.z() + sampling_offset) * hr - sampling_offset);
+
+ auto clamped_w = utility::clamp<int>(offset, 0, in_dim_w - 1);
+ auto clamped_w1 = utility::clamp<int>(offset + 1, 0, in_dim_w - 1);
+ auto clamped_h = utility::clamp<int>(in_hi, 0, in_dim_h - 1);
+ auto clamped_h1 = utility::clamp<int>(in_hi + 1, 0, in_dim_h - 1);
+
+ const auto a00 = *(reinterpret_cast<const uint8_t *>(in.ptr()) + clamped_w * in_stride_c + clamped_h * in_stride_wc);
+ const auto a01 = *(reinterpret_cast<const uint8_t *>(in.ptr()) + clamped_w1 * in_stride_c + clamped_h * in_stride_wc);
+ const auto a10 = *(reinterpret_cast<const uint8_t *>(in.ptr()) + clamped_w * in_stride_c + clamped_h1 * in_stride_wc);
+ const auto a11 = *(reinterpret_cast<const uint8_t *>(in.ptr()) + clamped_w1 * in_stride_c + clamped_h1 * in_stride_wc);
+
+ *reinterpret_cast<uint8_t *>(out.ptr()) = static_cast<uint8_t>(scale_helpers::delta_bilinear(a00, a01, a10, a11, dx_val, dy_val));
+ },
+ in, out);
+ }
+ else
+ {
+ ARM_COMPUTE_ERROR("Not implemented");
+ }
+}
+
+void s16_neon_scale_nearest(const ITensor *src, ITensor *dst, const ITensor *offsets,
+ float sampling_offset, bool align_corners, const Window &window)
+{
+ const size_t in_stride_c = src->info()->dimension(0) + src->info()->padding().left + src->info()->padding().right;
+ const size_t in_stride_w = src->info()->dimension(1) + src->info()->padding().top + src->info()->padding().bottom;
+ const size_t in_stride_wc = in_stride_w * in_stride_c;
+ const size_t in_dim_h = src->info()->dimension(2);
+
+ // Compute the ratio between source height and destination height
+ const auto hr = scale_utils::calculate_resize_ratio(in_dim_h, dst->info()->dimension(2), align_corners);
+ const auto window_start_x = static_cast<int32_t>(window.x().start());
+ const auto window_end_x = static_cast<int32_t>(window.x().end());
+ const int window_step_x = 8;
+
+ Window win(window);
+ win.set(Window::DimX, Window::Dimension(0, 1, 1));
+ Iterator out(dst, win);
+
+ const uint8_t *in_ptr_start = src->buffer() + src->info()->offset_first_element_in_bytes();
+ const unsigned int in_stride_bytes_hwc = src->info()->strides_in_bytes()[3];
+
+ execute_window_loop(win, [&](const Coordinates & id)
+ {
+ const int32_t offset = *reinterpret_cast<const int32_t *>(offsets->ptr_to_element(Coordinates(id.y(), id.z()))) * in_stride_c;
+ const auto in_hi = static_cast<int>(align_corners ? utils::rounding::round_half_away_from_zero((id.z() + sampling_offset) * hr) : std::floor((id.z() + sampling_offset) * hr));
+ const int offset_row = in_hi * in_stride_wc;
+ int32_t x = window_start_x;
+ const int16_t *in_ptr = reinterpret_cast<const int16_t *>(in_ptr_start + in_stride_bytes_hwc * id[3]);
+
+ for(; x <= window_end_x - window_step_x; x += window_step_x)
+ {
+ wrapper::vstore(reinterpret_cast<int16_t *>(out.ptr()) + x,
+ wrapper::vloadq(in_ptr + offset + offset_row + x));
+ }
+ for(; x < window_end_x; ++x)
+ {
+ *(reinterpret_cast<int16_t *>(out.ptr()) + x) = *(in_ptr + offset + offset_row + x);
+ }
+ },
+ out);
+}
+
+void s16_neon_scale_bilinear(const ITensor *src, ITensor *dst, const ITensor *offsets, const ITensor *dx, const ITensor *dy,
+ BorderMode border_mode, PixelValue constant_border_value, float sampling_offset,
+ bool align_corners, const Window &window)
+{
+ // Compute the ratio between source height and destination height
+ const auto hr = scale_utils::calculate_resize_ratio(src->info()->dimension(2), dst->info()->dimension(2), align_corners);
+
+ Iterator out(dst, window);
+ const int in_stride_c = src->info()->dimension(0) + src->info()->padding().left + src->info()->padding().right;
+ const int in_dim_w = src->info()->dimension(1);
+ const int in_dim_h = src->info()->dimension(2);
+ const int in_stride_wc = in_stride_c * (in_dim_w + src->info()->padding().top + src->info()->padding().bottom);
+
+ // Don't increment in Y and Z direction for the input tensor
+ // A pointer to the start of this plane is needed as base for the precomputed offsets
+ Window win_in(window);
+ win_in.set(Window::DimY, Window::Dimension(0, 0, 0));
+ win_in.set(Window::DimZ, Window::Dimension(0, 0, 0));
+ Iterator in(src, win_in);
+
+ if(border_mode == BorderMode::CONSTANT)
+ {
+ const int16_t const_border_value = static_cast<int16_t>(constant_border_value.get<int16_t>());
+ execute_window_loop(window, [&](const Coordinates & id)
+ {
+ const auto offset = *reinterpret_cast<const int32_t *>(offsets->ptr_to_element(Coordinates(id.y(), id.z())));
+ const auto dx_val = *reinterpret_cast<const float *>(dx->ptr_to_element(Coordinates(id.y(), id.z())));
+ const auto dy_val = *reinterpret_cast<const float *>(dy->ptr_to_element(Coordinates(id.y(), id.z())));
+ const int32_t in_hi = std::floor((id.z() + sampling_offset) * hr - sampling_offset);
+ const int16_t *in_ptr = reinterpret_cast<const int16_t *>(in.ptr()) + offset * in_stride_c + in_hi * in_stride_wc;
+
+ const auto a00 = (0 <= offset && offset < in_dim_w && 0 <= in_hi && in_hi < in_dim_h) ? *in_ptr : const_border_value;
+ const auto a01 = (-1 <= offset && offset < in_dim_w - 1 && 0 <= in_hi && in_hi < in_dim_h) ? *(in_ptr + in_stride_c) : const_border_value;
+ const auto a10 = (0 <= offset && offset < in_dim_w && -1 <= in_hi && in_hi < in_dim_h - 1) ? *(in_ptr + in_stride_wc) : const_border_value;
+ const auto a11 = (-1 <= offset && offset < in_dim_w - 1 && -1 <= in_hi && in_hi < in_dim_h - 1) ? *(in_ptr + in_stride_c + in_stride_wc) : const_border_value;
+
+ *reinterpret_cast<int16_t *>(out.ptr()) = static_cast<int16_t>(scale_helpers::delta_bilinear(a00, a01, a10, a11, dx_val, dy_val));
+ },
+ in, out);
+ }
+ else if(border_mode == BorderMode::REPLICATE)
+ {
+ execute_window_loop(window, [&](const Coordinates & id)
+ {
+ const auto offset = *reinterpret_cast<const int32_t *>(offsets->ptr_to_element(Coordinates(id.y(), id.z())));
+ const auto dx_val = *reinterpret_cast<const float *>(dx->ptr_to_element(Coordinates(id.y(), id.z())));
+ const auto dy_val = *reinterpret_cast<const float *>(dy->ptr_to_element(Coordinates(id.y(), id.z())));
+ const int in_hi = std::floor((id.z() + sampling_offset) * hr - sampling_offset);
+
+ auto clamped_w = utility::clamp<int>(offset, 0, in_dim_w - 1);
+ auto clamped_w1 = utility::clamp<int>(offset + 1, 0, in_dim_w - 1);
+ auto clamped_h = utility::clamp<int>(in_hi, 0, in_dim_h - 1);
+ auto clamped_h1 = utility::clamp<int>(in_hi + 1, 0, in_dim_h - 1);
+
+ const auto a00 = *(reinterpret_cast<const int16_t *>(in.ptr()) + clamped_w * in_stride_c + clamped_h * in_stride_wc);
+ const auto a01 = *(reinterpret_cast<const int16_t *>(in.ptr()) + clamped_w1 * in_stride_c + clamped_h * in_stride_wc);
+ const auto a10 = *(reinterpret_cast<const int16_t *>(in.ptr()) + clamped_w * in_stride_c + clamped_h1 * in_stride_wc);
+ const auto a11 = *(reinterpret_cast<const int16_t *>(in.ptr()) + clamped_w1 * in_stride_c + clamped_h1 * in_stride_wc);
+
+ *reinterpret_cast<int16_t *>(out.ptr()) = static_cast<int16_t>(scale_helpers::delta_bilinear(a00, a01, a10, a11, dx_val, dy_val));
+ },
+ in, out);
+ }
+ else
+ {
+ ARM_COMPUTE_ERROR("Not implemented");
+ }
+}
+}
+namespace cpu
+{
+void u8_neon_scale(const ITensor *src, ITensor *dst, const ITensor *offsets, const ITensor *dx, const ITensor *dy,
+ InterpolationPolicy policy, BorderMode border_mode, PixelValue constant_border_value, float sampling_offset,
+ bool align_corners, const Window &window)
+{
+ if(policy == InterpolationPolicy::BILINEAR)
+ {
+ u8_neon_scale_bilinear(src, dst, offsets, dx, dy, border_mode, constant_border_value, sampling_offset, align_corners, window);
+ }
+ else if(policy == InterpolationPolicy::NEAREST_NEIGHBOR)
+ {
+ u8_neon_scale_nearest(src, dst, offsets, sampling_offset, align_corners, window);
+ }
+}
+
+void s16_neon_scale(const ITensor *src, ITensor *dst, const ITensor *offsets, const ITensor *dx, const ITensor *dy,
+ InterpolationPolicy policy, BorderMode border_mode, PixelValue constant_border_value, float sampling_offset,
+ bool align_corners, const Window &window)
+{
+ if(policy == InterpolationPolicy::BILINEAR)
+ {
+ s16_neon_scale_bilinear(src, dst, offsets, dx, dy, border_mode, constant_border_value, sampling_offset, align_corners, window);
+ }
+ else if(policy == InterpolationPolicy::NEAREST_NEIGHBOR)
+ {
+ s16_neon_scale_nearest(src, dst, offsets, sampling_offset, align_corners, window);
+ }
+}
+} // namespace cpu
+} // namespace arm_compute \ No newline at end of file
diff --git a/src/core/NEON/kernels/scale/impl/NEON/list.h b/src/core/NEON/kernels/scale/impl/NEON/list.h
index 11cac26071..c91242f5b2 100644
--- a/src/core/NEON/kernels/scale/impl/NEON/list.h
+++ b/src/core/NEON/kernels/scale/impl/NEON/list.h
@@ -29,7 +29,6 @@
#include "arm_compute/core/Window.h"
#include "src/core/NEON/NEMath.h"
#include "src/core/NEON/wrapper/wrapper.h"
-#include "src/core/common/Validate.h"
#include "src/core/helpers/ScaleHelpers.h"
#include "src/core/utils/ScaleUtils.h"
#include "support/Rounding.h"
diff --git a/src/core/NEON/kernels/scale/impl/NEON/qasymm8_signed.cpp b/src/core/NEON/kernels/scale/impl/NEON/qasymm8_signed.cpp
index 7b1860802f..149cdf478f 100644
--- a/src/core/NEON/kernels/scale/impl/NEON/qasymm8_signed.cpp
+++ b/src/core/NEON/kernels/scale/impl/NEON/qasymm8_signed.cpp
@@ -21,7 +21,6 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-
#include "src/core/NEON/kernels/scale/impl/NEON/list.h"
namespace arm_compute
diff --git a/src/core/NEON/kernels/scale/impl/SVE/fp16.cpp b/src/core/NEON/kernels/scale/impl/SVE/fp16.cpp
index 91c3dc3b4e..99f08dbdf9 100644
--- a/src/core/NEON/kernels/scale/impl/SVE/fp16.cpp
+++ b/src/core/NEON/kernels/scale/impl/SVE/fp16.cpp
@@ -26,7 +26,6 @@
#include "arm_compute/core/Window.h"
#include "src/core/NEON/NEMath.h"
#include "src/core/NEON/wrapper/wrapper.h"
-#include "src/core/common/Validate.h"
#include "src/core/helpers/ScaleHelpers.h"
#include "src/core/utils/ScaleUtils.h"
#include "support/Rounding.h"
diff --git a/src/core/NEON/kernels/scale/impl/SVE/fp32.cpp b/src/core/NEON/kernels/scale/impl/SVE/fp32.cpp
index abb4faa6c5..94055ae953 100644
--- a/src/core/NEON/kernels/scale/impl/SVE/fp32.cpp
+++ b/src/core/NEON/kernels/scale/impl/SVE/fp32.cpp
@@ -26,7 +26,6 @@
#include "arm_compute/core/Window.h"
#include "src/core/NEON/NEMath.h"
#include "src/core/NEON/wrapper/wrapper.h"
-#include "src/core/common/Validate.h"
#include "src/core/helpers/ScaleHelpers.h"
#include "src/core/utils/ScaleUtils.h"
#include "support/Rounding.h"
diff --git a/src/core/NEON/kernels/scale/impl/SVE/integer.cpp b/src/core/NEON/kernels/scale/impl/SVE/integer.cpp
index 5f5263c5d3..2a724ece31 100644
--- a/src/core/NEON/kernels/scale/impl/SVE/integer.cpp
+++ b/src/core/NEON/kernels/scale/impl/SVE/integer.cpp
@@ -26,7 +26,6 @@
#include "arm_compute/core/Window.h"
#include "src/core/NEON/NEMath.h"
#include "src/core/NEON/wrapper/wrapper.h"
-#include "src/core/common/Validate.h"
#include "src/core/helpers/ScaleHelpers.h"
#include "src/core/utils/ScaleUtils.h"
#include "support/Rounding.h"
diff --git a/src/core/NEON/kernels/scale/impl/SVE/qasymm8.cpp b/src/core/NEON/kernels/scale/impl/SVE/qasymm8.cpp
index fc65ff44f0..c475ad615c 100644
--- a/src/core/NEON/kernels/scale/impl/SVE/qasymm8.cpp
+++ b/src/core/NEON/kernels/scale/impl/SVE/qasymm8.cpp
@@ -26,7 +26,6 @@
#include "arm_compute/core/Window.h"
#include "src/core/NEON/NEMath.h"
#include "src/core/NEON/wrapper/wrapper.h"
-#include "src/core/common/Validate.h"
#include "src/core/helpers/ScaleHelpers.h"
#include "src/core/helpers/ScaleHelpers.h"
#include "src/core/utils/ScaleUtils.h"
diff --git a/src/core/NEON/kernels/scale/impl/SVE/qasymm8_signed.cpp b/src/core/NEON/kernels/scale/impl/SVE/qasymm8_signed.cpp
index 676ca94fb0..b39b75abba 100644
--- a/src/core/NEON/kernels/scale/impl/SVE/qasymm8_signed.cpp
+++ b/src/core/NEON/kernels/scale/impl/SVE/qasymm8_signed.cpp
@@ -26,7 +26,6 @@
#include "arm_compute/core/Window.h"
#include "src/core/NEON/NEMath.h"
#include "src/core/NEON/wrapper/wrapper.h"
-#include "src/core/common/Validate.h"
#include "src/core/helpers/ScaleHelpers.h"
#include "src/core/helpers/ScaleHelpers.h"
#include "src/core/utils/ScaleUtils.h"
diff --git a/src/core/cpu/kernels/activation/NEON/fp16.cpp b/src/core/cpu/kernels/activation/NEON/fp16.cpp
index 7fe4ab3f63..0ddd43ea0e 100644
--- a/src/core/cpu/kernels/activation/NEON/fp16.cpp
+++ b/src/core/cpu/kernels/activation/NEON/fp16.cpp
@@ -26,7 +26,6 @@
#include "arm_compute/core/Helpers.h"
#include "arm_compute/core/Validate.h"
#include "src/core/NEON/wrapper/wrapper.h"
-#include "src/core/common/Validate.h"
#include <arm_neon.h>
#include <cmath>
diff --git a/src/core/cpu/kernels/activation/NEON/fp32.cpp b/src/core/cpu/kernels/activation/NEON/fp32.cpp
index f1f2753813..244ca5739f 100644
--- a/src/core/cpu/kernels/activation/NEON/fp32.cpp
+++ b/src/core/cpu/kernels/activation/NEON/fp32.cpp
@@ -26,7 +26,6 @@
#include "arm_compute/core/Window.h"
#include "src/core/NEON/NEMath.h"
#include "src/core/NEON/wrapper/wrapper.h"
-#include "src/core/common/Validate.h"
#include <arm_neon.h>
#include <cmath>
diff --git a/src/core/cpu/kernels/activation/NEON/qasymm8.cpp b/src/core/cpu/kernels/activation/NEON/qasymm8.cpp
index 7506a8294f..a1217435b6 100644
--- a/src/core/cpu/kernels/activation/NEON/qasymm8.cpp
+++ b/src/core/cpu/kernels/activation/NEON/qasymm8.cpp
@@ -27,7 +27,6 @@
#include "src/core/NEON/NEAsymm.h"
#include "src/core/NEON/NEMath.h"
#include "src/core/NEON/wrapper/wrapper.h"
-#include "src/core/common/Validate.h"
#include <arm_neon.h>
#include <cmath>
diff --git a/src/core/cpu/kernels/activation/NEON/qasymm8_signed.cpp b/src/core/cpu/kernels/activation/NEON/qasymm8_signed.cpp
index 8f75abea8e..8b40bf8e72 100644
--- a/src/core/cpu/kernels/activation/NEON/qasymm8_signed.cpp
+++ b/src/core/cpu/kernels/activation/NEON/qasymm8_signed.cpp
@@ -26,7 +26,6 @@
#include "src/core/NEON/NEAsymm.h"
#include "src/core/NEON/NEMath.h"
#include "src/core/NEON/wrapper/wrapper.h"
-#include "src/core/common/Validate.h"
#include <arm_neon.h>
#include <cmath>
diff --git a/src/core/cpu/kernels/activation/NEON/qsymm16.cpp b/src/core/cpu/kernels/activation/NEON/qsymm16.cpp
index 9eee360427..54b41820f2 100644
--- a/src/core/cpu/kernels/activation/NEON/qsymm16.cpp
+++ b/src/core/cpu/kernels/activation/NEON/qsymm16.cpp
@@ -28,7 +28,6 @@
#include "src/core/NEON/NEMath.h"
#include "src/core/NEON/NESymm.h"
#include "src/core/NEON/wrapper/wrapper.h"
-#include "src/core/common/Validate.h"
#include <arm_neon.h>
#include <cmath>
diff --git a/src/core/cpu/kernels/activation/SVE/fp16.cpp b/src/core/cpu/kernels/activation/SVE/fp16.cpp
index 8208813cd3..bf31fd7d93 100644
--- a/src/core/cpu/kernels/activation/SVE/fp16.cpp
+++ b/src/core/cpu/kernels/activation/SVE/fp16.cpp
@@ -24,7 +24,6 @@
#include "arm_compute/core/Helpers.h"
#include "arm_compute/core/ITensorPack.h"
#include "arm_compute/core/Window.h"
-#include "src/core/common/Validate.h"
#include <cmath>
#include <cstddef>
diff --git a/src/core/cpu/kernels/activation/SVE/fp32.cpp b/src/core/cpu/kernels/activation/SVE/fp32.cpp
index 55bdc9999e..75f9f8a4c3 100644
--- a/src/core/cpu/kernels/activation/SVE/fp32.cpp
+++ b/src/core/cpu/kernels/activation/SVE/fp32.cpp
@@ -25,7 +25,6 @@
#include "arm_compute/core/ITensorPack.h"
#include "arm_compute/core/Window.h"
#include "src/core/NEON/SVEMath.h"
-#include "src/core/common/Validate.h"
#include <cmath>
#include <cstddef>
diff --git a/src/core/cpu/kernels/activation/SVE/qasymm8.cpp b/src/core/cpu/kernels/activation/SVE/qasymm8.cpp
index 3d9476ac56..228b4ae530 100644
--- a/src/core/cpu/kernels/activation/SVE/qasymm8.cpp
+++ b/src/core/cpu/kernels/activation/SVE/qasymm8.cpp
@@ -24,7 +24,6 @@
#include "arm_compute/core/Helpers.h"
#include "arm_compute/core/Window.h"
-#include "src/core/common/Validate.h"
#include <cmath>
#include <cstddef>
diff --git a/src/core/cpu/kernels/activation/SVE/qasymm8_signed.cpp b/src/core/cpu/kernels/activation/SVE/qasymm8_signed.cpp
index 0b3d798942..989f825eb9 100644
--- a/src/core/cpu/kernels/activation/SVE/qasymm8_signed.cpp
+++ b/src/core/cpu/kernels/activation/SVE/qasymm8_signed.cpp
@@ -24,7 +24,6 @@
#include "arm_compute/core/Helpers.h"
#include "arm_compute/core/Window.h"
#include "src/core/NEON/wrapper/wrapper.h"
-#include "src/core/common/Validate.h"
#include <cmath>
#include <cstddef>
diff --git a/src/core/cpu/kernels/activation/SVE/qsymm16.cpp b/src/core/cpu/kernels/activation/SVE/qsymm16.cpp
index dbaf267bf9..66974875da 100644
--- a/src/core/cpu/kernels/activation/SVE/qsymm16.cpp
+++ b/src/core/cpu/kernels/activation/SVE/qsymm16.cpp
@@ -25,7 +25,6 @@
#include "arm_compute/core/ITensorPack.h"
#include "arm_compute/core/Window.h"
#include "arm_compute/core/experimental/Types.h"
-#include "src/core/common/Validate.h"
#include <cmath>
#include <cstddef>
diff --git a/src/core/cpu/kernels/floor/NEON/fp16.cpp b/src/core/cpu/kernels/floor/NEON/fp16.cpp
index 0d31eb77f8..f362676a36 100644
--- a/src/core/cpu/kernels/floor/NEON/fp16.cpp
+++ b/src/core/cpu/kernels/floor/NEON/fp16.cpp
@@ -23,8 +23,8 @@
*/
#if defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(ENABLE_FP16_KERNELS)
+#include "src/common/utils/Validate.h"
#include "src/core/NEON/NEMath.h"
-#include "src/core/common/Validate.h"
#include <arm_neon.h>
#include <cmath>
diff --git a/src/core/cpu/kernels/floor/NEON/fp32.cpp b/src/core/cpu/kernels/floor/NEON/fp32.cpp
index dd63f9f9d7..f5efb2e849 100644
--- a/src/core/cpu/kernels/floor/NEON/fp32.cpp
+++ b/src/core/cpu/kernels/floor/NEON/fp32.cpp
@@ -21,8 +21,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+#include "src/common/utils/Validate.h"
#include "src/core/NEON/NEMath.h"
-#include "src/core/common/Validate.h"
#include <arm_neon.h>
#include <cmath>
diff --git a/src/core/gpu/cl/kernels/ClElementwiseKernel.cpp b/src/core/gpu/cl/kernels/ClElementwiseKernel.cpp
index 7d204b1348..8f12eb2215 100644
--- a/src/core/gpu/cl/kernels/ClElementwiseKernel.cpp
+++ b/src/core/gpu/cl/kernels/ClElementwiseKernel.cpp
@@ -25,8 +25,8 @@
#include "arm_compute/core/CL/CLHelpers.h"
#include "arm_compute/core/CL/ICLTensor.h"
+#include "src/common/utils/Validate.h"
#include "src/core/CL/CLValidate.h"
-#include "src/core/common/Validate.h"
#include "src/core/helpers/AutoConfiguration.h"
#include "src/core/helpers/WindowHelpers.h"
#include "support/Cast.h"
diff --git a/src/cpu/CpuContext.cpp b/src/cpu/CpuContext.cpp
new file mode 100644
index 0000000000..5980a5ab0d
--- /dev/null
+++ b/src/cpu/CpuContext.cpp
@@ -0,0 +1,182 @@
+/*
+ * 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/cpu/CpuContext.h"
+
+#include "arm_compute/core/CPP/CPPTypes.h"
+#include "src/runtime/CPUUtils.h"
+
+#include <cstdlib>
+
+namespace arm_compute
+{
+namespace cpu
+{
+namespace
+{
+void *default_allocate(void *user_data, size_t size)
+{
+ ARM_COMPUTE_UNUSED(user_data);
+ return ::operator new(size);
+}
+void default_free(void *user_data, void *ptr)
+{
+ ARM_COMPUTE_UNUSED(user_data);
+ ::operator delete(ptr);
+}
+void *default_aligned_allocate(void *user_data, size_t size, size_t alignment)
+{
+ ARM_COMPUTE_UNUSED(user_data);
+ void *ptr = nullptr;
+#if defined(BARE_METAL) || defined(__APPLE__)
+ size_t rem = size % alignment;
+ size_t real_size = (rem) ? (size + alignment - rem) : size;
+ ptr = aligned_alloc(alignment, real_size);
+#else /* defined(BARE_METAL) || defined(__APPLE__) */
+ posix_memalign(&ptr, alignment, size);
+#endif /* defined(BARE_METAL) || defined(__APPLE__) */
+ return ptr;
+}
+void default_aligned_free(void *user_data, void *ptr)
+{
+ ARM_COMPUTE_UNUSED(user_data);
+ free(ptr);
+}
+static AclAllocator default_allocator = { &default_allocate,
+ &default_free,
+ &default_aligned_allocate,
+ &default_aligned_free,
+ nullptr
+ };
+
+AllocatorWrapper populate_allocator(AclAllocator *external_allocator)
+{
+ bool is_valid = (external_allocator != nullptr);
+ if(is_valid)
+ {
+ is_valid = is_valid && (external_allocator->alloc != nullptr);
+ is_valid = is_valid && (external_allocator->free != nullptr);
+ is_valid = is_valid && (external_allocator->aligned_alloc != nullptr);
+ is_valid = is_valid && (external_allocator->aligned_free != nullptr);
+ }
+ return is_valid ? AllocatorWrapper(*external_allocator) : AllocatorWrapper(default_allocator);
+}
+
+CpuCapabilities populate_capabilities_legacy(const CPUInfo &cpu_info)
+{
+ CpuCapabilities caps;
+
+ // Extract SIMD extension
+ caps.neon = true;
+#ifdef SVE2
+ caps.sve2 = true;
+#endif /* SVE2 */
+ // Extract data-type support
+ caps.fp16 = cpu_info.has_fp16();
+#ifdef V8P6_BF
+ caps.bf16 = true;
+#endif /* V8P6_BF */
+
+ // Extract ISA extensions
+ caps.dot = cpu_info.has_dotprod();
+#ifdef MMLA_FP32
+ caps.mmla_fp = true;
+#endif /* MMLA_FP32 */
+#ifdef MMLA_INT8
+ caps.mmla_int8 = true;
+#endif /* MMLA_INT8 */
+
+ return caps;
+}
+
+CpuCapabilities populate_capabilities_flags(AclTargetCapabilities external_caps)
+{
+ CpuCapabilities caps;
+
+ // Extract SIMD extension
+ caps.neon = external_caps & AclCpuCapabilitiesNeon;
+ caps.sve = external_caps & AclCpuCapabilitiesSve;
+ caps.sve2 = external_caps & AclCpuCapabilitiesSve2;
+ // Extract data-type support
+ caps.fp16 = external_caps & AclCpuCapabilitiesFp16;
+ caps.bf16 = external_caps & AclCpuCapabilitiesBf16;
+ // Extract ISA extensions
+ caps.dot = external_caps & AclCpuCapabilitiesDot;
+ caps.mmla_fp = external_caps & AclCpuCapabilitiesMmlaFp;
+ caps.mmla_int8 = external_caps & AclCpuCapabilitiesMmlaInt8;
+
+ return caps;
+}
+
+CpuCapabilities populate_capabilities(AclTargetCapabilities external_caps,
+ int32_t max_threads)
+{
+ // Extract legacy structure
+ CPUInfo cpu_info;
+ arm_compute::utils::cpu::get_cpu_configuration(cpu_info);
+
+ CpuCapabilities caps;
+ if(external_caps != AclCpuCapabilitiesAuto)
+ {
+ caps = populate_capabilities_flags(external_caps);
+ }
+ else
+ {
+ caps = populate_capabilities_legacy(cpu_info);
+ }
+
+ // Set max number of threads
+#if defined(BARE_METAL)
+ ARM_COMPUTE_UNUSED(max_threads);
+ caps.max_threads = 1;
+#else /* defined(BARE_METAL) */
+ caps.max_threads = (max_threads > 0) ? max_threads : std::thread::hardware_concurrency();
+#endif /* defined(BARE_METAL) */
+
+ return caps;
+}
+} // namespace
+
+CpuContext::CpuContext(const AclContextOptions *options)
+ : IContext(Target::Cpu),
+ _allocator(default_allocator),
+ _caps(populate_capabilities(AclCpuCapabilitiesAuto, -1))
+{
+ if(options != nullptr)
+ {
+ _allocator = populate_allocator(options->allocator);
+ _caps = populate_capabilities(options->capabilities, options->max_compute_units);
+ }
+}
+
+const CpuCapabilities &CpuContext::capabilities() const
+{
+ return _caps;
+}
+
+AllocatorWrapper &CpuContext::allocator()
+{
+ return _allocator;
+}
+} // namespace cpu
+} // namespace arm_compute
diff --git a/src/cpu/CpuContext.h b/src/cpu/CpuContext.h
new file mode 100644
index 0000000000..81bab97b8e
--- /dev/null
+++ b/src/cpu/CpuContext.h
@@ -0,0 +1,77 @@
+/*
+ * 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_CPU_CPUCONTEXT_H
+#define SRC_CPU_CPUCONTEXT_H
+
+#include "src/common/AllocatorWrapper.h"
+#include "src/common/IContext.h"
+
+namespace arm_compute
+{
+namespace cpu
+{
+/** Structure that encodes the CPU capabilities to be used */
+struct CpuCapabilities
+{
+ bool neon{ false };
+ bool sve{ false };
+ bool sve2{ false };
+
+ bool fp16{ false };
+ bool bf16{ false };
+ bool dot{ false };
+ bool mmla_int8{ false };
+ bool mmla_fp{ false };
+
+ int32_t max_threads{ -1 };
+};
+
+/** CPU context implementation class */
+class CpuContext final : public IContext
+{
+public:
+ /** Default Constructor
+ *
+ * @param[in] options Creational options
+ */
+ explicit CpuContext(const AclContextOptions *options);
+ /** Cpu Capabilities accessor
+ *
+ * @return The ISA capabilities to be used by the CPU
+ */
+ const CpuCapabilities &capabilities() const;
+ /** Backing memory allocator accessor
+ *
+ * @return Allocator that allocates CPU memory
+ */
+ AllocatorWrapper &allocator();
+
+private:
+ AllocatorWrapper _allocator;
+ CpuCapabilities _caps;
+};
+} // namespace cpu
+} // namespace arm_compute
+
+#endif /* SRC_CPU_CPUCONTEXT_H */ \ No newline at end of file
diff --git a/src/gpu/cl/ClContext.cpp b/src/gpu/cl/ClContext.cpp
new file mode 100644
index 0000000000..2bd8b8dd0e
--- /dev/null
+++ b/src/gpu/cl/ClContext.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/gpu/cl/ClContext.h"
+
+namespace arm_compute
+{
+namespace gpu
+{
+namespace opencl
+{
+namespace
+{
+mlgo::MLGOHeuristics populate_mlgo(const char *filename)
+{
+ mlgo::MLGOHeuristics heuristics;
+ bool status = heuristics.reload_from_file(filename);
+ return status ? std::move(heuristics) : mlgo::MLGOHeuristics();
+}
+} // namespace
+
+ClContext::ClContext(const AclContextOptions *options)
+ : IContext(Target::GpuOcl),
+ _mlgo_heuristics(),
+ _cl_context()
+{
+ if(options != nullptr)
+ {
+ _mlgo_heuristics = populate_mlgo(options->kernel_config_file);
+ }
+}
+
+const mlgo::MLGOHeuristics &ClContext::mlgo() const
+{
+ return _mlgo_heuristics;
+}
+
+::cl::Context ClContext::cl_ctx()
+{
+ return _cl_context;
+}
+
+bool ClContext::set_cl_ctx(::cl::Context ctx)
+{
+ if(this->refcount() == 0)
+ {
+ _cl_context = ctx;
+ return true;
+ }
+ return false;
+}
+} // namespace opencl
+} // namespace gpu
+} // namespace arm_compute
diff --git a/src/gpu/cl/ClContext.h b/src/gpu/cl/ClContext.h
new file mode 100644
index 0000000000..e3f16b1c3f
--- /dev/null
+++ b/src/gpu/cl/ClContext.h
@@ -0,0 +1,76 @@
+/*
+ * 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_GPU_CL_CPUCONTEXT_H
+#define SRC_GPU_CL_CPUCONTEXT_H
+
+#include "src/common/IContext.h"
+#include "src/runtime/CL/mlgo/MLGOHeuristics.h"
+
+#include "arm_compute/core/CL/OpenCL.h"
+
+namespace arm_compute
+{
+namespace gpu
+{
+namespace opencl
+{
+/** OpenCL context implementation class */
+class ClContext final : public IContext
+{
+public:
+ /** Default Constructor
+ *
+ * @param[in] options Creational options
+ */
+ explicit ClContext(const AclContextOptions *options);
+ /** Extract MLGO heuristics
+ *
+ * @return Heuristics tree
+ */
+ const mlgo::MLGOHeuristics &mlgo() const;
+
+ /** Underlying cl context accessor
+ *
+ * @return the cl context used
+ */
+ ::cl::Context cl_ctx();
+ /** Update/inject an underlying cl context object
+ *
+ * @warning Context will be able to set if the object doesn't have any pending reference to other objects
+ *
+ * @param[in] ctx Underlying cl context to be used
+ *
+ * @return true if the context was set successfully else falseS
+ */
+ bool set_cl_ctx(::cl::Context ctx);
+
+private:
+ mlgo::MLGOHeuristics _mlgo_heuristics;
+ ::cl::Context _cl_context;
+};
+} // namespace opencl
+} // namespace gpu
+} // namespace arm_compute
+
+#endif /* SRC_GPU_CL_CPUCONTEXT_H */ \ No newline at end of file
diff --git a/tests/SConscript b/tests/SConscript
index 8eebe5f2d8..fea68e0fe9 100644
--- a/tests/SConscript
+++ b/tests/SConscript
@@ -127,6 +127,7 @@ if env['opencl']:
files_validation += Glob('validation/CL/' + filter_pattern)
if env['external_tests_dir']:
files_validation += Glob(env['external_tests_dir'] + '/tests/validation/CL/' + filter_pattern)
+ files_validation += Glob('validation/gpu/unit/*.cpp')
if env['neon']:
filter_pattern = test_env['test_filter']
@@ -144,6 +145,7 @@ if env['neon']:
files_validation += Glob('validation/NEON/*/' + filter_pattern)
if env['external_tests_dir']:
files_validation += Glob(env['external_tests_dir'] + '/tests/validation/NEON/' + filter_pattern)
+ files_validation += Glob('validation/cpu/unit/*.cpp')
extra_link_flags = []
if env['os'] == 'android':
diff --git a/tests/validation/CL/UNIT/Extensions.cpp b/tests/validation/CL/UNIT/Extensions.cpp
new file mode 100644
index 0000000000..8119290d4b
--- /dev/null
+++ b/tests/validation/CL/UNIT/Extensions.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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 "arm_compute/AclVersion.h"
+#include "tests/framework/Asserts.h"
+#include "tests/framework/Macros.h"
+#include "tests/validation/Validation.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+TEST_SUITE(CL)
+TEST_SUITE(UNIT)
+TEST_CASE(GetClContext, framework::DatasetMode::ALL)
+{
+ const auto ver = AclVersionInfo();
+ ARM_COMPUTE_EXPECT(ver->major == ARM_COMPUTE_LIBRARY_VERSION_MAJOR, framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(ver->minor == ARM_COMPUTE_LIBRARY_VERSION_MINOR, framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(ver->patch == ARM_COMPUTE_LIBRARY_VERSION_PATCH, framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(!std::string(ver->build_info).empty(), framework::LogLevel::ERRORS);
+}
+TEST_SUITE_END() // UNIT
+TEST_SUITE_END() // CL
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/UNIT/Version.cpp b/tests/validation/UNIT/Version.cpp
new file mode 100644
index 0000000000..72e2d48113
--- /dev/null
+++ b/tests/validation/UNIT/Version.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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 "arm_compute/AclVersion.h"
+#include "tests/framework/Asserts.h"
+#include "tests/framework/Macros.h"
+#include "tests/validation/Validation.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+TEST_SUITE(UNIT)
+TEST_CASE(Version, framework::DatasetMode::ALL)
+{
+ const auto ver = AclVersionInfo();
+ ARM_COMPUTE_EXPECT(ver->major == ARM_COMPUTE_LIBRARY_VERSION_MAJOR, framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(ver->minor == ARM_COMPUTE_LIBRARY_VERSION_MINOR, framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(ver->patch == ARM_COMPUTE_LIBRARY_VERSION_PATCH, framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(!std::string(ver->build_info).empty(), framework::LogLevel::ERRORS);
+}
+TEST_SUITE_END() // UNIT
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/cpu/unit/Context.cpp b/tests/validation/cpu/unit/Context.cpp
new file mode 100644
index 0000000000..bf2a02df5d
--- /dev/null
+++ b/tests/validation/cpu/unit/Context.cpp
@@ -0,0 +1,197 @@
+/*
+ * 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 "tests/framework/Asserts.h"
+#include "tests/framework/Macros.h"
+#include "tests/validation/Validation.h"
+
+#include "arm_compute/Acl.hpp"
+
+#include "src/cpu/CpuContext.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+TEST_SUITE(CPU)
+TEST_SUITE(UNIT)
+TEST_SUITE(Context)
+
+/** Test-case for AclCreateContext
+ *
+ * Validate that AclCreateContext behaves as expected on invalid target
+ *
+ * Test Steps:
+ * - Call AclCreateContext with invalid target
+ * - Confirm that AclUnsupportedTarget is reported
+ * - Confirm that context is still nullptr
+ */
+TEST_CASE(CreateContextWithInvalidTarget, framework::DatasetMode::ALL)
+{
+ AclTarget invalid_target = static_cast<AclTarget>(-1);
+ AclContext ctx = nullptr;
+ ARM_COMPUTE_ASSERT(AclCreateContext(&ctx, invalid_target, nullptr) == AclStatus::AclUnsupportedTarget);
+ ARM_COMPUTE_ASSERT(ctx == nullptr);
+}
+
+/** Test-case for AclCreateContext
+ *
+ * Validate that AclCreateContext behaves as expected on invalid context options
+ *
+ * Test Steps:
+ * - Call AclCreateContext with valid target but invalid context options
+ * - Confirm that AclInvalidArgument is reported
+ * - Confirm that context is still nullptr
+ */
+TEST_CASE(CreateContextWithInvalidOptions, framework::DatasetMode::ALL)
+{
+ AclContextOptions invalid_ctx_opts;
+ invalid_ctx_opts.mode = static_cast<AclExecutionMode>(-1);
+ invalid_ctx_opts.capabilities = AclCpuCapabilitiesAuto;
+ invalid_ctx_opts.max_compute_units = 0;
+ invalid_ctx_opts.enable_fast_math = false;
+ invalid_ctx_opts.kernel_config_file = "";
+ AclContext ctx = nullptr;
+ ARM_COMPUTE_ASSERT(AclCreateContext(&ctx, AclCpu, &invalid_ctx_opts) == AclStatus::AclInvalidArgument);
+ ARM_COMPUTE_ASSERT(ctx == nullptr);
+}
+
+/** Test-case for AclDestroyContext
+ *
+ * Validate that AclDestroyContext behaves as expected when invalid inputs as context are given
+ *
+ * Test Steps:
+ * - Call AclDestroyContext with null context
+ * - Confirm that AclInvalidArgument is reported
+ * - Call AclDestroyContext on empty array
+ * - Confirm that AclInvalidArgument is reported
+ * - Call AclDestroyContext on an ACL object other than AclContext
+ * - Confirm that AclInvalidArgument is reported
+ * - Confirm that context is still nullptr
+ */
+TEST_CASE(DestroyInvalidContext, framework::DatasetMode::ALL)
+{
+ AclContext ctx = nullptr;
+ std::array<char, 256> empty_array{};
+ AclContext valid_ctx = nullptr;
+ ARM_COMPUTE_ASSERT(AclCreateContext(&valid_ctx, AclCpu, nullptr) == AclStatus::AclSuccess);
+ ARM_COMPUTE_ASSERT(AclDestroyContext(ctx) == AclStatus::AclInvalidArgument);
+ ARM_COMPUTE_ASSERT(AclDestroyContext(reinterpret_cast<AclContext>(empty_array.data())) == AclStatus::AclInvalidArgument);
+ ARM_COMPUTE_ASSERT(ctx == nullptr);
+ ARM_COMPUTE_ASSERT(AclDestroyContext(valid_ctx) == AclStatus::AclSuccess);
+}
+
+/** Test-case for AclCreateContext and AclDestroy Context
+ *
+ * Validate that AclCreateContext can create and destroy a context
+ *
+ * Test Steps:
+ * - Call AclCreateContext with valid target
+ * - Confirm that context is not nullptr and error code is AclSuccess
+ * - Destroy context
+ * - Confirm that AclSuccess is reported
+ */
+TEST_CASE(SimpleContextCApi, framework::DatasetMode::ALL)
+{
+ AclContext ctx = nullptr;
+ ARM_COMPUTE_ASSERT(AclCreateContext(&ctx, AclCpu, nullptr) == AclStatus::AclSuccess);
+ ARM_COMPUTE_ASSERT(ctx != nullptr);
+ ARM_COMPUTE_ASSERT(AclDestroyContext(ctx) == AclStatus::AclSuccess);
+}
+
+/** Test-case for Context from the C++ interface
+ *
+ * Test Steps:
+ * - Create a Context obejct
+ * - Confirm that StatusCode::Success is reported
+ * - Confirm that equality operator works
+ * - Confirm that inequality operator works
+ */
+TEST_CASE(SimpleContextCppApi, framework::DatasetMode::ALL)
+{
+ acl::StatusCode status = acl::StatusCode::Success;
+ acl::Context ctx(acl::Target::Cpu, &status);
+ ARM_COMPUTE_ASSERT(status == acl::StatusCode::Success);
+
+ auto ctx_eq = ctx;
+ ARM_COMPUTE_ASSERT(ctx_eq == ctx);
+
+ acl::Context ctx_ienq(acl::Target::Cpu, &status);
+ ARM_COMPUTE_ASSERT(status == acl::StatusCode::Success);
+ ARM_COMPUTE_ASSERT(ctx_ienq != ctx);
+}
+
+/** Test-case for CpuCapabilities
+ *
+ * Validate that AclCreateContext can create/destroy multiple contexts with different options
+ *
+ * Test Steps:
+ * - Call AclCreateContext with different targets
+ * - Confirm that AclSuccess is reported
+ * - Destroy all contexts
+ * - Confirm that AclSuccess is reported
+ */
+TEST_CASE(MultipleContexts, framework::DatasetMode::ALL)
+{
+ const unsigned int num_tests = 5;
+ std::array<AclContext, num_tests> ctxs{};
+ for(unsigned int i = 0; i < num_tests; ++i)
+ {
+ ARM_COMPUTE_ASSERT(AclCreateContext(&ctxs[i], AclTarget::AclCpu, nullptr) == AclStatus::AclSuccess);
+ ARM_COMPUTE_ASSERT(ctxs[i] != nullptr);
+ ARM_COMPUTE_ASSERT(AclDestroyContext(ctxs[i]) == AclStatus::AclSuccess);
+ }
+}
+
+/** Test-case for CpuCapabilities
+ *
+ * Validate that CpuCapabilities are set correctly
+ *
+ * Test Steps:
+ * - Create a context with a given list of capabilities
+ * - Confirm that AclSuccess is reported
+ * - Validate that all capabilities are set correctly
+ */
+TEST_CASE(CpuCapabilities, framework::DatasetMode::ALL)
+{
+ AclContextOptions opts = acl_default_ctx_options;
+ opts.capabilities = AclCpuCapabilitiesDot | AclCpuCapabilitiesMmlaInt8 | AclCpuCapabilitiesSve2;
+ arm_compute::cpu::CpuContext ctx(&opts);
+
+ ARM_COMPUTE_ASSERT(ctx.capabilities().dot == true);
+ ARM_COMPUTE_ASSERT(ctx.capabilities().mmla_int8 == true);
+ ARM_COMPUTE_ASSERT(ctx.capabilities().sve2 == true);
+ ARM_COMPUTE_ASSERT(ctx.capabilities().fp16 == false);
+
+ arm_compute::cpu::CpuContext ctx_legacy(nullptr);
+ ARM_COMPUTE_ASSERT(ctx_legacy.capabilities().neon == true);
+}
+
+TEST_SUITE_END() // Context
+TEST_SUITE_END() // UNIT
+TEST_SUITE_END() // CPU
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/gpu/unit/Context.cpp b/tests/validation/gpu/unit/Context.cpp
new file mode 100644
index 0000000000..06b4a83925
--- /dev/null
+++ b/tests/validation/gpu/unit/Context.cpp
@@ -0,0 +1,168 @@
+/*
+ * 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 "tests/framework/Asserts.h"
+#include "tests/framework/Macros.h"
+#include "tests/validation/Validation.h"
+
+#include "arm_compute/Acl.hpp"
+
+#include "src/gpu/cl/ClContext.h"
+
+using namespace arm_compute::mlgo;
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+TEST_SUITE(CL)
+TEST_SUITE(UNIT)
+TEST_SUITE(Context)
+
+/** Test-case for AclCreateContext and AclDestroy Context
+ *
+ * Validate that AclCreateContext can create and destroy a context
+ *
+ * Test Steps:
+ * - Call AclCreateContext with valid target
+ * - Confirm that context is not nullptr and error code is AclSuccess
+ * - Destroy context
+ * - Confirm that AclSuccess is reported
+ */
+TEST_CASE(SimpleContextCApi, framework::DatasetMode::ALL)
+{
+ AclContext ctx = nullptr;
+ ARM_COMPUTE_ASSERT(AclCreateContext(&ctx, AclGpuOcl, nullptr) == AclStatus::AclSuccess);
+ ARM_COMPUTE_ASSERT(ctx != nullptr);
+ ARM_COMPUTE_ASSERT(AclDestroyContext(ctx) == AclStatus::AclSuccess);
+}
+
+/** Test-case for Context from the C++ interface
+ *
+ * Test Steps:
+ * - Create a Context obejct
+ * - Confirm that StatusCode::Success is reported
+ * - Confirm that equality operator works
+ * - Confirm that inequality operator works
+ */
+TEST_CASE(SimpleContextCppApi, framework::DatasetMode::ALL)
+{
+ acl::StatusCode status = acl::StatusCode::Success;
+ acl::Context ctx(acl::Target::GpuOcl, &status);
+ ARM_COMPUTE_ASSERT(status == acl::StatusCode::Success);
+
+ auto ctx_eq = ctx;
+ ARM_COMPUTE_ASSERT(ctx_eq == ctx);
+
+ acl::Context ctx_ienq(acl::Target::GpuOcl, &status);
+ ARM_COMPUTE_ASSERT(status == acl::StatusCode::Success);
+ ARM_COMPUTE_ASSERT(ctx_ienq != ctx);
+}
+
+/** Test-case for CpuCapabilities
+ *
+ * Validate that AclCreateContext can create/destroy multiple contexts with different options
+ *
+ * Test Steps:
+ * - Call AclCreateContext with different targets
+ * - Confirm that AclSuccess is reported
+ * - Destroy all contexts
+ * - Confirm that AclSuccess is reported
+ */
+TEST_CASE(MultipleContexts, framework::DatasetMode::ALL)
+{
+ const unsigned int num_tests = 5;
+ std::array<AclContext, num_tests> ctxs{};
+ for(unsigned int i = 0; i < num_tests; ++i)
+ {
+ ARM_COMPUTE_ASSERT(AclCreateContext(&ctxs[i], AclTarget::AclGpuOcl, nullptr) == AclStatus::AclSuccess);
+ ARM_COMPUTE_ASSERT(ctxs[i] != nullptr);
+ ARM_COMPUTE_ASSERT(AclDestroyContext(ctxs[i]) == AclStatus::AclSuccess);
+ }
+}
+
+/** Test-case for MLGO kernel configuration file
+ *
+ * Validate that CpuCapabilities are set correctly
+ *
+ * Test Steps:
+ * - Create a file with the MLGO configuration
+ * - Pass the kernel file to the Context during creation
+ * - Validate that the MLGO file has been parsed successfully
+ */
+TEST_CASE(CheckMLGO, framework::DatasetMode::ALL)
+{
+ // Create test mlgo file
+ std::string mlgo_str = R"_(
+
+ <header>
+
+ gemm-version, [1,2,1]
+ ip-type,gpu
+ </header>
+ <heuristics-table>
+ 0, g76 , 8, f32, best-performance, static, gemm-type, [m,n,k,n]
+ 1, g76 , 8, f16, best-performance, static, gemm-config-reshaped, [m,n,k,n]
+ </heuristics-table>
+ <heuristic, 0>
+ b , 0, var, m, ==, num, 10., 1, 2
+ l , 1, gemm-type, reshaped
+ b , 2, var, r_mn, >=, num, 2., 3, 6
+
+ b , 3, var, n, >=, num, 200., 4, 5
+ l, 4, gemm-type, reshaped-only-rhs
+ l , 5, gemm-type, reshaped
+ l , 6, gemm-type, reshaped-only-rhs
+ </heuristic>
+
+ <heuristic, 1>
+ l ,0,gemm-config-reshaped,[4,2,4,2,8,1,0,1,0]
+ </heuristic>
+
+ )_";
+ const std::string mlgo_filename = "test.mlgo";
+ std::ofstream ofs(mlgo_filename, std::ofstream::trunc);
+ ARM_COMPUTE_EXPECT(ofs, framework::LogLevel::ERRORS);
+ ofs << mlgo_str;
+ ofs.close();
+
+ AclContextOptions opts = acl_default_ctx_options;
+ opts.kernel_config_file = mlgo_filename.c_str();
+ arm_compute::gpu::opencl::ClContext ctx(&opts);
+
+ const MLGOHeuristics &heuristics = ctx.mlgo();
+
+ ARM_COMPUTE_EXPECT(heuristics.query_gemm_type(Query{ "g76", DataType::F32, 10, 1024, 20, 1 }).second == GEMMType::RESHAPED,
+ framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT((heuristics.query_gemm_config_reshaped(Query{ "g76", DataType::F16, 100, 100, 20, 32 }).second == GEMMConfigReshaped{ 4, 2, 4, 2, 8, true, false, true, false }),
+ framework::LogLevel::ERRORS);
+}
+
+TEST_SUITE_END() // Context
+TEST_SUITE_END() // UNIT
+TEST_SUITE_END() // CL
+} // namespace validation
+} // namespace test
+} // namespace arm_compute