// // Copyright © 2017 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #pragma once #include "DriverTestHelpers.hpp" #include #include #include using namespace armnn; using namespace driverTestHelpers; struct DilationTestOptions { DilationTestOptions() : m_IsDepthwiseConvolution{false}, m_IsPaddingExplicit{false}, m_HasDilation{false} {} ~DilationTestOptions() = default; bool m_IsDepthwiseConvolution; bool m_IsPaddingExplicit; bool m_HasDilation; }; class DilationTestVisitor : public StrategyBase { public: DilationTestVisitor() : DilationTestVisitor(1u, 1u) {} DilationTestVisitor(uint32_t expectedDilationX, uint32_t expectedDilationY) : m_ExpectedDilationX{expectedDilationX}, m_ExpectedDilationY{expectedDilationY} {} void ExecuteStrategy(const armnn::IConnectableLayer* layer, const armnn::BaseDescriptor& descriptor, const std::vector& constants, const char* name, const armnn::LayerBindingId id = 0) override { armnn::IgnoreUnused(layer, constants, id, name); switch (layer->GetType()) { case armnn::LayerType::Constant: break; case armnn::LayerType::Convolution2d: { CheckDilationParams(static_cast(descriptor)); break; } case armnn::LayerType::DepthwiseConvolution2d: { CheckDilationParams(static_cast(descriptor)); break; } default: { m_DefaultStrategy.Apply(GetLayerTypeAsCString(layer->GetType())); } } } private: uint32_t m_ExpectedDilationX; uint32_t m_ExpectedDilationY; template void CheckDilationParams(const ConvolutionDescriptor& descriptor) { CHECK_EQ(descriptor.m_DilationX, m_ExpectedDilationX); CHECK_EQ(descriptor.m_DilationY, m_ExpectedDilationY); } }; template void DilationTestImpl(const DilationTestOptions& options) { using HalModel = typename HalPolicy::Model; using HalOperationType = typename HalPolicy::OperationType; const armnn::Compute backend = armnn::Compute::CpuRef; auto driver = std::make_unique(DriverOptions(backend, false)); HalModel model = {}; // add operands std::vector weightData(9, 1.0f); std::vector biasData(1, 0.0f ); // input AddInputOperand(model, hidl_vec{1, 3, 3, 1}); // weights & biases AddTensorOperand(model, hidl_vec{1, 3, 3, 1}, weightData.data()); AddTensorOperand(model, hidl_vec{1}, biasData.data()); uint32_t numInputs = 3u; // padding if (options.m_IsPaddingExplicit) { AddIntOperand(model, 1); AddIntOperand(model, 1); AddIntOperand(model, 1); AddIntOperand(model, 1); numInputs += 4; } else { AddIntOperand(model, android::nn::kPaddingSame); numInputs += 1; } AddIntOperand(model, 2); // stride x AddIntOperand(model, 2); // stride y numInputs += 2; if (options.m_IsDepthwiseConvolution) { AddIntOperand(model, 1); // depth multiplier numInputs++; } AddIntOperand(model, 0); // no activation numInputs += 1; // dilation if (options.m_HasDilation) { AddBoolOperand(model, false); // default data layout AddIntOperand(model, 2); // dilation X AddIntOperand(model, 2); // dilation Y numInputs += 3; } // output AddOutputOperand(model, hidl_vec{1, 1, 1, 1}); // set up the convolution operation model.operations.resize(1); model.operations[0].type = options.m_IsDepthwiseConvolution ? HalOperationType::DEPTHWISE_CONV_2D : HalOperationType::CONV_2D; std::vector inputs(numInputs); std::iota(inputs.begin(), inputs.end(), 0u); std::vector outputs = { numInputs }; model.operations[0].inputs = hidl_vec(inputs); model.operations[0].outputs = hidl_vec(outputs); // convert model ConversionData data({backend}); data.m_Network = armnn::INetwork::Create(); data.m_OutputSlotForOperand = std::vector(model.operands.size(), nullptr); bool ok = HalPolicy::ConvertOperation(model.operations[0], model, data); DOCTEST_CHECK(ok); // check if dilation params are as expected DilationTestVisitor visitor = options.m_HasDilation ? DilationTestVisitor(2, 2) : DilationTestVisitor(); data.m_Network->ExecuteStrategy(visitor); }