aboutsummaryrefslogtreecommitdiff
path: root/src/backends/tosaCommon
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 /src/backends/tosaCommon
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
Diffstat (limited to 'src/backends/tosaCommon')
-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
17 files changed, 401 insertions, 52 deletions
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());