Add Resize Nearest Neighbour support to TOSA Reference Backend

* Add support for quantized data in TosaRefPreCompiledWorkloadGetOutput.
* Remove extra includes from all TOSA operators headers.
* Added positive and negative unit tests for resize.

* Resolves: IVGCVSW-7346

Signed-off-by: Teresa Charlin <teresa.charlinreyes@arm.com>
Change-Id: Ib6e30d018a7a1bf26b380fc794560aae108b26c3
diff --git a/src/backends/tosaReference/TosaRefLayerSupport.cpp b/src/backends/tosaReference/TosaRefLayerSupport.cpp
index e1c349f..04be52d 100644
--- a/src/backends/tosaReference/TosaRefLayerSupport.cpp
+++ b/src/backends/tosaReference/TosaRefLayerSupport.cpp
@@ -71,6 +71,7 @@
         case LayerType::ElementwiseUnary:
         case LayerType::Pooling2d:
         case LayerType::Reshape:
+        case LayerType::Resize:
         case LayerType::Slice:
         case LayerType::Transpose:
             inputInfos.push_back(&infos[0]);
diff --git a/src/backends/tosaReference/test/TosaRefEndToEndTests.cpp b/src/backends/tosaReference/test/TosaRefEndToEndTests.cpp
index 26cadd2..b35dacb 100644
--- a/src/backends/tosaReference/test/TosaRefEndToEndTests.cpp
+++ b/src/backends/tosaReference/test/TosaRefEndToEndTests.cpp
@@ -11,6 +11,7 @@
 #include "backendsCommon/test/MultiplicationEndToEndTestImpl.hpp"
 #include "backendsCommon/test/Pooling2dEndToEndTestImpl.hpp"
 #include "backendsCommon/test/ReshapeEndToEndTestImpl.hpp"
+#include "backendsCommon/test/ResizeEndToEndTestImpl.hpp"
 #include "backendsCommon/test/ElementwiseUnaryEndToEndTestImpl.hpp"
 #include "backendsCommon/test/SliceEndToEndTestImpl.hpp"
 #include "backendsCommon/test/SubtractionEndToEndTestImpl.hpp"
@@ -145,6 +146,47 @@
                                                              UnaryOperation::Rsqrt);
 }
 
+// Resize
+TEST_CASE("TosaRefResizeNearestNeighborEndToEndFloat32AlignCornersNhwcTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::Float32>(tosaDefaultBackends, armnn::DataLayout::NHWC, true, false);
+}
+
+TEST_CASE("TosaRefResizeNearestNeighborEndToEndFloat32HalfPixelNhwcTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::Float32>(tosaDefaultBackends, armnn::DataLayout::NHWC, false, true);
+}
+
+TEST_CASE("TosaRefResizeNearestNeighborEndToEndFloat16AlignCornersNhwcTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::Float16>(tosaDefaultBackends, armnn::DataLayout::NHWC, true, false);
+}
+
+TEST_CASE("TosaRefResizeNearestNeighborEndToEndFloat16HalfPixelNhwcTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::Float16>(tosaDefaultBackends, armnn::DataLayout::NHWC, false, true);
+}
+
+TEST_CASE("TosaRefResizeNearestNeighborEndToEndInt8AlignCornersNhwcTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::QSymmS8>(tosaDefaultBackends, armnn::DataLayout::NHWC, true, false);
+}
+
+TEST_CASE("TosaRefResizeNearestNeighborEndToEndInt8HalfPixelNhwcTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::QSymmS8>(tosaDefaultBackends, armnn::DataLayout::NHWC, false, true);
+}
+
+TEST_CASE("TosaRefResizeNearestNeighborEndToEndInt16AlignCornersNhwcTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::QSymmS16>(tosaDefaultBackends, armnn::DataLayout::NHWC, true, false);
+}
+
+TEST_CASE("TosaRefResizeNearestNeighborEndToEndInt16HalfPixelNhwcTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::QSymmS16>(tosaDefaultBackends, armnn::DataLayout::NHWC, false, true);
+}
+
 // Slice
 TEST_CASE("TosaRefSliceEndtoEndTestFloat32")
 {
diff --git a/src/backends/tosaReference/test/TosaRefLayerSupportTests.cpp b/src/backends/tosaReference/test/TosaRefLayerSupportTests.cpp
index e32894f..fb4c84f 100644
--- a/src/backends/tosaReference/test/TosaRefLayerSupportTests.cpp
+++ b/src/backends/tosaReference/test/TosaRefLayerSupportTests.cpp
@@ -352,6 +352,30 @@
     CHECK(supported);
 }
 
