aboutsummaryrefslogtreecommitdiff
path: root/src/backends
diff options
context:
space:
mode:
authorTianle Cheng <tianle.cheng@arm.com>2023-06-28 13:20:47 +0100
committerTianle Cheng <tianle.cheng@arm.com>2023-07-04 10:36:43 +0000
commit988354de127528bdebb98fd25661fbf2f39f17dd (patch)
treec06f5250bdd0182055ac9e84e20d6e338518ad08 /src/backends
parent9414936e62ed8cd18cc33c0390bb605a782556c6 (diff)
downloadarmnn-988354de127528bdebb98fd25661fbf2f39f17dd.tar.gz
IVGCVSW-7831: Front end and Reference Implementation for REVERSE_V2
* Descriptors added for ReverseV2 * Layer definition added * Input validation added * Reference workload implementation for ReverseV2 added * Reference layer unit tests made for ReverseV2 * CompareTensors method updated to support comparison between empty tensors * CMake and other build files updated Signed-off-by: Tianle Cheng <tianle.cheng@arm.com> Change-Id: I805738454421309fda77c44218a8df171d68dc18
Diffstat (limited to 'src/backends')
-rw-r--r--src/backends/backendsCommon/WorkloadData.cpp66
-rw-r--r--src/backends/backendsCommon/WorkloadFactory.cpp11
-rw-r--r--src/backends/backendsCommon/common.mk1
-rw-r--r--src/backends/backendsCommon/test/CMakeLists.txt2
-rw-r--r--src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp2
-rw-r--r--src/backends/backendsCommon/test/LayerTests.hpp1
-rw-r--r--src/backends/backendsCommon/test/layerTests/ReverseV2TestImpl.cpp1084
-rw-r--r--src/backends/backendsCommon/test/layerTests/ReverseV2TestImpl.hpp156
-rw-r--r--src/backends/reference/RefLayerSupport.cpp35
-rw-r--r--src/backends/reference/RefLayerSupport.hpp5
-rw-r--r--src/backends/reference/RefWorkloadFactory.cpp5
-rw-r--r--src/backends/reference/backend.mk4
-rw-r--r--src/backends/reference/test/RefLayerTests.cpp31
-rw-r--r--src/backends/reference/workloads/CMakeLists.txt4
-rw-r--r--src/backends/reference/workloads/RefReverseV2Workload.cpp48
-rw-r--r--src/backends/reference/workloads/RefReverseV2Workload.hpp30
-rw-r--r--src/backends/reference/workloads/RefWorkloads.hpp1
-rw-r--r--src/backends/reference/workloads/ReverseV2Impl.cpp133
-rw-r--r--src/backends/reference/workloads/ReverseV2Impl.hpp21
19 files changed, 1639 insertions, 1 deletions
diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp
index d4ae08d874..6cde89c2e1 100644
--- a/src/backends/backendsCommon/WorkloadData.cpp
+++ b/src/backends/backendsCommon/WorkloadData.cpp
@@ -1640,6 +1640,72 @@ void ResizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
}
}
+void ReverseV2QueueDescriptor::Validate(const WorkloadInfo &workloadInfo) const {
+ const std::string descriptorName{"ReverseV2QueueDescriptor"};
+
+ ValidateNumInputs(workloadInfo, descriptorName, 1);
+ ValidateNumOutputs(workloadInfo, descriptorName, 1);
+
+ const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
+ const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
+
+ auto inputTensorNumDimensions = inputTensorInfo.GetNumDimensions();
+ if (inputTensorNumDimensions > m_Parameters.m_MaxDimension)
+ {
+ throw InvalidArgumentException(descriptorName +
+ ": Input tensors with rank greater than " +
+ std::to_string(m_Parameters.m_MaxDimension) + " are not supported.");
+ }
+
+ std::vector<DataType> supportedTypes =
+ {
+ DataType::BFloat16,
+ DataType::Float16,
+ DataType::Float32,
+ DataType::QAsymmS8,
+ DataType::QAsymmU8,
+ DataType::QSymmS16
+ };
+
+ ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
+ ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
+ ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
+
+ if (m_Parameters.m_Axis.size() > inputTensorNumDimensions)
+ {
+ throw InvalidArgumentException(descriptorName + ": More axes specified than is on the input tensor.");
+ }
+ if (m_Parameters.m_Axis.size() > m_Parameters.m_MaxDimension)
+ {
+ throw InvalidArgumentException(descriptorName +
+ ": More than " + std::to_string(m_Parameters.m_MaxDimension) + " axes cannot be specified.");
+ }
+
+ if (! m_Parameters.m_Axis.empty())
+ {
+ // First check that we have unique axis values
+ auto checkAxis = m_Parameters.m_Axis;
+ std::sort(checkAxis.begin(), checkAxis.end());
+ auto lastUnique = std::unique(checkAxis.begin(), checkAxis.end());
+ if (lastUnique != checkAxis.end())
+ {
+ throw InvalidArgumentException(descriptorName + ": Axes values must be unique.");
+ }
+
+ // Next check that the axes values are in range: [-rank, rank]
+ const auto minmax =
+ std::minmax_element(std::begin(m_Parameters.m_Axis), std::end(m_Parameters.m_Axis));
+ if (((*minmax.first) < int32_t(-inputTensorNumDimensions)) ||
+ ((*minmax.second) >= int32_t (inputTensorNumDimensions)))
+ {
+ throw InvalidArgumentException(descriptorName +
+ ": Axes values must in range [-" + std::to_string(inputTensorNumDimensions) + "," +
+ std::to_string(inputTensorNumDimensions) + "].");
+ }
+ }
+}
+
+
void FakeQuantizationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
{
const std::string descriptorName{"FakeQuantizationQueueDescriptor"};
diff --git a/src/backends/backendsCommon/WorkloadFactory.cpp b/src/backends/backendsCommon/WorkloadFactory.cpp
index 7042af1127..37f9382d6e 100644
--- a/src/backends/backendsCommon/WorkloadFactory.cpp
+++ b/src/backends/backendsCommon/WorkloadFactory.cpp
@@ -1119,6 +1119,17 @@ bool IWorkloadFactory::IsLayerConfigurationSupported(const BackendId& backendId,
reason);
break;
}
+ case LayerType::ReverseV2:
+ {
+ auto cLayer = PolymorphicDowncast<const ReverseV2Layer*>(&layer);
+ const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
+ const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
+ result = layerSupportObject.IsReverseV2Supported(OverrideDataType(input, dataType),
+ OverrideDataType(output, dataType),
+ cLayer->GetParameters(),
+ reason);
+ break;
+ }
case LayerType::Shape:
{
const TensorInfo& input = layer.GetInputSlot(0).GetTensorInfo();
diff --git a/src/backends/backendsCommon/common.mk b/src/backends/backendsCommon/common.mk
index c868cbe87a..1e0467deba 100644
--- a/src/backends/backendsCommon/common.mk
+++ b/src/backends/backendsCommon/common.mk
@@ -91,6 +91,7 @@ COMMON_TEST_SOURCES := \
test/layerTests/ReduceSumTestImpl.cpp \
test/layerTests/ReshapeTestImpl.cpp \
test/layerTests/ResizeTestImpl.cpp \
+ test/layerTests/ReverseV2TestImpl.cpp \
test/layerTests/RsqrtTestImpl.cpp \
test/layerTests/SliceTestImpl.cpp \
test/layerTests/SquaredDifferenceTestImpl.cpp \
diff --git a/src/backends/backendsCommon/test/CMakeLists.txt b/src/backends/backendsCommon/test/CMakeLists.txt
index aba9c72e6c..0139044432 100644
--- a/src/backends/backendsCommon/test/CMakeLists.txt
+++ b/src/backends/backendsCommon/test/CMakeLists.txt
@@ -170,6 +170,8 @@ list(APPEND armnnBackendsCommonUnitTests_sources
layerTests/ReshapeTestImpl.hpp
layerTests/ResizeTestImpl.cpp
layerTests/ResizeTestImpl.hpp
+ layerTests/ReverseV2TestImpl.cpp
+ layerTests/ReverseV2TestImpl.hpp
layerTests/RsqrtTestImpl.cpp
layerTests/RsqrtTestImpl.hpp
layerTests/SinTestImpl.cpp
diff --git a/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp b/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp
index 182fab97be..f7a852f440 100644
--- a/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp
+++ b/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp
@@ -744,6 +744,8 @@ DECLARE_LAYER_POLICY_2_PARAM(Resize)
DECLARE_LAYER_POLICY_2_PARAM(Reshape)
+DECLARE_LAYER_POLICY_2_PARAM(ReverseV2)
+
DECLARE_LAYER_POLICY_1_PARAM(Shape)
DECLARE_LAYER_POLICY_2_PARAM(Slice)
diff --git a/src/backends/backendsCommon/test/LayerTests.hpp b/src/backends/backendsCommon/test/LayerTests.hpp
index b6ddb31419..755a665ba6 100644
--- a/src/backends/backendsCommon/test/LayerTests.hpp
+++ b/src/backends/backendsCommon/test/LayerTests.hpp
@@ -60,6 +60,7 @@
#include <backendsCommon/test/layerTests/ReduceSumTestImpl.hpp>
#include <backendsCommon/test/layerTests/ReshapeTestImpl.hpp>
#include <backendsCommon/test/layerTests/ResizeTestImpl.hpp>
+#include <backendsCommon/test/layerTests/ReverseV2TestImpl.hpp>
#include <backendsCommon/test/layerTests/RsqrtTestImpl.hpp>
#include <backendsCommon/test/layerTests/ShapeTestImpl.hpp>
#include <backendsCommon/test/layerTests/SinTestImpl.hpp>
diff --git a/src/backends/backendsCommon/test/layerTests/ReverseV2TestImpl.cpp b/src/backends/backendsCommon/test/layerTests/ReverseV2TestImpl.cpp
new file mode 100644
index 0000000000..586b831e45
--- /dev/null
+++ b/src/backends/backendsCommon/test/layerTests/ReverseV2TestImpl.cpp
@@ -0,0 +1,1084 @@
+//
+// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "ReverseV2TestImpl.hpp"
+
+#include <armnn/backends/IBackendInternal.hpp>
+#include <armnn/backends/Workload.hpp>
+#include <armnn/backends/WorkloadData.hpp>
+#include <armnn/backends/WorkloadFactory.hpp>
+
+#include <armnnTestUtils/WorkloadTestUtils.hpp>
+#include <armnnUtils/QuantizeHelper.hpp>
+#include <armnnTestUtils/TensorCopyUtils.hpp>
+#include <armnn/Optional.hpp>
+#include <armnn/BackendHelper.hpp>
+
+namespace
+{
+ template<armnn::DataType ArmnnType, typename T, std::size_t NumDims>
+ LayerTestResult<T, NumDims> ReverseV2TestImpl(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory,
+ armnn::ReverseV2Descriptor descriptor,
+ const std::vector<T>& input,
+ const std::vector<T>& outputExpected,
+ const armnn::TensorInfo& inputInfo,
+ const armnn::TensorInfo& outputInfo)
+ {
+ LayerTestResult<T, NumDims> result(outputInfo);
+ std::vector<T> outputActual(outputInfo.GetNumElements());
+
+ std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputInfo);
+ std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputInfo);
+
+ armnn::ReverseV2QueueDescriptor queueDescriptor;
+ queueDescriptor.m_Parameters = std::move(descriptor);
+ armnn::WorkloadInfo workloadInfo;
+
+ AddInputToWorkload(queueDescriptor, workloadInfo, inputInfo, inputHandle.get());
+ AddOutputToWorkload(queueDescriptor, workloadInfo, outputInfo, outputHandle.get());
+
+ // Don't execute if ReverseV2 is not supported, as an exception will be raised.
+ const armnn::BackendId& backend = workloadFactory.GetBackendId();
+ std::string reasonIfUnsupported;
+ armnn::LayerSupportHandle handle = armnn::GetILayerSupportByBackendId(backend);
+ result.m_Supported = handle.IsReverseV2Supported(inputInfo,
+ outputInfo,
+ queueDescriptor.m_Parameters,
+ reasonIfUnsupported);
+ if (!result.m_Supported)
+ {
+ return result;
+ }
+
+ auto workload = workloadFactory.CreateWorkload(armnn::LayerType::ReverseV2, queueDescriptor, workloadInfo);
+
+ inputHandle->Allocate();
+ outputHandle->Allocate();
+
+ CopyDataToITensorHandle(inputHandle.get(), input.data());
+
+ workload->PostAllocationConfigure();
+ ExecuteWorkload(*workload, memoryManager);
+
+ CopyDataFromITensorHandle(outputActual.data(), outputHandle.get());
+
+ return LayerTestResult<T, NumDims>(outputActual,
+ outputExpected,
+ outputHandle->GetShape(),
+ outputInfo.GetShape());
+ }
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2SimpleTestEmptyAxis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ // Simple test with default descriptor. No axes set so output is the same as input
+ auto descriptor = armnn::ReverseV2Descriptor();
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({2,2}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({2,2}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2,
+ 3, 4
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 1, 2,
+ 3, 4
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2SimpleTestEmptyTensor(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ // Simple test with default descriptor. Empty tensor set so output is the same as input
+ auto descriptor = armnn::ReverseV2Descriptor();
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({0}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({0}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({}, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({}, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2SimpleTest1Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {0});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({4}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({4}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2,
+ 3, 4
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 4, 3,
+ 2, 1
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2SimpleTest2Dim1Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {1});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({2,2}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({2,2}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2,
+ 3, 4
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 2, 1,
+ 4, 3
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2SimpleTest2Dim2Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {1, 0});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({2,2}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({2,2}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2,
+ 3, 4
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 4, 3,
+ 2, 1
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2SimpleTest3Dim1Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {1});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({2, 3, 4}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({2, 3, 4}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+ 13, 14, 15, 16,
+ 17, 18, 19, 20,
+ 21, 22, 23, 24
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 9, 10, 11, 12,
+ 5, 6, 7, 8,
+ 1, 2, 3, 4,
+ 21, 22, 23, 24,
+ 17, 18, 19, 20,
+ 13, 14, 15, 16
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2SimpleTest3Dim2Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {0, 1});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({2, 3, 4}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({2, 3, 4}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+ 13, 14, 15, 16,
+ 17, 18, 19, 20,
+ 21, 22, 23, 24
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 21, 22, 23, 24,
+ 17, 18, 19, 20,
+ 13, 14, 15, 16,
+ 9, 10, 11, 12,
+ 5, 6, 7, 8,
+ 1, 2, 3, 4
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2SimpleTest3Dim3Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ // Simple test with default descriptor. No axes set so output is
+ // the same as input
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {1, 0, 2});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({2, 3, 4}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({2, 3, 4}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+ 13, 14, 15, 16,
+ 17, 18, 19, 20,
+ 21, 22, 23, 24
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 24, 23, 22, 21,
+ 20, 19, 18, 17,
+ 16, 15, 14, 13,
+ 12, 11, 10, 9,
+ 8, 7, 6, 5,
+ 4, 3, 2, 1
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2SimpleTest4Dim1Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ // Simple test with default descriptor. No axes set so output is
+ // the same as input
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {0});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({2, 2, 2, 3}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({2, 2, 2, 3}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2, 3,
+ 4, 5, 6,
+ 7, 8, 9,
+ 10, 11, 12,
+ 13, 14, 15,
+ 16, 17, 18,
+ 19, 20, 21,
+ 22, 23, 24
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 13, 14, 15,
+ 16, 17, 18,
+ 19, 20, 21,
+ 22, 23, 24,
+ 1, 2, 3,
+ 4, 5, 6,
+ 7, 8, 9,
+ 10, 11, 12
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2SimpleTest4Dim2Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ // Simple test with default descriptor. No axes set so output is
+ // the same as input
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {0, 1});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({2, 2, 2, 3}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({2, 2, 2, 3}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2, 3,
+ 4, 5, 6,
+ 7, 8, 9,
+ 10, 11, 12,
+ 13, 14, 15,
+ 16, 17, 18,
+ 19, 20, 21,
+ 22, 23, 24
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 19, 20, 21,
+ 22, 23, 24,
+ 13, 14, 15,
+ 16, 17, 18,
+ 7, 8, 9,
+ 10, 11, 12,
+ 1, 2, 3,
+ 4, 5, 6
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2SimpleTest4Dim3Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ // Simple test with default descriptor. No axes set so output is
+ // the same as input
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {0, 1, 2});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({2, 2, 2, 3}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({2, 2, 2, 3}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2, 3,
+ 4, 5, 6,
+ 7, 8, 9,
+ 10, 11, 12,
+ 13, 14, 15,
+ 16, 17, 18,
+ 19, 20, 21,
+ 22, 23, 24
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 22, 23, 24,
+ 19, 20, 21,
+ 16, 17, 18,
+ 13, 14, 15,
+ 10, 11, 12,
+ 7, 8, 9,
+ 4, 5, 6,
+ 1, 2, 3
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2SimpleTest4Dim4Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ // Simple test with default descriptor. No axes set so output is
+ // the same as input
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {0, 1, 2, 3});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({2, 2, 2, 3}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({2, 2, 2, 3}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2, 3,
+ 4, 5, 6,
+ 7, 8, 9,
+ 10, 11, 12,
+ 13, 14, 15,
+ 16, 17, 18,
+ 19, 20, 21,
+ 22, 23, 24
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 24, 23, 22,
+ 21, 20, 19,
+ 18, 17, 16,
+ 15, 14, 13,
+ 12, 11, 10,
+ 9, 8, 7,
+ 6, 5, 4,
+ 3, 2, 1
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2EvenRowOddColTest2Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ // Simple test with default descriptor. No axes set so output is the same as input
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {1});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({2, 3}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({2, 3}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2, 3,
+ 4, 5, 6
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 3, 2, 1,
+ 6, 5, 4
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2EvenRowOddColTest3Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ // Simple test with default descriptor. No axes set so output is
+ // the same as input
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {1});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({2, 3, 1}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({2, 3, 1}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2, 3,
+ 4, 5, 6
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 3, 2, 1,
+ 6, 5, 4
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2EvenRowEvenColTest2Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ // Simple test with default descriptor. No axes set so output is
+ // the same as input
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {1});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({2, 4}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({2, 4}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2, 3, 4,
+ 5, 6, 7, 8
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 4, 3, 2, 1,
+ 8, 7, 6, 5
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2EvenRowEvenColTest3Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ // Simple test with default descriptor. No axes set so output is
+ // the same as input
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {1});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({2, 4, 1}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({2, 4, 1}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2, 3, 4,
+ 5, 6, 7, 8
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 4, 3, 2, 1,
+ 8, 7, 6, 5
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2OddRowOddColTest2Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ // Simple test with default descriptor. No axes set so output is
+ // the same as input
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {1});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({3, 3}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({3, 3}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2, 3,
+ 4, 5, 6,
+ 7, 8, 9
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 3, 2, 1,
+ 6, 5, 4,
+ 9, 8, 7
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2OddRowOddColTest3Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ // Simple test with default descriptor. No axes set so output is
+ // the same as input
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {1});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({3, 3, 1}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({3, 3, 1}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2, 3,
+ 4, 5, 6,
+ 7, 8, 9
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 3, 2, 1,
+ 6, 5, 4,
+ 9, 8, 7
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2OddRowEvenColTest2Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ // Simple test with default descriptor. No axes set so output is
+ // the same as input
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {1});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({3, 4}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({3, 4}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 4, 3, 2, 1,
+ 8, 7, 6, 5,
+ 12, 11, 10, 9
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2OddRowEvenColTest3Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ // Simple test with default descriptor. No axes set so output is
+ // the same as input
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {1});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({3, 4, 1}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({3, 4, 1}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 4, 3, 2, 1,
+ 8, 7, 6, 5,
+ 12, 11, 10, 9
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2NegAxisTest2Dim1Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ // Simple test with default descriptor. No axes set so output is
+ // the same as input
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {-1});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({2, 4}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({2, 4}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 4, 3, 2, 1,
+ 8, 7, 6, 5
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 2> ReverseV2NegAxisTest3Dim2Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory)
+{
+ // Simple test with default descriptor. No axes set so output is
+ // the same as input
+ auto descriptor = armnn::ReverseV2Descriptor(std::vector<int> {1, -1});
+
+ float qScale = 1.0f;
+ int32_t qOffset = 0;
+
+ armnn::TensorInfo inputInfo({2, 4, 1}, ArmnnType, qScale, qOffset);
+ armnn::TensorInfo outputInfo({2, 4, 1}, ArmnnType, qScale, qOffset);
+
+ std::vector<T> input = armnnUtils::QuantizedVector<T>({
+ 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ }, qScale, qOffset);
+
+ std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>({
+ 4, 3, 2, 1,
+ 8, 7, 6, 5
+ }, qScale, qOffset);
+
+ return ReverseV2TestImpl<ArmnnType, T, 2>(workloadFactory,
+ memoryManager,
+ tensorHandleFactory,
+ descriptor,
+ input,
+ outputExpected,
+ inputInfo,
+ outputInfo);
+}
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2SimpleTestEmptyAxis<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2SimpleTestEmptyTensor<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2SimpleTest1Dim<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2SimpleTest2Dim1Axis<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2SimpleTest2Dim2Axis<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2SimpleTest3Dim1Axis<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2SimpleTest3Dim2Axis<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2SimpleTest3Dim3Axis<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2SimpleTest4Dim1Axis<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2SimpleTest4Dim2Axis<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2SimpleTest4Dim3Axis<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2SimpleTest4Dim4Axis<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2EvenRowOddColTest2Dim<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2EvenRowOddColTest3Dim<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2EvenRowEvenColTest2Dim<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2EvenRowEvenColTest3Dim<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2OddRowOddColTest2Dim<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2OddRowOddColTest3Dim<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2OddRowEvenColTest2Dim<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2OddRowEvenColTest3Dim<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2NegAxisTest2Dim1Axis<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 2>
+ReverseV2NegAxisTest3Dim2Axis<armnn::DataType::Float32>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float16>, 2>
+ReverseV2SimpleTest2Dim2Axis<armnn::DataType::Float16>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::QAsymmS8>, 2>
+ReverseV2SimpleTest2Dim2Axis<armnn::DataType::QAsymmS8>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::QAsymmU8>, 2>
+ReverseV2SimpleTest2Dim2Axis<armnn::DataType::QAsymmU8>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::QSymmS16>, 2>
+ReverseV2SimpleTest2Dim2Axis<armnn::DataType::QSymmS16>(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory); \ No newline at end of file
diff --git a/src/backends/backendsCommon/test/layerTests/ReverseV2TestImpl.hpp b/src/backends/backendsCommon/test/layerTests/ReverseV2TestImpl.hpp
new file mode 100644
index 0000000000..a40e7734a0
--- /dev/null
+++ b/src/backends/backendsCommon/test/layerTests/ReverseV2TestImpl.hpp
@@ -0,0 +1,156 @@
+//
+// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <armnnTestUtils/LayerTestResult.hpp>
+
+#include <ResolveType.hpp>
+
+#include <armnn/backends/IBackendInternal.hpp>
+
+// Empty test cases
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2SimpleTestEmptyAxis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2SimpleTestEmptyTensor(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+// Multidimensional input tensor and multi-axis tests
+// These test cases are conducted with even-row-even-column input tensors
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2SimpleTest1Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2SimpleTest2Dim1Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2SimpleTest2Dim2Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2SimpleTest3Dim1Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2SimpleTest3Dim2Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2SimpleTest3Dim3Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2SimpleTest4Dim1Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2SimpleTest4Dim2Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2SimpleTest4Dim3Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2SimpleTest4Dim4Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+// Even and odd row number tests
+// These tests are conducted with 1-axis input param
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2EvenRowOddColTest2Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2EvenRowOddColTest3Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2EvenRowEvenColTest2Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2EvenRowEvenColTest3Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2OddRowOddColTest2Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2OddRowOddColTest3Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2OddRowEvenColTest2Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2OddRowEvenColTest3Dim(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+// Negative axis input tests with even-row-even-column input
+
+// one negative axis
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2NegAxisTest2Dim1Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory);
+
+// one negative and one positive axis
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> ReverseV2NegAxisTest3Dim2Axis(
+ armnn::IWorkloadFactory& workloadFactory,
+ const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
+ const armnn::ITensorHandleFactory& tensorHandleFactory); \ No newline at end of file
diff --git a/src/backends/reference/RefLayerSupport.cpp b/src/backends/reference/RefLayerSupport.cpp
index 81e5c837a5..1d5fab1adc 100644
--- a/src/backends/reference/RefLayerSupport.cpp
+++ b/src/backends/reference/RefLayerSupport.cpp
@@ -341,6 +341,11 @@ bool RefLayerSupport::IsLayerSupported(const LayerType& type,
infos[1],
*(PolymorphicDowncast<const ResizeDescriptor*>(&descriptor)),
reasonIfUnsupported);
+ case LayerType::ReverseV2:
+ return IsReverseV2Supported(infos[0],
+ infos[1],
+ *(PolymorphicDowncast<const ReverseV2Descriptor*>(&descriptor)),
+ reasonIfUnsupported);
case LayerType::Reduce:
return IsReduceSupported(infos[0],
infos[1],
@@ -2356,6 +2361,36 @@ bool RefLayerSupport::IsResizeSupported(const TensorInfo& input,
return supported;
}
+bool RefLayerSupport::IsReverseV2Supported(const TensorInfo& input,
+ const TensorInfo& output,
+ const ReverseV2Descriptor& descriptor,
+ Optional<std::string&> reasonIfUnsupported) const
+{
+ IgnoreUnused(descriptor);
+ bool supported = true;
+ // ReverseV2 is data type agnostic so it can support all the types in the Reference backend
+ std::array<DataType,6> supportedTypes =
+ {
+ DataType::BFloat16,
+ DataType::Float32,
+ DataType::Float16,
+ DataType::QAsymmS8,
+ DataType::QAsymmU8,
+ DataType::QSymmS16
+ };
+
+ supported &= CheckSupportRule(TypeAnyOf(input, supportedTypes), reasonIfUnsupported,
+ "Reference ReverseV2: input type not supported");
+
+ supported &= CheckSupportRule(TypeAnyOf(output, supportedTypes), reasonIfUnsupported,
+ "Reference ReverseV2: output type not supported");
+
+ supported &= CheckSupportRule(TypesAreEqual(input, output), reasonIfUnsupported,
+ "Reference ReverseV2: input and output types not matching");
+
+ return supported;
+}
+
bool RefLayerSupport::IsShapeSupported(const TensorInfo& input,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported) const
diff --git a/src/backends/reference/RefLayerSupport.hpp b/src/backends/reference/RefLayerSupport.hpp
index 8e1f68ebfc..0afb9c2c94 100644
--- a/src/backends/reference/RefLayerSupport.hpp
+++ b/src/backends/reference/RefLayerSupport.hpp
@@ -299,6 +299,11 @@ public:
const ResizeDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported = EmptyOptional()) const override;
+ bool IsReverseV2Supported(const TensorInfo& input,
+ const TensorInfo& output,
+ const ReverseV2Descriptor& descriptor,
+ Optional<std::string&> reasonIfUnsupported = EmptyOptional()) const;
+
bool IsShapeSupported(const TensorInfo& input,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported = EmptyOptional()) const override;
diff --git a/src/backends/reference/RefWorkloadFactory.cpp b/src/backends/reference/RefWorkloadFactory.cpp
index 10f623eef3..7d5f742126 100644
--- a/src/backends/reference/RefWorkloadFactory.cpp
+++ b/src/backends/reference/RefWorkloadFactory.cpp
@@ -560,6 +560,11 @@ std::unique_ptr<IWorkload> RefWorkloadFactory::CreateWorkload(LayerType type,
auto resizeQueueDescriptor = PolymorphicDowncast<const ResizeQueueDescriptor*>(&descriptor);
return std::make_unique<RefResizeWorkload>(*resizeQueueDescriptor, info);
}
+ case LayerType::ReverseV2:
+ {
+ auto reverseV2QueueDescriptor = PolymorphicDowncast<const ReverseV2QueueDescriptor*>(&descriptor);
+ return std::make_unique<RefReverseV2Workload>(*reverseV2QueueDescriptor, info);
+ }
case LayerType::Shape:
{
auto shapeQueueDescriptor = PolymorphicDowncast<const ShapeQueueDescriptor*>(&descriptor);
diff --git a/src/backends/reference/backend.mk b/src/backends/reference/backend.mk
index c23984c3e9..dfafa0ac39 100644
--- a/src/backends/reference/backend.mk
+++ b/src/backends/reference/backend.mk
@@ -1,5 +1,5 @@
#
-# Copyright © 2017 ARM Ltd. All rights reserved.
+# Copyright © 2017-2023 ARM Ltd and Contributors. All rights reserved.
# SPDX-License-Identifier: MIT
#
@@ -94,6 +94,7 @@ BACKEND_SOURCES := \
workloads/RefReduceWorkload.cpp \
workloads/RefReshapeWorkload.cpp \
workloads/RefResizeWorkload.cpp \
+ workloads/RefReverseV2Workload.cpp \
workloads/RefSliceWorkload.cpp \
workloads/RefSoftmaxWorkload.cpp \
workloads/RefSpaceToBatchNdWorkload.cpp \
@@ -105,6 +106,7 @@ BACKEND_SOURCES := \
workloads/RefTransposeWorkload.cpp \
workloads/RefUnidirectionalSequenceLstmWorkload.cpp \
workloads/Resize.cpp \
+ workloads/ReverseV2Impl.cpp \
workloads/Slice.cpp \
workloads/SpaceToBatchNd.cpp \
workloads/SpaceToDepth.cpp \
diff --git a/src/backends/reference/test/RefLayerTests.cpp b/src/backends/reference/test/RefLayerTests.cpp
index 6e697723e9..a68775e8e9 100644
--- a/src/backends/reference/test/RefLayerTests.cpp
+++ b/src/backends/reference/test/RefLayerTests.cpp
@@ -1565,6 +1565,37 @@ ARMNN_AUTO_TEST_CASE_WITH_THF(AlignCornersResizeNearestNeighbourUint16Nchw,
AlignCornersResizeNearestNeighbourTest<DataType::QSymmS16>,
DataLayout::NCHW)
+// ReverseV2
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2SimpleEmptyAxisFloat32, ReverseV2SimpleTestEmptyAxis<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2SimpleEmptyTensorFloat32, ReverseV2SimpleTestEmptyTensor <DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2Simple1DimFloat32, ReverseV2SimpleTest1Dim<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2Simple2Dim1AxisFloat32, ReverseV2SimpleTest2Dim1Axis<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2Simple2Dim2AxisFloat32, ReverseV2SimpleTest2Dim2Axis<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2Simple3Dim1AxisFloat32, ReverseV2SimpleTest3Dim1Axis<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2Simple3Dim2AxisFloat32, ReverseV2SimpleTest3Dim2Axis<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2Simple3Dim3AxisFloat32, ReverseV2SimpleTest3Dim3Axis<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2Simple4Dim1AxisFloat32, ReverseV2SimpleTest4Dim1Axis<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2Simple4Dim2AxisFloat32, ReverseV2SimpleTest4Dim2Axis<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2Simple4Dim3AxisFloat32, ReverseV2SimpleTest4Dim3Axis<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2Simple4Dim4AxisFloat32, ReverseV2SimpleTest4Dim4Axis<DataType::Float32>)
+
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2EvenRowOddCol2DimFloat32, ReverseV2EvenRowOddColTest2Dim<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2EvenRowOddCol3DimFloat32, ReverseV2EvenRowOddColTest3Dim<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2EvenRowEvenCol2DimFloat32, ReverseV2EvenRowEvenColTest2Dim<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2EvenRowEvenCol3DimFloat32, ReverseV2EvenRowEvenColTest3Dim<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2OddRowOddCol2DimFloat32, ReverseV2OddRowOddColTest2Dim<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2OddRowOddCol3DimFloat32, ReverseV2OddRowOddColTest3Dim<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2OddRowEvenCol2DimFloat32, ReverseV2OddRowEvenColTest2Dim<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2OddRowEvenCol3DimFloat32, ReverseV2OddRowEvenColTest3Dim<DataType::Float32>)
+
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2NegAxis2Dim1AxisFloat32, ReverseV2NegAxisTest2Dim1Axis<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2NegAxis3Dim2AxisFloat32, ReverseV2NegAxisTest3Dim2Axis<DataType::Float32>)
+
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2Simple2Dim2AxisFloat16, ReverseV2SimpleTest2Dim2Axis<DataType::Float16>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2Simple2Dim2AxisQAsymmS8, ReverseV2SimpleTest2Dim2Axis<DataType::QAsymmS8>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2Simple2Dim2AxisQAsymmU8, ReverseV2SimpleTest2Dim2Axis<DataType::QAsymmU8>)
+ARMNN_AUTO_TEST_CASE_WITH_THF(ReverseV2Simple2Dim2AxisQSymmS16, ReverseV2SimpleTest2Dim2Axis<DataType::QSymmS16>)
+
// Fake Quantization
ARMNN_AUTO_TEST_CASE_WITH_THF(FakeQuantization, FakeQuantizationTest)
diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt
index 3592f2293d..28f6d2f371 100644
--- a/src/backends/reference/workloads/CMakeLists.txt
+++ b/src/backends/reference/workloads/CMakeLists.txt
@@ -66,6 +66,8 @@ list(APPEND armnnRefBackendWorkloads_sources
PreluImpl.hpp
Reduce.cpp
Reduce.hpp
+ ReverseV2Impl.cpp
+ ReverseV2Impl.hpp
RefActivationWorkload.cpp
RefActivationWorkload.hpp
RefArgMinMaxWorkload.cpp
@@ -161,6 +163,8 @@ list(APPEND armnnRefBackendWorkloads_sources
RefReshapeWorkload.hpp
RefResizeWorkload.cpp
RefResizeWorkload.hpp
+ RefReverseV2Workload.cpp
+ RefReverseV2Workload.hpp
RefShapeWorkload.hpp
RefSliceWorkload.cpp
RefSliceWorkload.hpp
diff --git a/src/backends/reference/workloads/RefReverseV2Workload.cpp b/src/backends/reference/workloads/RefReverseV2Workload.cpp
new file mode 100644
index 0000000000..cd2d9f930b
--- /dev/null
+++ b/src/backends/reference/workloads/RefReverseV2Workload.cpp
@@ -0,0 +1,48 @@
+//
+// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "RefReverseV2Workload.hpp"
+
+#include "ReverseV2Impl.hpp"
+#include "RefWorkloadUtils.hpp"
+#include "Profiling.hpp"
+
+namespace armnn
+{
+
+ RefReverseV2Workload::RefReverseV2Workload(const ReverseV2QueueDescriptor& descriptor, const WorkloadInfo& info)
+ : RefBaseWorkload(descriptor, info)
+ {}
+
+ void RefReverseV2Workload::Execute() const
+ {
+ Execute(m_Data.m_Inputs, m_Data.m_Outputs);
+ }
+
+ void RefReverseV2Workload::ExecuteAsync(ExecutionData& executionData)
+ {
+ WorkingMemDescriptor* workingMemDescriptor = static_cast<WorkingMemDescriptor*>(executionData.m_Data);
+ Execute(workingMemDescriptor->m_Inputs, workingMemDescriptor->m_Outputs);
+ }
+
+ void RefReverseV2Workload::Execute(std::vector<ITensorHandle*> inputs, std::vector<ITensorHandle*> outputs) const
+ {
+ ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefReverseV2Workload_Execute");
+
+ const TensorInfo& inputInfo = GetTensorInfo(inputs[0]);
+
+ std::unique_ptr<Decoder<float>> inputDecoder = MakeDecoder<float>(GetTensorInfo(inputs[0]),
+ inputs[0]->Map());
+
+ std::unique_ptr<Encoder<float>> outputEncoder = MakeEncoder<float>(GetTensorInfo(outputs[0]),
+ outputs[0]->Map());
+
+ ReverseV2(m_Data.m_Parameters,
+ inputInfo,
+ *inputDecoder,
+ *outputEncoder);
+ }
+
+} // namespace armnn \ No newline at end of file
diff --git a/src/backends/reference/workloads/RefReverseV2Workload.hpp b/src/backends/reference/workloads/RefReverseV2Workload.hpp
new file mode 100644
index 0000000000..89e7c9ea38
--- /dev/null
+++ b/src/backends/reference/workloads/RefReverseV2Workload.hpp
@@ -0,0 +1,30 @@
+//
+// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "RefBaseWorkload.hpp"
+#include <armnn/backends/WorkloadData.hpp>
+
+#include "ReverseV2Impl.hpp"
+
+namespace armnn
+{
+
+ class RefReverseV2Workload : public RefBaseWorkload<ReverseV2QueueDescriptor>
+ {
+ public:
+ explicit RefReverseV2Workload(const ReverseV2QueueDescriptor& descriptor,
+ const WorkloadInfo& info);
+
+ void Execute() const override;
+ void ExecuteAsync(ExecutionData& executionData) override;
+
+ private:
+ void Execute(std::vector<ITensorHandle*> inputs, std::vector<ITensorHandle*> outputs) const;
+
+ };
+
+} // namespace armnn \ No newline at end of file
diff --git a/src/backends/reference/workloads/RefWorkloads.hpp b/src/backends/reference/workloads/RefWorkloads.hpp
index dba880bafc..e15a7ca047 100644
--- a/src/backends/reference/workloads/RefWorkloads.hpp
+++ b/src/backends/reference/workloads/RefWorkloads.hpp
@@ -53,6 +53,7 @@
#include "RefReduceWorkload.hpp"
#include "RefReshapeWorkload.hpp"
#include "RefResizeWorkload.hpp"
+#include "RefReverseV2Workload.hpp"
#include "RefShapeWorkload.hpp"
#include "RefSliceWorkload.hpp"
#include "RefSplitterWorkload.hpp"
diff --git a/src/backends/reference/workloads/ReverseV2Impl.cpp b/src/backends/reference/workloads/ReverseV2Impl.cpp
new file mode 100644
index 0000000000..f6d5fd74d1
--- /dev/null
+++ b/src/backends/reference/workloads/ReverseV2Impl.cpp
@@ -0,0 +1,133 @@
+//
+// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "ReverseV2Impl.hpp"
+
+#include <armnn/backends/WorkloadData.hpp>
+#include <armnn/Logging.hpp>
+#include <armnnUtils/Permute.hpp>
+
+namespace armnn
+{
+
+// Get multi-dimensional index for input tensor
+std::vector<unsigned int> ReverseGetMultIdx(const unsigned int idx,
+ unsigned int inputRank,
+ std::vector<unsigned int>& elementNumInner)
+{
+ std::vector<unsigned int> indexList(inputRank);
+
+ unsigned int mIdx = idx;
+
+ for (unsigned int iDim = 0; iDim < inputRank; ++iDim)
+ {
+ indexList[iDim] = static_cast<unsigned int>(mIdx / elementNumInner[iDim]);
+ mIdx %= elementNumInner[iDim];
+ }
+
+ return indexList;
+}
+
+// Get flattened index for output encoder
+unsigned int ReverseGetFlatIdx(const std::vector<unsigned int>& idxList,
+ unsigned int inputRank,
+ std::vector<unsigned int>& elementNumInner)
+{
+ unsigned int idx = 0;
+
+ for (unsigned int iDim = 0; iDim < inputRank; ++iDim)
+ {
+ idx += idxList[iDim] * elementNumInner[iDim];
+ }
+
+ return idx;
+}
+
+// Relocate the coordinate to the reversed tensor
+unsigned int ReverseRelocateIdx(unsigned int idx,
+ unsigned int inputRank,
+ std::vector<bool>& axisFlag,
+ std::vector<unsigned int>& dimSize,
+ std::vector<unsigned int>& elementNumInner)
+{
+ // Get the multidimensional index list for input
+ auto inputIdxList = ReverseGetMultIdx(idx, inputRank, elementNumInner);
+
+ std::vector<unsigned int> outputIdxList(inputRank);
+
+ // Relocate the input index to the output one
+ for (unsigned int iDim = 0; iDim < inputRank; ++iDim)
+ {
+ if (axisFlag[iDim])
+ {
+ outputIdxList[iDim] = dimSize[iDim] - inputIdxList[iDim] - 1;
+ }
+ else
+ {
+ outputIdxList[iDim] = inputIdxList[iDim];
+ }
+ }
+
+ // Get the 1-dimensional flattened index for output
+ unsigned int outputIdx = ReverseGetFlatIdx(outputIdxList, inputRank, elementNumInner);
+ return outputIdx;
+}
+
+void ReverseV2(const ReverseV2Descriptor& params,
+ const TensorInfo& inputInfo,
+ Decoder<float>& inputDecoder,
+ Encoder<float>& outputEncoder)
+{
+ // Empty axis and empty tensor case: copy input to output
+ if (params.m_Axis.empty() || inputInfo.GetNumElements() == 0)
+ {
+ for (unsigned idx = 0; idx < inputInfo.GetNumElements(); idx++)
+ {
+ float inputValue = inputDecoder.Get();
+ inputDecoder += 1;
+ outputEncoder.Set(inputValue);
+ outputEncoder += 1;
+ }
+ return;
+ }
+
+ unsigned int inputRank = static_cast<unsigned int>(inputInfo.GetNumDimensions());
+
+ std::vector<bool>axisFlag(inputRank, false);
+ std::vector<unsigned int>dimSize(inputRank, 0);
+
+ // Make sure the axes are positive
+ for (int32_t axisElement: params.m_Axis)
+ {
+ axisElement = axisElement < 0 ? axisElement + static_cast<int32_t>(inputRank) : axisElement;
+ axisFlag[static_cast<uint32_t>(axisElement)] = true;
+ }
+
+ const TensorShape &inputShape = inputInfo.GetShape();
+
+ unsigned int elementNum = inputInfo.GetNumElements();
+ unsigned int baseDimSize = 1;
+
+ std::vector<unsigned int> elementNumInner;
+
+ // Get the number of element within the specific dimension
+ for (unsigned int iDim = 0; iDim < inputRank; ++iDim) {
+ dimSize[iDim] = inputShape[iDim];
+ baseDimSize *= dimSize[iDim];
+ elementNumInner.push_back(static_cast<unsigned int>(elementNum / baseDimSize));
+ }
+
+ // Iterate through all elements
+ for (unsigned int idx = 0; idx < elementNum; ++idx)
+ {
+ float inputValue = inputDecoder.Get();
+ inputDecoder += 1;
+ auto outputIdx = ReverseRelocateIdx(idx, inputRank, axisFlag, dimSize, elementNumInner);
+ outputEncoder[outputIdx];
+ outputEncoder.Set(inputValue);
+ }
+}
+
+} // namespace armnn \ No newline at end of file
diff --git a/src/backends/reference/workloads/ReverseV2Impl.hpp b/src/backends/reference/workloads/ReverseV2Impl.hpp
new file mode 100644
index 0000000000..bc1fe1d432
--- /dev/null
+++ b/src/backends/reference/workloads/ReverseV2Impl.hpp
@@ -0,0 +1,21 @@
+//
+// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "Encoders.hpp"
+#include "Decoders.hpp"
+
+#include <armnn/backends/WorkloadData.hpp>
+
+namespace armnn
+{
+
+void ReverseV2(const ReverseV2Descriptor& params,
+ const TensorInfo& inputInfo,
+ Decoder<float>& inputDecoder,
+ Encoder<float>& outputEncoder);
+
+} // namespace armnn \ No newline at end of file