xref: /aosp_15_r20/external/ComputeLibrary/tests/validation/NEON/DirectConvolutionLayer.cpp (revision c217d954acce2dbc11938adb493fc0abd69584f3)
1*c217d954SCole Faust /*
2*c217d954SCole Faust  * Copyright (c) 2017-2023 Arm Limited.
3*c217d954SCole Faust  *
4*c217d954SCole Faust  * SPDX-License-Identifier: MIT
5*c217d954SCole Faust  *
6*c217d954SCole Faust  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*c217d954SCole Faust  * of this software and associated documentation files (the "Software"), to
8*c217d954SCole Faust  * deal in the Software without restriction, including without limitation the
9*c217d954SCole Faust  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*c217d954SCole Faust  * sell copies of the Software, and to permit persons to whom the Software is
11*c217d954SCole Faust  * furnished to do so, subject to the following conditions:
12*c217d954SCole Faust  *
13*c217d954SCole Faust  * The above copyright notice and this permission notice shall be included in all
14*c217d954SCole Faust  * copies or substantial portions of the Software.
15*c217d954SCole Faust  *
16*c217d954SCole Faust  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*c217d954SCole Faust  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*c217d954SCole Faust  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*c217d954SCole Faust  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*c217d954SCole Faust  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21*c217d954SCole Faust  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*c217d954SCole Faust  * SOFTWARE.
23*c217d954SCole Faust  */
24*c217d954SCole Faust #include "arm_compute/core/Helpers.h"
25*c217d954SCole Faust #include "arm_compute/core/Types.h"
26*c217d954SCole Faust #include "arm_compute/runtime/NEON/functions/NEDirectConvolutionLayer.h"
27*c217d954SCole Faust #include "arm_compute/runtime/Tensor.h"
28*c217d954SCole Faust #include "arm_compute/runtime/TensorAllocator.h"
29*c217d954SCole Faust #include "src/common/cpuinfo/CpuIsaInfo.h"
30*c217d954SCole Faust #include "src/cpu/kernels/CpuDirectConv2dKernel.h"
31*c217d954SCole Faust #include "tests/NEON/Accessor.h"
32*c217d954SCole Faust #include "tests/PaddingCalculator.h"
33*c217d954SCole Faust #include "tests/datasets/ShapeDatasets.h"
34*c217d954SCole Faust #include "tests/framework/Asserts.h"
35*c217d954SCole Faust #include "tests/framework/Macros.h"
36*c217d954SCole Faust #include "tests/framework/datasets/Datasets.h"
37*c217d954SCole Faust #include "tests/validation/Validation.h"
38*c217d954SCole Faust #include "tests/validation/fixtures/DirectConvolutionLayerFixture.h"
39*c217d954SCole Faust 
40*c217d954SCole Faust namespace arm_compute
41*c217d954SCole Faust {
42*c217d954SCole Faust namespace test
43*c217d954SCole Faust {
44*c217d954SCole Faust namespace validation
45*c217d954SCole Faust {
46*c217d954SCole Faust namespace
47*c217d954SCole Faust {
48*c217d954SCole Faust #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
49*c217d954SCole Faust const RelativeTolerance<half_float::half> rel_tolerance_f16(half_float::half(0.2f)); /**< Relative tolerance value for FP16 types */
50*c217d954SCole Faust const AbsoluteTolerance<float>            abs_tolerance_f16(0.2f);                   /**< Absolute tolerance for FP16 types */
51*c217d954SCole Faust constexpr float                           tolerance_num = 0.07f;                     /**< Tolerance number for the FP16 implementation */
52*c217d954SCole Faust #endif                                                                               /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
53*c217d954SCole Faust constexpr AbsoluteTolerance<float> tolerance_fp32(0.001f);                           /**< Tolerance for floating point tests */
54*c217d954SCole Faust 
55*c217d954SCole Faust /** Direct convolution data set.for FP32 */
56*c217d954SCole Faust const auto data_pad_f32 = concat(concat(combine(framework::dataset::make("PadX", { 0, 1 }),
57*c217d954SCole Faust                                                 combine(framework::dataset::make("PadY", { 0, 1 }),
58*c217d954SCole Faust                                                         framework::dataset::make("KernelSize", 3))),
59*c217d954SCole Faust                                         combine(framework::dataset::make("PadX", { 0, 2 }),
60*c217d954SCole Faust                                                 combine(framework::dataset::make("PadY", { 0, 2 }),
61*c217d954SCole Faust                                                         framework::dataset::make("KernelSize", 3)))),
62*c217d954SCole Faust                                  combine(framework::dataset::make("PadX", { 0, 3 }),
63*c217d954SCole Faust                                          combine(framework::dataset::make("PadY", { 0, 3 }),
64*c217d954SCole Faust                                                  framework::dataset::make("KernelSize", 5))));
65*c217d954SCole Faust 
66*c217d954SCole Faust /** Direct convolution data set.for FP16 */
67*c217d954SCole Faust const auto data_pad_f16 = concat(combine(framework::dataset::make("PadX", { 0, 1 }),
68*c217d954SCole Faust                                          combine(framework::dataset::make("PadY", { 0, 1 }),
69*c217d954SCole Faust                                                  framework::dataset::make("KernelSize", 3))),
70*c217d954SCole Faust                                  combine(framework::dataset::make("PadX", { 0 }),
71*c217d954SCole Faust                                          combine(framework::dataset::make("PadY", { 0 }),
72*c217d954SCole Faust                                                  framework::dataset::make("KernelSize", 1))));
73*c217d954SCole Faust 
74*c217d954SCole Faust const auto data_f32 = combine(datasets::SmallDirectConvolutionShapes(),
75*c217d954SCole Faust                               combine(framework::dataset::make("StrideX", { 1, 2, 3, 4 }),
76*c217d954SCole Faust                                       combine(framework::dataset::make("StrideY", { 1, 2, 3, 4 }),
77*c217d954SCole Faust                                               data_pad_f32)));
78*c217d954SCole Faust 
79*c217d954SCole Faust const auto data_f16 = combine(datasets::SmallDirectConvolutionShapes(),
80*c217d954SCole Faust                               combine(framework::dataset::make("StrideX", { 1, 2, 3 }),
81*c217d954SCole Faust                                       combine(framework::dataset::make("StrideY", { 1, 2, 3 }),
82*c217d954SCole Faust                                               data_pad_f16)));
83*c217d954SCole Faust 
84*c217d954SCole Faust const auto data_prec = combine(datasets::SmallDirectConvolutionShapes(),
85*c217d954SCole Faust                                combine(framework::dataset::make("StrideX", { 1 }),
86*c217d954SCole Faust                                        combine(framework::dataset::make("StrideY", { 1 }),
87*c217d954SCole Faust                                                combine(framework::dataset::make("PadX", { 1 }),
88*c217d954SCole Faust                                                        combine(framework::dataset::make("PadY", { 1 }),
89*c217d954SCole Faust                                                                framework::dataset::make("KernelSize", 3))))));
90*c217d954SCole Faust 
91*c217d954SCole Faust const auto data9x9 = combine(datasets::SmallDirectConvolutionShapes(),
92*c217d954SCole Faust                              combine(framework::dataset::make("StrideX", { 1, 2, 3 }),
93*c217d954SCole Faust                                      combine(framework::dataset::make("StrideY", { 1, 2, 3 }),
94*c217d954SCole Faust                                              combine(framework::dataset::make("PadX", { 0, 2 }),
95*c217d954SCole Faust                                                      combine(framework::dataset::make("PadY", { 0, 3 }),
96*c217d954SCole Faust                                                              framework::dataset::make("KernelSize", 9))))));
97*c217d954SCole Faust 
98*c217d954SCole Faust const auto data8x8 = combine(datasets::SmallDirectConvolutionShapes(),
99*c217d954SCole Faust                              combine(framework::dataset::make("StrideX", { 1, 2, 3 }),
100*c217d954SCole Faust                                      combine(framework::dataset::make("StrideY", { 1, 2, 3 }),
101*c217d954SCole Faust                                              combine(framework::dataset::make("PadX", { 0 }),
102*c217d954SCole Faust                                                      combine(framework::dataset::make("PadY", { 0 }),
103*c217d954SCole Faust                                                              framework::dataset::make("KernelSize", 8))))));
104*c217d954SCole Faust 
105*c217d954SCole Faust const auto data_f32_nightly = combine(data_f32, framework::dataset::make("NumKernels", { 1, 4, 5 }));
106*c217d954SCole Faust const auto data_f16_nightly = combine(data_f16, framework::dataset::make("NumKernels", { 1, 4, 5 }));
107*c217d954SCole Faust 
108*c217d954SCole Faust const auto data_precommit    = combine(data_prec, framework::dataset::make("NumKernels", { 1 }));
109*c217d954SCole Faust const auto data_precommit9x9 = combine(data9x9, framework::dataset::make("NumKernels", { 4 }));
110*c217d954SCole Faust const auto data_precommit8x8 = combine(data8x8, framework::dataset::make("NumKernels", { 4 }));
111*c217d954SCole Faust 
112*c217d954SCole Faust /* The following tests is from real use-case that made DirectConvolution
113*c217d954SCole Faust  * overflows in terms of its tensor indexing. This test case is using
114*c217d954SCole Faust  * a separate tolerance due to the following reason.
115*c217d954SCole Faust  * - It has shown that it requires generally larger absolute tolerance
116*c217d954SCole Faust  *   for large numbers or larger relative tolerance for small numbers.
117*c217d954SCole Faust  * - With the first reason, since it is mainly testing index overflow,
118*c217d954SCole Faust  *   a value with a margin is used to avoid uninteded test failures
119*c217d954SCole Faust  *   during nightly.
120*c217d954SCole Faust  */
121*c217d954SCole Faust constexpr AbsoluteTolerance<float> usecase_tolerance_fp32(0.05f);
122*c217d954SCole Faust 
123*c217d954SCole Faust const auto data_nightly_usecase = combine(framework::dataset::make("InputShape", { TensorShape{ 3U, 800U, 800U } }),
124*c217d954SCole Faust                                           combine(framework::dataset::make("StrideX", { 1 }),
125*c217d954SCole Faust                                                   combine(framework::dataset::make("StrideY", { 1 }),
126*c217d954SCole Faust                                                           combine(framework::dataset::make("PadX", { 4 }),
127*c217d954SCole Faust                                                                   combine(framework::dataset::make("PadY", { 4 }),
128*c217d954SCole Faust                                                                           combine(framework::dataset::make("KernelSize", 9),
129*c217d954SCole Faust                                                                                   framework::dataset::make("NumKernels", { 16 })))))));
130*c217d954SCole Faust 
131*c217d954SCole Faust /** Activation function Dataset*/
132*c217d954SCole Faust const auto ActivationFunctionsDataset = framework::dataset::make("ActivationInfo",
133*c217d954SCole Faust {
134*c217d954SCole Faust     ActivationLayerInfo(),
135*c217d954SCole Faust     ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 0.5f)
136*c217d954SCole Faust });
137*c217d954SCole Faust } // namespace
138*c217d954SCole Faust 
139*c217d954SCole Faust TEST_SUITE(NEON)
TEST_SUITE(DirectConvolutionLayer)140*c217d954SCole Faust TEST_SUITE(DirectConvolutionLayer)
141*c217d954SCole Faust 
142*c217d954SCole Faust /** Check whether the configuration of a Direct Convolution layer with no
143*c217d954SCole Faust  * bias leads to a successful execution.
144*c217d954SCole Faust  */
145*c217d954SCole Faust TEST_CASE(NoBias, framework::DatasetMode::PRECOMMIT)
146*c217d954SCole Faust {
147*c217d954SCole Faust     const auto     src_shape     = TensorShape(27U, 13U, 2U);
148*c217d954SCole Faust     const auto     weights_shape = TensorShape(3U, 3U, 2U, 4U);
149*c217d954SCole Faust     const auto     bias_shape    = TensorShape(4U);
150*c217d954SCole Faust     const auto     dst_shape     = TensorShape(25U, 11U, 4U);
151*c217d954SCole Faust     constexpr auto dt            = DataType::F32;
152*c217d954SCole Faust 
153*c217d954SCole Faust     auto src     = create_tensor<Tensor>(src_shape, dt);
154*c217d954SCole Faust     auto weights = create_tensor<Tensor>(weights_shape, dt);
155*c217d954SCole Faust     auto dst     = create_tensor<Tensor>(dst_shape, dt);
156*c217d954SCole Faust 
157*c217d954SCole Faust     const auto conv_info = PadStrideInfo(1, 1, 0, 0);
158*c217d954SCole Faust 
159*c217d954SCole Faust     // Create Direct Convolution function
160*c217d954SCole Faust     NEDirectConvolutionLayer conv{};
161*c217d954SCole Faust     conv.configure(&src, &weights, nullptr, &dst, conv_info);
162*c217d954SCole Faust 
163*c217d954SCole Faust     src.allocator()->allocate();
164*c217d954SCole Faust     weights.allocator()->allocate();
165*c217d954SCole Faust     dst.allocator()->allocate();
166*c217d954SCole Faust 
167*c217d954SCole Faust     library->fill_tensor_value(Accessor(src), 1.f);
168*c217d954SCole Faust     library->fill_tensor_value(Accessor(weights), 1.f);
169*c217d954SCole Faust 
170*c217d954SCole Faust     conv.run();
171*c217d954SCole Faust 
172*c217d954SCole Faust     // Compute reference to compare
173*c217d954SCole Faust     SimpleTensor<float> ref_src{ src_shape, dt };
174*c217d954SCole Faust     SimpleTensor<float> ref_weights{ weights_shape, dt };
175*c217d954SCole Faust     SimpleTensor<float> ref_bias{ bias_shape, dt };
176*c217d954SCole Faust     library->fill_tensor_value(ref_src, 1.f);
177*c217d954SCole Faust     library->fill_tensor_value(ref_weights, 1.f);
178*c217d954SCole Faust     // No bias
179*c217d954SCole Faust     library->fill_tensor_value(ref_bias, 0.f);
180*c217d954SCole Faust     auto ref_dst = reference::convolution_layer<float>(ref_src, ref_weights, ref_bias, dst_shape, conv_info);
181*c217d954SCole Faust 
182*c217d954SCole Faust     validate(Accessor(dst), ref_dst);
183*c217d954SCole Faust }
184*c217d954SCole Faust 
185*c217d954SCole Faust DATA_TEST_CASE(KernelSelection, framework::DatasetMode::ALL,
186*c217d954SCole Faust                concat(combine(combine(framework::dataset::make("CpuExt", std::string("NEON")),
187*c217d954SCole Faust                                       framework::dataset::make("DataType", { DataType::F32 })),
188*c217d954SCole Faust                               framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })),
189*c217d954SCole Faust                       combine(combine(framework::dataset::make("CpuExt", std::string("NEON")),
190*c217d954SCole Faust                                       framework::dataset::make("DataType", { DataType::F16 })),
191*c217d954SCole Faust                               framework::dataset::make("DataLayout", { DataLayout::NCHW }))),
192*c217d954SCole Faust                cpu_ext, data_type, data_layout)
193*c217d954SCole Faust {
194*c217d954SCole Faust     using namespace cpu::kernels;
195*c217d954SCole Faust 
196*c217d954SCole Faust     cpuinfo::CpuIsaInfo cpu_isa{};
197*c217d954SCole Faust     cpu_isa.neon = (cpu_ext == "NEON");
198*c217d954SCole Faust     cpu_isa.fp16 = (data_type == DataType::F16);
199*c217d954SCole Faust 
200*c217d954SCole Faust     const auto *selected_impl = CpuDirectConv2dKernel::get_implementation(DataTypeDataLayoutISASelectorData{ data_type, data_layout, cpu_isa }, cpu::KernelSelectionType::Preferred);
201*c217d954SCole Faust 
202*c217d954SCole Faust     ARM_COMPUTE_ERROR_ON_NULLPTR(selected_impl);
203*c217d954SCole Faust 
204*c217d954SCole Faust     std::string data_layout_str;
205*c217d954SCole Faust     if(data_layout == DataLayout::NCHW)
206*c217d954SCole Faust     {
207*c217d954SCole Faust         data_layout_str = "nchw";
208*c217d954SCole Faust     }
209*c217d954SCole Faust     else
210*c217d954SCole Faust     {
211*c217d954SCole Faust         data_layout_str = "nhwc";
212*c217d954SCole Faust     }
213*c217d954SCole Faust 
214*c217d954SCole Faust     std::string expected = lower_string(cpu_ext) + "_" + cpu_impl_dt(data_type) + "_" + data_layout_str + "_directconv2d";
215*c217d954SCole Faust     std::string actual   = selected_impl->name;
216*c217d954SCole Faust 
217*c217d954SCole Faust     ARM_COMPUTE_EXPECT_EQUAL(expected, actual, framework::LogLevel::ERRORS);
218*c217d954SCole Faust }
219*c217d954SCole Faust 
220*c217d954SCole Faust // *INDENT-OFF*
221*c217d954SCole Faust // clang-format off
222*c217d954SCole Faust DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(zip(
223*c217d954SCole Faust         framework::dataset::make("InputInfo", { TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid: Mismatching data type input/weights
224*c217d954SCole Faust                                                 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid: Mismatching input feature maps
225*c217d954SCole Faust                                                 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Unsupported kernel width
226*c217d954SCole Faust                                                 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Unsupported non-rectangular weights dimensions
227*c217d954SCole Faust                                                 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid weights dimensions
228*c217d954SCole Faust                                                 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Unsupported stride
229*c217d954SCole Faust                                                 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Unsupported biases size
230*c217d954SCole Faust                                                 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Unsupported biases dimensions
231*c217d954SCole Faust                                                 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid output size
232*c217d954SCole Faust                                               }),
233*c217d954SCole Faust         framework::dataset::make("WeightsInfo",{ TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F16),
234*c217d954SCole Faust                                                  TensorInfo(TensorShape(3U, 3U, 3U, 4U), 1, DataType::F32),
235*c217d954SCole Faust                                                  TensorInfo(TensorShape(9U, 9U, 2U, 4U), 1, DataType::F32),
236*c217d954SCole Faust                                                  TensorInfo(TensorShape(5U, 3U, 2U, 4U), 1, DataType::F32),
237*c217d954SCole Faust                                                  TensorInfo(TensorShape(3U, 3U, 2U, 4U, 3U), 1, DataType::F32),
238*c217d954SCole Faust                                                  TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
239*c217d954SCole Faust                                                  TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
240*c217d954SCole Faust                                                  TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
241*c217d954SCole Faust                                                  TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
242*c217d954SCole Faust                                               })),
243*c217d954SCole Faust         framework::dataset::make("BiasesInfo",{ TensorInfo(TensorShape(4U), 1, DataType::F32),
244*c217d954SCole Faust                                                 TensorInfo(TensorShape(4U), 1, DataType::F32),
245*c217d954SCole Faust                                                 TensorInfo(TensorShape(4U), 1, DataType::F32),
246*c217d954SCole Faust                                                 TensorInfo(TensorShape(4U), 1, DataType::F32),
247*c217d954SCole Faust                                                 TensorInfo(TensorShape(4U), 1, DataType::F32),
248*c217d954SCole Faust                                                 TensorInfo(TensorShape(4U), 1, DataType::F32),
249*c217d954SCole Faust                                                 TensorInfo(TensorShape(3U), 1, DataType::F32),
250*c217d954SCole Faust                                                 TensorInfo(TensorShape(4U, 2U), 1, DataType::F32),
251*c217d954SCole Faust                                                 TensorInfo(TensorShape(4U), 1, DataType::F32),
252*c217d954SCole Faust                                               })),
253*c217d954SCole Faust         framework::dataset::make("OutputInfo",{ TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
254*c217d954SCole Faust                                                 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
255*c217d954SCole Faust                                                 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
256*c217d954SCole Faust                                                 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
257*c217d954SCole Faust                                                 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
258*c217d954SCole Faust                                                 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
259*c217d954SCole Faust                                                 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
260*c217d954SCole Faust                                                 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
261*c217d954SCole Faust                                                 TensorInfo(TensorShape(26U, 11U, 4U), 1, DataType::F32),
262*c217d954SCole Faust                                               })),
263*c217d954SCole Faust         framework::dataset::make("ConvInfo",  { PadStrideInfo(1, 1, 0, 0),
264*c217d954SCole Faust                                                 PadStrideInfo(1, 1, 0, 0),
265*c217d954SCole Faust                                                 PadStrideInfo(1, 1, 0, 0),
266*c217d954SCole Faust                                                 PadStrideInfo(1, 1, 0, 0),
267*c217d954SCole Faust                                                 PadStrideInfo(1, 1, 0, 0),
268*c217d954SCole Faust                                                 PadStrideInfo(3, 3, 0, 0),
269*c217d954SCole Faust                                                 PadStrideInfo(1, 1, 0, 0),
270*c217d954SCole Faust                                                 PadStrideInfo(1, 1, 0, 0),
271*c217d954SCole Faust                                                 PadStrideInfo(1, 1, 0, 0),
272*c217d954SCole Faust                                                })),
273*c217d954SCole Faust                                                        framework::dataset::make("ActivationInfo",
274*c217d954SCole Faust {
275*c217d954SCole Faust     ActivationLayerInfo(),
276*c217d954SCole Faust     ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
277*c217d954SCole Faust     ActivationLayerInfo(),
278*c217d954SCole Faust     ActivationLayerInfo(),
279*c217d954SCole Faust     ActivationLayerInfo(),
280*c217d954SCole Faust     ActivationLayerInfo(),
281*c217d954SCole Faust     ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
282*c217d954SCole Faust     ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
283*c217d954SCole Faust     ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
284*c217d954SCole Faust })),
285*c217d954SCole Faust         framework::dataset::make("Expected", { false, false, false, false, false, false, false, false, false })),
286*c217d954SCole Faust         input_info, weights_info, biases_info, output_info, conv_info, act_info, expected)
287*c217d954SCole Faust {
288*c217d954SCole Faust         bool is_valid = bool(NEDirectConvolutionLayer::validate(&input_info.clone()->set_is_resizable(false), &weights_info.clone()->set_is_resizable(false), &biases_info.clone()->set_is_resizable(false), &output_info.clone()->set_is_resizable(false), conv_info, act_info));
289*c217d954SCole Faust         ARM_COMPUTE_EXPECT(is_valid == expected, framework::LogLevel::ERRORS);
290*c217d954SCole Faust }
291*c217d954SCole Faust // clang-format on
292*c217d954SCole Faust // *INDENT-ON*
293*c217d954SCole Faust 
294*c217d954SCole Faust DATA_TEST_CASE(NoPaddingNHWCKernel, framework::DatasetMode::ALL, combine(combine(combine(data_precommit,
295*c217d954SCole Faust                                                                                          framework::dataset::make("DataType", DataType::F32)),
296*c217d954SCole Faust                                                                                  ActivationFunctionsDataset),
297*c217d954SCole Faust                                                                          framework::dataset::make("DataLayout", { DataLayout::NHWC })),
298*c217d954SCole Faust 
299*c217d954SCole Faust                shape, stride_x, stride_y, pad_x, pad_y, kernel_size, num_kernels, data_type, act_info, data_layout)
300*c217d954SCole Faust {
301*c217d954SCole Faust     TensorShape         input_shape = TensorShape(shape);
302*c217d954SCole Faust     TensorShape         weights_shape(kernel_size, kernel_size, input_shape.z(), num_kernels);
303*c217d954SCole Faust     const PadStrideInfo info(stride_x, stride_y, pad_x, pad_y, DimensionRoundingType::FLOOR);
304*c217d954SCole Faust 
305*c217d954SCole Faust     TensorInfo input_info   = TensorInfo(input_shape, 1, data_type);
306*c217d954SCole Faust     TensorInfo weights_info = TensorInfo(weights_shape, 1, data_type);
307*c217d954SCole Faust 
308*c217d954SCole Faust     TensorShape output_shape = compute_deep_convolution_shape(input_info, weights_info, info);
309*c217d954SCole Faust 
310*c217d954SCole Faust     if(data_layout == DataLayout::NHWC)
311*c217d954SCole Faust     {
312*c217d954SCole Faust         permute(input_shape, PermutationVector(2U, 0U, 1U));
313*c217d954SCole Faust         permute(weights_shape, PermutationVector(2U, 0U, 1U));
314*c217d954SCole Faust         permute(output_shape, PermutationVector(2U, 0U, 1U));
315*c217d954SCole Faust     }
316*c217d954SCole Faust 
317*c217d954SCole Faust     // Create tensors
318*c217d954SCole Faust     Tensor src     = create_tensor<Tensor>(input_shape, data_type, 1, QuantizationInfo(), data_layout);
319*c217d954SCole Faust     Tensor weights = create_tensor<Tensor>(weights_shape, data_type, 1, QuantizationInfo(), data_layout);
320*c217d954SCole Faust     Tensor dst     = create_tensor<Tensor>(output_shape, data_type, 1, QuantizationInfo(), data_layout);
321*c217d954SCole Faust 
322*c217d954SCole Faust     // Create and configure function
323*c217d954SCole Faust     NEDirectConvolutionLayer conv;
324*c217d954SCole Faust     conv.configure(&src, &weights, nullptr, &dst, info, act_info);
325*c217d954SCole Faust 
326*c217d954SCole Faust     validate(src.info()->padding(), PaddingSize(0, 0, 0, 0));
327*c217d954SCole Faust     validate(weights.info()->padding(), PaddingSize(0, 0, 0, 0));
328*c217d954SCole Faust     validate(dst.info()->padding(), PaddingSize(0, 0, 0, 0));
329*c217d954SCole Faust }
330*c217d954SCole Faust 
331*c217d954SCole Faust template <typename T>
332*c217d954SCole Faust using NEDirectConvolutionLayerFixture = DirectConvolutionValidationFixture<Tensor, Accessor, NEDirectConvolutionLayer, T>;
333*c217d954SCole Faust template <typename T>
334*c217d954SCole Faust using NEDirectConvolutionLayerMixedDataLayoutFixture = DirectConvolutionValidationFixture<Tensor, Accessor, NEDirectConvolutionLayer, T, true>;
335*c217d954SCole Faust 
336*c217d954SCole Faust TEST_SUITE(Float)
337*c217d954SCole Faust #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
TEST_SUITE(FP16)338*c217d954SCole Faust TEST_SUITE(FP16)
339*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEDirectConvolutionLayerFixture<half>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(data_precommit, framework::dataset::make("DataType",
340*c217d954SCole Faust                                                                                                                    DataType::F16)),
341*c217d954SCole Faust                                                                                                                    ActivationFunctionsDataset),
342*c217d954SCole Faust                                                                                                                    framework::dataset::make("DataLayout", DataLayout::NCHW)))
343*c217d954SCole Faust {
344*c217d954SCole Faust     // Validate output
345*c217d954SCole Faust     validate(Accessor(_target), _reference, rel_tolerance_f16, tolerance_num, abs_tolerance_f16);
346*c217d954SCole Faust }
347*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunLarge, NEDirectConvolutionLayerFixture<half>, framework::DatasetMode::NIGHTLY, combine(combine(combine(data_f16_nightly, framework::dataset::make("DataType", DataType::F16)),
348*c217d954SCole Faust                                                                                                                  ActivationFunctionsDataset),
349*c217d954SCole Faust                                                                                                                  framework::dataset::make("DataLayout", DataLayout::NCHW)))
350*c217d954SCole Faust {
351*c217d954SCole Faust     // Validate output
352*c217d954SCole Faust     validate(Accessor(_target), _reference, rel_tolerance_f16, tolerance_num, abs_tolerance_f16);
353*c217d954SCole Faust }
354*c217d954SCole Faust TEST_SUITE_END() // FP16
355*c217d954SCole Faust #endif           /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
356*c217d954SCole Faust 
TEST_SUITE(FP32)357*c217d954SCole Faust TEST_SUITE(FP32)
358*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEDirectConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(data_precommit, framework::dataset::make("DataType",
359*c217d954SCole Faust                                                                                                                     DataType::F32)),
360*c217d954SCole Faust                                                                                                                     ActivationFunctionsDataset),
361*c217d954SCole Faust                                                                                                                     framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
362*c217d954SCole Faust {
363*c217d954SCole Faust     // Validate output
364*c217d954SCole Faust     validate(Accessor(_target), _reference, tolerance_fp32);
365*c217d954SCole Faust }
366*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunMixedDataLayout, NEDirectConvolutionLayerMixedDataLayoutFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(data_precommit,
367*c217d954SCole Faust                        framework::dataset::make("DataType", DataType::F32)),
368*c217d954SCole Faust                        ActivationFunctionsDataset),
369*c217d954SCole Faust                        framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
370*c217d954SCole Faust {
371*c217d954SCole Faust     // Validate output
372*c217d954SCole Faust     validate(Accessor(_target), _reference, tolerance_fp32);
373*c217d954SCole Faust }
374*c217d954SCole Faust 
375*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall8x8, NEDirectConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(data_precommit8x8, framework::dataset::make("DataType",
376*c217d954SCole Faust                                                                                                                        DataType::F32)),
377*c217d954SCole Faust                                                                                                                        ActivationFunctionsDataset),
378*c217d954SCole Faust                                                                                                                        framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
379*c217d954SCole Faust {
380*c217d954SCole Faust     // Validate output
381*c217d954SCole Faust     validate(Accessor(_target), _reference, tolerance_fp32);
382*c217d954SCole Faust }
383*c217d954SCole Faust 
384*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall9x9, NEDirectConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(data_precommit9x9, framework::dataset::make("DataType",
385*c217d954SCole Faust                                                                                                                        DataType::F32)),
386*c217d954SCole Faust                                                                                                                        ActivationFunctionsDataset),
387*c217d954SCole Faust                                                                                                                        framework::dataset::make("DataLayout", { DataLayout::NHWC })))
388*c217d954SCole Faust {
389*c217d954SCole Faust     // Validate output
390*c217d954SCole Faust     validate(Accessor(_target), _reference, tolerance_fp32);
391*c217d954SCole Faust }
392*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunLarge, NEDirectConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(data_f32_nightly, framework::dataset::make("DataType",
393*c217d954SCole Faust                                                                                                                   DataType::F32)),
394*c217d954SCole Faust                                                                                                                   ActivationFunctionsDataset),
395*c217d954SCole Faust                                                                                                                   framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
396*c217d954SCole Faust {
397*c217d954SCole Faust     // Validate output
398*c217d954SCole Faust     validate(Accessor(_target), _reference, tolerance_fp32);
399*c217d954SCole Faust }
400*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunLargeUsecase, NEDirectConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(data_nightly_usecase, framework::dataset::make("DataType",
401*c217d954SCole Faust                        DataType::F32)),
402*c217d954SCole Faust                        framework::dataset::make("ActivationInfo", { ActivationLayerInfo() })),
403*c217d954SCole Faust                        framework::dataset::make("DataLayout", { DataLayout::NHWC })))
404*c217d954SCole Faust {
405*c217d954SCole Faust     // Validate output
406*c217d954SCole Faust     validate(Accessor(_target), _reference, usecase_tolerance_fp32);
407*c217d954SCole Faust }
408*c217d954SCole Faust TEST_SUITE_END() // FP32
409*c217d954SCole Faust TEST_SUITE_END() // Float
410*c217d954SCole Faust TEST_SUITE_END() // DirectConvolutionLayer
411*c217d954SCole Faust TEST_SUITE_END() // Neon
412*c217d954SCole Faust } // namespace validation
413*c217d954SCole Faust } // namespace test
414*c217d954SCole Faust } // namespace arm_compute
415