• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #pragma once
7 
8 #include "DriverTestHelpers.hpp"
9 
10 #include <armnn/LayerVisitorBase.hpp>
11 #include <armnn/utility/IgnoreUnused.hpp>
12 
13 #include <boost/test/unit_test.hpp>
14 
15 #include <numeric>
16 
17 BOOST_AUTO_TEST_SUITE(DilationTests)
18 
19 using namespace armnn;
20 using namespace boost;
21 using namespace driverTestHelpers;
22 
23 struct DilationTestOptions
24 {
DilationTestOptionsDilationTestOptions25     DilationTestOptions() :
26         m_IsDepthwiseConvolution{false},
27         m_IsPaddingExplicit{false},
28         m_HasDilation{false}
29     {}
30 
31     ~DilationTestOptions() = default;
32 
33     bool m_IsDepthwiseConvolution;
34     bool m_IsPaddingExplicit;
35     bool m_HasDilation;
36 };
37 
38 class DilationTestVisitor : public LayerVisitorBase<VisitorThrowingPolicy>
39 {
40 public:
DilationTestVisitor()41     DilationTestVisitor() :
42         DilationTestVisitor(1u, 1u)
43     {}
44 
DilationTestVisitor(uint32_t expectedDilationX,uint32_t expectedDilationY)45     DilationTestVisitor(uint32_t expectedDilationX, uint32_t expectedDilationY) :
46         m_ExpectedDilationX{expectedDilationX},
47         m_ExpectedDilationY{expectedDilationY}
48     {}
49 
VisitConvolution2dLayer(const IConnectableLayer * layer,const Convolution2dDescriptor & descriptor,const ConstTensor & weights,const Optional<ConstTensor> & biases,const char * name=nullptr)50     void VisitConvolution2dLayer(const IConnectableLayer *layer,
51                                  const Convolution2dDescriptor& descriptor,
52                                  const ConstTensor& weights,
53                                  const Optional<ConstTensor>& biases,
54                                  const char *name = nullptr) override
55     {
56         IgnoreUnused(layer);
57         IgnoreUnused(weights);
58         IgnoreUnused(biases);
59         IgnoreUnused(name);
60 
61         CheckDilationParams(descriptor);
62     }
63 
VisitDepthwiseConvolution2dLayer(const IConnectableLayer * layer,const DepthwiseConvolution2dDescriptor & descriptor,const ConstTensor & weights,const Optional<ConstTensor> & biases,const char * name=nullptr)64     void VisitDepthwiseConvolution2dLayer(const IConnectableLayer *layer,
65                                           const DepthwiseConvolution2dDescriptor& descriptor,
66                                           const ConstTensor& weights,
67                                           const Optional<ConstTensor>& biases,
68                                           const char *name = nullptr) override
69     {
70         IgnoreUnused(layer);
71         IgnoreUnused(weights);
72         IgnoreUnused(biases);
73         IgnoreUnused(name);
74 
75         CheckDilationParams(descriptor);
76     }
77 
78 private:
79     uint32_t m_ExpectedDilationX;
80     uint32_t m_ExpectedDilationY;
81 
82     template<typename ConvolutionDescriptor>
CheckDilationParams(const ConvolutionDescriptor & descriptor)83     void CheckDilationParams(const ConvolutionDescriptor& descriptor)
84     {
85         BOOST_CHECK_EQUAL(descriptor.m_DilationX, m_ExpectedDilationX);
86         BOOST_CHECK_EQUAL(descriptor.m_DilationY, m_ExpectedDilationY);
87     }
88 };
89 
90 template<typename HalPolicy>
DilationTestImpl(const DilationTestOptions & options)91 void DilationTestImpl(const DilationTestOptions& options)
92 {
93     using HalModel         = typename HalPolicy::Model;
94     using HalOperationType = typename HalPolicy::OperationType;
95 
96     const armnn::Compute backend = armnn::Compute::CpuRef;
97     auto driver = std::make_unique<ArmnnDriver>(DriverOptions(backend, false));
98     HalModel model = {};
99 
100     // add operands
101     std::vector<float> weightData(9, 1.0f);
102     std::vector<float> biasData(1, 0.0f );
103 
104     // input
105     AddInputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 3, 3, 1});
106 
107     // weights & biases
108     AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 3, 3, 1}, weightData.data());
109     AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{1}, biasData.data());
110 
111     uint32_t numInputs = 3u;
112     // padding
113     if (options.m_IsPaddingExplicit)
114     {
115         AddIntOperand<HalPolicy>(model, 1);
116         AddIntOperand<HalPolicy>(model, 1);
117         AddIntOperand<HalPolicy>(model, 1);
118         AddIntOperand<HalPolicy>(model, 1);
119         numInputs += 4;
120     }
121     else
122     {
123         AddIntOperand<HalPolicy>(model, android::nn::kPaddingSame);
124         numInputs += 1;
125     }
126 
127     AddIntOperand<HalPolicy>(model, 2); // stride x
128     AddIntOperand<HalPolicy>(model, 2); // stride y
129     numInputs += 2;
130 
131     if (options.m_IsDepthwiseConvolution)
132     {
133         AddIntOperand<HalPolicy>(model, 1); // depth multiplier
134         numInputs++;
135     }
136 
137     AddIntOperand<HalPolicy>(model, 0); // no activation
138     numInputs += 1;
139 
140     // dilation
141     if (options.m_HasDilation)
142     {
143         AddBoolOperand<HalPolicy>(model, false); // default data layout
144 
145         AddIntOperand<HalPolicy>(model, 2); // dilation X
146         AddIntOperand<HalPolicy>(model, 2); // dilation Y
147 
148         numInputs += 3;
149     }
150 
151     // output
152     AddOutputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 1, 1, 1});
153 
154     // set up the convolution operation
155     model.operations.resize(1);
156     model.operations[0].type = options.m_IsDepthwiseConvolution ?
157         HalOperationType::DEPTHWISE_CONV_2D : HalOperationType::CONV_2D;
158 
159     std::vector<uint32_t> inputs(numInputs);
160     std::iota(inputs.begin(), inputs.end(), 0u);
161     std::vector<uint32_t> outputs = { numInputs };
162 
163     model.operations[0].inputs  = hidl_vec<uint32_t>(inputs);
164     model.operations[0].outputs = hidl_vec<uint32_t>(outputs);
165 
166     // convert model
167     ConversionData data({backend});
168     data.m_Network = armnn::INetwork::Create();
169     data.m_OutputSlotForOperand = std::vector<IOutputSlot*>(model.operands.size(), nullptr);
170 
171     bool ok = HalPolicy::ConvertOperation(model.operations[0], model, data);
172     BOOST_CHECK(ok);
173 
174     // check if dilation params are as expected
175     DilationTestVisitor visitor = options.m_HasDilation ? DilationTestVisitor(2, 2) : DilationTestVisitor();
176     data.m_Network->Accept(visitor);
177 }
178 
179 BOOST_AUTO_TEST_SUITE_END()
180