IVGCVSW-7835 Add ReverseV2 CL and Neon Workloads

 * Added ReverseV2 to CL and Neon backends
 * Added Cl and Neon ReverseV2 Layer unit tests

Signed-off-by: Tianle Cheng <tianle.cheng@arm.com>
Change-Id: I646275c629caf17dac1950b0cd7083f23f87f387
diff --git a/src/backends/cl/ClLayerSupport.cpp b/src/backends/cl/ClLayerSupport.cpp
index 1acaba0..bfe4f6e 100644
--- a/src/backends/cl/ClLayerSupport.cpp
+++ b/src/backends/cl/ClLayerSupport.cpp
@@ -70,6 +70,7 @@
 #include "workloads/ClReduceWorkload.hpp"
 #include "workloads/ClReshapeWorkload.hpp"
 #include "workloads/ClResizeWorkload.hpp"
+#include "workloads/ClReverseV2Workload.hpp"
 #include "workloads/ClRsqrtWorkload.hpp"
 #include "workloads/ClSinWorkload.hpp"
 #include "workloads/ClSliceWorkload.hpp"
@@ -571,6 +572,11 @@
                                      infos[1],
                                      *(PolymorphicDowncast<const ResizeDescriptor*>(&descriptor)),
                                      reasonIfUnsupported);
