aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeresa Charlin <teresa.charlinreyes@arm.com>2023-11-21 15:44:13 +0000
committerTeresaARM <teresa.charlinreyes@arm.com>2023-12-13 14:33:54 +0000
commitce65588484ed1e553bdebf24123a30b5575f1bce (patch)
treeba5229241cdeee6d9c6ed0c0db9ffbd510574b34
parent1685bcca5dae227d90be62b36d66e9897298ce84 (diff)
downloadarmnn-ce65588484ed1e553bdebf24123a30b5575f1bce.tar.gz
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
-rw-r--r--AUTHORS-TensorFlow11
-rw-r--r--src/backends/backendsCommon/WorkloadData.cpp1
-rw-r--r--src/backends/backendsCommon/test/ResizeEndToEndTestImpl.hpp62
-rw-r--r--src/backends/reference/RefLayerSupport.cpp3
-rw-r--r--src/backends/reference/test/RefEndToEndTests.cpp41
-rw-r--r--src/backends/tosaCommon/TosaMappings.cpp5
-rw-r--r--src/backends/tosaCommon/operatorMappings/CMakeLists.txt2
-rw-r--r--src/backends/tosaCommon/operatorMappings/ConcatOperator.hpp6
-rw-r--r--src/backends/tosaCommon/operatorMappings/ConstantOperator.hpp6
-rw-r--r--src/backends/tosaCommon/operatorMappings/Conv2dOperator.hpp6
-rw-r--r--src/backends/tosaCommon/operatorMappings/ElementwiseBinaryOperator.hpp6
-rw-r--r--src/backends/tosaCommon/operatorMappings/ElementwiseUnaryOperator.hpp3
-rw-r--r--src/backends/tosaCommon/operatorMappings/Pooling2DOperator.hpp6
-rw-r--r--src/backends/tosaCommon/operatorMappings/ReshapeOperator.hpp6
-rw-r--r--src/backends/tosaCommon/operatorMappings/ResizeOperator.cpp173
-rw-r--r--src/backends/tosaCommon/operatorMappings/ResizeOperator.hpp16
-rw-r--r--src/backends/tosaCommon/operatorMappings/SliceOperator.hpp6
-rw-r--r--src/backends/tosaCommon/operatorMappings/TosaCommonOperators.hpp1
-rw-r--r--src/backends/tosaCommon/operatorMappings/TransposeConv2dOperator.hpp6
-rw-r--r--src/backends/tosaCommon/operatorMappings/TransposeOperator.hpp6
-rw-r--r--src/backends/tosaCommon/test/OneToOneMappingTests.cpp142
-rw-r--r--src/backends/tosaCommon/test/TosaTestUtils.hpp57
-rw-r--r--src/backends/tosaReference/TosaRefLayerSupport.cpp1
-rw-r--r--src/backends/tosaReference/test/TosaRefEndToEndTests.cpp42
-rw-r--r--src/backends/tosaReference/test/TosaRefLayerSupportTests.cpp24
-rw-r--r--src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.cpp41
-rw-r--r--src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.hpp6
27 files changed, 619 insertions, 66 deletions
diff --git a/AUTHORS-TensorFlow b/AUTHORS-TensorFlow
new file mode 100644
index 0000000000..f4f92e15cb
--- /dev/null
+++ b/AUTHORS-TensorFlow
@@ -0,0 +1,11 @@
+# This is the official list of TensorFlow authors for copyright purposes.
+# This file is distinct from the CONTRIBUTORS files.
+# See the latter for an explanation.
+
+# Names should be added to this file as:
+# Name or Organization <email address>
+# The email address is not required for organizations.
+
+Google Inc.
+Yuan Tang <terrytangyuan@gmail.com>
+Arm Ltd \ No newline at end of file
diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp
index 021435ea40..2d7a5fdffc 100644
--- a/src/backends/backendsCommon/WorkloadData.cpp
+++ b/src/backends/backendsCommon/WorkloadData.cpp
@@ -1592,6 +1592,7 @@ void ResizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
DataType::Float32,
DataType::QAsymmS8,
DataType::QAsymmU8,
+ DataType::QSymmS8,
DataType::QSymmS16
};
diff --git a/src/backends/backendsCommon/test/ResizeEndToEndTestImpl.hpp b/src/backends/backendsCommon/test/ResizeEndToEndTestImpl.hpp
index f8d17a89b7..071daa7a31 100644
--- a/src/backends/backendsCommon/test/ResizeEndToEndTestImpl.hpp
+++ b/src/backends/backendsCommon/test/ResizeEndToEndTestImpl.hpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2017 Arm Ltd. All rights reserved.
+// Copyright © 2017, 2019-2023 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#pragma once
@@ -37,7 +37,9 @@ armnn::INetworkPtr CreateResizeNetwork(const armnn::ResizeDescriptor& descriptor
template<armnn::DataType ArmnnType>
void ResizeEndToEnd(const std::vector<armnn::BackendId>& backends,
armnn::DataLayout dataLayout,
- armnn::ResizeMethod resizeMethod)
+ armnn::ResizeMethod resizeMethod,
+ bool alignCorners = false,
+ bool halfPixel = false)
{
using namespace armnn;
using T = ResolveType<ArmnnType>;
@@ -64,6 +66,11 @@ void ResizeEndToEnd(const std::vector<armnn::BackendId>& backends,
7.f, 8.f, 9.f
};
+ if (alignCorners && halfPixel)
+ {
+ throw InvalidArgumentException("alignCorners and halfPixel cannot be true simultaneously ");
+ }
+
std::vector<float> expectedOutputData;
switch(resizeMethod)
{
@@ -81,14 +88,42 @@ void ResizeEndToEnd(const std::vector<armnn::BackendId>& backends,
}
case ResizeMethod::NearestNeighbor:
{
- expectedOutputData =
+ if (alignCorners)
{
- 1.f, 1.f, 2.f, 2.f, 3.f,
- 1.f, 1.f, 2.f, 2.f, 3.f,
- 4.f, 4.f, 5.f, 5.f, 6.f,
- 4.f, 4.f, 5.f, 5.f, 6.f,
- 7.f, 7.f, 8.f, 8.f, 9.f
- };
+ expectedOutputData =
+ {
+ 1.f, 2.f, 2.f, 3.f, 3.f,
+ 4.f, 5.f, 5.f, 6.f, 6.f,
+ 4.f, 5.f, 5.f, 6.f, 6.f,
+ 7.f, 8.f, 8.f, 9.f, 9.f,
+ 7.f, 8.f, 8.f, 9.f, 9.f
+ };
+ }
+ else
+ {
+ if (halfPixel)
+ {
+ expectedOutputData =
+ {
+ 1.f, 1.f, 2.f, 3.f, 3.f,
+ 1.f, 1.f, 2.f, 3.f, 3.f,
+ 4.f, 4.f, 5.f, 6.f, 6.f,
+ 7.f, 7.f, 8.f, 9.f, 9.f,
+ 7.f, 7.f, 8.f, 9.f, 9.f
+ };
+ }
+ else
+ {
+ expectedOutputData =
+ {
+ 1.f, 1.f, 2.f, 2.f, 3.f,
+ 1.f, 1.f, 2.f, 2.f, 3.f,
+ 4.f, 4.f, 5.f, 5.f, 6.f,
+ 4.f, 4.f, 5.f, 5.f, 6.f,
+ 7.f, 7.f, 8.f, 8.f, 9.f
+ };
+ }
+ }
break;
}
default:
@@ -102,6 +137,9 @@ void ResizeEndToEnd(const std::vector<armnn::BackendId>& backends,
descriptor.m_TargetHeight = outputHeight;
descriptor.m_Method = resizeMethod;
descriptor.m_DataLayout = dataLayout;
+ descriptor.m_AlignCorners = alignCorners;
+ descriptor.m_HalfPixelCenters = halfPixel;
+
// swizzle data if needed
if (dataLayout == armnn::DataLayout::NHWC)
@@ -137,7 +175,9 @@ void ResizeBilinearEndToEnd(const std::vector<armnn::BackendId>& backends,
template<armnn::DataType ArmnnType>
void ResizeNearestNeighborEndToEnd(const std::vector<armnn::BackendId>& backends,
- armnn::DataLayout dataLayout)
+ armnn::DataLayout dataLayout,
+ bool alignCorners = false,
+ bool halfPixel = false)
{
- ResizeEndToEnd<ArmnnType>(backends, dataLayout, armnn::ResizeMethod::NearestNeighbor);
+ ResizeEndToEnd<ArmnnType>(backends, dataLayout, armnn::ResizeMethod::NearestNeighbor, alignCorners, halfPixel);
}
diff --git a/src/backends/reference/RefLayerSupport.cpp b/src/backends/reference/RefLayerSupport.cpp
index 2be227ae8f..40d243e10a 100644
--- a/src/backends/reference/RefLayerSupport.cpp
+++ b/src/backends/reference/RefLayerSupport.cpp
@@ -2381,13 +2381,14 @@ bool RefLayerSupport::IsResizeSupported(const TensorInfo& input,
{
IgnoreUnused(descriptor);
bool supported = true;
- std::array<DataType,6> supportedTypes =
+ std::array<DataType,7> supportedTypes =
{
DataType::BFloat16,
DataType::Float32,
DataType::Float16,
DataType::QAsymmS8,
DataType::QAsymmU8,
+ DataType::QSymmS8,
DataType::QSymmS16
};
diff --git a/src/backends/reference/test/RefEndToEndTests.cpp b/src/backends/reference/test/RefEndToEndTests.cpp
index 13995f5c6f..7e07c658fa 100644
--- a/src/backends/reference/test/RefEndToEndTests.cpp
+++ b/src/backends/reference/test/RefEndToEndTests.cpp
@@ -1274,6 +1274,11 @@ TEST_CASE("RefResizeBilinearEndToEndUint8NchwTest")
ResizeBilinearEndToEnd<armnn::DataType::QAsymmU8>(defaultBackends, armnn::DataLayout::NCHW);
}
+TEST_CASE("RefResizeBilinearEndToEndInt8NchwTest")
+{
+ ResizeBilinearEndToEnd<armnn::DataType::QSymmS8>(defaultBackends, armnn::DataLayout::NCHW);
+}
+
TEST_CASE("RefResizeBilinearEndToEndInt16NchwTest")
{
ResizeBilinearEndToEnd<armnn::DataType::QSymmS16>(defaultBackends, armnn::DataLayout::NCHW);
@@ -1289,6 +1294,11 @@ TEST_CASE("RefResizeBilinearEndToEndUint8NhwcTest")
ResizeBilinearEndToEnd<armnn::DataType::QAsymmU8>(defaultBackends, armnn::DataLayout::NHWC);
}
+TEST_CASE("RefResizeBilinearEndToEndInt8NhwcTest")
+{
+ ResizeBilinearEndToEnd<armnn::DataType::QSymmS8>(defaultBackends, armnn::DataLayout::NHWC);
+}
+
TEST_CASE("RefResizeBilinearEndToEndInt16NhwcTest")
{
ResizeBilinearEndToEnd<armnn::DataType::QSymmS16>(defaultBackends, armnn::DataLayout::NHWC);
@@ -1305,6 +1315,11 @@ TEST_CASE("RefResizeNearestNeighborEndToEndUint8NchwTest")
ResizeNearestNeighborEndToEnd<armnn::DataType::QAsymmU8>(defaultBackends, armnn::DataLayout::NCHW);
}
+TEST_CASE("RefResizeNearestNeighborEndToEndInt8NchwTest")
+{
+ ResizeNearestNeighborEndToEnd<armnn::DataType::QAsymmS8>(defaultBackends, armnn::DataLayout::NCHW);
+}
+
TEST_CASE("RefResizeNearestNeighborEndToEndInt16NchwTest")
{
ResizeNearestNeighborEndToEnd<armnn::DataType::QSymmS16>(defaultBackends, armnn::DataLayout::NCHW);
@@ -1320,11 +1335,37 @@ TEST_CASE("RefResizeNearestNeighborEndToEndUint8NhwcTest")
ResizeNearestNeighborEndToEnd<armnn::DataType::QAsymmU8>(defaultBackends, armnn::DataLayout::NHWC);
}
+TEST_CASE("RefResizeNearestNeighborEndToEndInt8NhwcTest")
+{
+ ResizeNearestNeighborEndToEnd<armnn::DataType::QAsymmS8>(defaultBackends, armnn::DataLayout::NHWC);
+}
+
TEST_CASE("RefResizeNearestNeighborEndToEndInt16NhwcTest")
{
ResizeNearestNeighborEndToEnd<armnn::DataType::QSymmS16>(defaultBackends, armnn::DataLayout::NHWC);
}
+TEST_CASE("RefResizeNearestNeighborEndToEndFloatAlignCornersNhwcTest")
+{
+ ResizeNearestNeighborEndToEnd<armnn::DataType::Float32>(defaultBackends, armnn::DataLayout::NHWC, true, false);
+}
+
+TEST_CASE("RefResizeNearestNeighborEndToEndFloatHalfPixelNhwcTest")
+{
+ ResizeNearestNeighborEndToEnd<armnn::DataType::Float32>(defaultBackends, armnn::DataLayout::NHWC, false, true);
+}
+
+TEST_CASE("RefResizeNearestNeighborEndToEndInt8AlignCornersNhwcTest")
+{
+ ResizeNearestNeighborEndToEnd<armnn::DataType::QAsymmS8>(defaultBackends, armnn::DataLayout::NHWC, true, false);
+}
+
+TEST_CASE("TosaRefResizeNearestNeighborEndToEndInt8HalfPixelNhwcTest")
+{
+ ResizeNearestNeighborEndToEnd<armnn::DataType::QSymmS8>(defaultBackends, armnn::DataLayout::NHWC, false, true);
+}
+
+
// ReverseV2
TEST_CASE("RefReverseV2EndToEndFloat16Test")
{
diff --git a/src/backends/tosaCommon/TosaMappings.cpp b/src/backends/tosaCommon/TosaMappings.cpp
index a998996f19..6567026de0 100644
--- a/src/backends/tosaCommon/TosaMappings.cpp
+++ b/src/backends/tosaCommon/TosaMappings.cpp
@@ -74,6 +74,11 @@ TosaSerializationBasicBlock* GetTosaMapping(const Layer* layer,
auto reshapeDesc = PolymorphicDowncast<const ReshapeDescriptor*>(&descriptor);
return ConvertReshapeToTosaOperator(layer, inputs, outputs, reshapeDesc);
}
+ case LayerType::Resize:
+ {
+ auto resizeDesc = PolymorphicDowncast<const ResizeDescriptor*>(&descriptor);
+ return ConvertResizeToTosaOperator(layer, inputs, outputs, resizeDesc);
+ }
case LayerType::Slice:
{
auto sliceDesc = PolymorphicDowncast<const SliceDescriptor*>(&descriptor);
diff --git a/src/backends/tosaCommon/operatorMappings/CMakeLists.txt b/src/backends/tosaCommon/operatorMappings/CMakeLists.txt
index 26f51b643f..c864544241 100644
--- a/src/backends/tosaCommon/operatorMappings/CMakeLists.txt
+++ b/src/backends/tosaCommon/operatorMappings/CMakeLists.txt
@@ -20,6 +20,8 @@ list(APPEND armnnTosaBackendOperators_sources
Pooling2DOperator.cpp
ReshapeOperator.hpp
ReshapeOperator.cpp
+ ResizeOperator.hpp
+ ResizeOperator.cpp
SliceOperator.hpp
SliceOperator.cpp
TosaOperatorUtils.hpp
diff --git a/src/backends/tosaCommon/operatorMappings/ConcatOperator.hpp b/src/backends/tosaCommon/operatorMappings/ConcatOperator.hpp
index e6094ce03a..cbd7aca6e8 100644
--- a/src/backends/tosaCommon/operatorMappings/ConcatOperator.hpp
+++ b/src/backends/tosaCommon/operatorMappings/ConcatOperator.hpp
@@ -1,14 +1,10 @@
//
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#pragma once
-#include <Layer.hpp>
-
-#include <tosa_serialization_handler.h>
-
#include "TosaOperatorUtils.hpp"
using namespace armnn;
diff --git a/src/backends/tosaCommon/operatorMappings/ConstantOperator.hpp b/src/backends/tosaCommon/operatorMappings/ConstantOperator.hpp
index df158aca3d..598e041232 100644
--- a/src/backends/tosaCommon/operatorMappings/ConstantOperator.hpp
+++ b/src/backends/tosaCommon/operatorMappings/ConstantOperator.hpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
@@ -7,10 +7,6 @@
#include "TosaOperatorUtils.hpp"
-#include <Layer.hpp>
-
-#include <tosa_serialization_handler.h>
-
using namespace armnn;
using namespace tosa;
diff --git a/src/backends/tosaCommon/operatorMappings/Conv2dOperator.hpp b/src/backends/tosaCommon/operatorMappings/Conv2dOperator.hpp
index 909151b9ac..f22a8d2933 100644
--- a/src/backends/tosaCommon/operatorMappings/Conv2dOperator.hpp
+++ b/src/backends/tosaCommon/operatorMappings/Conv2dOperator.hpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
@@ -7,10 +7,6 @@
#include "TosaOperatorUtils.hpp"
-#include <Layer.hpp>
-
-#include <tosa_serialization_handler.h>
-
using namespace armnn;
using namespace tosa;
diff --git a/src/backends/tosaCommon/operatorMappings/ElementwiseBinaryOperator.hpp b/src/backends/tosaCommon/operatorMappings/ElementwiseBinaryOperator.hpp
index 86031c6e06..4966ed1659 100644
--- a/src/backends/tosaCommon/operatorMappings/ElementwiseBinaryOperator.hpp
+++ b/src/backends/tosaCommon/operatorMappings/ElementwiseBinaryOperator.hpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
@@ -7,10 +7,6 @@
#include "TosaOperatorUtils.hpp"
-#include <Layer.hpp>
-
-#include <tosa_serialization_handler.h>
-
using namespace armnn;
using namespace tosa;
diff --git a/src/backends/tosaCommon/operatorMappings/ElementwiseUnaryOperator.hpp b/src/backends/tosaCommon/operatorMappings/ElementwiseUnaryOperator.hpp
index d13428ca5a..635abd6f3c 100644
--- a/src/backends/tosaCommon/operatorMappings/ElementwiseUnaryOperator.hpp
+++ b/src/backends/tosaCommon/operatorMappings/ElementwiseUnaryOperator.hpp
@@ -6,9 +6,6 @@
#pragma once
#include "TosaOperatorUtils.hpp"
-#include <Layer.hpp>
-
-#include <tosa_serialization_handler.h>
using namespace armnn;
using namespace tosa;
diff --git a/src/backends/tosaCommon/operatorMappings/Pooling2DOperator.hpp b/src/backends/tosaCommon/operatorMappings/Pooling2DOperator.hpp
index cc9ec097f9..1323abc6a3 100644
--- a/src/backends/tosaCommon/operatorMappings/Pooling2DOperator.hpp
+++ b/src/backends/tosaCommon/operatorMappings/Pooling2DOperator.hpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
@@ -7,10 +7,6 @@
#include "TosaOperatorUtils.hpp"
-#include <Layer.hpp>
-
-#include <tosa_serialization_handler.h>
-
using namespace armnn;
using namespace tosa;
diff --git a/src/backends/tosaCommon/operatorMappings/ReshapeOperator.hpp b/src/backends/tosaCommon/operatorMappings/ReshapeOperator.hpp
index 4f363df052..007d2dfbb1 100644
--- a/src/backends/tosaCommon/operatorMappings/ReshapeOperator.hpp
+++ b/src/backends/tosaCommon/operatorMappings/ReshapeOperator.hpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
@@ -7,10 +7,6 @@
#include "TosaOperatorUtils.hpp"
-#include <Layer.hpp>
-
-#include <tosa_serialization_handler.h>
-
using namespace armnn;
using namespace tosa;
diff --git a/src/backends/tosaCommon/operatorMappings/ResizeOperator.cpp b/src/backends/tosaCommon/operatorMappings/ResizeOperator.cpp
new file mode 100644
index 0000000000..72c7352a65
--- /dev/null
+++ b/src/backends/tosaCommon/operatorMappings/ResizeOperator.cpp
@@ -0,0 +1,173 @@
+//
+// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+// Copyright © 2020, 2023 The TensorFlow Authors. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#include <numeric>
+#include "ResizeOperator.hpp"
+
+// This function is paraphrased from:
+// tensorflow/compiler/mlir/tosa/transforms/legalize_common.cc from function convertResizeOp
+// tensorflow/lite/kernels/internal/reference/resize_utils.h
+TosaSerializationBasicBlock* ConvertResizeToTosaOperator(const Layer* layer,
+ const std::vector<const TensorInfo*>& inputs,
+ const std::vector<const TensorInfo*>& outputs,
+ const ResizeDescriptor* resizeDescriptor)
+{
+ ARMNN_THROW_INVALIDARG_MSG_IF_FALSE( inputs.size() == 1,
+ "ConvertResizeToTosaOperator: Resize must have only one input." );
+ ARMNN_THROW_INVALIDARG_MSG_IF_FALSE( resizeDescriptor->m_DataLayout == DataLayout::NHWC,
+ "ConvertResizeToTosaOperator: NCHW not supported.");
+
+ ResizeMode mode;
+ if (resizeDescriptor->m_Method == ResizeMethod::NearestNeighbor)
+ {
+ mode = tosa::ResizeMode_NEAREST;
+ }
+ else if (resizeDescriptor->m_Method == ResizeMethod::Bilinear)
+ {
+ mode = tosa::ResizeMode_BILINEAR;
+ throw armnn::InvalidArgumentException("ConvertResizeToTosaOperator: Unimplemented Resize method.");
+ }
+ else
+ {
+ throw armnn::InvalidArgumentException("ConvertResizeToTosaOperator: Unsupported Resize method.");
+ }
+
+ std::string inputName = std::string("input0_");
+ std::string outputName = std::string("output0_");
+ std::string blockName = std::string("Op_RESIZE_block_") + GetUniqueTosaMappingID();
+
+ // If a layer is present then the block will be used for execution, so input and output names need to be determined
+ // using the previous and following layers so the graph is connected correctly. For validation this doesn't matter.
+ if(layer != nullptr)
+ {
+ // Get the layers connected to the input slots and determine unique tensor names.
+ Layer& connectedLayer = layer->GetInputSlot(0).GetConnectedOutputSlot()->GetOwningLayer();
+ inputName = GenerateUniqueName(connectedLayer, 0);
+
+ // Determine unique output tensor name.
+ outputName = GenerateUniqueOutputName(*layer, 0);
+ }
+
+ int32_t inputHeight = static_cast<int32_t>(inputs[0]->GetShape()[1]);
+ int32_t inputWidth = static_cast<int32_t>(inputs[0]->GetShape()[2]);
+
+ int32_t outputHeight = static_cast<int32_t>(resizeDescriptor->m_TargetHeight);
+ int32_t outputWidth = static_cast<int32_t>(resizeDescriptor->m_TargetWidth);
+ bool alignCorners = resizeDescriptor->m_AlignCorners;
+ bool halfPixel = resizeDescriptor->m_HalfPixelCenters;
+
+ // Go from ArmNN parameters (outputShape, halfPixel and alignedCorners)
+ // to TOSA parameters (scale, offset and border)
+ // Align corners sets the scaling ratio to (O - 1)/(I - 1) rather than O / I.
+ auto preprocessResizeParameters = [&](int inputSize, int outputSize, int& scale_n, int& scale_d, int& offset)
+ {
+ // Dimension is length 1, we are just sampling from one value.
+ if (inputSize == 1)
+ {
+ scale_n = outputSize;
+ scale_d = 1;
+ offset = 0;
+ return;
+ }
+
+ // Apply if aligned and capable to be aligned.
+ // Align corners sets the scaling ratio to (OH - 1)/(IH - 1) rather than OH / IH. Same for width.
+ bool applyAligned = alignCorners && (outputSize > 1);
+ scale_n = applyAligned ? (outputSize - 1) : outputSize;
+ scale_d = applyAligned ? (inputSize - 1) : inputSize;
+
+ // Simplify the scales, make sure they are even values.
+ int gcd = std::gcd(scale_n, scale_d);
+ scale_n = 2 * scale_n / gcd;
+ scale_d = 2 * scale_d / gcd;
+
+ // If half pixel centers then input and output sampling positions are offset by 1/2 pixel.
+ offset = halfPixel ? (scale_d / 2 - scale_n / 2) : 0;
+
+ // Reduce the scaling ratio if possible, we know scale_n and scale_d are even
+ if ((offset & 1) == 0)
+ {
+ scale_n /= 2;
+ scale_d /= 2;
+ offset /= 2;
+ }
+ };
+
+ int scale_y_n, scale_y_d, offset_y;
+ int scale_x_n, scale_x_d, offset_x;
+ preprocessResizeParameters(inputHeight, outputHeight, scale_y_n, scale_y_d, offset_y);
+ preprocessResizeParameters(inputWidth, outputWidth, scale_x_n, scale_x_d, offset_x);
+
+ int border_y = scale_y_d * (outputHeight - 1) - scale_y_n * (inputHeight - 1) + offset_y;
+ int border_x = scale_x_d * (outputWidth - 1) - scale_x_n * (inputWidth - 1) + offset_x;
+
+ // [scale_y_n, scale_y_d, scale_x_n, scale_x_d]
+ std::vector<int16_t> scale = { static_cast<int16_t>(scale_y_n),
+ static_cast<int16_t>(scale_y_d),
+ static_cast<int16_t>(scale_x_n),
+ static_cast<int16_t>(scale_x_d) };
+
+ // [offset_y, offset_x]
+ std::vector<int16_t> offset = { static_cast<int16_t>(offset_y),
+ static_cast<int16_t>(offset_x) };
+ // [border_y, border_x]
+ std::vector<int16_t> border = { static_cast<int16_t>(border_y),
+ static_cast<int16_t>(border_x) };
+
+ auto isInt16Range = [](int x)
+ {
+ return (x <= std::numeric_limits<int16_t>::max()) && (x >= std::numeric_limits<int16_t>::min());
+ };
+
+ if (inputs[0]->IsQuantized())
+ {
+ // It isn't commonly seen these numbers aren't fit within 16 bits, and won't match TFLite reference.
+ if (!isInt16Range(scale_y_n) || !isInt16Range(scale_y_d) ||
+ !isInt16Range(scale_x_n) || !isInt16Range(scale_x_d) ||
+ !isInt16Range(offset_y) || !isInt16Range(offset_x) ||
+ !isInt16Range(border_y) || !isInt16Range(border_x))
+ {
+ throw armnn::Exception("ConvertResizeToTosaOperator: stride or offset out of 16 bit range");
+ }
+ }
+
+ TosaResizeAttribute resizeAttribute(scale, offset, border, mode);
+
+ auto* op = new TosaSerializationOperator(Op_RESIZE,
+ Attribute_ResizeAttribute,
+ &resizeAttribute,
+ {inputName},
+ {outputName});
+
+ std::vector<TosaSerializationTensor*> tensors;
+
+ // Only add input tensors if connected layer is an input layer.
+ // As intermediate or constant tensors will be created separately.
+ // There also can't be duplicate tensor.
+ if(inputName.find("input0_") != std::string::npos)
+ {
+ std::vector<int32_t> inputShape = GetTosaTensorShape(inputs[0]->GetShape());
+ DType inputDType = ArmNNToDType(inputs[0]->GetDataType());
+
+ tensors.push_back(new TosaSerializationTensor(inputName, inputShape, inputDType, {}));
+ }
+
+ std::vector<int32_t> outputShape = GetTosaTensorShape(outputs[0]->GetShape());
+ DType outputDType = ArmNNToDType(outputs[0]->GetDataType());
+
+ tensors.push_back(new TosaSerializationTensor(outputName, outputShape, outputDType, {}));
+
+ // operatorInputNames/operatorOutputNames ends up being the same as
+ // blockInputNames/blockOutputNames for one-to-one ArmNN to TOSA mappings
+ return new TosaSerializationBasicBlock(blockName, // name
+ mainName, // region name
+ {op}, // operators
+ tensors, // tensors
+ {inputName}, // inputs
+ {outputName}); // outputs
+} \ No newline at end of file
diff --git a/src/backends/tosaCommon/operatorMappings/ResizeOperator.hpp b/src/backends/tosaCommon/operatorMappings/ResizeOperator.hpp
new file mode 100644
index 0000000000..881e7c79ad
--- /dev/null
+++ b/src/backends/tosaCommon/operatorMappings/ResizeOperator.hpp
@@ -0,0 +1,16 @@
+//
+// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "TosaOperatorUtils.hpp"
+
+using namespace armnn;
+using namespace tosa;
+
+TosaSerializationBasicBlock* ConvertResizeToTosaOperator(const Layer* inputSize,
+ const std::vector<const TensorInfo*>& outputSize,
+ const std::vector<const TensorInfo*>& scale_n,
+ const ResizeDescriptor* scale_d);
diff --git a/src/backends/tosaCommon/operatorMappings/SliceOperator.hpp b/src/backends/tosaCommon/operatorMappings/SliceOperator.hpp
index 127cc81255..69a4df5d4f 100644
--- a/src/backends/tosaCommon/operatorMappings/SliceOperator.hpp
+++ b/src/backends/tosaCommon/operatorMappings/SliceOperator.hpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
@@ -7,10 +7,6 @@
#include "TosaOperatorUtils.hpp"
-#include <Layer.hpp>
-
-#include <tosa_serialization_handler.h>
-
using namespace armnn;
using namespace tosa;
diff --git a/src/backends/tosaCommon/operatorMappings/TosaCommonOperators.hpp b/src/backends/tosaCommon/operatorMappings/TosaCommonOperators.hpp
index 66dc1b342a..369b37f35e 100644
--- a/src/backends/tosaCommon/operatorMappings/TosaCommonOperators.hpp
+++ b/src/backends/tosaCommon/operatorMappings/TosaCommonOperators.hpp
@@ -13,6 +13,7 @@
#include "ElementwiseUnaryOperator.hpp"
#include "Pooling2DOperator.hpp"
#include "ReshapeOperator.hpp"
+#include "ResizeOperator.hpp"
#include "SliceOperator.hpp"
#include "TransposeConv2dOperator.hpp"
#include "TransposeOperator.hpp"
diff --git a/src/backends/tosaCommon/operatorMappings/TransposeConv2dOperator.hpp b/src/backends/tosaCommon/operatorMappings/TransposeConv2dOperator.hpp
index eb911a1195..c94795cef2 100644
--- a/src/backends/tosaCommon/operatorMappings/TransposeConv2dOperator.hpp
+++ b/src/backends/tosaCommon/operatorMappings/TransposeConv2dOperator.hpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
@@ -7,10 +7,6 @@
#include "TosaOperatorUtils.hpp"
-#include <Layer.hpp>
-
-#include <tosa_serialization_handler.h>
-
using namespace armnn;
using namespace tosa;
diff --git a/src/backends/tosaCommon/operatorMappings/TransposeOperator.hpp b/src/backends/tosaCommon/operatorMappings/TransposeOperator.hpp
index 3d1e2acd14..19c97cf176 100644
--- a/src/backends/tosaCommon/operatorMappings/TransposeOperator.hpp
+++ b/src/backends/tosaCommon/operatorMappings/TransposeOperator.hpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
@@ -7,10 +7,6 @@
#include "TosaOperatorUtils.hpp"
-#include <Layer.hpp>
-
-#include <tosa_serialization_handler.h>
-
using namespace armnn;
using namespace tosa;
diff --git a/src/backends/tosaCommon/test/OneToOneMappingTests.cpp b/src/backends/tosaCommon/test/OneToOneMappingTests.cpp
index 0cf8002cd1..267c9fb49d 100644
--- a/src/backends/tosaCommon/test/OneToOneMappingTests.cpp
+++ b/src/backends/tosaCommon/test/OneToOneMappingTests.cpp
@@ -553,6 +553,148 @@ TEST_CASE("GetTosaMappingFromLayer_ReshapeLayer")
LayerType::Reshape);
}
+
+TEST_CASE("GetTosaMapping_ResizeLayer")
+{
+ TensorInfo inputInfo = TensorInfo({ 1, 2, 3, 3 }, DataType::Float32);
+ TensorInfo outputInfo = TensorInfo({ 1, 4, 6, 3 }, DataType::Float32);
+
+ std::vector<std::vector<int32_t>> inputShape = {{ 1, 2, 3, 3 }};
+ std::vector<std::vector<int32_t>> outputShape = {{ 1, 4, 6, 3 }};
+
+ ResizeDescriptor descriptor;
+ descriptor.m_DataLayout = DataLayout::NHWC;
+ descriptor.m_TargetHeight = 4;
+ descriptor.m_TargetWidth = 6;
+
+ TosaSerializationBasicBlock* basicBlock = GetTosaMapping(nullptr,
+ LayerType::Resize,
+ {&inputInfo},
+ {&outputInfo},
+ descriptor);
+ AssertTosaOneToOneMappingBasicBlock(basicBlock,
+ inputShape,
+ outputShape,
+ Op_RESIZE,
+ Attribute_ResizeAttribute,
+ descriptor,
+ LayerType::Resize);
+}
+
+TEST_CASE("GetTosaMappingFromLayer_ResizeLayer")
+{
+ IRuntime::CreationOptions options;
+ IRuntimePtr runtime(IRuntime::Create(options));
+
+ // Builds up the structure of the network.
+ INetworkPtr net(INetwork::Create());
+
+ ResizeDescriptor descriptor;
+ descriptor.m_DataLayout = DataLayout::NHWC;
+ descriptor.m_TargetHeight = 2;
+ descriptor.m_TargetWidth = 3;
+
+ IConnectableLayer* input = net->AddInputLayer(0, "input");
+ IConnectableLayer* resize = net->AddResizeLayer(descriptor, "resize");
+ IConnectableLayer* output = net->AddOutputLayer(0, "output");
+
+ input->GetOutputSlot(0).Connect(resize->GetInputSlot(0));
+ resize->GetOutputSlot(0).Connect(output->GetInputSlot(0));
+
+ TensorInfo inputInfo = TensorInfo({ 1, 4, 6, 3 }, DataType::Float32);
+ TensorInfo outputInfo = TensorInfo({ 1, 2, 3, 3 }, DataType::Float32);
+
+ input->GetOutputSlot(0).SetTensorInfo(inputInfo);
+ resize->GetOutputSlot(0).SetTensorInfo(outputInfo);
+
+ std::vector<std::vector<int32_t>> inputShape = {{ 1, 4, 6, 3 }};
+ std::vector<std::vector<int32_t>> outputShape = {{ 1, 2, 3, 3 }};
+
+ TosaSerializationBasicBlock* basicBlock = GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(resize));
+ AssertTosaOneToOneMappingBasicBlock(basicBlock,
+ inputShape,
+ outputShape,
+ Op_RESIZE,
+ Attribute_ResizeAttribute,
+ descriptor,
+ LayerType::Resize);
+}
+
+TEST_CASE("UNSUPPORTED_GetTosaMapping_ResizeLayer_NCHW")
+{
+ TensorInfo inputInfo = TensorInfo({ 1, 3, 2, 3 }, DataType::Float32);
+ TensorInfo outputInfo = TensorInfo({ 1, 3, 4, 6 }, DataType::Float32);
+
+ std::vector<std::vector<int32_t>> inputShape = {{ 1, 3, 2, 3 }};
+ std::vector<std::vector<int32_t>> outputShape = {{ 1, 3, 4, 6 }};
+
+ ResizeDescriptor descriptor;
+ descriptor.m_DataLayout = DataLayout::NCHW;
+ descriptor.m_TargetHeight = 4;
+ descriptor.m_TargetWidth = 6;
+
+ try
+ {
+ TosaSerializationBasicBlock* basicBlock = GetTosaMapping(nullptr,
+ LayerType::Resize,
+ {&inputInfo},
+ {&outputInfo},
+ descriptor);
+
+ AssertTosaOneToOneMappingBasicBlock(basicBlock,
+ inputShape,
+ outputShape,
+ Op_RESIZE,
+ Attribute_ResizeAttribute,
+ descriptor,
+ LayerType::Resize);
+
+ FAIL("An exception should have been thrown");
+ }
+ catch (const armnn::InvalidArgumentException& e)
+ {
+ CHECK(strcmp(e.what(), "ConvertResizeToTosaOperator: NCHW not supported.") == 0);
+ }
+}
+
+TEST_CASE("UNSUPPORTED_GetTosaMapping_ResizeLayer_Bilinear")
+{
+ TensorInfo inputInfo = TensorInfo({ 1, 2, 3, 3 }, DataType::Float32);
+ TensorInfo outputInfo = TensorInfo({ 1, 4, 6, 3 }, DataType::Float32);
+
+ std::vector<std::vector<int32_t>> inputShape = {{ 1, 2, 3, 3 }};
+ std::vector<std::vector<int32_t>> outputShape = {{ 1, 4, 6, 3 }};
+
+ ResizeDescriptor descriptor;
+ descriptor.m_Method = ResizeMethod::Bilinear;
+ descriptor.m_DataLayout = DataLayout::NHWC;
+ descriptor.m_TargetHeight = 4;
+ descriptor.m_TargetWidth = 6;
+
+ try
+ {
+ TosaSerializationBasicBlock* basicBlock = GetTosaMapping(nullptr,
+ LayerType::Resize,
+ {&inputInfo},
+ {&outputInfo},
+ descriptor);
+
+ AssertTosaOneToOneMappingBasicBlock(basicBlock,
+ inputShape,
+ outputShape,
+ Op_RESIZE,
+ Attribute_ResizeAttribute,
+ descriptor,
+ LayerType::Resize);
+
+ FAIL("An exception should have been thrown");
+ }
+ catch (const armnn::InvalidArgumentException& e)
+ {
+ CHECK(strcmp(e.what(), "ConvertResizeToTosaOperator: Unimplemented Resize method.") == 0);
+ }
+}
+
TEST_CASE("GetTosaMapping_SliceLayer")
{
TensorInfo inputInfo = TensorInfo({ 3, 2, 3 }, DataType::Float32);
diff --git a/src/backends/tosaCommon/test/TosaTestUtils.hpp b/src/backends/tosaCommon/test/TosaTestUtils.hpp
index e24055371f..87ff5ff532 100644
--- a/src/backends/tosaCommon/test/TosaTestUtils.hpp
+++ b/src/backends/tosaCommon/test/TosaTestUtils.hpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
@@ -125,16 +125,65 @@ inline void VerifyTosaAttribute(const BaseDescriptor& descriptor,
break;
}
+ case LayerType::Resize:
+ {
+ auto resizeDesc = PolymorphicDowncast<const ResizeDescriptor*>(&descriptor);
+ TosaResizeAttribute resizeAttribute(attribute);
+
+ // Check output shape
+ uint32_t outputHeight = resizeDesc->m_TargetHeight;
+ uint32_t outputWidth = resizeDesc->m_TargetWidth;
+
+ CHECK((outputShape.size() == 4));
+ if (resizeDesc->m_DataLayout == DataLayout::NHWC)
+ {
+ //Check output is not dynamic
+ CHECK((outputShape[1] > 0));
+ CHECK((outputShape[2] > 0));
+
+ CHECK((outputHeight == static_cast<uint32_t>(outputShape[1])));
+ CHECK((outputWidth == static_cast<uint32_t>(outputShape[2])));
+ }
+ else if (resizeDesc->m_DataLayout == DataLayout::NCHW)
+ {
+ //Check output is not dynamic
+ CHECK((outputShape[2] > 0));
+ CHECK((outputShape[3] > 0));
+
+ CHECK((outputHeight == static_cast<uint32_t>(outputShape[2])));
+ CHECK((outputWidth == static_cast<uint32_t>(outputShape[3])));
+ }
+ else
+ {
+ throw armnn::Exception("VerifyTosaAttribute: Invalid DataLayout in Resize.");
+ }
+
+ // Check Resize mode/method
+ if (resizeDesc->m_Method == ResizeMethod::NearestNeighbor)
+ {
+ CHECK((resizeAttribute.mode() == tosa::ResizeMode_NEAREST));
+ }
+ else if (resizeDesc->m_Method == ResizeMethod::Bilinear)
+ {
+ CHECK((resizeAttribute.mode() == tosa::ResizeMode_BILINEAR));
+ }
+ else
+ {
+ throw armnn::Exception("VerifyTosaAttribute: Unsupported Resize method.");
+ }
+
+ break;
+ }
case LayerType::Slice:
{
auto sliceDesc = PolymorphicDowncast<const SliceDescriptor*>(&descriptor);
- TosaSliceAttribute reshapeAttribute(attribute);
+ TosaSliceAttribute sliceAttribute(attribute);
std::vector<int32_t> begin(sliceDesc->m_Begin.begin(), sliceDesc->m_Begin.end());
std::vector<int32_t> size(sliceDesc->m_Size.begin(), sliceDesc->m_Size.end());
- CHECK(begin == reshapeAttribute.start());
- CHECK(size == reshapeAttribute.size());
+ CHECK(begin == sliceAttribute.start());
+ CHECK(size == sliceAttribute.size());
CHECK(begin.size() == inputShape.size());
CHECK(size.size() == inputShape.size());
diff --git a/src/backends/tosaReference/TosaRefLayerSupport.cpp b/src/backends/tosaReference/TosaRefLayerSupport.cpp
index e1c349feb4..04be52d25b 100644
--- a/src/backends/tosaReference/TosaRefLayerSupport.cpp
+++ b/src/backends/tosaReference/TosaRefLayerSupport.cpp
@@ -71,6 +71,7 @@ bool TosaRefLayerSupport::IsLayerSupported(const LayerType& type,
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 26cadd22db..b35dacb1a1 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 @@ TEST_CASE("TosaRefRsqrtEndtoEndTestFloat32")
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 e32894f0b6..fb4c84f07c 100644
--- a/src/backends/tosaReference/test/TosaRefLayerSupportTests.cpp
+++ b/src/backends/tosaReference/test/TosaRefLayerSupportTests.cpp
@@ -352,6 +352,30 @@ TEST_CASE("IsLayerSupportedTosaReferenceReshape")
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 8b08f01b23..5e4103aed1 100644
--- a/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.cpp
+++ b/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.cpp
@@ -50,9 +50,15 @@ void TosaRefPreCompiledWorkload::Execute() const
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 @@ void TosaRefPreCompiledWorkload::Execute() const
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 @@ void TosaRefPreCompiledWorkload::SetInput(TosaReference::IModelRunner& runner,
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 @@ void TosaRefPreCompiledWorkload::GetOutput(TosaReference::IModelRunner& runner,
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 2b3a314888..337e8f9572 100644
--- a/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.hpp
+++ b/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.hpp
@@ -42,9 +42,15 @@ private:
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;