// // Copyright © 2022, 2024 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #pragma once #include "EndToEndTestImpl.hpp" #include #include #include #include #include #include namespace { armnn::INetworkPtr CreateConstConvolution2dNetwork(const armnn::Convolution2dDescriptor& descriptor, const armnn::TensorInfo& inputInfo, const armnn::TensorInfo& weightsInfo, const armnn::TensorInfo& biasInfo, const armnn::TensorInfo& outputInfo, const armnn::ConstTensor& weights, const armnn::ConstTensor& biases, bool biasEnabled) { using namespace armnn; INetworkPtr network(INetwork::Create()); IConnectableLayer* input = network->AddInputLayer(0, "input"); IConnectableLayer* weightsLayer = network->AddConstantLayer(weights, "Weights"); IConnectableLayer* convolution2d = network->AddConvolution2dLayer(descriptor, "convolution2d"); IConnectableLayer* output = network->AddOutputLayer(0, "output"); Connect(input, convolution2d, inputInfo, 0, 0); Connect(weightsLayer, convolution2d, weightsInfo, 0, 1); if(biasEnabled) { armnn::IConnectableLayer* biasLayer = network->AddConstantLayer(biases, "Bias"); Connect(biasLayer, convolution2d, biasInfo, 0, 2); } Connect(convolution2d, output, outputInfo, 0, 0); return network; } template void Convolution2dEndToEnd(const std::vector& backends, armnn::DataLayout dataLayout, bool biasEnabled = true) { using namespace armnn; using IT = ResolveType; using WT = ResolveType; using BT = ResolveType; using OT = ResolveType; const float qScale = 1.0f; const int32_t qOffset = IsQuantizedType() ? 10 : 0; // offset must be zero for non-quantized types TensorInfo inputInfo( { 1, 5, 5, 1 }, ArmnnIType, qScale, qOffset, true); TensorInfo weightsInfo({ 1, 3, 3, 1 }, ArmnnWType, qScale, qOffset, true); TensorInfo biasesInfo( { 1 }, ArmnnBType, qScale * qScale, 0, true); TensorInfo outputInfo( { 1, 3, 3, 1 }, ArmnnOType, qScale, qOffset); std::vector inputData = { 1, 5, 2, 3, 5, 8, 7, 3, 6, 3, 3, 3, 9, 1, 9, 4, 1, 8, 1, 3, 6, 8, 1, 9, 2 }; std::vector weightsData = { 4, 5, 6, 0, 0, 0, 3, 2, 1 }; std::vector biasesData = { 1 }; float bias = biasEnabled ? biasesData[0] : 0; std::vector expectedOutputData = { 65 + bias, 76 + bias, 91 + bias, 107 + bias, 99 + bias, 89 + bias, 116 + bias, 98 + bias, 118 + bias }; Convolution2dDescriptor descriptor; descriptor.m_PadLeft = 0; descriptor.m_PadRight = 0; descriptor.m_PadTop = 0; descriptor.m_PadBottom = 0; descriptor.m_StrideX = 1; descriptor.m_StrideY = 1; descriptor.m_BiasEnabled = biasEnabled; descriptor.m_DataLayout = dataLayout; if (dataLayout == DataLayout::NCHW) { PermuteTensorNhwcToNchw(inputInfo, inputData); PermuteTensorNhwcToNchw(weightsInfo, weightsData); PermuteTensorNhwcToNchw(outputInfo, expectedOutputData); } // Convert data std::vector qInputData = armnnUtils::QuantizedVector(inputData, qScale, qOffset); std::vector qWeightsData = armnnUtils::QuantizedVector(weightsData, qScale, qOffset); std::vector qBiasesData = armnnUtils::QuantizedVector(biasesData, qScale * qScale, 0); std::vector qExpectedOutputData = armnnUtils::QuantizedVector(expectedOutputData, qScale, qOffset); ConstTensor weights(weightsInfo, qWeightsData); ConstTensor biases(biasesInfo, qBiasesData); INetworkPtr network = CreateConstConvolution2dNetwork(descriptor, inputInfo, weightsInfo, biasesInfo, outputInfo, weights, biases, biasEnabled); EndToEndLayerTestImpl(std::move(network), {{ 0, qInputData }}, {{ 0, qExpectedOutputData }}, backends); } } // anonymous namespace