+        case LayerType::ReverseV2:
+            return IsReverseV2Supported(infos[0],
+                                        infos[1],
+                                        infos[2],
+                                        reasonIfUnsupported);
         case LayerType::Shape:
             return LayerSupportBase::IsShapeSupported(infos[0],
                                                       infos[1],
@@ -1423,6 +1429,18 @@
     FORWARD_WORKLOAD_VALIDATE_FUNC(ClResizeWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
 }
 
+bool ClLayerSupport::IsReverseV2Supported(const TensorInfo& input,
+                                          const TensorInfo& axis,
+                                          const TensorInfo& output,
+                                          Optional<std::string&> reasonIfUnsupported) const
+{
+    FORWARD_WORKLOAD_VALIDATE_FUNC(ClReverseV2WorkloadValidate,
+                                   reasonIfUnsupported,
+                                   input,
+                                   axis,
+                                   output);
+}
+
 bool ClLayerSupport::IsSliceSupported(const TensorInfo& input,
                                       const TensorInfo& output,
                                       const SliceDescriptor& descriptor,
diff --git a/src/backends/cl/ClLayerSupport.hpp b/src/backends/cl/ClLayerSupport.hpp
index 9a8f896..907db01 100644
--- a/src/backends/cl/ClLayerSupport.hpp
+++ b/src/backends/cl/ClLayerSupport.hpp
@@ -295,6 +295,11 @@
                            const ResizeDescriptor& descriptor,
                            Optional<std::string&> reasonIfUnsupported = EmptyOptional()) const;
 
+    bool IsReverseV2Supported(const TensorInfo& input,
+                              const TensorInfo& axis,
+                              const TensorInfo& output,
+                              Optional<std::string&> reasonIfUnsupported) const;
+
     bool IsSliceSupported(const TensorInfo& input,
                           const TensorInfo& output,
                           const SliceDescriptor& descriptor,
diff --git a/src/backends/cl/ClWorkloadFactory.cpp b/src/backends/cl/ClWorkloadFactory.cpp
index da05f67..6fe4264 100644
--- a/src/backends/cl/ClWorkloadFactory.cpp
+++ b/src/backends/cl/ClWorkloadFactory.cpp
@@ -711,6 +711,11 @@
             auto resizeQueueDescriptor = PolymorphicDowncast<const ResizeQueueDescriptor*>(&descriptor);
             return MakeWorkload<ClResizeWorkload>(*resizeQueueDescriptor, info, m_CLCompileContext);
         }
+        case LayerType::ReverseV2:
+        {
+            auto reverseV2QueueDescriptor = PolymorphicDowncast<const ReverseV2QueueDescriptor*>(&descriptor);
+            return MakeWorkload<ClReverseV2Workload>(*reverseV2QueueDescriptor, info, m_CLCompileContext);
+        }
         case LayerType::Slice :
         {
             auto sliceQueueDescriptor = PolymorphicDowncast<const SliceQueueDescriptor*>(&descriptor);
diff --git a/src/backends/cl/backend.mk b/src/backends/cl/backend.mk
index 3499305..2143c30 100644
--- a/src/backends/cl/backend.mk
+++ b/src/backends/cl/backend.mk
@@ -79,6 +79,7 @@
         workloads/ClReduceWorkload.cpp \
         workloads/ClReshapeWorkload.cpp \
         workloads/ClResizeWorkload.cpp \
+        workloads/ClReverseV2Workload.cpp \
         workloads/ClRsqrtWorkload.cpp \
         workloads/ClSinWorkload.cpp \
         workloads/ClSliceWorkload.cpp \
diff --git a/src/backends/cl/test/ClEndToEndTests.cpp b/src/backends/cl/test/ClEndToEndTests.cpp
index 50ba1db..2436a82 100644
--- a/src/backends/cl/test/ClEndToEndTests.cpp
+++ b/src/backends/cl/test/ClEndToEndTests.cpp
@@ -22,6 +22,7 @@
 #include <backendsCommon/test/QuantizedLstmEndToEndTestImpl.hpp>
 #include <backendsCommon/test/ReduceEndToEndTestImpl.hpp>
 #include <backendsCommon/test/ReshapeEndToEndTestImpl.hpp>
+#include <backendsCommon/test/ReverseV2EndToEndTestImpl.hpp>
 #include <backendsCommon/test/SliceEndToEndTestImpl.hpp>
 #include <backendsCommon/test/SpaceToDepthEndToEndTestImpl.hpp>
 #include <backendsCommon/test/SplitterEndToEndTestImpl.hpp>
@@ -345,6 +346,12 @@
     ReshapeEndToEndFloat16<armnn::DataType::Float16>(clDefaultBackends);
 }
 
+// ReverseV2
+TEST_CASE("ClReverseV2EndToEndTest")
+{
+    ReverseV2EndToEnd<armnn::DataType::Float32>(clDefaultBackends);
+}
+
 // Space to depth
 TEST_CASE("ClSpaceToDepthNhwcEndToEndTest1")
 {
diff --git a/src/backends/cl/test/ClLayerTests.cpp b/src/backends/cl/test/ClLayerTests.cpp
index a596a01..da2b967 100644
--- a/src/backends/cl/test/ClLayerTests.cpp
+++ b/src/backends/cl/test/ClLayerTests.cpp
@@ -2015,6 +2015,35 @@
                                  AlignCornersResizeNearestNeighbourTest<DataType::QAsymmU8>,
                                  DataLayout::NHWC)
 
+// ReverseV2
+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>)
+
 // Rsqrt
 ARMNN_AUTO_TEST_FIXTURE_WITH_THF(Rsqrt2d, ClContextControlFixture, Rsqrt2dTest<DataType::Float32>)
 ARMNN_AUTO_TEST_FIXTURE_WITH_THF(Rsqrt3d, ClContextControlFixture, Rsqrt3dTest<DataType::Float32>)
diff --git a/src/backends/cl/workloads/CMakeLists.txt b/src/backends/cl/workloads/CMakeLists.txt
index cb16ab1..f38366f 100644
--- a/src/backends/cl/workloads/CMakeLists.txt
+++ b/src/backends/cl/workloads/CMakeLists.txt
@@ -109,6 +109,8 @@
     ClReshapeWorkload.hpp
     ClResizeWorkload.cpp
     ClResizeWorkload.hpp
+    ClReverseV2Workload.cpp
+    ClReverseV2Workload.hpp
     ClRsqrtWorkload.cpp
     ClRsqrtWorkload.hpp
     ClSinWorkload.cpp
