diff options
author | Cathal Corbett <cathal.corbett@arm.com> | 2022-11-15 12:56:16 +0000 |
---|---|---|
committer | Cathal Corbett <cathal.corbett@arm.com> | 2022-11-16 11:12:24 +0000 |
commit | bd18eab07a8f30492de1e462b1815189014cb8d5 (patch) | |
tree | 7c26e2ecb94ffa1ea67204e02011a8166931eb09 /src/backends/tosaCommon/test | |
parent | 194086f01bdd1af52ddd976eb5b4152255565127 (diff) | |
download | armnn-bd18eab07a8f30492de1e462b1815189014cb8d5.tar.gz |
IVGCVSW-7345 Add Pooling2d support to TOSA Reference Backend
Signed-off-by: Cathal Corbett <cathal.corbett@arm.com>
Change-Id: I73a47e513fe2d064ef233b121a68ef2edf0396dc
Diffstat (limited to 'src/backends/tosaCommon/test')
-rw-r--r-- | src/backends/tosaCommon/test/AvgPool2DIgnoreValueChecker.hpp | 125 | ||||
-rw-r--r-- | src/backends/tosaCommon/test/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/backends/tosaCommon/test/OneToManyMappingTests.cpp | 84 | ||||
-rw-r--r-- | src/backends/tosaCommon/test/OneToOneMappingTests.cpp | 213 | ||||
-rw-r--r-- | src/backends/tosaCommon/test/TosaOperatorMappingTests.cpp | 124 | ||||
-rw-r--r-- | src/backends/tosaCommon/test/TosaTestUtils.hpp | 162 |
6 files changed, 586 insertions, 125 deletions
diff --git a/src/backends/tosaCommon/test/AvgPool2DIgnoreValueChecker.hpp b/src/backends/tosaCommon/test/AvgPool2DIgnoreValueChecker.hpp new file mode 100644 index 0000000000..8869b3a8ff --- /dev/null +++ b/src/backends/tosaCommon/test/AvgPool2DIgnoreValueChecker.hpp @@ -0,0 +1,125 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "TosaTestUtils.hpp" + +using namespace armnn; +using namespace tosa; + +void VerifyAvgPool2DIgnoreValue(TosaSerializationBasicBlock* basicBlock, + std::vector<std::vector<int32_t>> inputShape, + std::vector<std::vector<int32_t>> outputShape, + std::vector<std::vector<int32_t>> intermediateShape, + const BaseDescriptor& descriptor, + DType dataType = DType_FP32) +{ + uint32_t numInputs = static_cast<uint32_t>(inputShape.size()); + uint32_t numOutputs = static_cast<uint32_t>(outputShape.size()); + std::string operatorString0 = TosaOpToString(Op_PAD); + std::string operatorString1 = TosaOpToString(Op_AVG_POOL2D); + + std::string blockStr = operatorString1 + "_block_"; + CHECK(basicBlock->GetName().find(blockStr) != std::string::npos); + CHECK(basicBlock->GetInputs().size() == numInputs); + CHECK(basicBlock->GetOutputs().size() == numOutputs); + CHECK(basicBlock->GetOperators().size() == 2); + CHECK(basicBlock->GetTensors().size() == 3); + + // + // Verify padding operator first. + // + + TosaSerializationOperator* padOp = basicBlock->GetOperators().at(0); + uint32_t padOpOutputs = 1; + CHECK(padOp->GetInputTensorNames().size() == numInputs); + CHECK(padOp->GetOutputTensorNames().size() == padOpOutputs); + + for (uint32_t i = 0; i < numInputs; i++) + { + std::basic_string<char> blockInputName = basicBlock->GetInputs()[i]; + std::basic_string<char> operatorInputName = padOp->GetInputTensorNames()[i]; + + std::string opStr = operatorString0 + "_input" + std::to_string(i) + "_"; + + CHECK(blockInputName == operatorInputName); + CHECK(basicBlock->GetTensorByName(blockInputName)); + CHECK(blockInputName.find(opStr) != std::string::npos); + + TosaSerializationTensor* tensor = basicBlock->GetTensorByName(operatorInputName); + CHECK(tensor->GetDtype() == dataType); + CHECK(tensor->GetData().size() == 0); + CHECK(tensor->GetShape() == inputShape[static_cast<unsigned long int>(i)]); + } + + for (uint32_t i = 0; i < padOpOutputs; i++) + { + std::basic_string<char> operatorOutputName = padOp->GetOutputTensorNames()[i]; + std::string opStr = operatorString0 + "_intermediate" + std::to_string(i) + "_"; + + CHECK(basicBlock->GetTensorByName(operatorOutputName)); + CHECK(operatorOutputName.find(opStr) != std::string::npos); + + TosaSerializationTensor* tensor = basicBlock->GetTensorByName(operatorOutputName); + CHECK(tensor->GetDtype() == dataType); + CHECK(tensor->GetData().size() == 0); + CHECK(tensor->GetShape() == intermediateShape[static_cast<unsigned long int>(i)]); + } + + CHECK(padOp->GetAttributeType() == Attribute_PadAttribute); + CHECK(padOp->GetOp() == Op_PAD); + + VerifyTosaAttributeFromDescriptor(descriptor, + padOp->GetAttribute(), + LayerType::Pooling2d); + + // + // Verify average pool operator second. + // + + TosaSerializationOperator* poolOp = basicBlock->GetOperators().at(1); + uint32_t poolOpInputs = 1; + CHECK(poolOp->GetInputTensorNames().size() == poolOpInputs); + CHECK(poolOp->GetOutputTensorNames().size() == numOutputs); + + for (uint32_t i = 0; i < poolOpInputs; i++) + { + std::basic_string<char> operatorInputName = poolOp->GetInputTensorNames()[i]; + std::string opStr = operatorString0 + "_intermediate" + std::to_string(i) + "_"; + + CHECK(basicBlock->GetTensorByName(operatorInputName)); + CHECK(operatorInputName.find(opStr) != std::string::npos); + + TosaSerializationTensor* tensor = basicBlock->GetTensorByName(operatorInputName); + CHECK(tensor->GetDtype() == dataType); + CHECK(tensor->GetData().size() == 0); + CHECK(tensor->GetShape() == intermediateShape[static_cast<unsigned long int>(i)]); + } + + for (uint32_t i = 0; i < numOutputs; i++) + { + std::basic_string<char> blockOutputName = basicBlock->GetOutputs()[i]; + std::basic_string<char> operatorOutputName = poolOp->GetOutputTensorNames()[i]; + + std::string opStr = operatorString1 + "_output" + std::to_string(i) + "_"; + + CHECK(blockOutputName == operatorOutputName); + CHECK(basicBlock->GetTensorByName(blockOutputName)); + CHECK(blockOutputName.find(opStr) != std::string::npos); + + TosaSerializationTensor* tensor = basicBlock->GetTensorByName(operatorOutputName); + CHECK(tensor->GetDtype() == dataType); + CHECK(tensor->GetData().size() == 0); + CHECK(tensor->GetShape() == outputShape[static_cast<unsigned long int>(i)]); + } + + CHECK(poolOp->GetAttributeType() == Attribute_PoolAttribute); + CHECK(poolOp->GetOp() == Op_AVG_POOL2D); + + VerifyTosaAttributeFromDescriptor(descriptor, + poolOp->GetAttribute(), + LayerType::Pooling2d, + 1); + +}
\ No newline at end of file diff --git a/src/backends/tosaCommon/test/CMakeLists.txt b/src/backends/tosaCommon/test/CMakeLists.txt index 56cc66e51c..34c4b0c009 100644 --- a/src/backends/tosaCommon/test/CMakeLists.txt +++ b/src/backends/tosaCommon/test/CMakeLists.txt @@ -4,7 +4,8 @@ # list(APPEND armnnTosaBackendUnitTests_sources - TosaOperatorMappingTests.cpp + OneToManyMappingTests.cpp + OneToOneMappingTests.cpp ) add_library(armnnTosaBackendUnitTests OBJECT ${armnnTosaBackendUnitTests_sources}) diff --git a/src/backends/tosaCommon/test/OneToManyMappingTests.cpp b/src/backends/tosaCommon/test/OneToManyMappingTests.cpp new file mode 100644 index 0000000000..98fd563da1 --- /dev/null +++ b/src/backends/tosaCommon/test/OneToManyMappingTests.cpp @@ -0,0 +1,84 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "AvgPool2DIgnoreValueChecker.hpp" + +using namespace armnn; +using namespace tosa; + +TEST_SUITE("TosaOperatorMappingOneToManyTests") +{ +TEST_CASE("GetTosaMapping_AvgPool2DIgnoreValueLayer") +{ + armnn::Pooling2dDescriptor descriptor; + descriptor.m_PoolType = armnn::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::IgnoreValue; + + armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, DataType::Float32); + armnn::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>> intermediateShape = {{ 1, 1, 6, 6 }}; + std::vector<std::vector<int32_t>> outputShape = {{ 1, 1, 3, 3 }}; + + TosaSerializationBasicBlock* basicBlock = + GetTosaMapping(LayerType::Pooling2d, {&inputTensorInfo}, {&outputTensorInfo}, descriptor, false); + VerifyAvgPool2DIgnoreValue(basicBlock, + inputShape, + outputShape, + intermediateShape, + descriptor); +} + +TEST_CASE("GetTosaMappingFromLayer_AvgPool2DIgnoreValueLayer") +{ + IRuntime::CreationOptions options; + IRuntimePtr runtime(IRuntime::Create(options)); + + // Builds up the structure of the network. + INetworkPtr net(INetwork::Create()); + + armnn::Pooling2dDescriptor descriptor; + descriptor.m_PoolType = armnn::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::IgnoreValue; + + IConnectableLayer* input0 = net->AddInputLayer(0, "input0"); + IConnectableLayer* pool = net->AddPooling2dLayer(descriptor, "pool"); + IConnectableLayer* output = net->AddOutputLayer(0, "output"); + + 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); + + std::vector<std::vector<int32_t>> inputShape = {{ 1, 1, 4, 4 }}; + std::vector<std::vector<int32_t>> intermediateShape = {{ 1, 1, 6, 6 }}; + std::vector<std::vector<int32_t>> outputShape = {{ 1, 1, 3, 3 }}; + + input0->GetOutputSlot(0).SetTensorInfo(inputTensorInfo); + pool->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); + + TosaSerializationBasicBlock* basicBlock = + GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(pool), false); + VerifyAvgPool2DIgnoreValue(basicBlock, + inputShape, + outputShape, + intermediateShape, + descriptor); +} +}
\ No newline at end of file diff --git a/src/backends/tosaCommon/test/OneToOneMappingTests.cpp b/src/backends/tosaCommon/test/OneToOneMappingTests.cpp new file mode 100644 index 0000000000..04d1eb46aa --- /dev/null +++ b/src/backends/tosaCommon/test/OneToOneMappingTests.cpp @@ -0,0 +1,213 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "TosaTestUtils.hpp" + +using namespace armnn; +using namespace tosa; + +TEST_SUITE("TosaOperatorMappingOneToOneTests") +{ +TEST_CASE("GetTosaMapping_AdditionLayer") +{ + TensorInfo info = TensorInfo({ 1, 2, 4, 2 }, DataType::Float32, 0.0f, 0, true); + + std::vector<std::vector<int32_t>> inputShape = {{ 1, 2, 4, 2 }, { 1, 2, 4, 2 }}; + std::vector<std::vector<int32_t>> outputShape = {{ 1, 2, 4, 2 }}; + + TosaSerializationBasicBlock* basicBlock = + GetTosaMapping(LayerType::Addition, {&info, &info}, {&info}, BaseDescriptor(), false); + AssertTosaOneToOneMappingBasicBlock( + basicBlock, inputShape, outputShape, Op_ADD, Attribute_NONE, BaseDescriptor(), LayerType::Addition); +} + +TEST_CASE("GetTosaMappingFromLayer_AdditionLayer") +{ + IRuntime::CreationOptions options; + IRuntimePtr runtime(IRuntime::Create(options)); + + // Builds up the structure of the network. + INetworkPtr net(INetwork::Create()); + + IConnectableLayer* input0 = net->AddInputLayer(0, "input0"); + IConnectableLayer* input1 = net->AddInputLayer(1, "input1"); + IConnectableLayer* add = net->AddAdditionLayer("add"); + IConnectableLayer* output = net->AddOutputLayer(0, "output"); + + input0->GetOutputSlot(0).Connect(add->GetInputSlot(0)); + input1->GetOutputSlot(0).Connect(add->GetInputSlot(1)); + add->GetOutputSlot(0).Connect(output->GetInputSlot(0)); + + TensorInfo info = TensorInfo({ 1, 2, 4, 2 }, DataType::Float32, 0.0f, 0, true); + + input0->GetOutputSlot(0).SetTensorInfo(info); + input1->GetOutputSlot(0).SetTensorInfo(info); + add->GetOutputSlot(0).SetTensorInfo(info); + + std::vector<std::vector<int32_t>> inputShape = {{ 1, 2, 4, 2 }, { 1, 2, 4, 2 }}; + std::vector<std::vector<int32_t>> outputShape = {{ 1, 2, 4, 2 }}; + + TosaSerializationBasicBlock* basicBlock = + GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(add), false); + AssertTosaOneToOneMappingBasicBlock( + basicBlock, inputShape, outputShape, Op_ADD, Attribute_NONE, BaseDescriptor(), LayerType::Addition); +} + +TEST_CASE("GetTosaMapping_MaxPool2DLayer") +{ + armnn::Pooling2dDescriptor descriptor; + descriptor.m_PoolType = armnn::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; + + armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, DataType::Float32); + armnn::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 }}; + + TosaSerializationBasicBlock* basicBlock = + GetTosaMapping(LayerType::Pooling2d, {&inputTensorInfo}, {&outputTensorInfo}, descriptor, false); + AssertTosaOneToOneMappingBasicBlock( + basicBlock, inputShape, outputShape, Op_MAX_POOL2D, Attribute_PoolAttribute, descriptor, LayerType::Pooling2d); +} + +TEST_CASE("GetTosaMappingFromLayer_MaxPool2DLayer") +{ + IRuntime::CreationOptions options; + IRuntimePtr runtime(IRuntime::Create(options)); + + // Builds up the structure of the network. + INetworkPtr net(INetwork::Create()); + + armnn::Pooling2dDescriptor descriptor; + descriptor.m_PoolType = armnn::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; + + IConnectableLayer* input0 = net->AddInputLayer(0, "input0"); + IConnectableLayer* pool = net->AddPooling2dLayer(descriptor, "pool"); + IConnectableLayer* output = net->AddOutputLayer(0, "output"); + + 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); + + 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); + pool->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); + + TosaSerializationBasicBlock* basicBlock = + GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(pool), false); + AssertTosaOneToOneMappingBasicBlock( + basicBlock, inputShape, outputShape, Op_MAX_POOL2D, Attribute_PoolAttribute, descriptor, LayerType::Pooling2d); +} + +TEST_CASE("GetTosaMapping_AvgPool2DLayer") +{ + armnn::Pooling2dDescriptor descriptor; + descriptor.m_PoolType = armnn::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; + + armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, DataType::Float32); + armnn::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 }}; + + TosaSerializationBasicBlock* basicBlock = + GetTosaMapping(LayerType::Pooling2d, {&inputTensorInfo}, {&outputTensorInfo}, descriptor, false); + AssertTosaOneToOneMappingBasicBlock(basicBlock, + inputShape, + outputShape, + Op_AVG_POOL2D, + Attribute_PoolAttribute, + descriptor, + LayerType::Pooling2d); +} + +TEST_CASE("GetTosaMappingFromLayer_AvgPool2DLayer") +{ + IRuntime::CreationOptions options; + IRuntimePtr runtime(IRuntime::Create(options)); + + // Builds up the structure of the network. + INetworkPtr net(INetwork::Create()); + + armnn::Pooling2dDescriptor descriptor; + descriptor.m_PoolType = armnn::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; + + IConnectableLayer* input0 = net->AddInputLayer(0, "input0"); + IConnectableLayer* pool = net->AddPooling2dLayer(descriptor, "pool"); + IConnectableLayer* output = net->AddOutputLayer(0, "output"); + + 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); + + 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); + pool->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); + + TosaSerializationBasicBlock* basicBlock = + GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(pool), false); + AssertTosaOneToOneMappingBasicBlock(basicBlock, + inputShape, + outputShape, + Op_AVG_POOL2D, + Attribute_PoolAttribute, + descriptor, + LayerType::Pooling2d); +} + +TEST_CASE("GetTosaMapping_Unimplemented") +{ + TosaSerializationBasicBlock* basicBlock = + GetTosaMapping(LayerType::UnidirectionalSequenceLstm, {}, {}, BaseDescriptor(), false); + + CHECK(basicBlock->GetName() == ""); + CHECK(basicBlock->GetTensors().size() == 0); + CHECK(basicBlock->GetOperators().size() == 1); + CHECK(basicBlock->GetInputs().size() == 0); + CHECK(basicBlock->GetOutputs().size() == 0); + + TosaSerializationOperator* op = basicBlock->GetOperators()[0]; + CHECK(op->GetAttributeType() == Attribute_NONE); + CHECK(op->GetOp() == tosa::Op_UNKNOWN); + CHECK(op->GetInputTensorNames().size() == 0); + CHECK(op->GetOutputTensorNames().size() == 0); +} +} diff --git a/src/backends/tosaCommon/test/TosaOperatorMappingTests.cpp b/src/backends/tosaCommon/test/TosaOperatorMappingTests.cpp deleted file mode 100644 index d7cc5d8f91..0000000000 --- a/src/backends/tosaCommon/test/TosaOperatorMappingTests.cpp +++ /dev/null @@ -1,124 +0,0 @@ -// -// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. -// SPDX-License-Identifier: MIT -// - -#include <Layer.hpp> - -#include <tosaCommon/TosaMappings.hpp> - -#include <doctest/doctest.h> - -using namespace armnn; -using namespace tosa; - -void AssertTosaOneToOneMappingBasicBlock(TosaSerializationBasicBlock* basicBlock, - std::vector<int32_t> shape, - uint32_t numInputs, - uint32_t numOutputs, - Op tosaOp, - std::string operatorString, - DType dataType = DType_FP32) -{ - std::string blockStr = operatorString + "_block_"; - CHECK(basicBlock->GetName().find(blockStr) != std::string::npos); - CHECK(basicBlock->GetInputs().size() == numInputs); - CHECK(basicBlock->GetOutputs().size() == numOutputs); - CHECK(basicBlock->GetOperators().size() == 1); - CHECK(basicBlock->GetTensors().size() == (numInputs + numOutputs)); - - TosaSerializationOperator* op = basicBlock->GetOperators().at(0); - CHECK(op->GetInputTensorNames().size() == numInputs); - CHECK(op->GetOutputTensorNames().size() == numOutputs); - - for (uint32_t i = 0; i < numInputs; i++) - { - std::basic_string<char> blockInputName = basicBlock->GetInputs()[i]; - std::basic_string<char> operatorInputName = op->GetInputTensorNames()[i]; - std::basic_string<char> tensorName = basicBlock->GetTensors()[i]->GetName(); - - std::string opStr = operatorString + "_input" + std::to_string(i) + "_"; - - CHECK(blockInputName == operatorInputName); - CHECK(tensorName == operatorInputName); - CHECK(blockInputName.find(opStr) != std::string::npos); - } - - for (uint32_t i = 0; i < numOutputs; i++) - { - std::basic_string<char> blockOutputName = basicBlock->GetOutputs()[i]; - std::basic_string<char> operatorOutputName = op->GetOutputTensorNames()[i]; - std::basic_string<char> tensorName = basicBlock->GetTensors()[numInputs + i]->GetName(); - - std::string opStr = operatorString + "_output" + std::to_string(i) + "_"; - - CHECK(blockOutputName == operatorOutputName); - CHECK(tensorName == operatorOutputName); - CHECK(blockOutputName.find(opStr) != std::string::npos); - } - - CHECK(op->GetAttributeType() == Attribute_NONE); - CHECK(op->GetOp() == tosaOp); - - TosaSerializationTensor* tensor0 = basicBlock->GetTensors()[0]; - CHECK(tensor0->GetDtype() == dataType); - CHECK(tensor0->GetData().size() == 0); - CHECK(tensor0->GetShape() == shape); -} - -TEST_SUITE("TosaOperatorMappingOneToOneTests") -{ -TEST_CASE("GetTosaMapping_AdditionLayer") -{ - TensorInfo info = TensorInfo({ 1, 2, 4, 2 }, DataType::Float32, 0.0f, 0, true); - TosaSerializationBasicBlock* basicBlock = - GetTosaMapping(LayerType::Addition, {&info, &info}, {&info}, BaseDescriptor(), false); - AssertTosaOneToOneMappingBasicBlock(basicBlock, { 1, 2, 4, 2 }, 2, 1, Op::Op_ADD, "Op_ADD"); -} - -TEST_CASE("GetTosaMappingFromLayer_AdditionLayer") -{ - IRuntime::CreationOptions options; - IRuntimePtr runtime(IRuntime::Create(options)); - - // Builds up the structure of the network. - INetworkPtr net(INetwork::Create()); - - IConnectableLayer* input0 = net->AddInputLayer(0, "input0"); - IConnectableLayer* input1 = net->AddInputLayer(1, "input1"); - IConnectableLayer* add = net->AddAdditionLayer("add"); - IConnectableLayer* output = net->AddOutputLayer(0, "output"); - - input0->GetOutputSlot(0).Connect(add->GetInputSlot(0)); - input1->GetOutputSlot(0).Connect(add->GetInputSlot(1)); - add->GetOutputSlot(0).Connect(output->GetInputSlot(0)); - - TensorInfo info = TensorInfo({ 1, 2, 4, 2 }, DataType::Float32, 0.0f, 0, true); - - input0->GetOutputSlot(0).SetTensorInfo(info); - input1->GetOutputSlot(0).SetTensorInfo(info); - add->GetOutputSlot(0).SetTensorInfo(info); - - TosaSerializationBasicBlock* basicBlock = - GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(add), false); - AssertTosaOneToOneMappingBasicBlock(basicBlock, { 1, 2, 4, 2 }, 2, 1, Op::Op_ADD, "Op_ADD"); -} - -TEST_CASE("GetTosaMapping_Unimplemented") -{ - TosaSerializationBasicBlock* basicBlock = - GetTosaMapping(LayerType::UnidirectionalSequenceLstm, {}, {}, BaseDescriptor(), false); - - CHECK(basicBlock->GetName() == ""); - CHECK(basicBlock->GetTensors().size() == 0); - CHECK(basicBlock->GetOperators().size() == 1); - CHECK(basicBlock->GetInputs().size() == 0); - CHECK(basicBlock->GetOutputs().size() == 0); - - TosaSerializationOperator* op = basicBlock->GetOperators()[0]; - CHECK(op->GetAttributeType() == Attribute_NONE); - CHECK(op->GetOp() == tosa::Op_UNKNOWN); - CHECK(op->GetInputTensorNames().size() == 0); - CHECK(op->GetOutputTensorNames().size() == 0); -} -} diff --git a/src/backends/tosaCommon/test/TosaTestUtils.hpp b/src/backends/tosaCommon/test/TosaTestUtils.hpp new file mode 100644 index 0000000000..a362bde10d --- /dev/null +++ b/src/backends/tosaCommon/test/TosaTestUtils.hpp @@ -0,0 +1,162 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include <Layer.hpp> + +#include <tosaCommon/TosaMappings.hpp> + +#include <doctest/doctest.h> + +using namespace armnn; +using namespace tosa; + +inline void VerifyTosaAttributeFromDescriptor(const BaseDescriptor& descriptor, + const TosaAttributeBase* attribute, + LayerType type, + uint32_t mappingOpNumber = 0) +{ + switch (type) + { + case LayerType::Pooling2d: + { + auto poolDesc = PolymorphicDowncast<const Pooling2dDescriptor*>(&descriptor); + std::vector<int> pad = {static_cast<int>(poolDesc->m_PadTop), + static_cast<int>(poolDesc->m_PadBottom), + static_cast<int>(poolDesc->m_PadLeft), + static_cast<int>(poolDesc->m_PadRight)}; + + bool avgPoolIgnoreValue = + (poolDesc->m_PoolType == PoolingAlgorithm::Average) && + (poolDesc->m_PaddingMethod == PaddingMethod::IgnoreValue); + if (avgPoolIgnoreValue) + { + if (mappingOpNumber == 0) + { + if (poolDesc->m_DataLayout == DataLayout::NHWC) + { + pad = {0, + 0, + static_cast<int>(poolDesc->m_PadTop), + static_cast<int>(poolDesc->m_PadBottom), + static_cast<int>(poolDesc->m_PadLeft), + static_cast<int>(poolDesc->m_PadRight), + 0, + 0 + }; + } + else + { + pad = {0, + 0, + 0, + 0, + static_cast<int>(poolDesc->m_PadTop), + static_cast<int>(poolDesc->m_PadBottom), + static_cast<int>(poolDesc->m_PadLeft), + static_cast<int>(poolDesc->m_PadRight) + }; + } + + TosaPadAttribute padAttribute(attribute); + + CHECK(pad == padAttribute.padding()); + CHECK(0.0f == padAttribute.pad_const_fp()); + CHECK(0 == padAttribute.pad_const_int()); + + break; + } + pad = {0, 0, 0, 0}; + } + + std::vector<int> kernel = {static_cast<int>(poolDesc->m_PoolHeight), + static_cast<int>(poolDesc->m_PoolWidth)}; + std::vector<int> stride = {static_cast<int>(poolDesc->m_StrideY), + static_cast<int>(poolDesc->m_StrideX)}; + TosaPoolAttribute poolAttribute(attribute); + CHECK(pad == poolAttribute.pad()); + CHECK(kernel == poolAttribute.kernel()); + CHECK(stride == poolAttribute.stride()); + } + default: + break; + } + return; +} + +inline void AssertTosaOneToOneMappingBasicBlock(TosaSerializationBasicBlock* basicBlock, + std::vector<std::vector<int32_t>> inputShape, + std::vector<std::vector<int32_t>> outputShape, + Op tosaOp, + Attribute tosaAttribute, + const BaseDescriptor& descriptor, + LayerType type, + DType dataType = DType_FP32) +{ + uint32_t numInputs = static_cast<uint32_t>(inputShape.size()); + uint32_t numOutputs = static_cast<uint32_t>(outputShape.size()); + std::string operatorString = TosaOpToString(tosaOp); + + std::string blockStr = operatorString + "_block_"; + CHECK(basicBlock->GetName().find(blockStr) != std::string::npos); + CHECK(basicBlock->GetInputs().size() == numInputs); + CHECK(basicBlock->GetOutputs().size() == numOutputs); + CHECK(basicBlock->GetOperators().size() == 1); + CHECK(basicBlock->GetTensors().size() == (numInputs + numOutputs)); + + TosaSerializationOperator* op = basicBlock->GetOperators().at(0); + CHECK(op->GetInputTensorNames().size() == numInputs); + CHECK(op->GetOutputTensorNames().size() == numOutputs); + + for (uint32_t i = 0; i < numInputs; i++) + { + std::basic_string<char> blockInputName = basicBlock->GetInputs()[i]; + std::basic_string<char> operatorInputName = op->GetInputTensorNames()[i]; + std::basic_string<char> tensorName = basicBlock->GetTensors()[i]->GetName(); + + std::string opStr = operatorString + "_input" + std::to_string(i) + "_"; + + CHECK(blockInputName == operatorInputName); + CHECK(tensorName == operatorInputName); + CHECK(blockInputName.find(opStr) != std::string::npos); + } + + for (uint32_t i = 0; i < numOutputs; i++) + { + std::basic_string<char> blockOutputName = basicBlock->GetOutputs()[i]; + std::basic_string<char> operatorOutputName = op->GetOutputTensorNames()[i]; + std::basic_string<char> tensorName = basicBlock->GetTensors()[numInputs + i]->GetName(); + + std::string opStr = operatorString + "_output" + std::to_string(i) + "_"; + + CHECK(blockOutputName == operatorOutputName); + CHECK(tensorName == operatorOutputName); + CHECK(blockOutputName.find(opStr) != std::string::npos); + } + + CHECK(op->GetAttributeType() == tosaAttribute); + CHECK(op->GetOp() == tosaOp); + + for (uint32_t i = 0; i < numInputs; i++) + { + TosaSerializationTensor* tensor = basicBlock->GetTensors()[i]; + CHECK(tensor->GetDtype() == dataType); + CHECK(tensor->GetData().size() == 0); + CHECK(tensor->GetShape() == inputShape[static_cast<unsigned long int>(i)]); + } + + for (uint32_t i = 0; i < numOutputs; i++) + { + TosaSerializationTensor* tensor = basicBlock->GetTensors()[i + inputShape.size()]; + CHECK(tensor->GetDtype() == dataType); + CHECK(tensor->GetData().size() == 0); + CHECK(tensor->GetShape() == outputShape[static_cast<unsigned long int>(i)]); + } + + VerifyTosaAttributeFromDescriptor(descriptor, + op->GetAttribute(), + type); +}
\ No newline at end of file |