aboutsummaryrefslogtreecommitdiff
path: root/src/backends/tosaCommon
diff options
context:
space:
mode:
authorCathal Corbett <cathal.corbett@arm.com>2022-12-07 11:50:50 +0000
committerCathal Corbett <cathal.corbett@arm.com>2022-12-12 20:09:36 +0000
commitb30e6554ad41f21c8326e387aa2c1f8a5d4e6445 (patch)
tree7267ad8027a9eed45348b3808da5fcf901b0b767 /src/backends/tosaCommon
parentec67a0f08e0f96a5aebf3cac65331c67f6649f5e (diff)
downloadarmnn-b30e6554ad41f21c8326e387aa2c1f8a5d4e6445.tar.gz
IVGCVSW-7174 Add Reshape support to TOSA Reference Backend
* Spelling corrections and code refactors added to TosaCommon * TosaDTypeToString() implemented and used in TosaRef IsLayerSupported() instead of enum integer. * Using namespace armnn in TosaCommon OneToOneMappingTests and TosaReference TosaRefLayerSupportTests instead of armnn::ClassName. * Updated VerifyTosaAttribute() to also verify certain attributes from input and output shapes. Signed-off-by: Cathal Corbett <cathal.corbett@arm.com> Change-Id: I71dfca404d081a665f748ab724153c6dc36b7eca
Diffstat (limited to 'src/backends/tosaCommon')
-rw-r--r--src/backends/tosaCommon/TosaMappings.cpp5
-rw-r--r--src/backends/tosaCommon/operatorMappings/AdditionOperator.cpp2
-rw-r--r--src/backends/tosaCommon/operatorMappings/AvgPool2DIgnoreValueOperator.cpp2
-rw-r--r--src/backends/tosaCommon/operatorMappings/CMakeLists.txt2
-rw-r--r--src/backends/tosaCommon/operatorMappings/Pooling2DOperator.cpp2
-rw-r--r--src/backends/tosaCommon/operatorMappings/ReshapeOperator.cpp54
-rw-r--r--src/backends/tosaCommon/operatorMappings/ReshapeOperator.hpp20
-rw-r--r--src/backends/tosaCommon/operatorMappings/TosaCommonOperators.hpp3
-rw-r--r--src/backends/tosaCommon/operatorMappings/TosaOperatorUtils.hpp57
-rw-r--r--src/backends/tosaCommon/test/AvgPool2DIgnoreValueChecker.hpp18
-rw-r--r--src/backends/tosaCommon/test/OneToOneMappingTests.cpp146
-rw-r--r--src/backends/tosaCommon/test/TosaTestUtils.hpp52
12 files changed, 285 insertions, 78 deletions
diff --git a/src/backends/tosaCommon/TosaMappings.cpp b/src/backends/tosaCommon/TosaMappings.cpp
index 00ba429555..318735db77 100644
--- a/src/backends/tosaCommon/TosaMappings.cpp
+++ b/src/backends/tosaCommon/TosaMappings.cpp
@@ -57,6 +57,11 @@ TosaSerializationBasicBlock* GetTosaMapping(const Layer* layer,
return ConvertPooling2DToTosaOperator(layer, inputs, outputs, poolDesc);
}
}
+ case LayerType::Reshape:
+ {
+ auto reshapeDesc = PolymorphicDowncast<const ReshapeDescriptor*>(&descriptor);
+ return ConvertReshapeToTosaOperator(layer, inputs, outputs, reshapeDesc);
+ }
default:
{
return CreateEmptyTosaSerializationBasicBlock();
diff --git a/src/backends/tosaCommon/operatorMappings/AdditionOperator.cpp b/src/backends/tosaCommon/operatorMappings/AdditionOperator.cpp
index 66ca869ac4..f1fb34c5e2 100644
--- a/src/backends/tosaCommon/operatorMappings/AdditionOperator.cpp
+++ b/src/backends/tosaCommon/operatorMappings/AdditionOperator.cpp
@@ -50,7 +50,7 @@ TosaSerializationBasicBlock* ConvertAdditionToTosaOperator(const Layer* layer,
auto* outputTensor0 = new TosaSerializationTensor(outputName, outputShape0, outputDType0, {});
// operatorInputNames/operatorOutputNames ends up being the same as
- // blockInputNames/blockOutputNames for one-to-one ArmNN to Tosa mappings
+ // blockInputNames/blockOutputNames for one-to-one ArmNN to TOSA mappings
return new TosaSerializationBasicBlock(blockName, // name
{op}, // operators
{inputTensor0, inputTensor1, outputTensor0}, // tensors
diff --git a/src/backends/tosaCommon/operatorMappings/AvgPool2DIgnoreValueOperator.cpp b/src/backends/tosaCommon/operatorMappings/AvgPool2DIgnoreValueOperator.cpp
index 2601a6243d..7e7631dcef 100644
--- a/src/backends/tosaCommon/operatorMappings/AvgPool2DIgnoreValueOperator.cpp
+++ b/src/backends/tosaCommon/operatorMappings/AvgPool2DIgnoreValueOperator.cpp
@@ -101,7 +101,7 @@ TosaSerializationBasicBlock* ConvertAvgPool2DIgnoreValueToTosaOperator(const Lay
auto* outputTensor = new TosaSerializationTensor(poolOutputName, outputShape, outputDType, {});
// operatorInputNames/operatorOutputNames ends up being the same as
- // blockInputNames/blockOutputNames for one-to-one ArmNN to Tosa mappings
+ // blockInputNames/blockOutputNames for one-to-one ArmNN to TOSA mappings
return new TosaSerializationBasicBlock(blockName, // name
{opPad, opPool}, // operators
{inputTensor, intermediateTensor, outputTensor}, // tensors
diff --git a/src/backends/tosaCommon/operatorMappings/CMakeLists.txt b/src/backends/tosaCommon/operatorMappings/CMakeLists.txt
index b256eddda1..7733d01abb 100644
--- a/src/backends/tosaCommon/operatorMappings/CMakeLists.txt
+++ b/src/backends/tosaCommon/operatorMappings/CMakeLists.txt
@@ -14,6 +14,8 @@ list(APPEND armnnTosaBackendOperators_sources
Conv2dOperator.cpp
Pooling2DOperator.hpp
Pooling2DOperator.cpp
+ ReshapeOperator.hpp
+ ReshapeOperator.cpp
TosaOperatorUtils.hpp
)
diff --git a/src/backends/tosaCommon/operatorMappings/Pooling2DOperator.cpp b/src/backends/tosaCommon/operatorMappings/Pooling2DOperator.cpp
index eaeb8a4cde..265901e1ae 100644
--- a/src/backends/tosaCommon/operatorMappings/Pooling2DOperator.cpp
+++ b/src/backends/tosaCommon/operatorMappings/Pooling2DOperator.cpp
@@ -56,7 +56,7 @@ TosaSerializationBasicBlock* ConvertPooling2DToTosaOperator(const Layer* layer,
auto* outputTensor0 = new TosaSerializationTensor(outputName, outputShape0, outputDType0, {});
// operatorInputNames/operatorOutputNames ends up being the same as
- // blockInputNames/blockOutputNames for one-to-one ArmNN to Tosa mappings
+ // blockInputNames/blockOutputNames for one-to-one ArmNN to TOSA mappings
return new TosaSerializationBasicBlock(blockName, // name
{op}, // operators
{inputTensor0, outputTensor0}, // tensors
diff --git a/src/backends/tosaCommon/operatorMappings/ReshapeOperator.cpp b/src/backends/tosaCommon/operatorMappings/ReshapeOperator.cpp
new file mode 100644
index 0000000000..b88a6ef894
--- /dev/null
+++ b/src/backends/tosaCommon/operatorMappings/ReshapeOperator.cpp
@@ -0,0 +1,54 @@
+//
+// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "ReshapeOperator.hpp"
+
+TosaSerializationBasicBlock* ConvertReshapeToTosaOperator(const Layer* layer,
+ const std::vector<const TensorInfo*>& inputs,
+ const std::vector<const TensorInfo*>& outputs,
+ const ReshapeDescriptor* reshapeDescriptor)
+{
+ std::string inputName = std::string("input0_");
+ std::string outputName = std::string("output0_");
+ std::string blockName = std::string("Op_RESHAPE_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 layer names.
+ Layer& connectedLayer = layer->GetInputSlot(0).GetConnectedOutputSlot()->GetOwningLayer();
+ inputName = GenerateUniqueName(connectedLayer, 0);
+
+ // Get the layer connected to the output slot and determine unique layer name.
+ Layer& connectedOutputLayer = layer->GetOutputSlot().GetConnection(0)->GetOwningLayer();
+ outputName = GenerateUniqueName(connectedOutputLayer, 0);
+ }
+
+ TosaReshapeAttribute attribute(GetTosaTensorShape(reshapeDescriptor->m_TargetShape));
+
+ auto* op = new TosaSerializationOperator(Op_RESHAPE,
+ Attribute_ReshapeAttribute,
+ &attribute,
+ {inputName},
+ {outputName});
+
+ std::vector<int32_t> inputShape = GetTosaTensorShape(inputs[0]->GetShape());
+ DType inputDType = ArmNNToDType(inputs[0]->GetDataType());
+
+ std::vector<int32_t> outputShape = GetTosaTensorShape(outputs[0]->GetShape());
+ DType outputDType = ArmNNToDType(outputs[0]->GetDataType());
+
+ auto* inputTensor = new TosaSerializationTensor(inputName, inputShape, inputDType, {});
+ auto* outputTensor = 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
+ {op}, // operators
+ {inputTensor, outputTensor}, // tensors
+ {inputName}, // inputs
+ {outputName}); // outputs
+} \ No newline at end of file
diff --git a/src/backends/tosaCommon/operatorMappings/ReshapeOperator.hpp b/src/backends/tosaCommon/operatorMappings/ReshapeOperator.hpp
new file mode 100644
index 0000000000..4f363df052
--- /dev/null
+++ b/src/backends/tosaCommon/operatorMappings/ReshapeOperator.hpp
@@ -0,0 +1,20 @@
+//
+// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "TosaOperatorUtils.hpp"
+
+#include <Layer.hpp>
+
+#include <tosa_serialization_handler.h>
+
+using namespace armnn;
+using namespace tosa;
+
+TosaSerializationBasicBlock* ConvertReshapeToTosaOperator(const Layer* layer,
+ const std::vector<const TensorInfo*>& inputs,
+ const std::vector<const TensorInfo*>& outputs,
+ const ReshapeDescriptor* reshapeDescriptor);
diff --git a/src/backends/tosaCommon/operatorMappings/TosaCommonOperators.hpp b/src/backends/tosaCommon/operatorMappings/TosaCommonOperators.hpp
index 513db0c039..0711095a25 100644
--- a/src/backends/tosaCommon/operatorMappings/TosaCommonOperators.hpp
+++ b/src/backends/tosaCommon/operatorMappings/TosaCommonOperators.hpp
@@ -9,4 +9,5 @@
#include "ConstantOperator.hpp"
#include "Conv2dOperator.hpp"
#include "AvgPool2DIgnoreValueOperator.hpp"
-#include "Pooling2DOperator.hpp" \ No newline at end of file
+#include "Pooling2DOperator.hpp"
+#include "ReshapeOperator.hpp" \ No newline at end of file
diff --git a/src/backends/tosaCommon/operatorMappings/TosaOperatorUtils.hpp b/src/backends/tosaCommon/operatorMappings/TosaOperatorUtils.hpp
index 176e4e1cfb..288966badd 100644
--- a/src/backends/tosaCommon/operatorMappings/TosaOperatorUtils.hpp
+++ b/src/backends/tosaCommon/operatorMappings/TosaOperatorUtils.hpp
@@ -59,28 +59,20 @@ inline std::vector<int32_t> GetTosaTensorShape(const TensorShape& shape)
// Function that generates unique name using the layer type, input slot and layer guid.
inline std::string GenerateUniqueName(const Layer& layer, uint32_t layerSlot)
{
- std::string name;
std::string guid = std::to_string(layer.GetGuid());
std::string slotAndGuid = std::to_string(layerSlot) + "_" + guid;
- LayerType layerType = layer.GetType();
- if (layerType == LayerType::Input)
+ switch (layer.GetType())
{
- name = "input" + slotAndGuid;
- }
- else if (layerType == LayerType::Output)
- {
- name = "output" + slotAndGuid;
- }
- else if (layerType == LayerType::Constant)
- {
- name = "constant_" + guid;
- }
- else
- {
- name = "intermediate" + slotAndGuid;
+ case LayerType::Input:
+ return "input" + slotAndGuid;
+ case LayerType::Output:
+ return "output" + slotAndGuid;
+ case LayerType::Constant:
+ return "constant_" + guid;
+ default:
+ return "intermediate" + slotAndGuid;
}
- return name;
}
// Function to return unique int as a string to ensure uniqueness between all input, output and block names.
@@ -90,6 +82,37 @@ inline std::string GetUniqueTosaMappingID()
return std::to_string(++uniqueTosaMappingID);
}
+// Function to return Tosa DType as string.
+inline std::string TosaDTypeToString(DType tosaDType)
+{
+ switch (tosaDType)
+ {
+ case DType_UNKNOWN:
+ return "DType_UNKNOWN";
+ case DType_BOOL:
+ return "DType_BOOL";
+ case DType_UINT8:
+ return "DType_UINT8";
+ case DType_INT4:
+ return "DType_INT4";
+ case DType_INT8:
+ return "DType_INT8";
+ case DType_INT16:
+ return "DType_INT16";
+ case DType_INT32:
+ return "DType_INT32";
+ case DType_INT48:
+ return "DType_INT48";
+ case DType_FP32:
+ return "DType_FP32";
+ case DType_UINT16:
+ return "DType_UINT16";
+ case DType_FP16:
+ return "DType_FP16";
+ }
+ return "";
+}
+
// Function to return Tosa Op as string.
inline std::string TosaOpToString(Op tosaOp)
{
diff --git a/src/backends/tosaCommon/test/AvgPool2DIgnoreValueChecker.hpp b/src/backends/tosaCommon/test/AvgPool2DIgnoreValueChecker.hpp
index a38f66b466..6f57c4a61e 100644
--- a/src/backends/tosaCommon/test/AvgPool2DIgnoreValueChecker.hpp
+++ b/src/backends/tosaCommon/test/AvgPool2DIgnoreValueChecker.hpp
@@ -68,9 +68,11 @@ void VerifyAvgPool2DIgnoreValue(TosaSerializationBasicBlock* basicBlock,
CHECK(padOp->GetAttributeType() == Attribute_PadAttribute);
CHECK(padOp->GetOp() == Op_PAD);
- VerifyTosaAttributeFromDescriptor(descriptor,
- padOp->GetAttribute(),
- LayerType::Pooling2d);
+ VerifyTosaAttribute(descriptor,
+ padOp->GetAttribute(),
+ inputShape[0],
+ outputShape[0],
+ LayerType::Pooling2d);
//
// Verify average pool operator second.
@@ -115,9 +117,11 @@ void VerifyAvgPool2DIgnoreValue(TosaSerializationBasicBlock* basicBlock,
CHECK(poolOp->GetAttributeType() == Attribute_PoolAttribute);
CHECK(poolOp->GetOp() == Op_AVG_POOL2D);
- VerifyTosaAttributeFromDescriptor(descriptor,
- poolOp->GetAttribute(),
- LayerType::Pooling2d,
- 1);
+ VerifyTosaAttribute(descriptor,
+ poolOp->GetAttribute(),
+ inputShape[0],
+ outputShape[0],
+ LayerType::Pooling2d,
+ 1);
} \ No newline at end of file
diff --git a/src/backends/tosaCommon/test/OneToOneMappingTests.cpp b/src/backends/tosaCommon/test/OneToOneMappingTests.cpp
index af9f9e26df..b1fa6847bc 100644
--- a/src/backends/tosaCommon/test/OneToOneMappingTests.cpp
+++ b/src/backends/tosaCommon/test/OneToOneMappingTests.cpp
@@ -79,7 +79,7 @@ TEST_CASE("GetTosaMappingFromLayer_ConstantLayer")
std::vector<std::vector<int32_t>> outputShape = {{ 1, 2, 4, 2 }};
std::vector<float> data = GenerateRandomData<float>(info.GetNumElements());
- armnn::ConstTensor constTensor(info, data);
+ ConstTensor constTensor(info, data);
IConnectableLayer* constant = net->AddConstantLayer(constTensor, "constant");
IConnectableLayer* output = net->AddOutputLayer(0, "output");
@@ -95,7 +95,7 @@ TEST_CASE("GetTosaMappingFromLayer_ConstantLayer")
TEST_CASE("GetTosaMapping_Conv2dLayer")
{
- armnn::Convolution2dDescriptor descriptor;
+ Convolution2dDescriptor descriptor;
descriptor.m_PadLeft = 1;
descriptor.m_PadRight = 1;
descriptor.m_PadTop = 1;
@@ -106,10 +106,10 @@ TEST_CASE("GetTosaMapping_Conv2dLayer")
descriptor.m_DilationY = 2;
descriptor.m_BiasEnabled = true;
- const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
- const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
- const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32, 0.0f, 0, true);
- const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32, 0.0f, 0, true);
+ const TensorInfo inputInfo ({ 1, 5, 5, 1 }, DataType::Float32);
+ const TensorInfo outputInfo({ 1, 3, 3, 1 }, DataType::Float32);
+ const TensorInfo weightsInfo({ 1, 3, 3, 1 }, DataType::Float32, 0.0f, 0, true);
+ const TensorInfo biasesInfo ({ 1 }, DataType::Float32, 0.0f, 0, true);
std::vector<std::vector<int32_t>> inputShape = {{ 1, 5, 5, 1 }, { 1, 3, 3, 1 }, { 1 }};
std::vector<std::vector<int32_t>> outputShape = {{ 1, 3, 3, 1 }};
@@ -131,7 +131,7 @@ TEST_CASE("GetTosaMappingFromLayer_Conv2dLayer")
// Builds up the structure of the network.
INetworkPtr net(INetwork::Create());
- armnn::Convolution2dDescriptor descriptor;
+ Convolution2dDescriptor descriptor;
descriptor.m_PadLeft = 1;
descriptor.m_PadRight = 1;
descriptor.m_PadTop = 1;
@@ -142,25 +142,25 @@ TEST_CASE("GetTosaMappingFromLayer_Conv2dLayer")
descriptor.m_DilationY = 2;
descriptor.m_BiasEnabled = true;
- const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
- const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
- const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32, 0.0f, 0, true);
- const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32, 0.0f, 0, true);
+ const TensorInfo inputInfo ({ 1, 5, 5, 1 }, DataType::Float32);
+ const TensorInfo outputInfo({ 1, 3, 3, 1 }, DataType::Float32);
+ const TensorInfo weightsInfo({ 1, 3, 3, 1 }, DataType::Float32, 0.0f, 0, true);
+ const TensorInfo biasesInfo ({ 1 }, DataType::Float32, 0.0f, 0, true);
std::vector<std::vector<int32_t>> inputShape = {{ 1, 5, 5, 1 }};
std::vector<std::vector<int32_t>> outputShape = {{ 1, 3, 3, 1 }};
std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
- armnn::ConstTensor weights(weightsInfo, weightsData);
+ ConstTensor weights(weightsInfo, weightsData);
std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
- armnn::ConstTensor biases(biasesInfo, biasesData);
+ ConstTensor biases(biasesInfo, biasesData);
- armnn::IConnectableLayer* const inputLayer = net->AddInputLayer(0, "input0");
- armnn::IConnectableLayer* const weightsLayer = net->AddConstantLayer(weights, "weights");
- armnn::IConnectableLayer* const biasesLayer = net->AddConstantLayer(biases, "biases");
- armnn::IConnectableLayer* const convLayer = net->AddConvolution2dLayer(descriptor, "conv2d");
- armnn::IConnectableLayer* const outputLayer = net->AddOutputLayer(0);
+ IConnectableLayer* const inputLayer = net->AddInputLayer(0, "input0");
+ IConnectableLayer* const weightsLayer = net->AddConstantLayer(weights, "weights");
+ IConnectableLayer* const biasesLayer = net->AddConstantLayer(biases, "biases");
+ IConnectableLayer* const convLayer = net->AddConvolution2dLayer(descriptor, "conv2d");
+ IConnectableLayer* const outputLayer = net->AddOutputLayer(0);
inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
weightsLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(1));
@@ -179,18 +179,18 @@ TEST_CASE("GetTosaMappingFromLayer_Conv2dLayer")
TEST_CASE("GetTosaMapping_MaxPool2DLayer")
{
- armnn::Pooling2dDescriptor descriptor;
- descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
+ Pooling2dDescriptor descriptor;
+ descriptor.m_PoolType = PoolingAlgorithm::Max;
descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
descriptor.m_StrideX = descriptor.m_StrideY = 2;
descriptor.m_PadLeft = 1;
descriptor.m_PadRight = 1;
descriptor.m_PadTop = 1;
descriptor.m_PadBottom = 1;
- descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
+ descriptor.m_PaddingMethod = PaddingMethod::Exclude;
- armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, DataType::Float32);
- armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, DataType::Float32);
+ TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, DataType::Float32);
+ TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, DataType::Float32);
std::vector<std::vector<int32_t>> inputShape = {{ 1, 1, 4, 4 }};
std::vector<std::vector<int32_t>> outputShape = {{ 1, 1, 3, 3 }};
@@ -209,30 +209,30 @@ TEST_CASE("GetTosaMappingFromLayer_MaxPool2DLayer")
// Builds up the structure of the network.
INetworkPtr net(INetwork::Create());
- armnn::Pooling2dDescriptor descriptor;
- descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
+ Pooling2dDescriptor descriptor;
+ descriptor.m_PoolType = PoolingAlgorithm::Max;
descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
descriptor.m_StrideX = descriptor.m_StrideY = 2;
descriptor.m_PadLeft = 1;
descriptor.m_PadRight = 1;
descriptor.m_PadTop = 1;
descriptor.m_PadBottom = 1;
- descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
+ descriptor.m_PaddingMethod = PaddingMethod::Exclude;
- IConnectableLayer* input0 = net->AddInputLayer(0, "input0");
- IConnectableLayer* pool = net->AddPooling2dLayer(descriptor, "pool");
- IConnectableLayer* output = net->AddOutputLayer(0, "output");
+ IConnectableLayer* input = net->AddInputLayer(0, "input0");
+ IConnectableLayer* pool = net->AddPooling2dLayer(descriptor, "pool");
+ IConnectableLayer* output = net->AddOutputLayer(0, "output");
- input0->GetOutputSlot(0).Connect(pool->GetInputSlot(0));
+ input->GetOutputSlot(0).Connect(pool->GetInputSlot(0));
pool->GetOutputSlot(0).Connect(output->GetInputSlot(0));
- armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, DataType::Float32);
- armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, DataType::Float32);
+ TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, DataType::Float32);
+ TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, DataType::Float32);
std::vector<std::vector<int32_t>> inputShape = {{ 1, 1, 4, 4 }};
std::vector<std::vector<int32_t>> outputShape = {{ 1, 1, 3, 3 }};
- input0->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
+ input->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
pool->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
TosaSerializationBasicBlock* basicBlock =
@@ -243,18 +243,18 @@ TEST_CASE("GetTosaMappingFromLayer_MaxPool2DLayer")
TEST_CASE("GetTosaMapping_AvgPool2DLayer")
{
- armnn::Pooling2dDescriptor descriptor;
- descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
+ Pooling2dDescriptor descriptor;
+ descriptor.m_PoolType = PoolingAlgorithm::Average;
descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
descriptor.m_StrideX = descriptor.m_StrideY = 2;
descriptor.m_PadLeft = 1;
descriptor.m_PadRight = 1;
descriptor.m_PadTop = 1;
descriptor.m_PadBottom = 1;
- descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
+ descriptor.m_PaddingMethod = PaddingMethod::Exclude;
- armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, DataType::Float32);
- armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, DataType::Float32);
+ TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, DataType::Float32);
+ TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, DataType::Float32);
std::vector<std::vector<int32_t>> inputShape = {{ 1, 1, 4, 4 }};
std::vector<std::vector<int32_t>> outputShape = {{ 1, 1, 3, 3 }};
@@ -278,15 +278,15 @@ TEST_CASE("GetTosaMappingFromLayer_AvgPool2DLayer")
// Builds up the structure of the network.
INetworkPtr net(INetwork::Create());
- armnn::Pooling2dDescriptor descriptor;
- descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
+ Pooling2dDescriptor descriptor;
+ descriptor.m_PoolType = PoolingAlgorithm::Average;
descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
descriptor.m_StrideX = descriptor.m_StrideY = 2;
descriptor.m_PadLeft = 1;
descriptor.m_PadRight = 1;
descriptor.m_PadTop = 1;
descriptor.m_PadBottom = 1;
- descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
+ descriptor.m_PaddingMethod = PaddingMethod::Exclude;
IConnectableLayer* input0 = net->AddInputLayer(0, "input0");
IConnectableLayer* pool = net->AddPooling2dLayer(descriptor, "pool");
@@ -295,8 +295,8 @@ TEST_CASE("GetTosaMappingFromLayer_AvgPool2DLayer")
input0->GetOutputSlot(0).Connect(pool->GetInputSlot(0));
pool->GetOutputSlot(0).Connect(output->GetInputSlot(0));
- armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, DataType::Float32);
- armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, DataType::Float32);
+ TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, DataType::Float32);
+ TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, DataType::Float32);
std::vector<std::vector<int32_t>> inputShape = {{ 1, 1, 4, 4 }};
std::vector<std::vector<int32_t>> outputShape = {{ 1, 1, 3, 3 }};
@@ -315,6 +315,66 @@ TEST_CASE("GetTosaMappingFromLayer_AvgPool2DLayer")
LayerType::Pooling2d);
}
+TEST_CASE("GetTosaMapping_ReshapeLayer")
+{
+ TensorInfo inputInfo = TensorInfo({ 2, 3 }, DataType::Float32);
+ TensorInfo outputInfo = TensorInfo({ 6 }, DataType::Float32);
+
+ std::vector<std::vector<int32_t>> inputShape = {{ 2, 3 }};
+ std::vector<std::vector<int32_t>> outputShape = {{ 6 }};
+
+ ReshapeDescriptor descriptor;
+ descriptor.m_TargetShape = { 6 };
+
+ TosaSerializationBasicBlock* basicBlock =
+ GetTosaMapping(nullptr, LayerType::Reshape, {&inputInfo}, {&outputInfo}, descriptor);
+ AssertTosaOneToOneMappingBasicBlock(basicBlock,
+ inputShape,
+ outputShape,
+ Op_RESHAPE,
+ Attribute_ReshapeAttribute,
+ descriptor,
+ LayerType::Reshape);
+}
+
+TEST_CASE("GetTosaMappingFromLayer_ReshapeLayer")
+{
+ IRuntime::CreationOptions options;
+ IRuntimePtr runtime(IRuntime::Create(options));
+
+ // Builds up the structure of the network.
+ INetworkPtr net(INetwork::Create());
+
+ ReshapeDescriptor descriptor;
+ descriptor.m_TargetShape = { 6 };
+
+ IConnectableLayer* input = net->AddInputLayer(0, "input");
+ IConnectableLayer* reshape = net->AddReshapeLayer(descriptor, "reshape");
+ IConnectableLayer* output = net->AddOutputLayer(0, "output");
+
+ input->GetOutputSlot(0).Connect(reshape->GetInputSlot(0));
+ reshape->GetOutputSlot(0).Connect(output->GetInputSlot(0));
+
+ TensorInfo inputInfo = TensorInfo({ 2, 3 }, DataType::Float32);
+ TensorInfo outputInfo = TensorInfo({ 6 }, DataType::Float32);
+
+ input->GetOutputSlot(0).SetTensorInfo(inputInfo);
+ reshape->GetOutputSlot(0).SetTensorInfo(outputInfo);
+
+ std::vector<std::vector<int32_t>> inputShape = {{ 2, 3 }};
+ std::vector<std::vector<int32_t>> outputShape = {{ 6 }};
+
+ TosaSerializationBasicBlock* basicBlock =
+ GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(reshape));
+ AssertTosaOneToOneMappingBasicBlock(basicBlock,
+ inputShape,
+ outputShape,
+ Op_RESHAPE,
+ Attribute_ReshapeAttribute,
+ descriptor,
+ LayerType::Reshape);
+}
+
TEST_CASE("GetTosaMapping_Unimplemented")
{
TosaSerializationBasicBlock* basicBlock =
diff --git a/src/backends/tosaCommon/test/TosaTestUtils.hpp b/src/backends/tosaCommon/test/TosaTestUtils.hpp
index dd63c0efdf..5c10a6d638 100644
--- a/src/backends/tosaCommon/test/TosaTestUtils.hpp
+++ b/src/backends/tosaCommon/test/TosaTestUtils.hpp
@@ -8,16 +8,20 @@
#include <Layer.hpp>
#include <tosaCommon/TosaMappings.hpp>
+#include <tosaCommon/operatorMappings/TosaOperatorUtils.hpp>
#include <doctest/doctest.h>
+#include <numeric>
using namespace armnn;
using namespace tosa;
-inline void VerifyTosaAttributeFromDescriptor(const BaseDescriptor& descriptor,
- const TosaAttributeBase* attribute,
- LayerType type,
- uint32_t mappingOpNumber = 0)
+inline void VerifyTosaAttribute(const BaseDescriptor& descriptor,
+ const TosaAttributeBase* attribute,
+ std::vector<int32_t> inputShape,
+ std::vector<int32_t> outputShape,
+ LayerType type,
+ uint32_t mappingOpNumber = 0)
{
switch (type)
{
@@ -100,6 +104,25 @@ inline void VerifyTosaAttributeFromDescriptor(const BaseDescriptor& descriptor,
CHECK(stride == poolAttribute.stride());
break;
}
+ case LayerType::Reshape:
+ {
+ auto reshapeDesc = PolymorphicDowncast<const ReshapeDescriptor*>(&descriptor);
+ TosaReshapeAttribute reshapeAttribute(attribute);
+ std::vector<int32_t> shapeAttrib = reshapeAttribute.new_shape();
+
+ CHECK(GetTosaTensorShape(reshapeDesc->m_TargetShape) == shapeAttrib);
+ CHECK(outputShape == shapeAttrib);
+
+ auto numInputElements = std::accumulate(std::begin(inputShape),
+ std::end(inputShape),
+ 1,
+ std::multiplies<int32_t>());
+ auto numAttributeShapeElements = std::accumulate(std::begin(shapeAttrib),
+ std::end(shapeAttrib),
+ 1,
+ std::multiplies<int32_t>());
+ CHECK(numInputElements == numAttributeShapeElements);
+ }
default:
break;
}
@@ -195,7 +218,22 @@ inline void AssertTosaOneToOneMappingBasicBlock(TosaSerializationBasicBlock* bas
}
}
- VerifyTosaAttributeFromDescriptor(descriptor,
- op->GetAttribute(),
- type);
+ std::vector<int32_t> input = {};
+ std::vector<int32_t> output = {};
+
+ if (!inputShape.empty())
+ {
+ input = inputShape[0];
+ }
+
+ if (!outputShape.empty())
+ {
+ output = outputShape[0];
+ }
+
+ VerifyTosaAttribute(descriptor,
+ op->GetAttribute(),
+ input,
+ output,
+ type);
} \ No newline at end of file