diff --git a/src/backends/cl/workloads/ClReverseV2Workload.cpp b/src/backends/cl/workloads/ClReverseV2Workload.cpp
new file mode 100644
index 0000000..8802d33
--- /dev/null
+++ b/src/backends/cl/workloads/ClReverseV2Workload.cpp
@@ -0,0 +1,50 @@
+//
+// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "ClReverseV2Workload.hpp"
+#include "ClWorkloadUtils.hpp"
+#include <aclCommon/ArmComputeUtils.hpp>
+#include <cl/ClTensorHandle.hpp>
+#include <backendsCommon/WorkloadUtils.hpp>
+
+using namespace armnn::armcomputetensorutils;
+
+namespace armnn
+{
+arm_compute::Status ClReverseV2WorkloadValidate(const TensorInfo& input,
+                                                const TensorInfo& axis,
+                                                const TensorInfo& output)
+{
+    const arm_compute::TensorInfo aclInput = BuildArmComputeTensorInfo(input);
+    const arm_compute::TensorInfo aclAxis = BuildArmComputeTensorInfo(axis);
+    const arm_compute::TensorInfo aclOutput = BuildArmComputeTensorInfo(output);
+
+    return arm_compute::CLReverse::validate(&aclInput, &aclOutput, &aclAxis, true);
+}
+
+ClReverseV2Workload::ClReverseV2Workload(const armnn::ReverseV2QueueDescriptor &descriptor,
+                                         const armnn::WorkloadInfo &info,
+                                         const arm_compute::CLCompileContext& clCompileContext)
+        : BaseWorkload<ReverseV2QueueDescriptor>(descriptor, info)
+{
+    m_Data.ValidateInputsOutputs("ClReverseV2Workload", 2, 1);
+
+    arm_compute::ICLTensor& input = static_cast<IClTensorHandle*>(m_Data.m_Inputs[0])->GetTensor();
+    arm_compute::ICLTensor& axis = static_cast<IClTensorHandle*>(m_Data.m_Inputs[1])->GetTensor();
+    arm_compute::ICLTensor& output = static_cast<IClTensorHandle*>(m_Data.m_Outputs[0])->GetTensor();
+
+    {
+        ARMNN_SCOPED_PROFILING_EVENT_CL_NAME_GUID("ClReverseV2Workload_configure");
+        m_Layer.configure(clCompileContext, &input, &output, &axis, true);
+    }
+}
+
+void ClReverseV2Workload::Execute() const
+{
+    ARMNN_SCOPED_PROFILING_EVENT_CL_NAME_GUID("ClReverseV2Workload_Execute");
+    m_Layer.run();
+}
+
+} //namespace armnn
\ No newline at end of file
diff --git a/src/backends/cl/workloads/ClReverseV2Workload.hpp b/src/backends/cl/workloads/ClReverseV2Workload.hpp
new file mode 100644
index 0000000..60d4a50
--- /dev/null
+++ b/src/backends/cl/workloads/ClReverseV2Workload.hpp
@@ -0,0 +1,33 @@
+//
+// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "ClBaseWorkload.hpp"
+
+#include <arm_compute/runtime/CL/functions/CLReverse.h>
+#include <arm_compute/runtime/Tensor.h>
+#include "arm_compute/runtime/CL/CLTensor.h"
+
+namespace armnn
+{
+arm_compute::Status ClReverseV2WorkloadValidate(const TensorInfo& input,
+                                                const TensorInfo& axis,
+                                                const TensorInfo& output);
+
+class ClReverseV2Workload : public BaseWorkload<ReverseV2QueueDescriptor> 
+{
+public:
+    ClReverseV2Workload(const ReverseV2QueueDescriptor &descriptor,
+                        const WorkloadInfo &info,
+                        const arm_compute::CLCompileContext& clCompileContext);
+
+    void Execute() const override;
+
+private:
+    mutable arm_compute::CLReverse m_Layer;
+};
+
+} //namespace armnn
\ No newline at end of file
diff --git a/src/backends/cl/workloads/ClWorkloads.hpp b/src/backends/cl/workloads/ClWorkloads.hpp
index cec8706..40b3e99 100644
--- a/src/backends/cl/workloads/ClWorkloads.hpp
+++ b/src/backends/cl/workloads/ClWorkloads.hpp
@@ -55,6 +55,7 @@
 #include "ClReduceWorkload.hpp"
 #include "ClReshapeWorkload.hpp"
 #include "ClResizeWorkload.hpp"
+#include "ClReverseV2Workload.hpp"
 #include "ClRsqrtWorkload.hpp"
 #include "ClSinWorkload.hpp"
 #include "ClSliceWorkload.hpp"