+TEST_CASE("IsLayerSupportedTosaReferenceResize")
+{
+    TensorShape inShape  = { 1, 720, 1280, 3 };
+    TensorShape outShape = { 1, 1080, 1920, 3 };
+    TensorInfo in(inShape, DataType::Float32);
+    TensorInfo out(outShape, DataType::Float32);
+
+    ResizeDescriptor descriptor;
+    descriptor.m_DataLayout = armnn::DataLayout::NHWC;
+    descriptor.m_TargetHeight = 1080;
+    descriptor.m_TargetWidth = 1920;
+
+    TosaRefLayerSupport supportChecker;
+    std::string reasonIfNotSupported;
+    auto supported = supportChecker.IsLayerSupported(LayerType::Resize,
+                                                     {in, out},
+                                                     descriptor,
+                                                     EmptyOptional(),
+                                                     EmptyOptional(),
+                                                     reasonIfNotSupported);
+
+    CHECK(supported);
+}
+
 TEST_CASE("IsLayerSupportedTosaReferenceReshapeUnsupported")
 {
     TensorShape inShape = {3,4};
diff --git a/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.cpp b/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.cpp
index 8b08f01..5e4103a 100644
--- a/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.cpp
+++ b/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.cpp
@@ -50,9 +50,15 @@
                 SetInput<float>(runner, inputNames[inputSlotIdx], inputSlotIdx);
                 break;
             case DataType::QAsymmU8:
+                SetInput<uint8_t, int32_t>(runner, inputNames[inputSlotIdx], inputSlotIdx);
+                break;
             case DataType::QAsymmS8:
             case DataType::QSymmS8:
+                SetInput<int8_t, int32_t>(runner, inputNames[inputSlotIdx], inputSlotIdx);
+                break;
             case DataType::QSymmS16:
+                SetInput<int16_t, int32_t>(runner, inputNames[inputSlotIdx], inputSlotIdx);
+                break;
             case DataType::Signed32:
                 SetInput<int32_t>(runner, inputNames[inputSlotIdx], inputSlotIdx);
                 break;
@@ -87,9 +93,15 @@
                 GetOutput<float>(runner, outputNames[outputSlotIdx], outputSlotIdx);
                 break;
             case DataType::QAsymmU8:
+                GetOutput<uint8_t, int32_t>(runner, outputNames[outputSlotIdx], outputSlotIdx);
+                break;
             case DataType::QAsymmS8:
             case DataType::QSymmS8:
+                GetOutput<int8_t, int32_t>(runner, outputNames[outputSlotIdx], outputSlotIdx);
+                break;
             case DataType::QSymmS16:
+                GetOutput<int16_t, int32_t>(runner, outputNames[outputSlotIdx], outputSlotIdx);
+                break;
             case DataType::Signed32:
                 GetOutput<int32_t>(runner, outputNames[outputSlotIdx], outputSlotIdx);
                 break;
@@ -110,10 +122,23 @@
                                           std::string inputName,
                                           uint32_t inputIndex) const
 {
+    SetInput<T, T>(runner, inputName, inputIndex);
+}
+
+template <typename T, typename Trunner>
+void TosaRefPreCompiledWorkload::SetInput(TosaReference::IModelRunner& runner,
+                                          std::string inputName,
+                                          uint32_t inputIndex) const
+{
     std::vector<T> inputData(m_Data.m_Inputs[inputIndex]->GetShape().GetNumElements());
+    std::vector<Trunner> inputDataRunner(m_Data.m_Inputs[inputIndex]->GetShape().GetNumElements());
+
     m_Data.m_Inputs[inputIndex]->CopyOutTo(inputData.data());
 
-    runner.setInput<T>(inputName, inputData);
+    std::transform(inputData.begin(), inputData.end(),
+                   inputDataRunner.begin(), [](T x) { return static_cast<Trunner>(x);});
+
+    runner.setInput<Trunner>(inputName, inputDataRunner);
 }
 
 template <typename T>
@@ -121,7 +146,19 @@
                                            std::string outputName,
                                            uint32_t outputIndex) const
 {
-    std::vector<T> actualOutputs = runner.getOutput<T>(outputName);
+    GetOutput<T, T>(runner, outputName, outputIndex);
+}
+
+template <typename T, typename Trunner>
+void TosaRefPreCompiledWorkload::GetOutput(TosaReference::IModelRunner& runner,
+                                           std::string outputName,
+                                           uint32_t outputIndex) const
+{
+    std::vector<Trunner> actualOutputsRunner = runner.getOutput<Trunner>(outputName);
+    std::vector<T> actualOutputs (actualOutputsRunner.size());
+
+    std::transform(actualOutputsRunner.begin(), actualOutputsRunner.end(),
+                   actualOutputs.begin(), [](Trunner x) { return static_cast<T>(x);});
 
     m_Data.m_Outputs[outputIndex]->CopyInFrom(actualOutputs.data());
 }
diff --git a/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.hpp b/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.hpp
index 2b3a314..337e8f9 100644
--- a/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.hpp
+++ b/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.hpp
@@ -42,9 +42,15 @@
         this->m_Data.m_Outputs[slot] = tensorHandle;
     }
 
+    template <typename T, typename Trunner>
+    void SetInput(TosaReference::IModelRunner& runner, std::string inputName, uint32_t inputIndex) const;
+
     template <typename T>
     void SetInput(TosaReference::IModelRunner& runner, std::string inputName, uint32_t inputIndex) const;
 
+    template <typename T, typename Trunner>
+    void GetOutput(TosaReference::IModelRunner& runner, std::string outputName, uint32_t outputIndex) const;
+
     template <typename T>
     void GetOutput(TosaReference::IModelRunner& runner, std::string outputName, uint32_t outputIndex) const;