From 03acd6871b2e752f6ea6b1a4e1b739cdae698477 Mon Sep 17 00:00:00 2001 From: Nattapat Chaimanowong Date: Wed, 20 Mar 2019 11:19:52 +0000 Subject: IVGCVSW-2788 Modify Serializer test to use introspection API Change-Id: Ie97012b42cd7847a437dd9f21c9b59179b2e7897 Signed-off-by: Nattapat Chaimanowong --- src/armnnSerializer/test/SerializerTests.cpp | 2400 +++++++++++++++----------- 1 file changed, 1357 insertions(+), 1043 deletions(-) (limited to 'src') diff --git a/src/armnnSerializer/test/SerializerTests.cpp b/src/armnnSerializer/test/SerializerTests.cpp index d0586c988c..ca15553f9a 100644 --- a/src/armnnSerializer/test/SerializerTests.cpp +++ b/src/armnnSerializer/test/SerializerTests.cpp @@ -3,25 +3,120 @@ // SPDX-License-Identifier: MIT // -#include -#include - #include "../Serializer.hpp" +#include +#include #include #include -#include #include #include -#include using armnnDeserializer::IDeserializer; namespace { +struct DefaultLayerVerifierPolicy +{ + static void Apply() + { + BOOST_TEST_MESSAGE("Unexpected layer found in network"); + BOOST_TEST(false); + } +}; + +class LayerVerifierBase : public armnn::LayerVisitorBase +{ +public: + LayerVerifierBase(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos) + : m_LayerName(layerName) + , m_InputTensorInfos(inputInfos) + , m_OutputTensorInfos(outputInfos) {} + + void VisitInputLayer(const armnn::IConnectableLayer*, armnn::LayerBindingId, const char*) override {} + + void VisitOutputLayer(const armnn::IConnectableLayer*, armnn::LayerBindingId id, const char*) override {} + +protected: + void VerifyNameAndConnections(const armnn::IConnectableLayer* layer, const char* name) + { + BOOST_TEST(name == m_LayerName.c_str()); + + BOOST_TEST(layer->GetNumInputSlots() == m_InputTensorInfos.size()); + BOOST_TEST(layer->GetNumOutputSlots() == m_OutputTensorInfos.size()); + + for (unsigned int i = 0; i < m_InputTensorInfos.size(); i++) + { + const armnn::IOutputSlot* connectedOutput = layer->GetInputSlot(i).GetConnection(); + BOOST_CHECK(connectedOutput); + + const armnn::TensorInfo& connectedInfo = connectedOutput->GetTensorInfo(); + BOOST_TEST(connectedInfo.GetShape() == m_InputTensorInfos[i].GetShape()); + BOOST_TEST( + GetDataTypeName(connectedInfo.GetDataType()) == GetDataTypeName(m_InputTensorInfos[i].GetDataType())); + } + + for (unsigned int i = 0; i < m_OutputTensorInfos.size(); i++) + { + const armnn::TensorInfo& outputInfo = layer->GetOutputSlot(i).GetTensorInfo(); + BOOST_TEST(outputInfo.GetShape() == m_OutputTensorInfos[i].GetShape()); + BOOST_TEST( + GetDataTypeName(outputInfo.GetDataType()) == GetDataTypeName(m_OutputTensorInfos[i].GetDataType())); + } + } + +private: + std::string m_LayerName; + std::vector m_InputTensorInfos; + std::vector m_OutputTensorInfos; +}; + +template +void CompareConstTensorData(const void* data1, const void* data2, unsigned int numElements) +{ + T typedData1 = static_cast(data1); + T typedData2 = static_cast(data2); + BOOST_CHECK(typedData1); + BOOST_CHECK(typedData2); + + for (unsigned int i = 0; i < numElements; i++) + { + BOOST_TEST(typedData1[i] == typedData2[i]); + } +} + +void CompareConstTensor(const armnn::ConstTensor& tensor1, const armnn::ConstTensor& tensor2) +{ + BOOST_TEST(tensor1.GetShape() == tensor2.GetShape()); + BOOST_TEST(GetDataTypeName(tensor1.GetDataType()) == GetDataTypeName(tensor2.GetDataType())); + + switch (tensor1.GetDataType()) + { + case armnn::DataType::Float32: + CompareConstTensorData( + tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements()); + break; + case armnn::DataType::QuantisedAsymm8: + case armnn::DataType::Boolean: + CompareConstTensorData( + tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements()); + break; + case armnn::DataType::Signed32: + CompareConstTensorData( + tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements()); + break; + default: + // Note that Float16 is not yet implemented + BOOST_TEST_MESSAGE("Unexpected datatype"); + BOOST_TEST(false); + } +} + armnn::INetworkPtr DeserializeNetwork(const std::string& serializerString) { std::vector const serializerVector{serializerString.begin(), serializerString.end()}; @@ -61,182 +156,238 @@ static std::vector GenerateRandomData(size_t size) return randomData; } -template -void CheckDeserializedNetworkAgainstOriginal(const armnn::INetwork& deserializedNetwork, - const armnn::INetwork& originalNetwork, - const std::vector& inputShapes, - const std::vector& outputShapes, - const std::vector& inputBindingIds = {0}, - const std::vector& outputBindingIds = {0}) +} // anonymous namespace + +BOOST_AUTO_TEST_SUITE(SerializerTests) + +BOOST_AUTO_TEST_CASE(SerializeAddition) { - BOOST_CHECK(inputShapes.size() == inputBindingIds.size()); - BOOST_CHECK(outputShapes.size() == outputBindingIds.size()); + class AdditionLayerVerifier : public LayerVerifierBase + { + public: + AdditionLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos) + : LayerVerifierBase(layerName, inputInfos, outputInfos) {} + + void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name) override + { + VerifyNameAndConnections(layer, name); + } + }; + + const std::string layerName("addition"); + const armnn::TensorInfo tensorInfo({1, 2, 3}, armnn::DataType::Float32); - armnn::IRuntime::CreationOptions options; - armnn::IRuntimePtr runtime = armnn::IRuntime::Create(options); + armnn::INetworkPtr network = armnn::INetwork::Create(); + armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0); + armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1); + armnn::IConnectableLayer* const additionLayer = network->AddAdditionLayer(layerName.c_str()); + armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - std::vector preferredBackends = { armnn::BackendId("CpuRef") }; + inputLayer0->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(0)); + inputLayer1->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(1)); + additionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - // Optimize original network - armnn::IOptimizedNetworkPtr optimizedOriginalNetwork = - armnn::Optimize(originalNetwork, preferredBackends, runtime->GetDeviceSpec()); - BOOST_CHECK(optimizedOriginalNetwork); + inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo); + inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo); + additionLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo); - // Optimize deserialized network - armnn::IOptimizedNetworkPtr optimizedDeserializedNetwork = - armnn::Optimize(deserializedNetwork, preferredBackends, runtime->GetDeviceSpec()); - BOOST_CHECK(optimizedDeserializedNetwork); + armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); + BOOST_CHECK(deserializedNetwork); - armnn::NetworkId networkId1; - armnn::NetworkId networkId2; + AdditionLayerVerifier verifier(layerName, {tensorInfo, tensorInfo}, {tensorInfo}); + deserializedNetwork->Accept(verifier); +} - // Load original and deserialized network - armnn::Status status1 = runtime->LoadNetwork(networkId1, std::move(optimizedOriginalNetwork)); - BOOST_CHECK(status1 == armnn::Status::Success); +BOOST_AUTO_TEST_CASE(SerializeBatchNormalization) +{ + class BatchNormalizationLayerVerifier : public LayerVerifierBase + { + public: + BatchNormalizationLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::BatchNormalizationDescriptor& descriptor, + const armnn::ConstTensor& mean, + const armnn::ConstTensor& variance, + const armnn::ConstTensor& beta, + const armnn::ConstTensor& gamma) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) + , m_Mean(mean) + , m_Variance(variance) + , m_Beta(beta) + , m_Gamma(gamma) {} + + void VisitBatchNormalizationLayer(const armnn::IConnectableLayer* layer, + const armnn::BatchNormalizationDescriptor& descriptor, + const armnn::ConstTensor& mean, + const armnn::ConstTensor& variance, + const armnn::ConstTensor& beta, + const armnn::ConstTensor& gamma, + const char* name) override + { + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); - armnn::Status status2 = runtime->LoadNetwork(networkId2, std::move(optimizedDeserializedNetwork)); - BOOST_CHECK(status2 == armnn::Status::Success); + CompareConstTensor(mean, m_Mean); + CompareConstTensor(variance, m_Variance); + CompareConstTensor(beta, m_Beta); + CompareConstTensor(gamma, m_Gamma); + } - // Generate some input data - armnn::InputTensors inputTensors1; - armnn::InputTensors inputTensors2; - std::vector> inputData; - inputData.reserve(inputShapes.size()); + private: + void VerifyDescriptor(const armnn::BatchNormalizationDescriptor& descriptor) + { + BOOST_TEST(descriptor.m_Eps == m_Descriptor.m_Eps); + BOOST_TEST(static_cast(descriptor.m_DataLayout) == static_cast(m_Descriptor.m_DataLayout)); + } - for (unsigned int i = 0; i < inputShapes.size(); i++) { - inputData.push_back(GenerateRandomData(inputShapes[i].GetNumElements())); + armnn::BatchNormalizationDescriptor m_Descriptor; + armnn::ConstTensor m_Mean; + armnn::ConstTensor m_Variance; + armnn::ConstTensor m_Beta; + armnn::ConstTensor m_Gamma; + }; - inputTensors1.emplace_back( - i, armnn::ConstTensor(runtime->GetInputTensorInfo(networkId1, inputBindingIds[i]), inputData[i].data())); + const std::string layerName("batchNormalization"); + const armnn::TensorInfo inputInfo ({ 1, 3, 3, 1 }, armnn::DataType::Float32); + const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32); - inputTensors2.emplace_back( - i, armnn::ConstTensor(runtime->GetInputTensorInfo(networkId2, inputBindingIds[i]), inputData[i].data())); - } + const armnn::TensorInfo meanInfo({1}, armnn::DataType::Float32); + const armnn::TensorInfo varianceInfo({1}, armnn::DataType::Float32); + const armnn::TensorInfo betaInfo({1}, armnn::DataType::Float32); + const armnn::TensorInfo gammaInfo({1}, armnn::DataType::Float32); - armnn::OutputTensors outputTensors1; - armnn::OutputTensors outputTensors2; - std::vector> outputData1; - std::vector> outputData2; - outputData1.reserve(outputShapes.size()); - outputData2.reserve(outputShapes.size()); + armnn::BatchNormalizationDescriptor descriptor; + descriptor.m_Eps = 0.0010000000475f; + descriptor.m_DataLayout = armnn::DataLayout::NHWC; - for (unsigned int i = 0; i < outputShapes.size(); i++) - { - outputData1.emplace_back(outputShapes[i].GetNumElements()); - outputData2.emplace_back(outputShapes[i].GetNumElements()); + std::vector meanData({5.0}); + std::vector varianceData({2.0}); + std::vector betaData({1.0}); + std::vector gammaData({0.0}); - outputTensors1.emplace_back( - i, armnn::Tensor(runtime->GetOutputTensorInfo(networkId1, outputBindingIds[i]), outputData1[i].data())); + armnn::ConstTensor mean(meanInfo, meanData); + armnn::ConstTensor variance(varianceInfo, varianceData); + armnn::ConstTensor beta(betaInfo, betaData); + armnn::ConstTensor gamma(gammaInfo, gammaData); - outputTensors2.emplace_back( - i, armnn::Tensor(runtime->GetOutputTensorInfo(networkId2, outputBindingIds[i]), outputData2[i].data())); - } + armnn::INetworkPtr network = armnn::INetwork::Create(); + armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); + armnn::IConnectableLayer* const batchNormalizationLayer = + network->AddBatchNormalizationLayer(descriptor, mean, variance, beta, gamma, layerName.c_str()); + armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - // Run original and deserialized network - runtime->EnqueueWorkload(networkId1, inputTensors1, outputTensors1); - runtime->EnqueueWorkload(networkId2, inputTensors2, outputTensors2); + inputLayer->GetOutputSlot(0).Connect(batchNormalizationLayer->GetInputSlot(0)); + batchNormalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - // Compare output data - for (unsigned int i = 0; i < outputShapes.size(); i++) - { - BOOST_CHECK_EQUAL_COLLECTIONS( - outputData1[i].begin(), outputData1[i].end(), outputData2[i].begin(), outputData2[i].end()); - } -} + inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo); + batchNormalizationLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); -} // anonymous namespace + armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); + BOOST_CHECK(deserializedNetwork); -BOOST_AUTO_TEST_SUITE(SerializerTests) + BatchNormalizationLayerVerifier verifier( + layerName, {inputInfo}, {outputInfo}, descriptor, mean, variance, beta, gamma); + deserializedNetwork->Accept(verifier); +} -BOOST_AUTO_TEST_CASE(SerializeDeserializeAddition) +BOOST_AUTO_TEST_CASE(SerializeBatchToSpaceNd) { - class VerifyAdditionName : public armnn::LayerVisitorBase + class BatchToSpaceNdLayerVerifier : public LayerVerifierBase { public: - void VisitAdditionLayer(const armnn::IConnectableLayer*, const char* name) override + BatchToSpaceNdLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::BatchToSpaceNdDescriptor& descriptor) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) {} + + void VisitBatchToSpaceNdLayer(const armnn::IConnectableLayer* layer, + const armnn::BatchToSpaceNdDescriptor& descriptor, + const char* name) override + { + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); + } + + private: + void VerifyDescriptor(const armnn::BatchToSpaceNdDescriptor& descriptor) { - BOOST_TEST(name == "addition"); + BOOST_TEST(descriptor.m_Crops == m_Descriptor.m_Crops); + BOOST_TEST(descriptor.m_BlockShape == m_Descriptor.m_BlockShape); + BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout)); } + + armnn::BatchToSpaceNdDescriptor m_Descriptor; }; - armnn::INetworkPtr network = armnn::INetwork::Create(); - armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0); - armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1); + const std::string layerName("spaceToBatchNd"); + const armnn::TensorInfo inputInfo({4, 1, 2, 2}, armnn::DataType::Float32); + const armnn::TensorInfo outputInfo({1, 1, 4, 4}, armnn::DataType::Float32); - armnn::IConnectableLayer* const additionLayer = network->AddAdditionLayer("addition"); - inputLayer0->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(0)); - inputLayer1->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(1)); + armnn::BatchToSpaceNdDescriptor desc; + desc.m_DataLayout = armnn::DataLayout::NCHW; + desc.m_BlockShape = {2, 2}; + desc.m_Crops = {{0, 0}, {0, 0}}; + armnn::INetworkPtr network = armnn::INetwork::Create(); + armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); + armnn::IConnectableLayer* const batchToSpaceNdLayer = network->AddBatchToSpaceNdLayer(desc, layerName.c_str()); armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - additionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - - armnn::TensorShape shape{1U}; - armnn::TensorInfo info(shape, armnn::DataType::Float32); - inputLayer0->GetOutputSlot(0).SetTensorInfo(info); - inputLayer1->GetOutputSlot(0).SetTensorInfo(info); - additionLayer->GetOutputSlot(0).SetTensorInfo(info); - armnnSerializer::Serializer serializer; - serializer.Serialize(*network); + inputLayer->GetOutputSlot(0).Connect(batchToSpaceNdLayer->GetInputSlot(0)); + batchToSpaceNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - std::stringstream stream; - serializer.SaveSerializedToStream(stream); - BOOST_TEST(stream.str().length() > 0); + inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo); + batchToSpaceNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); - armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(stream.str()); + armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyAdditionName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {info.GetShape(), info.GetShape()}, - {info.GetShape()}, - {0, 1}); + BatchToSpaceNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc); + deserializedNetwork->Accept(verifier); } BOOST_AUTO_TEST_CASE(SerializeConstant) { - armnn::INetworkPtr network = armnn::INetwork::Create(); - - armnn::ConstTensor inputTensor; - - armnn::IConnectableLayer* const inputLayer0 = network->AddConstantLayer(inputTensor, "constant"); - armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0); - - inputLayer0->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0)); - - armnnSerializer::Serializer serializer; - serializer.Serialize(*network); - - std::stringstream stream; - serializer.SaveSerializedToStream(stream); - BOOST_TEST(stream.str().length() > 0); - BOOST_TEST(stream.str().find("constant") != stream.str().npos); -} - -BOOST_AUTO_TEST_CASE(SerializeDeserializeConstant) -{ - class VerifyConstantName : public armnn::LayerVisitorBase + class ConstantLayerVerifier : public LayerVerifierBase { public: - void VisitConstantLayer(const armnn::IConnectableLayer*, const armnn::ConstTensor&, const char* name) override + ConstantLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::ConstTensor& layerInput) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_LayerInput(layerInput) {} + + void VisitConstantLayer(const armnn::IConnectableLayer* layer, + const armnn::ConstTensor& input, + const char* name) override { - BOOST_TEST(name == "constant"); + VerifyNameAndConnections(layer, name); + + CompareConstTensor(input, m_LayerInput); } + + void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {} + + private: + armnn::ConstTensor m_LayerInput; }; - armnn::TensorInfo commonTensorInfo({ 2, 3 }, armnn::DataType::Float32); + const std::string layerName("constant"); + const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32); - std::vector constantData = GenerateRandomData(commonTensorInfo.GetNumElements()); - armnn::ConstTensor constTensor(commonTensorInfo, constantData); + std::vector constantData = GenerateRandomData(info.GetNumElements()); + armnn::ConstTensor constTensor(info, constantData); - // Builds up the structure of the network. armnn::INetworkPtr network(armnn::INetwork::Create()); - armnn::IConnectableLayer* input = network->AddInputLayer(0); - armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, "constant"); + armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str()); armnn::IConnectableLayer* add = network->AddAdditionLayer(); armnn::IConnectableLayer* output = network->AddOutputLayer(0); @@ -244,912 +395,940 @@ BOOST_AUTO_TEST_CASE(SerializeDeserializeConstant) constant->GetOutputSlot(0).Connect(add->GetInputSlot(1)); add->GetOutputSlot(0).Connect(output->GetInputSlot(0)); - // Sets the tensors in the network. - input->GetOutputSlot(0).SetTensorInfo(commonTensorInfo); - constant->GetOutputSlot(0).SetTensorInfo(commonTensorInfo); - add->GetOutputSlot(0).SetTensorInfo(commonTensorInfo); + input->GetOutputSlot(0).SetTensorInfo(info); + constant->GetOutputSlot(0).SetTensorInfo(info); + add->GetOutputSlot(0).SetTensorInfo(info); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyConstantName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {commonTensorInfo.GetShape()}, - {commonTensorInfo.GetShape()}); + ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeFloor) +BOOST_AUTO_TEST_CASE(SerializeConvolution2d) { - class VerifyFloorName : public armnn::LayerVisitorBase + class Convolution2dLayerVerifier : public LayerVerifierBase { public: - void VisitMultiplicationLayer(const armnn::IConnectableLayer*, const char* name) override + Convolution2dLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::Convolution2dDescriptor& descriptor, + const armnn::ConstTensor& weight, + const armnn::Optional& bias) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) + , m_Weight(weight) + , m_Bias(bias) {} + + void VisitConvolution2dLayer(const armnn::IConnectableLayer* layer, + const armnn::Convolution2dDescriptor& descriptor, + const armnn::ConstTensor& weight, + const armnn::Optional& bias, + const char* name) override + { + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); + + CompareConstTensor(weight, m_Weight); + + BOOST_TEST(bias.has_value() == m_Bias.has_value()); + if (bias.has_value() && m_Bias.has_value()) + { + CompareConstTensor(bias.value(), m_Bias.value()); + } + } + + private: + void VerifyDescriptor(const armnn::Convolution2dDescriptor& descriptor) { - BOOST_TEST(name == "floor"); + BOOST_TEST(descriptor.m_PadLeft == m_Descriptor.m_PadLeft); + BOOST_TEST(descriptor.m_PadRight == m_Descriptor.m_PadRight); + BOOST_TEST(descriptor.m_PadTop == m_Descriptor.m_PadTop); + BOOST_TEST(descriptor.m_PadBottom == m_Descriptor.m_PadBottom); + BOOST_TEST(descriptor.m_StrideX == m_Descriptor.m_StrideX); + BOOST_TEST(descriptor.m_StrideY == m_Descriptor.m_StrideY); + BOOST_TEST(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled); + BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout)); } + + armnn::Convolution2dDescriptor m_Descriptor; + armnn::ConstTensor m_Weight; + armnn::Optional m_Bias; }; - const armnn::TensorInfo info({4,4}, armnn::DataType::Float32); + const std::string layerName("convolution2d"); + const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32); + const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32); - armnn::INetworkPtr network = armnn::INetwork::Create(); - armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); + const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32); + const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32); - const char* floorLayerName = "floor"; + std::vector weightsData = GenerateRandomData(weightsInfo.GetNumElements()); + armnn::ConstTensor weights(weightsInfo, weightsData); - armnn::IConnectableLayer* const floorLayer = network->AddFloorLayer(floorLayerName); - inputLayer->GetOutputSlot(0).Connect(floorLayer->GetInputSlot(0)); + std::vector biasesData = GenerateRandomData(biasesInfo.GetNumElements()); + armnn::ConstTensor biases(biasesInfo, biasesData); - armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - floorLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + armnn::Convolution2dDescriptor descriptor; + descriptor.m_PadLeft = 1; + descriptor.m_PadRight = 1; + descriptor.m_PadTop = 1; + descriptor.m_PadBottom = 1; + descriptor.m_StrideX = 2; + descriptor.m_StrideY = 2; + descriptor.m_BiasEnabled = true; + descriptor.m_DataLayout = armnn::DataLayout::NHWC; - inputLayer->GetOutputSlot(0).SetTensorInfo(info); - floorLayer->GetOutputSlot(0).SetTensorInfo(info); + armnn::INetworkPtr network = armnn::INetwork::Create(); + armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); + armnn::IConnectableLayer* const convLayer = + network->AddConvolution2dLayer(descriptor, weights, biases, layerName.c_str()); + armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - armnnSerializer::Serializer serializer; - serializer.Serialize(*network); + inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0)); + convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - std::stringstream stream; - serializer.SaveSerializedToStream(stream); - BOOST_TEST(stream.str().length() > 0); - BOOST_TEST(stream.str().find(floorLayerName) != stream.str().npos); + inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo); + convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); - armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(stream.str()); + armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyFloorName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {info.GetShape()}, - {info.GetShape()}); + Convolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeMinimum) +BOOST_AUTO_TEST_CASE(SerializeDepthwiseConvolution2d) { - class VerifyMinimumName : public armnn::LayerVisitorBase + class DepthwiseConvolution2dLayerVerifier : public LayerVerifierBase { public: - explicit VerifyMinimumName(const std::string& expectedMinimumLayerName) - : m_ExpectedMinimumLayerName(expectedMinimumLayerName) {} - - void VisitMinimumLayer(const armnn::IConnectableLayer*, const char* name) override + DepthwiseConvolution2dLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::DepthwiseConvolution2dDescriptor& descriptor, + const armnn::ConstTensor& weight, + const armnn::Optional& bias) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) + , m_Weight(weight) + , m_Bias(bias) {} + + void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer, + const armnn::DepthwiseConvolution2dDescriptor& descriptor, + const armnn::ConstTensor& weight, + const armnn::Optional& bias, + const char* name) override { - BOOST_TEST(name == m_ExpectedMinimumLayerName.c_str()); + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); + + CompareConstTensor(weight, m_Weight); + + BOOST_TEST(bias.has_value() == m_Bias.has_value()); + if (bias.has_value() && m_Bias.has_value()) + { + CompareConstTensor(bias.value(), m_Bias.value()); + } } private: - std::string m_ExpectedMinimumLayerName; + void VerifyDescriptor(const armnn::DepthwiseConvolution2dDescriptor& descriptor) + { + BOOST_TEST(descriptor.m_PadLeft == m_Descriptor.m_PadLeft); + BOOST_TEST(descriptor.m_PadRight == m_Descriptor.m_PadRight); + BOOST_TEST(descriptor.m_PadTop == m_Descriptor.m_PadTop); + BOOST_TEST(descriptor.m_PadBottom == m_Descriptor.m_PadBottom); + BOOST_TEST(descriptor.m_StrideX == m_Descriptor.m_StrideX); + BOOST_TEST(descriptor.m_StrideY == m_Descriptor.m_StrideY); + BOOST_TEST(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled); + BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout)); + } + + armnn::DepthwiseConvolution2dDescriptor m_Descriptor; + armnn::ConstTensor m_Weight; + armnn::Optional m_Bias; }; - const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32); + const std::string layerName("depwiseConvolution2d"); + const armnn::TensorInfo inputInfo ({ 1, 5, 5, 3 }, armnn::DataType::Float32); + const armnn::TensorInfo outputInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32); - armnn::INetworkPtr network = armnn::INetwork::Create(); - armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0); - armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1); + const armnn::TensorInfo weightsInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32); + const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32); - const std::string minimumLayerName("minimum"); + std::vector weightsData = GenerateRandomData(weightsInfo.GetNumElements()); + armnn::ConstTensor weights(weightsInfo, weightsData); - armnn::IConnectableLayer* const minimumLayer = network->AddMinimumLayer(minimumLayerName.c_str()); - inputLayer0->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(0)); - inputLayer1->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(1)); + std::vector biasesData = GenerateRandomData(biasesInfo.GetNumElements()); + armnn::ConstTensor biases(biasesInfo, biasesData); - armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - minimumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + armnn::DepthwiseConvolution2dDescriptor descriptor; + descriptor.m_StrideX = 1; + descriptor.m_StrideY = 1; + descriptor.m_BiasEnabled = true; + descriptor.m_DataLayout = armnn::DataLayout::NHWC; - inputLayer0->GetOutputSlot(0).SetTensorInfo(info); - inputLayer1->GetOutputSlot(0).SetTensorInfo(info); - minimumLayer->GetOutputSlot(0).SetTensorInfo(info); + armnn::INetworkPtr network = armnn::INetwork::Create(); + armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); + armnn::IConnectableLayer* const depthwiseConvLayer = + network->AddDepthwiseConvolution2dLayer(descriptor, weights, biases, layerName.c_str()); + armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - armnnSerializer::Serializer serializer; - serializer.Serialize(*network); + inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0)); + depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - std::stringstream stream; - serializer.SaveSerializedToStream(stream); - BOOST_TEST(stream.str().length() > 0); - BOOST_TEST(stream.str().find(minimumLayerName) != stream.str().npos); + inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo); + depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); - armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(stream.str()); + armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyMinimumName nameChecker(minimumLayerName); - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {info.GetShape(), info.GetShape()}, - {info.GetShape()}, - {0, 1}); + DepthwiseConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeMaximum) +BOOST_AUTO_TEST_CASE(SerializeDeserializeDetectionPostProcess) { - class VerifyMaximumName : public armnn::LayerVisitorBase + class DetectionPostProcessLayerVerifier : public LayerVerifierBase { public: - explicit VerifyMaximumName(const std::string& expectedMaximumLayerName) - : m_ExpectedMaximumLayerName(expectedMaximumLayerName) {} + DetectionPostProcessLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::DetectionPostProcessDescriptor& descriptor, + const armnn::ConstTensor& anchors) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) + , m_Anchors(anchors) {} - void VisitMaximumLayer(const armnn::IConnectableLayer*, const char* name) override + void VisitDetectionPostProcessLayer(const armnn::IConnectableLayer* layer, + const armnn::DetectionPostProcessDescriptor& descriptor, + const armnn::ConstTensor& anchors, + const char* name) override { - BOOST_TEST(name == m_ExpectedMaximumLayerName.c_str()); + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); + + CompareConstTensor(anchors, m_Anchors); } private: - std::string m_ExpectedMaximumLayerName; + void VerifyDescriptor(const armnn::DetectionPostProcessDescriptor& descriptor) + { + BOOST_TEST(descriptor.m_UseRegularNms == m_Descriptor.m_UseRegularNms); + BOOST_TEST(descriptor.m_MaxDetections == m_Descriptor.m_MaxDetections); + BOOST_TEST(descriptor.m_MaxClassesPerDetection == m_Descriptor.m_MaxClassesPerDetection); + BOOST_TEST(descriptor.m_DetectionsPerClass == m_Descriptor.m_DetectionsPerClass); + BOOST_TEST(descriptor.m_NmsScoreThreshold == m_Descriptor.m_NmsScoreThreshold); + BOOST_TEST(descriptor.m_NmsIouThreshold == m_Descriptor.m_NmsIouThreshold); + BOOST_TEST(descriptor.m_NumClasses == m_Descriptor.m_NumClasses); + BOOST_TEST(descriptor.m_ScaleY == m_Descriptor.m_ScaleY); + BOOST_TEST(descriptor.m_ScaleX == m_Descriptor.m_ScaleX); + BOOST_TEST(descriptor.m_ScaleH == m_Descriptor.m_ScaleH); + BOOST_TEST(descriptor.m_ScaleW == m_Descriptor.m_ScaleW); + } + + armnn::DetectionPostProcessDescriptor m_Descriptor; + armnn::ConstTensor m_Anchors; }; - const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32); + const std::string layerName("detectionPostProcess"); - armnn::INetworkPtr network = armnn::INetwork::Create(); - armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0); - armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1); + const std::vector inputInfos({ + armnn::TensorInfo({ 1, 6, 4 }, armnn::DataType::Float32), + armnn::TensorInfo({ 1, 6, 3}, armnn::DataType::Float32) + }); - const std::string maximumLayerName("maximum"); + const std::vector outputInfos({ + armnn::TensorInfo({ 1, 3, 4 }, armnn::DataType::Float32), + armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32), + armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32), + armnn::TensorInfo({ 1 }, armnn::DataType::Float32) + }); - armnn::IConnectableLayer* const maximumLayer = network->AddMaximumLayer(maximumLayerName.c_str()); - inputLayer0->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(0)); - inputLayer1->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(1)); + armnn::DetectionPostProcessDescriptor descriptor; + descriptor.m_UseRegularNms = true; + descriptor.m_MaxDetections = 3; + descriptor.m_MaxClassesPerDetection = 1; + descriptor.m_DetectionsPerClass =1; + descriptor.m_NmsScoreThreshold = 0.0; + descriptor.m_NmsIouThreshold = 0.5; + descriptor.m_NumClasses = 2; + descriptor.m_ScaleY = 10.0; + descriptor.m_ScaleX = 10.0; + descriptor.m_ScaleH = 5.0; + descriptor.m_ScaleW = 5.0; - armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - maximumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - - inputLayer0->GetOutputSlot(0).SetTensorInfo(info); - inputLayer1->GetOutputSlot(0).SetTensorInfo(info); - maximumLayer->GetOutputSlot(0).SetTensorInfo(info); - - armnnSerializer::Serializer serializer; - serializer.Serialize(*network); - - std::stringstream stream; - serializer.SaveSerializedToStream(stream); - BOOST_TEST(stream.str().length() > 0); - BOOST_TEST(stream.str().find(maximumLayerName) != stream.str().npos); - - armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(stream.str()); - BOOST_CHECK(deserializedNetwork); - - VerifyMaximumName nameChecker(maximumLayerName); - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {info.GetShape(), info.GetShape()}, - {info.GetShape()}, - {0, 1}); -} - -BOOST_AUTO_TEST_CASE(SerializeDeserializeL2Normalization) -{ - class VerifyL2NormalizationName : public armnn::LayerVisitorBase - { - public: - explicit VerifyL2NormalizationName(const std::string& expectedL2NormalizationLayerName) - : m_ExpectedL2NormalizationLayerName(expectedL2NormalizationLayerName) {} - - void VisitL2NormalizationLayer(const armnn::IConnectableLayer*, - const armnn::L2NormalizationDescriptor&, - const char* name) override - { - BOOST_TEST(name == m_ExpectedL2NormalizationLayerName.c_str()); - } - private: - std::string m_ExpectedL2NormalizationLayerName; - }; - - const armnn::TensorInfo info({ 1, 2, 1, 5 }, armnn::DataType::Float32); - - armnn::L2NormalizationDescriptor desc; - desc.m_DataLayout = armnn::DataLayout::NCHW; + const armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32); + const std::vector anchorsData({ + 0.5f, 0.5f, 1.0f, 1.0f, + 0.5f, 0.5f, 1.0f, 1.0f, + 0.5f, 0.5f, 1.0f, 1.0f, + 0.5f, 10.5f, 1.0f, 1.0f, + 0.5f, 10.5f, 1.0f, 1.0f, + 0.5f, 100.5f, 1.0f, 1.0f + }); + armnn::ConstTensor anchors(anchorsInfo, anchorsData); armnn::INetworkPtr network = armnn::INetwork::Create(); - armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0); - - const char* l2NormLayerName = "l2Normalization"; - - armnn::IConnectableLayer* const l2NormLayer = network->AddL2NormalizationLayer(desc, l2NormLayerName); - inputLayer0->GetOutputSlot(0).Connect(l2NormLayer->GetInputSlot(0)); - - armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - l2NormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - - inputLayer0->GetOutputSlot(0).SetTensorInfo(info); - l2NormLayer->GetOutputSlot(0).SetTensorInfo(info); + armnn::IConnectableLayer* const detectionLayer = + network->AddDetectionPostProcessLayer(descriptor, anchors, layerName.c_str()); - armnnSerializer::Serializer serializer; - serializer.Serialize(*network); + for (unsigned int i = 0; i < 2; i++) + { + armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(static_cast(i)); + inputLayer->GetOutputSlot(0).Connect(detectionLayer->GetInputSlot(i)); + inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfos[i]); + } - std::stringstream stream; - serializer.SaveSerializedToStream(stream); - BOOST_TEST(stream.str().length() > 0); - BOOST_TEST(stream.str().find(l2NormLayerName) != stream.str().npos); + for (unsigned int i = 0; i < 4; i++) + { + armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(static_cast(i)); + detectionLayer->GetOutputSlot(i).Connect(outputLayer->GetInputSlot(0)); + detectionLayer->GetOutputSlot(i).SetTensorInfo(outputInfos[i]); + } - armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(stream.str()); + armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyL2NormalizationName nameChecker(l2NormLayerName); - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - { info.GetShape() }, - { info.GetShape() }); + DetectionPostProcessLayerVerifier verifier(layerName, inputInfos, outputInfos, descriptor, anchors); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeMultiplication) +BOOST_AUTO_TEST_CASE(SerializeDivision) { - class VerifyMultiplicationName : public armnn::LayerVisitorBase + class DivisionLayerVerifier : public LayerVerifierBase { public: - void VisitMultiplicationLayer(const armnn::IConnectableLayer*, const char* name) override + DivisionLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos) + : LayerVerifierBase(layerName, inputInfos, outputInfos) {} + + void VisitDivisionLayer(const armnn::IConnectableLayer* layer, const char* name) override { - BOOST_TEST(name == "multiplication"); + VerifyNameAndConnections(layer, name); } }; + const std::string layerName("division"); const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32); armnn::INetworkPtr network = armnn::INetwork::Create(); armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0); armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1); - - const char* multLayerName = "multiplication"; - - armnn::IConnectableLayer* const multiplicationLayer = network->AddMultiplicationLayer(multLayerName); - inputLayer0->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(0)); - inputLayer1->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(1)); - + armnn::IConnectableLayer* const divisionLayer = network->AddDivisionLayer(layerName.c_str()); armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - multiplicationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + + inputLayer0->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(0)); + inputLayer1->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(1)); + divisionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); inputLayer0->GetOutputSlot(0).SetTensorInfo(info); inputLayer1->GetOutputSlot(0).SetTensorInfo(info); - multiplicationLayer->GetOutputSlot(0).SetTensorInfo(info); - - armnnSerializer::Serializer serializer; - serializer.Serialize(*network); - - std::stringstream stream; - serializer.SaveSerializedToStream(stream); - BOOST_TEST(stream.str().length() > 0); - BOOST_TEST(stream.str().find(multLayerName) != stream.str().npos); - - armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(stream.str()); - BOOST_CHECK(deserializedNetwork); - - VerifyMultiplicationName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {info.GetShape(), info.GetShape()}, - {info.GetShape()}, - {0, 1}); -} - -BOOST_AUTO_TEST_CASE(SerializeDeserializeConvolution2d) -{ - - class VerifyConvolution2dName : public armnn::LayerVisitorBase - { - public: - void VisitConvolution2dLayer(const armnn::IConnectableLayer*, - const armnn::Convolution2dDescriptor&, - const armnn::ConstTensor&, - const armnn::Optional&, - const char* name) override - { - BOOST_TEST(name == "convolution"); - } - }; - - armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32); - armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32); - - armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32); - armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32); - - // Construct network - armnn::INetworkPtr network = armnn::INetwork::Create(); - - armnn::Convolution2dDescriptor descriptor; - descriptor.m_PadLeft = 1; - descriptor.m_PadRight = 1; - descriptor.m_PadTop = 1; - descriptor.m_PadBottom = 1; - descriptor.m_StrideX = 2; - descriptor.m_StrideY = 2; - descriptor.m_BiasEnabled = true; - descriptor.m_DataLayout = armnn::DataLayout::NHWC; - - std::vector weightsData = GenerateRandomData(weightsInfo.GetNumElements()); - armnn::ConstTensor weights(weightsInfo, weightsData); - - std::vector biasesData = GenerateRandomData(biasesInfo.GetNumElements()); - armnn::ConstTensor biases(biasesInfo, biasesData); - - armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0, "input"); - armnn::IConnectableLayer* const convLayer = - network->AddConvolution2dLayer(descriptor, weights, biases, "convolution"); - armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0, "output"); - - inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0)); - inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo); - - convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); + divisionLayer->GetOutputSlot(0).SetTensorInfo(info); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyConvolution2dName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {inputInfo.GetShape()}, - {outputInfo.GetShape()}); + DivisionLayerVerifier verifier(layerName, {info, info}, {info}); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeGreater) +BOOST_AUTO_TEST_CASE(SerializeEqual) { - class VerifyGreaterName : public armnn::LayerVisitorBase + class EqualLayerVerifier : public LayerVerifierBase { public: - void VisitGreaterLayer(const armnn::IConnectableLayer*, const char* name) override + EqualLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos) + : LayerVerifierBase(layerName, inputInfos, outputInfos) {} + + void VisitEqualLayer(const armnn::IConnectableLayer* layer, const char* name) override { - BOOST_TEST(name == "greater"); + VerifyNameAndConnections(layer, name); } }; - const armnn::TensorInfo inputTensorInfo1({ 1, 2, 2, 2 }, armnn::DataType::Float32); - const armnn::TensorInfo inputTensorInfo2({ 1, 2, 2, 2 }, armnn::DataType::Float32); - const armnn::TensorInfo outputTensorInfo({ 1, 2, 2, 2 }, armnn::DataType::Boolean); + const std::string layerName("equal"); + const armnn::TensorInfo inputTensorInfo1 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32); + const armnn::TensorInfo inputTensorInfo2 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32); + const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Boolean); armnn::INetworkPtr network = armnn::INetwork::Create(); armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0); armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1); - armnn::IConnectableLayer* const greaterLayer = network->AddGreaterLayer("greater"); + armnn::IConnectableLayer* const equalLayer = network->AddEqualLayer(layerName.c_str()); armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - inputLayer1->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(0)); + inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0)); + inputLayer2->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1)); + equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1); - inputLayer2->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(1)); inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2); - greaterLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - greaterLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); + equalLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyGreaterName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {inputTensorInfo1.GetShape(), inputTensorInfo2.GetShape()}, - {outputTensorInfo.GetShape()}, - {0, 1}); + EqualLayerVerifier verifier(layerName, {inputTensorInfo1, inputTensorInfo2}, {outputTensorInfo}); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeReshape) +BOOST_AUTO_TEST_CASE(SerializeFloor) { - class VerifyReshapeName : public armnn::LayerVisitorBase + class FloorLayerVerifier : public LayerVerifierBase { public: - void VisitReshapeLayer(const armnn::IConnectableLayer*, const armnn::ReshapeDescriptor&, const char* name) + FloorLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos) + : LayerVerifierBase(layerName, inputInfos, outputInfos) {} + + void VisitFloorLayer(const armnn::IConnectableLayer* layer, const char* name) override { - BOOST_TEST(name == "reshape"); + VerifyNameAndConnections(layer, name); } }; - unsigned int inputShape[] = { 1, 9 }; - unsigned int outputShape[] = { 3, 3 }; - - auto inputTensorInfo = armnn::TensorInfo(2, inputShape, armnn::DataType::Float32); - auto outputTensorInfo = armnn::TensorInfo(2, outputShape, armnn::DataType::Float32); - auto reshapeOutputTensorInfo = armnn::TensorInfo(2, outputShape, armnn::DataType::Float32); - - armnn::ReshapeDescriptor reshapeDescriptor; - reshapeDescriptor.m_TargetShape = reshapeOutputTensorInfo.GetShape(); + const std::string layerName("floor"); + const armnn::TensorInfo info({4,4}, armnn::DataType::Float32); armnn::INetworkPtr network = armnn::INetwork::Create(); armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); - armnn::IConnectableLayer* const reshapeLayer = network->AddReshapeLayer(reshapeDescriptor, "reshape"); + armnn::IConnectableLayer* const floorLayer = network->AddFloorLayer(layerName.c_str()); armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - inputLayer->GetOutputSlot(0).Connect(reshapeLayer->GetInputSlot(0)); - inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo); - reshapeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - reshapeLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); + inputLayer->GetOutputSlot(0).Connect(floorLayer->GetInputSlot(0)); + floorLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + + inputLayer->GetOutputSlot(0).SetTensorInfo(info); + floorLayer->GetOutputSlot(0).SetTensorInfo(info); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyReshapeName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {inputTensorInfo.GetShape()}, - {outputTensorInfo.GetShape()}); + FloorLayerVerifier verifier(layerName, {info}, {info}); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeDepthwiseConvolution2d) +BOOST_AUTO_TEST_CASE(SerializeFullyConnected) { - class VerifyDepthwiseConvolution2dName : public armnn::LayerVisitorBase + class FullyConnectedLayerVerifier : public LayerVerifierBase { public: - void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer*, - const armnn::DepthwiseConvolution2dDescriptor&, - const armnn::ConstTensor&, - const armnn::Optional&, - const char* name) override + FullyConnectedLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::FullyConnectedDescriptor& descriptor, + const armnn::ConstTensor& weight, + const armnn::Optional& bias) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) + , m_Weight(weight) + , m_Bias(bias) {} + + void VisitFullyConnectedLayer(const armnn::IConnectableLayer* layer, + const armnn::FullyConnectedDescriptor& descriptor, + const armnn::ConstTensor& weight, + const armnn::Optional& bias, + const char* name) override { - BOOST_TEST(name == "depthwise_convolution"); + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); + + CompareConstTensor(weight, m_Weight); + + BOOST_TEST(bias.has_value() == m_Bias.has_value()); + if (bias.has_value() && m_Bias.has_value()) + { + CompareConstTensor(bias.value(), m_Bias.value()); + } } - }; - armnn::TensorInfo inputInfo ({ 1, 5, 5, 3 }, armnn::DataType::Float32); - armnn::TensorInfo outputInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32); + private: + void VerifyDescriptor(const armnn::FullyConnectedDescriptor& descriptor) + { + BOOST_TEST(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled); + BOOST_TEST(descriptor.m_TransposeWeightMatrix == m_Descriptor.m_TransposeWeightMatrix); + } - armnn::TensorInfo weightsInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32); - armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32); + armnn::FullyConnectedDescriptor m_Descriptor; + armnn::ConstTensor m_Weight; + armnn::Optional m_Bias; + }; - armnn::DepthwiseConvolution2dDescriptor descriptor; - descriptor.m_StrideX = 1; - descriptor.m_StrideY = 1; - descriptor.m_BiasEnabled = true; - descriptor.m_DataLayout = armnn::DataLayout::NHWC; + const std::string layerName("fullyConnected"); + const armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32); + const armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32); + const armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32); + const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32); std::vector weightsData = GenerateRandomData(weightsInfo.GetNumElements()); + std::vector biasesData = GenerateRandomData(biasesInfo.GetNumElements()); armnn::ConstTensor weights(weightsInfo, weightsData); - - std::vector biasesData = GenerateRandomData(biasesInfo.GetNumElements()); armnn::ConstTensor biases(biasesInfo, biasesData); + armnn::FullyConnectedDescriptor descriptor; + descriptor.m_BiasEnabled = true; + descriptor.m_TransposeWeightMatrix = false; + armnn::INetworkPtr network = armnn::INetwork::Create(); armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); - armnn::IConnectableLayer* const depthwiseConvLayer = - network->AddDepthwiseConvolution2dLayer(descriptor, weights, biases, "depthwise_convolution"); + armnn::IConnectableLayer* const fullyConnectedLayer = + network->AddFullyConnectedLayer(descriptor, weights, biases, layerName.c_str()); armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0)); + inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0)); + fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo); - depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); + fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyDepthwiseConvolution2dName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {inputInfo.GetShape()}, - {outputInfo.GetShape()}); + FullyConnectedLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeSoftmax) +BOOST_AUTO_TEST_CASE(SerializeGather) { - class VerifySoftmaxName : public armnn::LayerVisitorBase + class GatherLayerVerifier : public LayerVerifierBase { public: - void VisitSoftmaxLayer(const armnn::IConnectableLayer*, const armnn::SoftmaxDescriptor&, const char* name) + GatherLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos) + : LayerVerifierBase(layerName, inputInfos, outputInfos) {} + + void VisitGatherLayer(const armnn::IConnectableLayer* layer, const char *name) override { - BOOST_TEST(name == "softmax"); + VerifyNameAndConnections(layer, name); } + + void VisitConstantLayer(const armnn::IConnectableLayer* layer, + const armnn::ConstTensor& input, + const char *name) override {} }; - armnn::TensorInfo tensorInfo({1, 10}, armnn::DataType::Float32); + const std::string layerName("gather"); + armnn::TensorInfo paramsInfo({ 8 }, armnn::DataType::QuantisedAsymm8); + armnn::TensorInfo outputInfo({ 3 }, armnn::DataType::QuantisedAsymm8); + const armnn::TensorInfo indicesInfo({ 3 }, armnn::DataType::Signed32); - armnn::SoftmaxDescriptor descriptor; - descriptor.m_Beta = 1.0f; + paramsInfo.SetQuantizationScale(1.0f); + paramsInfo.SetQuantizationOffset(0); + outputInfo.SetQuantizationScale(1.0f); + outputInfo.SetQuantizationOffset(0); + + const std::vector& indicesData = {7, 6, 5}; armnn::INetworkPtr network = armnn::INetwork::Create(); - armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); - armnn::IConnectableLayer* const softmaxLayer = network->AddSoftmaxLayer(descriptor, "softmax"); - armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); + armnn::IConnectableLayer *const inputLayer = network->AddInputLayer(0); + armnn::IConnectableLayer *const constantLayer = + network->AddConstantLayer(armnn::ConstTensor(indicesInfo, indicesData)); + armnn::IConnectableLayer *const gatherLayer = network->AddGatherLayer(layerName.c_str()); + armnn::IConnectableLayer *const outputLayer = network->AddOutputLayer(0); - inputLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0)); - inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo); - softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - softmaxLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo); + inputLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(0)); + constantLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(1)); + gatherLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + + inputLayer->GetOutputSlot(0).SetTensorInfo(paramsInfo); + constantLayer->GetOutputSlot(0).SetTensorInfo(indicesInfo); + gatherLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifySoftmaxName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {tensorInfo.GetShape()}, - {tensorInfo.GetShape()}); + GatherLayerVerifier verifier(layerName, {paramsInfo, indicesInfo}, {outputInfo}); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializePooling2d) +BOOST_AUTO_TEST_CASE(SerializeGreater) { - class VerifyPooling2dName : public armnn::LayerVisitorBase + class GreaterLayerVerifier : public LayerVerifierBase { - void VisitPooling2dLayer(const armnn::IConnectableLayer*, const armnn::Pooling2dDescriptor&, const char* name) + public: + GreaterLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos) + : LayerVerifierBase(layerName, inputInfos, outputInfos) {} + + void VisitGreaterLayer(const armnn::IConnectableLayer* layer, const char* name) override { - BOOST_TEST(name == "pooling2d"); + VerifyNameAndConnections(layer, name); } }; - unsigned int inputShape[] = {1, 2, 2, 1}; - unsigned int outputShape[] = {1, 1, 1, 1}; - - auto inputInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32); - auto outputInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32); - - armnn::Pooling2dDescriptor desc; - desc.m_DataLayout = armnn::DataLayout::NHWC; - desc.m_PadTop = 0; - desc.m_PadBottom = 0; - desc.m_PadLeft = 0; - desc.m_PadRight = 0; - desc.m_PoolType = armnn::PoolingAlgorithm::Average; - desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor; - desc.m_PaddingMethod = armnn::PaddingMethod::Exclude; - desc.m_PoolHeight = 2; - desc.m_PoolWidth = 2; - desc.m_StrideX = 2; - desc.m_StrideY = 2; + const std::string layerName("greater"); + const armnn::TensorInfo inputTensorInfo1({ 1, 2, 2, 2 }, armnn::DataType::Float32); + const armnn::TensorInfo inputTensorInfo2({ 1, 2, 2, 2 }, armnn::DataType::Float32); + const armnn::TensorInfo outputTensorInfo({ 1, 2, 2, 2 }, armnn::DataType::Boolean); armnn::INetworkPtr network = armnn::INetwork::Create(); - armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); - armnn::IConnectableLayer* const pooling2dLayer = network->AddPooling2dLayer(desc, "pooling2d"); + armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0); + armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1); + armnn::IConnectableLayer* const greaterLayer = network->AddGreaterLayer(layerName.c_str()); armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - inputLayer->GetOutputSlot(0).Connect(pooling2dLayer->GetInputSlot(0)); - inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo); - pooling2dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - pooling2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); + inputLayer1->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(0)); + inputLayer2->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(1)); + greaterLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + + inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1); + inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2); + greaterLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyPooling2dName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {inputInfo.GetShape()}, - {outputInfo.GetShape()}); + GreaterLayerVerifier verifier(layerName, {inputTensorInfo1, inputTensorInfo2}, {outputTensorInfo}); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializePermute) +BOOST_AUTO_TEST_CASE(SerializeL2Normalization) { - class VerifyPermuteName : public armnn::LayerVisitorBase + class L2NormalizationLayerVerifier : public LayerVerifierBase { public: - void VisitPermuteLayer(const armnn::IConnectableLayer*, const armnn::PermuteDescriptor&, const char* name) + L2NormalizationLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::L2NormalizationDescriptor& descriptor) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) {} + + void VisitL2NormalizationLayer(const armnn::IConnectableLayer* layer, + const armnn::L2NormalizationDescriptor& descriptor, + const char* name) override { - BOOST_TEST(name == "permute"); + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); + } + private: + void VerifyDescriptor(const armnn::L2NormalizationDescriptor& descriptor) + { + BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout)); } - }; - unsigned int inputShape[] = { 4, 3, 2, 1 }; - unsigned int outputShape[] = { 1, 2, 3, 4 }; - unsigned int dimsMapping[] = { 3, 2, 1, 0 }; + armnn::L2NormalizationDescriptor m_Descriptor; + }; - auto inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32); - auto outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32); + const std::string l2NormLayerName("l2Normalization"); + const armnn::TensorInfo info({1, 2, 1, 5}, armnn::DataType::Float32); - armnn::PermuteDescriptor permuteDescriptor(armnn::PermutationVector(dimsMapping, 4)); + armnn::L2NormalizationDescriptor desc; + desc.m_DataLayout = armnn::DataLayout::NCHW; armnn::INetworkPtr network = armnn::INetwork::Create(); - armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); - armnn::IConnectableLayer* const permuteLayer = network->AddPermuteLayer(permuteDescriptor, "permute"); + armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0); + armnn::IConnectableLayer* const l2NormLayer = network->AddL2NormalizationLayer(desc, l2NormLayerName.c_str()); armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - inputLayer->GetOutputSlot(0).Connect(permuteLayer->GetInputSlot(0)); - inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo); - permuteLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - permuteLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); + inputLayer0->GetOutputSlot(0).Connect(l2NormLayer->GetInputSlot(0)); + l2NormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + + inputLayer0->GetOutputSlot(0).SetTensorInfo(info); + l2NormLayer->GetOutputSlot(0).SetTensorInfo(info); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyPermuteName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {inputTensorInfo.GetShape()}, - {outputTensorInfo.GetShape()}); + L2NormalizationLayerVerifier verifier(l2NormLayerName, {info}, {info}, desc); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeFullyConnected) +BOOST_AUTO_TEST_CASE(SerializeMaximum) { - class VerifyFullyConnectedName : public armnn::LayerVisitorBase + class MaximumLayerVerifier : public LayerVerifierBase { public: - void VisitFullyConnectedLayer(const armnn::IConnectableLayer*, - const armnn::FullyConnectedDescriptor&, - const armnn::ConstTensor&, - const armnn::Optional&, - const char* name) override + MaximumLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos) + : LayerVerifierBase(layerName, inputInfos, outputInfos) {} + + void VisitMaximumLayer(const armnn::IConnectableLayer* layer, const char* name) override { - BOOST_TEST(name == "fully_connected"); + VerifyNameAndConnections(layer, name); } }; - armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32); - armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32); - - armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32); - armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32); - - armnn::FullyConnectedDescriptor descriptor; - descriptor.m_BiasEnabled = true; - descriptor.m_TransposeWeightMatrix = false; - - std::vector weightsData = GenerateRandomData(weightsInfo.GetNumElements()); - std::vector biasesData = GenerateRandomData(biasesInfo.GetNumElements()); - - armnn::ConstTensor weights(weightsInfo, weightsData); - armnn::ConstTensor biases(biasesInfo, biasesData); + const std::string layerName("maximum"); + const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32); armnn::INetworkPtr network = armnn::INetwork::Create(); - armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0, "input"); - armnn::IConnectableLayer* const fullyConnectedLayer = network->AddFullyConnectedLayer(descriptor, - weights, - biases, - "fully_connected"); - armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0, "output"); + armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0); + armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1); + armnn::IConnectableLayer* const maximumLayer = network->AddMaximumLayer(layerName.c_str()); + armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0)); - inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo); + inputLayer0->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(0)); + inputLayer1->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(1)); + maximumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); + inputLayer0->GetOutputSlot(0).SetTensorInfo(info); + inputLayer1->GetOutputSlot(0).SetTensorInfo(info); + maximumLayer->GetOutputSlot(0).SetTensorInfo(info); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyFullyConnectedName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {inputInfo.GetShape()}, - {outputInfo.GetShape()}); + MaximumLayerVerifier verifier(layerName, {info, info}, {info}); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeSpaceToBatchNd) +BOOST_AUTO_TEST_CASE(SerializeMean) { - class VerifySpaceToBatchNdName : public armnn::LayerVisitorBase + class MeanLayerVerifier : public LayerVerifierBase { public: - void VisitSpaceToBatchNdLayer(const armnn::IConnectableLayer*, - const armnn::SpaceToBatchNdDescriptor& spaceToBatchNdDescriptor, - const char* name) override + MeanLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::MeanDescriptor& descriptor) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) {} + + void VisitMeanLayer(const armnn::IConnectableLayer* layer, + const armnn::MeanDescriptor& descriptor, + const char* name) override { - BOOST_TEST(name == "SpaceToBatchNdLayer"); + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); } - }; - unsigned int inputShape[] = {2, 1, 2, 4}; - unsigned int outputShape[] = {8, 1, 1, 3}; + private: + void VerifyDescriptor(const armnn::MeanDescriptor& descriptor) + { + BOOST_TEST(descriptor.m_Axis == m_Descriptor.m_Axis); + BOOST_TEST(descriptor.m_KeepDims == m_Descriptor.m_KeepDims); + } - armnn::SpaceToBatchNdDescriptor desc; - desc.m_DataLayout = armnn::DataLayout::NCHW; - desc.m_BlockShape = {2, 2}; - desc.m_PadList = {{0, 0}, {2, 0}}; + armnn::MeanDescriptor m_Descriptor; + }; + + const std::string layerName("mean"); + const armnn::TensorInfo inputInfo({1, 1, 3, 2}, armnn::DataType::Float32); + const armnn::TensorInfo outputInfo({1, 1, 1, 2}, armnn::DataType::Float32); - auto inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32); - auto outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32); + armnn::MeanDescriptor descriptor; + descriptor.m_Axis = { 2 }; + descriptor.m_KeepDims = true; armnn::INetworkPtr network = armnn::INetwork::Create(); - armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); - armnn::IConnectableLayer* const spaceToBatchNdLayer = network->AddSpaceToBatchNdLayer(desc, "SpaceToBatchNdLayer"); - armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); + armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); + armnn::IConnectableLayer* const meanLayer = network->AddMeanLayer(descriptor, layerName.c_str()); + armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - inputLayer->GetOutputSlot(0).Connect(spaceToBatchNdLayer->GetInputSlot(0)); - inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo); - spaceToBatchNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - spaceToBatchNdLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); + inputLayer->GetOutputSlot(0).Connect(meanLayer->GetInputSlot(0)); + meanLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + + inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo); + meanLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifySpaceToBatchNdName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {inputTensorInfo.GetShape()}, - {outputTensorInfo.GetShape()}); + MeanLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeGather) +BOOST_AUTO_TEST_CASE(SerializeMerger) { - class VerifyGatherName : public armnn::LayerVisitorBase + class MergerLayerVerifier : public LayerVerifierBase { public: - void VerifyGatherLayer(const armnn::IConnectableLayer *, const char *name) + MergerLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::OriginsDescriptor& descriptor) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) {} + + void VisitMergerLayer(const armnn::IConnectableLayer* layer, + const armnn::OriginsDescriptor& descriptor, + const char* name) override { - BOOST_TEST(name == "gatherLayer"); + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); } + + private: + void VerifyDescriptor(const armnn::OriginsDescriptor& descriptor) + { + BOOST_TEST(descriptor.GetConcatAxis() == m_Descriptor.GetConcatAxis()); + BOOST_TEST(descriptor.GetNumViews() == m_Descriptor.GetNumViews()); + BOOST_TEST(descriptor.GetNumDimensions() == m_Descriptor.GetNumDimensions()); + + for (uint32_t i = 0; i < descriptor.GetNumViews(); i++) + { + for (uint32_t j = 0; j < descriptor.GetNumDimensions(); j++) + { + BOOST_TEST(descriptor.GetViewOrigin(i)[j] == m_Descriptor.GetViewOrigin(i)[j]); + } + } + } + + armnn::OriginsDescriptor m_Descriptor; }; - armnn::TensorInfo paramsInfo({ 8 }, armnn::DataType::QuantisedAsymm8); - armnn::TensorInfo indicesInfo({ 3 }, armnn::DataType::Signed32); - armnn::TensorInfo outputInfo({ 3 }, armnn::DataType::QuantisedAsymm8); + const std::string layerName("merger"); + const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32); + const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32); - paramsInfo.SetQuantizationScale(1.0f); - paramsInfo.SetQuantizationOffset(0); - outputInfo.SetQuantizationScale(1.0f); - outputInfo.SetQuantizationOffset(0); + const std::vector shapes({inputInfo.GetShape(), inputInfo.GetShape()}); + + armnn::OriginsDescriptor descriptor = + armnn::CreateMergerDescriptorForConcatenation(shapes.begin(), shapes.end(), 0); - const std::vector& indicesData = {7, 6, 5}; armnn::INetworkPtr network = armnn::INetwork::Create(); - armnn::IConnectableLayer *const inputLayer = network->AddInputLayer(0); - armnn::IConnectableLayer *const constantLayer = - network->AddConstantLayer(armnn::ConstTensor(indicesInfo, indicesData)); - armnn::IConnectableLayer *const gatherLayer = network->AddGatherLayer("gatherLayer"); - armnn::IConnectableLayer *const outputLayer = network->AddOutputLayer(0); + armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0); + armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1); + armnn::IConnectableLayer* const mergerLayer = network->AddMergerLayer(descriptor, layerName.c_str()); + armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - inputLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(0)); - inputLayer->GetOutputSlot(0).SetTensorInfo(paramsInfo); - constantLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(1)); - constantLayer->GetOutputSlot(0).SetTensorInfo(indicesInfo); - gatherLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - gatherLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); + inputLayerOne->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(0)); + inputLayerTwo->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(1)); + mergerLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + + inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo); + inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo); + mergerLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyGatherName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {paramsInfo.GetShape()}, - {outputInfo.GetShape()}); + MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeBatchNormalization) +BOOST_AUTO_TEST_CASE(SerializeMinimum) { - class VerifyBatchNormalizationName : public armnn::LayerVisitorBase + class MinimumLayerVerifier : public LayerVerifierBase { public: - void VisitBatchNormalizationLayer(const armnn::IConnectableLayer*, - const armnn::BatchNormalizationDescriptor&, - const armnn::ConstTensor&, - const armnn::ConstTensor&, - const armnn::ConstTensor&, - const armnn::ConstTensor&, - const char* name) override + MinimumLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos) + : LayerVerifierBase(layerName, inputInfos, outputInfos) {} + + void VisitMinimumLayer(const armnn::IConnectableLayer* layer, const char* name) override { - BOOST_TEST(name == "BatchNormalizationLayer"); + VerifyNameAndConnections(layer, name); } }; - armnn::TensorInfo inputInfo ({ 1, 3, 3, 1 }, armnn::DataType::Float32); - armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32); - - armnn::TensorInfo meanInfo({1}, armnn::DataType::Float32); - armnn::TensorInfo varianceInfo({1}, armnn::DataType::Float32); - armnn::TensorInfo scaleInfo({1}, armnn::DataType::Float32); - armnn::TensorInfo offsetInfo({1}, armnn::DataType::Float32); - - armnn::BatchNormalizationDescriptor descriptor; - descriptor.m_Eps = 0.0010000000475f; - descriptor.m_DataLayout = armnn::DataLayout::NHWC; - - std::vector meanData({5.0}); - std::vector varianceData({2.0}); - std::vector scaleData({1.0}); - std::vector offsetData({0.0}); - - armnn::ConstTensor mean(meanInfo, meanData); - armnn::ConstTensor variance(varianceInfo, varianceData); - armnn::ConstTensor scale(scaleInfo, scaleData); - armnn::ConstTensor offset(offsetInfo, offsetData); + const std::string layerName("minimum"); + const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32); armnn::INetworkPtr network = armnn::INetwork::Create(); - armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); - armnn::IConnectableLayer* const batchNormalizationLayer = network->AddBatchNormalizationLayer( - descriptor, - mean, - variance, - scale, - offset, - "BatchNormalizationLayer"); + armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0); + armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1); + armnn::IConnectableLayer* const minimumLayer = network->AddMinimumLayer(layerName.c_str()); armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - inputLayer->GetOutputSlot(0).Connect(batchNormalizationLayer->GetInputSlot(0)); - inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo); + inputLayer0->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(0)); + inputLayer1->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(1)); + minimumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - batchNormalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - batchNormalizationLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); + inputLayer0->GetOutputSlot(0).SetTensorInfo(info); + inputLayer1->GetOutputSlot(0).SetTensorInfo(info); + minimumLayer->GetOutputSlot(0).SetTensorInfo(info); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyBatchNormalizationName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {inputInfo.GetShape()}, - {outputInfo.GetShape()}); + MinimumLayerVerifier verifier(layerName, {info, info}, {info}); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeDivision) +BOOST_AUTO_TEST_CASE(SerializeMultiplication) { - class VerifyDivisionName : public armnn::LayerVisitorBase + class MultiplicationLayerVerifier : public LayerVerifierBase { public: - void VisitDivisionLayer(const armnn::IConnectableLayer*, const char* name) override + MultiplicationLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos) + : LayerVerifierBase(layerName, inputInfos, outputInfos) {} + + void VisitMultiplicationLayer(const armnn::IConnectableLayer* layer, const char* name) override { - BOOST_TEST(name == "division"); + VerifyNameAndConnections(layer, name); } }; + const std::string layerName("multiplication"); const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32); armnn::INetworkPtr network = armnn::INetwork::Create(); armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0); armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1); - - const char* divLayerName = "division"; - - armnn::IConnectableLayer* const divisionLayer = network->AddDivisionLayer(divLayerName); - inputLayer0->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(0)); - inputLayer1->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(1)); - + armnn::IConnectableLayer* const multiplicationLayer = network->AddMultiplicationLayer(layerName.c_str()); armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - divisionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + + inputLayer0->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(0)); + inputLayer1->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(1)); + multiplicationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); inputLayer0->GetOutputSlot(0).SetTensorInfo(info); inputLayer1->GetOutputSlot(0).SetTensorInfo(info); - divisionLayer->GetOutputSlot(0).SetTensorInfo(info); - - armnnSerializer::Serializer serializer; - serializer.Serialize(*network); - - std::stringstream stream; - serializer.SaveSerializedToStream(stream); - BOOST_TEST(stream.str().length() > 0); - BOOST_TEST(stream.str().find(divLayerName) != stream.str().npos); + multiplicationLayer->GetOutputSlot(0).SetTensorInfo(info); - armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(stream.str()); + armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyDivisionName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {info.GetShape(), info.GetShape()}, - {info.GetShape()}, - {0, 1}); + MultiplicationLayerVerifier verifier(layerName, {info, info}, {info}); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeNormalization) +BOOST_AUTO_TEST_CASE(SerializeNormalization) { - class VerifyNormalizationName : public armnn::LayerVisitorBase + class NormalizationLayerVerifier : public LayerVerifierBase { - public: - void VisitNormalizationLayer(const armnn::IConnectableLayer*, - const armnn::NormalizationDescriptor& normalizationDescriptor, + public: + NormalizationLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::NormalizationDescriptor& descriptor) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) {} + + void VisitNormalizationLayer(const armnn::IConnectableLayer* layer, + const armnn::NormalizationDescriptor& descriptor, const char* name) override { - BOOST_TEST(name == "NormalizationLayer"); + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); } + + private: + void VerifyDescriptor(const armnn::NormalizationDescriptor& descriptor) + { + BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout)); + BOOST_TEST(descriptor.m_NormSize == m_Descriptor.m_NormSize); + BOOST_TEST(descriptor.m_Alpha == m_Descriptor.m_Alpha); + BOOST_TEST(descriptor.m_Beta == m_Descriptor.m_Beta); + BOOST_TEST(descriptor.m_K == m_Descriptor.m_K); + BOOST_TEST( + static_cast(descriptor.m_NormChannelType) == static_cast(m_Descriptor.m_NormChannelType)); + BOOST_TEST( + static_cast(descriptor.m_NormMethodType) == static_cast(m_Descriptor.m_NormMethodType)); + } + + armnn::NormalizationDescriptor m_Descriptor; }; - unsigned int inputShape[] = {2, 1, 2, 2}; - unsigned int outputShape[] = {2, 1, 2, 2}; + const std::string layerName("normalization"); + const armnn::TensorInfo info({2, 1, 2, 2}, armnn::DataType::Float32); armnn::NormalizationDescriptor desc; desc.m_DataLayout = armnn::DataLayout::NCHW; @@ -1158,391 +1337,514 @@ BOOST_AUTO_TEST_CASE(SerializeDeserializeNormalization) desc.m_Beta = 1; desc.m_K = 1; - auto inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32); - auto outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32); + armnn::INetworkPtr network = armnn::INetwork::Create(); + armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); + armnn::IConnectableLayer* const normalizationLayer = network->AddNormalizationLayer(desc, layerName.c_str()); + armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); + + inputLayer->GetOutputSlot(0).Connect(normalizationLayer->GetInputSlot(0)); + normalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + + inputLayer->GetOutputSlot(0).SetTensorInfo(info); + normalizationLayer->GetOutputSlot(0).SetTensorInfo(info); + + armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); + BOOST_CHECK(deserializedNetwork); + + NormalizationLayerVerifier verifier(layerName, {info}, {info}, desc); + deserializedNetwork->Accept(verifier); +} + +BOOST_AUTO_TEST_CASE(SerializePad) +{ + class PadLayerVerifier : public LayerVerifierBase + { + public: + PadLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::PadDescriptor& descriptor) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) {} + + void VisitPadLayer(const armnn::IConnectableLayer* layer, + const armnn::PadDescriptor& descriptor, + const char* name) override + { + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); + } + + private: + void VerifyDescriptor(const armnn::PadDescriptor& descriptor) + { + BOOST_TEST(descriptor.m_PadList == m_Descriptor.m_PadList); + } + + armnn::PadDescriptor m_Descriptor; + }; + + const std::string layerName("pad"); + const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32); + const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32); + + armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}}); armnn::INetworkPtr network = armnn::INetwork::Create(); armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); - armnn::IConnectableLayer* const normalizationLayer = network->AddNormalizationLayer(desc, "NormalizationLayer"); + armnn::IConnectableLayer* const padLayer = network->AddPadLayer(desc, layerName.c_str()); armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - inputLayer->GetOutputSlot(0).Connect(normalizationLayer->GetInputSlot(0)); + inputLayer->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0)); + padLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo); - normalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - normalizationLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); + padLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyNormalizationName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {inputTensorInfo.GetShape()}, - {outputTensorInfo.GetShape()}); + PadLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, desc); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeEqual) +BOOST_AUTO_TEST_CASE(SerializePermute) { - class VerifyEqualName : public armnn::LayerVisitorBase + class PermuteLayerVerifier : public LayerVerifierBase { public: - void VisitEqualLayer(const armnn::IConnectableLayer*, - const char* name) override + PermuteLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::PermuteDescriptor& descriptor) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) {} + + void VisitPermuteLayer(const armnn::IConnectableLayer* layer, + const armnn::PermuteDescriptor& descriptor, + const char* name) override + { + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); + } + + private: + void VerifyDescriptor(const armnn::PermuteDescriptor& descriptor) { - BOOST_TEST(name == "EqualLayer"); + BOOST_TEST(descriptor.m_DimMappings.IsEqual(m_Descriptor.m_DimMappings)); } + + armnn::PermuteDescriptor m_Descriptor; }; - const armnn::TensorInfo inputTensorInfo1 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32); - const armnn::TensorInfo inputTensorInfo2 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32); - const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Boolean); + const std::string layerName("permute"); + const armnn::TensorInfo inputTensorInfo({4, 3, 2, 1}, armnn::DataType::Float32); + const armnn::TensorInfo outputTensorInfo({1, 2, 3, 4}, armnn::DataType::Float32); + + armnn::PermuteDescriptor descriptor(armnn::PermutationVector({3, 2, 1, 0})); armnn::INetworkPtr network = armnn::INetwork::Create(); - armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0); - armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1); - armnn::IConnectableLayer* const equalLayer = network->AddEqualLayer("EqualLayer"); + armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); + armnn::IConnectableLayer* const permuteLayer = network->AddPermuteLayer(descriptor, layerName.c_str()); armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0)); - inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1); - inputLayer2->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1)); - inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2); - equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - equalLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); + inputLayer->GetOutputSlot(0).Connect(permuteLayer->GetInputSlot(0)); + permuteLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + + inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo); + permuteLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyEqualName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {inputTensorInfo1.GetShape(), inputTensorInfo2.GetShape()}, - {outputTensorInfo.GetShape()}, - {0, 1}); + PermuteLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, descriptor); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializePad) +BOOST_AUTO_TEST_CASE(SerializePooling2d) { - class VerifyPadName : public armnn::LayerVisitorBase + class Pooling2dLayerVerifier : public LayerVerifierBase { public: - void VisitPadLayer(const armnn::IConnectableLayer*, - const armnn::PadDescriptor& descriptor, - const char* name) override + Pooling2dLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::Pooling2dDescriptor& descriptor) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) {} + + void VisitPooling2dLayer(const armnn::IConnectableLayer* layer, + const armnn::Pooling2dDescriptor& descriptor, + const char* name) override { - BOOST_TEST(name == "PadLayer"); + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); } + + private: + void VerifyDescriptor(const armnn::Pooling2dDescriptor& descriptor) + { + BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout)); + BOOST_TEST(descriptor.m_PadLeft == m_Descriptor.m_PadLeft); + BOOST_TEST(descriptor.m_PadRight == m_Descriptor.m_PadRight); + BOOST_TEST(descriptor.m_PadTop == m_Descriptor.m_PadTop); + BOOST_TEST(descriptor.m_PadBottom == m_Descriptor.m_PadBottom); + BOOST_TEST(descriptor.m_PoolWidth == m_Descriptor.m_PoolWidth); + BOOST_TEST(descriptor.m_PoolHeight == m_Descriptor.m_PoolHeight); + BOOST_TEST(descriptor.m_StrideX == m_Descriptor.m_StrideX); + BOOST_TEST(descriptor.m_StrideY == m_Descriptor.m_StrideY); + + BOOST_TEST( + static_cast(descriptor.m_PaddingMethod) == static_cast(m_Descriptor.m_PaddingMethod)); + BOOST_TEST( + static_cast(descriptor.m_PoolType) == static_cast(m_Descriptor.m_PoolType)); + BOOST_TEST( + static_cast(descriptor.m_OutputShapeRounding) == + static_cast(m_Descriptor.m_OutputShapeRounding)); + } + + armnn::Pooling2dDescriptor m_Descriptor; }; - armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}}); + const std::string layerName("pooling2d"); + const armnn::TensorInfo inputInfo({1, 2, 2, 1}, armnn::DataType::Float32); + const armnn::TensorInfo outputInfo({1, 1, 1, 1}, armnn::DataType::Float32); - const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32); - const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32); + armnn::Pooling2dDescriptor desc; + desc.m_DataLayout = armnn::DataLayout::NHWC; + desc.m_PadTop = 0; + desc.m_PadBottom = 0; + desc.m_PadLeft = 0; + desc.m_PadRight = 0; + desc.m_PoolType = armnn::PoolingAlgorithm::Average; + desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor; + desc.m_PaddingMethod = armnn::PaddingMethod::Exclude; + desc.m_PoolHeight = 2; + desc.m_PoolWidth = 2; + desc.m_StrideX = 2; + desc.m_StrideY = 2; armnn::INetworkPtr network = armnn::INetwork::Create(); armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); - armnn::IConnectableLayer* const padLayer = network->AddPadLayer(desc, "PadLayer"); + armnn::IConnectableLayer* const pooling2dLayer = network->AddPooling2dLayer(desc, layerName.c_str()); armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - inputLayer->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0)); - inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo); - padLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - padLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); + inputLayer->GetOutputSlot(0).Connect(pooling2dLayer->GetInputSlot(0)); + pooling2dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + + inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo); + pooling2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyPadName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {inputTensorInfo.GetShape()}, - {outputTensorInfo.GetShape()}); + Pooling2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeRsqrt) +BOOST_AUTO_TEST_CASE(SerializeReshape) { - class VerifyRsqrtName : public armnn::LayerVisitorBase + class ReshapeLayerVerifier : public LayerVerifierBase { public: - void VisitRsqrtLayer(const armnn::IConnectableLayer*, const char* name) override + ReshapeLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::ReshapeDescriptor& descriptor) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) {} + + void VisitReshapeLayer(const armnn::IConnectableLayer* layer, + const armnn::ReshapeDescriptor& descriptor, + const char* name) override + { + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); + } + + private: + void VerifyDescriptor(const armnn::ReshapeDescriptor& descriptor) { - BOOST_TEST(name == "rsqrt"); + BOOST_TEST(descriptor.m_TargetShape == m_Descriptor.m_TargetShape); } + + armnn::ReshapeDescriptor m_Descriptor; }; - const armnn::TensorInfo tensorInfo({ 3, 1, 2 }, armnn::DataType::Float32); + const std::string layerName("reshape"); + const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32); + const armnn::TensorInfo outputInfo({3, 3}, armnn::DataType::Float32); + + armnn::ReshapeDescriptor descriptor({3, 3}); armnn::INetworkPtr network = armnn::INetwork::Create(); - armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); - armnn::IConnectableLayer* const rsqrtLayer = network->AddRsqrtLayer("rsqrt"); + armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); + armnn::IConnectableLayer* const reshapeLayer = network->AddReshapeLayer(descriptor, layerName.c_str()); armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - inputLayer->GetOutputSlot(0).Connect(rsqrtLayer->GetInputSlot(0)); - rsqrtLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + inputLayer->GetOutputSlot(0).Connect(reshapeLayer->GetInputSlot(0)); + reshapeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo); - rsqrtLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo); + inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo); + reshapeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyRsqrtName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {tensorInfo.GetShape()}, - {tensorInfo.GetShape()}); + ReshapeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeResizeBilinear) +BOOST_AUTO_TEST_CASE(SerializeResizeBilinear) { - class VerifyResizeBilinearName : public armnn::LayerVisitorBase + class ResizeBilinearLayerVerifier : public LayerVerifierBase { public: - void VisitResizeBilinearLayer(const armnn::IConnectableLayer*, + ResizeBilinearLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::ResizeBilinearDescriptor& descriptor) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) {} + + void VisitResizeBilinearLayer(const armnn::IConnectableLayer* layer, const armnn::ResizeBilinearDescriptor& descriptor, const char* name) override { - BOOST_TEST(name == "ResizeBilinearLayer"); + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); } + + private: + void VerifyDescriptor(const armnn::ResizeBilinearDescriptor& descriptor) + { + BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout)); + BOOST_TEST(descriptor.m_TargetWidth == m_Descriptor.m_TargetWidth); + BOOST_TEST(descriptor.m_TargetHeight == m_Descriptor.m_TargetHeight); + } + + armnn::ResizeBilinearDescriptor m_Descriptor; }; + const std::string layerName("resizeBilinear"); + const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32); + const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32); + armnn::ResizeBilinearDescriptor desc; desc.m_TargetWidth = 4; desc.m_TargetHeight = 2; - const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32); - const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32); - armnn::INetworkPtr network = armnn::INetwork::Create(); armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); - armnn::IConnectableLayer* const resizeLayer = network->AddResizeBilinearLayer(desc, "ResizeBilinearLayer"); + armnn::IConnectableLayer* const resizeLayer = network->AddResizeBilinearLayer(desc, layerName.c_str()); armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0)); - inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo); resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - resizeLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); + + inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo); + resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyResizeBilinearName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {inputTensorInfo.GetShape()}, - {outputTensorInfo.GetShape()}); + ResizeBilinearLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeSubtraction) +BOOST_AUTO_TEST_CASE(SerializeRsqrt) { - class VerifySubtractionName : public armnn::LayerVisitorBase + class RsqrtLayerVerifier : public LayerVerifierBase { public: - void VisitSubtractionLayer(const armnn::IConnectableLayer*, const char* name) override + RsqrtLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos) + : LayerVerifierBase(layerName, inputInfos, outputInfos) {} + + void VisitRsqrtLayer(const armnn::IConnectableLayer* layer, const char* name) override { - BOOST_TEST(name == "subtraction"); + VerifyNameAndConnections(layer, name); } }; - const armnn::TensorInfo info = armnn::TensorInfo({ 1, 4 }, armnn::DataType::Float32); + const std::string layerName("rsqrt"); + const armnn::TensorInfo tensorInfo({ 3, 1, 2 }, armnn::DataType::Float32); armnn::INetworkPtr network = armnn::INetwork::Create(); - armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0); - armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1); - armnn::IConnectableLayer* const subtractionLayer = network->AddSubtractionLayer("subtraction"); + armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); + armnn::IConnectableLayer* const rsqrtLayer = network->AddRsqrtLayer(layerName.c_str()); armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - inputLayer0->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(0)); - inputLayer1->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(1)); - subtractionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + inputLayer->GetOutputSlot(0).Connect(rsqrtLayer->GetInputSlot(0)); + rsqrtLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - inputLayer0->GetOutputSlot(0).SetTensorInfo(info); - inputLayer1->GetOutputSlot(0).SetTensorInfo(info); - subtractionLayer->GetOutputSlot(0).SetTensorInfo(info); + inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo); + rsqrtLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifySubtractionName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {info.GetShape(), info.GetShape()}, - {info.GetShape()}, - {0, 1}); + RsqrtLayerVerifier verifier(layerName, {tensorInfo}, {tensorInfo}); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeStridedSlice) +BOOST_AUTO_TEST_CASE(SerializeSoftmax) { - class VerifyStridedSliceName : public armnn::LayerVisitorBase + class SoftmaxLayerVerifier : public LayerVerifierBase { public: - void VisitStridedSliceLayer(const armnn::IConnectableLayer*, - const armnn::StridedSliceDescriptor& descriptor, - const char* name) override + SoftmaxLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::SoftmaxDescriptor& descriptor) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) {} + + void VisitSoftmaxLayer(const armnn::IConnectableLayer* layer, + const armnn::SoftmaxDescriptor& descriptor, + const char* name) override { - BOOST_TEST(name == "StridedSliceLayer"); + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); } - }; - - armnn::StridedSliceDescriptor desc({0, 0, 1, 0}, {1, 1, 1, 1}, {1, 1, 1, 1}); - desc.m_EndMask = (1 << 4) - 1; - desc.m_ShrinkAxisMask = (1 << 1) | (1 << 2); - desc.m_DataLayout = armnn::DataLayout::NCHW; - - const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32); - const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({3, 1}, armnn::DataType::Float32); - - armnn::INetworkPtr network = armnn::INetwork::Create(); - armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); - armnn::IConnectableLayer* const stridedSliceLayer = network->AddStridedSliceLayer(desc, "StridedSliceLayer"); - armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - - inputLayer->GetOutputSlot(0).Connect(stridedSliceLayer->GetInputSlot(0)); - inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo); - stridedSliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - stridedSliceLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); - - armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); - BOOST_CHECK(deserializedNetwork); - - VerifyStridedSliceName nameChecker; - deserializedNetwork->Accept(nameChecker); - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {inputTensorInfo.GetShape()}, - {outputTensorInfo.GetShape()}); -} - -BOOST_AUTO_TEST_CASE(SerializeDeserializeMean) -{ - class VerifyMeanName : public armnn::LayerVisitorBase - { - public: - void VisitMeanLayer(const armnn::IConnectableLayer*, const armnn::MeanDescriptor&, const char* name) + private: + void VerifyDescriptor(const armnn::SoftmaxDescriptor& descriptor) { - BOOST_TEST(name == "mean"); + BOOST_TEST(descriptor.m_Beta == m_Descriptor.m_Beta); } + + armnn::SoftmaxDescriptor m_Descriptor; }; - armnn::TensorInfo inputTensorInfo({1, 1, 3, 2}, armnn::DataType::Float32); - armnn::TensorInfo outputTensorInfo({1, 1, 1, 2}, armnn::DataType::Float32); + const std::string layerName("softmax"); + const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32); - armnn::MeanDescriptor descriptor; - descriptor.m_Axis = { 2 }; - descriptor.m_KeepDims = true; + armnn::SoftmaxDescriptor descriptor; + descriptor.m_Beta = 1.0f; armnn::INetworkPtr network = armnn::INetwork::Create(); armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); - armnn::IConnectableLayer* const meanLayer = network->AddMeanLayer(descriptor, "mean"); + armnn::IConnectableLayer* const softmaxLayer = network->AddSoftmaxLayer(descriptor, layerName.c_str()); armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - inputLayer->GetOutputSlot(0).Connect(meanLayer->GetInputSlot(0)); - inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo); - meanLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - meanLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); + inputLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0)); + softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + + inputLayer->GetOutputSlot(0).SetTensorInfo(info); + softmaxLayer->GetOutputSlot(0).SetTensorInfo(info); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyMeanName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {inputTensorInfo.GetShape()}, - {outputTensorInfo.GetShape()}); + SoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeMerger) +BOOST_AUTO_TEST_CASE(SerializeSpaceToBatchNd) { - class VerifyMergerName : public armnn::LayerVisitorBase + class SpaceToBatchNdLayerVerifier : public LayerVerifierBase { public: - void VisitMergerLayer(const armnn::IConnectableLayer* layer, - const armnn::OriginsDescriptor& mergerDescriptor, - const char* name = nullptr) override + SpaceToBatchNdLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::SpaceToBatchNdDescriptor& descriptor) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) {} + + void VisitSpaceToBatchNdLayer(const armnn::IConnectableLayer* layer, + const armnn::SpaceToBatchNdDescriptor& descriptor, + const char* name) override { - BOOST_TEST(name == "MergerLayer"); + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); } - }; - unsigned int inputShapeOne[] = {2, 3, 2, 2}; - unsigned int inputShapeTwo[] = {2, 3, 2, 2}; - unsigned int outputShape[] = {4, 3, 2, 2}; + private: + void VerifyDescriptor(const armnn::SpaceToBatchNdDescriptor& descriptor) + { + BOOST_TEST(descriptor.m_PadList == m_Descriptor.m_PadList); + BOOST_TEST(descriptor.m_BlockShape == m_Descriptor.m_BlockShape); + BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout)); + } - const armnn::TensorInfo inputOneTensorInfo = armnn::TensorInfo(4, inputShapeOne, armnn::DataType::Float32); - const armnn::TensorInfo inputTwoTensorInfo = armnn::TensorInfo(4, inputShapeTwo, armnn::DataType::Float32); - const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32); + armnn::SpaceToBatchNdDescriptor m_Descriptor; + }; - std::vector shapes; - shapes.push_back(inputOneTensorInfo.GetShape()); - shapes.push_back(inputTwoTensorInfo.GetShape()); + const std::string layerName("spaceToBatchNd"); + const armnn::TensorInfo inputInfo({2, 1, 2, 4}, armnn::DataType::Float32); + const armnn::TensorInfo outputInfo({8, 1, 1, 3}, armnn::DataType::Float32); - armnn::MergerDescriptor descriptor = - armnn::CreateMergerDescriptorForConcatenation(shapes.begin(), shapes.end(), 0); + armnn::SpaceToBatchNdDescriptor desc; + desc.m_DataLayout = armnn::DataLayout::NCHW; + desc.m_BlockShape = {2, 2}; + desc.m_PadList = {{0, 0}, {2, 0}}; armnn::INetworkPtr network = armnn::INetwork::Create(); - armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0); - inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputOneTensorInfo); - armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1); - inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputTwoTensorInfo); - armnn::IConnectableLayer* const mergerLayer = network->AddMergerLayer(descriptor, "MergerLayer"); - mergerLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); + armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); + armnn::IConnectableLayer* const spaceToBatchNdLayer = network->AddSpaceToBatchNdLayer(desc, layerName.c_str()); armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - inputLayerOne->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(0)); - inputLayerTwo->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(1)); - mergerLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + inputLayer->GetOutputSlot(0).Connect(spaceToBatchNdLayer->GetInputSlot(0)); + spaceToBatchNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + + inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo); + spaceToBatchNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyMergerName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {inputOneTensorInfo.GetShape(), inputTwoTensorInfo.GetShape()}, - {outputTensorInfo.GetShape()}, - {0, 1}); + SpaceToBatchNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeSplitter) +BOOST_AUTO_TEST_CASE(SerializeSplitter) { - class VerifySplitterName : public armnn::LayerVisitorBase + class SplitterLayerVerifier : public LayerVerifierBase { public: - void VisitSplitterLayer(const armnn::IConnectableLayer*, - const armnn::ViewsDescriptor& viewsDescriptor, + SplitterLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::ViewsDescriptor& descriptor) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) {} + + void VisitSplitterLayer(const armnn::IConnectableLayer* layer, + const armnn::ViewsDescriptor& descriptor, const char* name) override { - BOOST_TEST(name == "splitter"); + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); + } + + private: + void VerifyDescriptor(const armnn::ViewsDescriptor& descriptor) + { + BOOST_TEST(descriptor.GetNumViews() == m_Descriptor.GetNumViews()); + BOOST_TEST(descriptor.GetNumDimensions() == m_Descriptor.GetNumDimensions()); + + for (uint32_t i = 0; i < descriptor.GetNumViews(); i++) + { + for (uint32_t j = 0; j < descriptor.GetNumDimensions(); j++) + { + BOOST_TEST(descriptor.GetViewOrigin(i)[j] == m_Descriptor.GetViewOrigin(i)[j]); + BOOST_TEST(descriptor.GetViewSizes(i)[j] == m_Descriptor.GetViewSizes(i)[j]); + } + } } - }; - unsigned int numViews = 3; - unsigned int numDimensions = 4; - unsigned int inputShape[] = {1,18, 4, 4}; - unsigned int outputShape[] = {1, 6, 4, 4}; + armnn::ViewsDescriptor m_Descriptor; + }; - auto inputTensorInfo = armnn::TensorInfo(numDimensions, inputShape, armnn::DataType::Float32); - auto outputTensorInfo = armnn::TensorInfo(numDimensions, outputShape, armnn::DataType::Float32); + const unsigned int numViews = 3; + const unsigned int numDimensions = 4; + const unsigned int inputShape[] = {1, 18, 4, 4}; + const unsigned int outputShape[] = {1, 6, 4, 4}; - // This is modelled on how the caffe parser sets up a splitter layer to partition an input - // along dimension one. + // This is modelled on how the caffe parser sets up a splitter layer to partition an input along dimension one. unsigned int splitterDimSizes[4] = {static_cast(inputShape[0]), static_cast(inputShape[1]), static_cast(inputShape[2]), @@ -1554,129 +1856,141 @@ BOOST_AUTO_TEST_CASE(SerializeDeserializeSplitter) { desc.SetViewOriginCoord(g, 1, splitterDimSizes[1] * g); - // Set the size of the views. for (unsigned int dimIdx=0; dimIdx < 4; dimIdx++) { - desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]); + desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]); } } - const char* splitterLayerName = "splitter"; + const std::string layerName("splitter"); + const armnn::TensorInfo inputInfo(numDimensions, inputShape, armnn::DataType::Float32); + const armnn::TensorInfo outputInfo(numDimensions, outputShape, armnn::DataType::Float32); armnn::INetworkPtr network = armnn::INetwork::Create(); armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); - armnn::IConnectableLayer* const splitterLayer = network->AddSplitterLayer(desc, splitterLayerName); + armnn::IConnectableLayer* const splitterLayer = network->AddSplitterLayer(desc, layerName.c_str()); armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0); armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1); armnn::IConnectableLayer* const outputLayer2 = network->AddOutputLayer(2); inputLayer->GetOutputSlot(0).Connect(splitterLayer->GetInputSlot(0)); - inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo); splitterLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0)); - splitterLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo); splitterLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0)); - splitterLayer->GetOutputSlot(1).SetTensorInfo(outputTensorInfo); splitterLayer->GetOutputSlot(2).Connect(outputLayer2->GetInputSlot(0)); - splitterLayer->GetOutputSlot(2).SetTensorInfo(outputTensorInfo); + + inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo); + splitterLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); + splitterLayer->GetOutputSlot(1).SetTensorInfo(outputInfo); + splitterLayer->GetOutputSlot(2).SetTensorInfo(outputInfo); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifySplitterName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal(*deserializedNetwork, - *network, - {inputTensorInfo.GetShape()}, - {outputTensorInfo.GetShape(), - outputTensorInfo.GetShape(), - outputTensorInfo.GetShape()}, - {0}, - {0, 1, 2}); + SplitterLayerVerifier verifier(layerName, {inputInfo}, {outputInfo, outputInfo, outputInfo}, desc); + deserializedNetwork->Accept(verifier); } -BOOST_AUTO_TEST_CASE(SerializeDeserializeDetectionPostProcess) +BOOST_AUTO_TEST_CASE(SerializeStridedSlice) { - class VerifyDetectionPostProcessName : public armnn::LayerVisitorBase + class StridedSliceLayerVerifier : public LayerVerifierBase { public: - void VisitDetectionPostProcessLayer(const armnn::IConnectableLayer* layer, - const armnn::DetectionPostProcessDescriptor& descriptor, - const armnn::ConstTensor& anchors, - const char* name) override + StridedSliceLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos, + const armnn::StridedSliceDescriptor& descriptor) + : LayerVerifierBase(layerName, inputInfos, outputInfos) + , m_Descriptor(descriptor) {} + + void VisitStridedSliceLayer(const armnn::IConnectableLayer* layer, + const armnn::StridedSliceDescriptor& descriptor, + const char* name) override { - BOOST_TEST(name == "DetectionPostProcessLayer"); + VerifyNameAndConnections(layer, name); + VerifyDescriptor(descriptor); } - }; - - const armnn::TensorInfo inputInfos[] = { - armnn::TensorInfo({ 1, 6, 4 }, armnn::DataType::Float32), - armnn::TensorInfo({ 1, 6, 3}, armnn::DataType::Float32) - }; - const armnn::TensorInfo outputInfos[] = { - armnn::TensorInfo({ 1, 3, 4 }, armnn::DataType::Float32), - armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32), - armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32), - armnn::TensorInfo({ 1 }, armnn::DataType::Float32) + private: + void VerifyDescriptor(const armnn::StridedSliceDescriptor& descriptor) + { + BOOST_TEST(descriptor.m_Begin == m_Descriptor.m_Begin); + BOOST_TEST(descriptor.m_End == m_Descriptor.m_End); + BOOST_TEST(descriptor.m_Stride == m_Descriptor.m_Stride); + BOOST_TEST(descriptor.m_BeginMask == m_Descriptor.m_BeginMask); + BOOST_TEST(descriptor.m_EndMask == m_Descriptor.m_EndMask); + BOOST_TEST(descriptor.m_ShrinkAxisMask == m_Descriptor.m_ShrinkAxisMask); + BOOST_TEST(descriptor.m_EllipsisMask == m_Descriptor.m_EllipsisMask); + BOOST_TEST(descriptor.m_NewAxisMask == m_Descriptor.m_NewAxisMask); + BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout)); + } + armnn::StridedSliceDescriptor m_Descriptor; }; - armnn::DetectionPostProcessDescriptor desc; - desc.m_UseRegularNms = true; - desc.m_MaxDetections = 3; - desc.m_MaxClassesPerDetection = 1; - desc.m_DetectionsPerClass =1; - desc.m_NmsScoreThreshold = 0.0; - desc.m_NmsIouThreshold = 0.5; - desc.m_NumClasses = 2; - desc.m_ScaleY = 10.0; - desc.m_ScaleX = 10.0; - desc.m_ScaleH = 5.0; - desc.m_ScaleW = 5.0; + const std::string layerName("stridedSlice"); + const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32); + const armnn::TensorInfo outputInfo = armnn::TensorInfo({3, 1}, armnn::DataType::Float32); - const armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32); - const std::vector anchorsData({ - 0.5f, 0.5f, 1.0f, 1.0f, - 0.5f, 0.5f, 1.0f, 1.0f, - 0.5f, 0.5f, 1.0f, 1.0f, - 0.5f, 10.5f, 1.0f, 1.0f, - 0.5f, 10.5f, 1.0f, 1.0f, - 0.5f, 100.5f, 1.0f, 1.0f - }); - armnn::ConstTensor anchors(anchorsInfo, anchorsData); + armnn::StridedSliceDescriptor desc({0, 0, 1, 0}, {1, 1, 1, 1}, {1, 1, 1, 1}); + desc.m_EndMask = (1 << 4) - 1; + desc.m_ShrinkAxisMask = (1 << 1) | (1 << 2); + desc.m_DataLayout = armnn::DataLayout::NCHW; armnn::INetworkPtr network = armnn::INetwork::Create(); + armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0); + armnn::IConnectableLayer* const stridedSliceLayer = network->AddStridedSliceLayer(desc, layerName.c_str()); + armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); - armnn::IConnectableLayer* const detectionLayer = - network->AddDetectionPostProcessLayer(desc, anchors, "DetectionPostProcessLayer"); + inputLayer->GetOutputSlot(0).Connect(stridedSliceLayer->GetInputSlot(0)); + stridedSliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); - for (unsigned int i = 0; i < 2; i++) - { - armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(static_cast(i)); - inputLayer->GetOutputSlot(0).Connect(detectionLayer->GetInputSlot(i)); - inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfos[i]); - } + inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo); + stridedSliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo); - for (unsigned int i = 0; i < 4; i++) + armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); + BOOST_CHECK(deserializedNetwork); + + StridedSliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc); + deserializedNetwork->Accept(verifier); +} + +BOOST_AUTO_TEST_CASE(SerializeSubtraction) +{ + class SubtractionLayerVerifier : public LayerVerifierBase { - armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(static_cast(i)); - detectionLayer->GetOutputSlot(i).Connect(outputLayer->GetInputSlot(0)); - detectionLayer->GetOutputSlot(i).SetTensorInfo(outputInfos[i]); - } + public: + SubtractionLayerVerifier(const std::string& layerName, + const std::vector& inputInfos, + const std::vector& outputInfos) + : LayerVerifierBase(layerName, inputInfos, outputInfos) {} + + void VisitSubtractionLayer(const armnn::IConnectableLayer* layer, const char* name) override + { + VerifyNameAndConnections(layer, name); + } + }; + + const std::string layerName("subtraction"); + const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32); + + armnn::INetworkPtr network = armnn::INetwork::Create(); + armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0); + armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1); + armnn::IConnectableLayer* const subtractionLayer = network->AddSubtractionLayer(layerName.c_str()); + armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0); + + inputLayer0->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(0)); + inputLayer1->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(1)); + subtractionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + + inputLayer0->GetOutputSlot(0).SetTensorInfo(info); + inputLayer1->GetOutputSlot(0).SetTensorInfo(info); + subtractionLayer->GetOutputSlot(0).SetTensorInfo(info); armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network)); BOOST_CHECK(deserializedNetwork); - VerifyDetectionPostProcessName nameChecker; - deserializedNetwork->Accept(nameChecker); - - CheckDeserializedNetworkAgainstOriginal( - *network, - *deserializedNetwork, - {inputInfos[0].GetShape(), inputInfos[1].GetShape()}, - {outputInfos[0].GetShape(), outputInfos[1].GetShape(), outputInfos[2].GetShape(), outputInfos[3].GetShape()}, - {0, 1}, - {0, 1, 2, 3}); + SubtractionLayerVerifier verifier(layerName, {info, info}, {info}); + deserializedNetwork->Accept(verifier); } BOOST_AUTO_TEST_SUITE_END() -- cgit v1.2.1