Imported Upstream version 1.19.0
[platform/core/ml/nnfw.git] / compiler / luci-interpreter / src / kernels / Conv2D.test.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "kernels/Conv2D.h"
18 #include "kernels/TestUtils.h"
19 #include "luci_interpreter/TestMemoryManager.h"
20
21 namespace luci_interpreter
22 {
23 namespace kernels
24 {
25 namespace
26 {
27
28 using namespace testing;
29
30 class Conv2DTest : public ::testing::Test
31 {
32 protected:
33   void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
34
35   std::unique_ptr<IMemoryManager> _memory_manager;
36 };
37
38 TEST_F(Conv2DTest, Float)
39 {
40   Shape input_shape{1, 4, 3, 2};
41   Shape filter_shape{2, 2, 2, 2};
42   Shape bias_shape{2};
43   std::vector<float> input_data{
44     1,  2,  3,  4,  5,  6,  // row = 0
45     7,  8,  9,  10, 11, 12, // row = 1
46     13, 14, 15, 16, 17, 18, // row = 2
47     19, 20, 21, 22, 23, 24, // row = 3
48   };
49   std::vector<float> filter_data{
50     1,  2,  -3, -4, // out = 0, row = 0
51     -5, 6,  -7, 8,  // out = 1, row = 0
52     4,  -2, 3,  -1, // out = 0, row = 1
53     -8, -6, 7,  5,  // out = 1, row = 1
54   };
55   std::vector<float> bias_data{1, 2};
56   Tensor input_tensor =
57     makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
58   Tensor filter_tensor =
59     makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data, _memory_manager.get());
60   Tensor bias_tensor =
61     makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, _memory_manager.get());
62   Tensor im2col(DataType::FLOAT32, Shape({}), {}, "");
63   Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
64
65   Conv2DParams params{};
66   params.padding = Padding::VALID;
67   params.stride_height = 2;
68   params.stride_width = 1;
69   params.dilation_height_factor = 1;
70   params.dilation_width_factor = 1;
71   params.activation = Activation::RELU;
72
73   Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
74   kernel.configure();
75   _memory_manager->allocate_memory(im2col);
76   _memory_manager->allocate_memory(output_tensor);
77   kernel.execute();
78
79   std::vector<float> ref_output_data{
80     11, 16, 7, 20, // row = 0
81     0,  40, 0, 44, // row = 1
82   };
83   std::vector<int32_t> ref_output_shape{1, 2, 2, 2};
84   EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
85   EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
86 }
87
88 TEST_F(Conv2DTest, FloatPointwise)
89 {
90   Shape input_shape{1, 2, 2, 2};
91   Shape filter_shape{2, 1, 1, 2};
92   Shape bias_shape{2};
93   std::vector<float> input_data{
94     1, 2, // row = 0, col = 0
95     3, 4, // row = 0, col = 1
96     5, 6, // row = 1, col = 0
97     7, 8, // row = 1, col = 1
98   };
99   std::vector<float> filter_data{
100     -1, 2, // out = 0
101     -3, 4, // out = 1
102   };
103   std::vector<float> bias_data{1, 2};
104   Tensor input_tensor =
105     makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
106   Tensor filter_tensor =
107     makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data, _memory_manager.get());
108   Tensor bias_tensor =
109     makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, _memory_manager.get());
110   Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
111   Tensor im2col(DataType::FLOAT32, Shape({}), {}, "");
112
113   Conv2DParams params{};
114   params.padding = Padding::VALID;
115   params.stride_height = 1;
116   params.stride_width = 1;
117   params.dilation_height_factor = 1;
118   params.dilation_width_factor = 1;
119   params.activation = Activation::RELU;
120
121   Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
122   kernel.configure();
123   _memory_manager->allocate_memory(im2col);
124   _memory_manager->allocate_memory(output_tensor);
125   kernel.execute();
126
127   std::vector<float> ref_output_data{
128     4, 7,  6,  9,  // row = 0
129     8, 11, 10, 13, // row = 1
130   };
131   std::vector<int32_t> ref_output_shape{1, 2, 2, 2};
132   EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
133   EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
134 }
135
136 TEST_F(Conv2DTest, FloatCheck)
137 {
138   Shape input_shape{2, 2, 4, 1};
139   Shape filter_shape{3, 2, 2, 1};
140   Shape bias_shape{3};
141   std::vector<float> input_data{
142     // First batch
143     1, 1, 1, 1, // row = 1
144     2, 2, 2, 2, // row = 2
145     // Second batch
146     1, 2, 3, 4, // row = 1
147     1, 2, 3, 4, // row = 2
148   };
149   std::vector<float> filter_data{
150     1,  2,  3,  4, // first 2x2 filter
151     -1, 1,  -1, 1, // second 2x2 filter
152     -1, -1, 1,  1, // third 2x2 filter
153   };
154   std::vector<float> bias_data{1, 2, 3};
155   Tensor input_tensor =
156     makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
157   Tensor filter_tensor =
158     makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data, _memory_manager.get());
159   Tensor bias_tensor =
160     makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, _memory_manager.get());
161   Tensor im2col(DataType::FLOAT32, Shape({}), {}, "");
162   Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
163
164   Conv2DParams params{};
165   params.padding = Padding::VALID;
166   params.stride_height = 2;
167   params.stride_width = 2;
168   params.dilation_height_factor = 1;
169   params.dilation_width_factor = 1;
170   params.activation = Activation::NONE;
171
172   Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
173   kernel.configure();
174   _memory_manager->allocate_memory(output_tensor);
175   _memory_manager->allocate_memory(im2col);
176   kernel.execute();
177
178   std::vector<float> ref_output_data{
179     18, 2, 5, // first batch, left
180     18, 2, 5, // first batch, right
181     17, 4, 3, // second batch, left
182     37, 4, 3, // second batch, right
183   };
184   std::vector<int32_t> ref_output_shape{2, 1, 2, 3};
185   EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
186   EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
187 }
188
189 TEST_F(Conv2DTest, Uint8)
190 {
191   std::vector<float> input_data{
192     // First batch
193     1, 1, 1, 1, // row = 1
194     2, 2, 2, 2, // row = 2
195                 // Second batch
196     1, 2, 3, 4, // row = 1
197     1, 2, 3, 4, // row = 2
198   };
199   std::vector<float> filter_data{
200     1,  2,  3,  4, // first 2x2 filter
201     -1, 1,  -1, 1, // second 2x2 filter
202     -1, -1, 1,  1, // third 2x2 filter
203   };
204   std::vector<float> bias_data{1, 2, 3};
205
206   std::pair<float, int32_t> input_quant_param = quantizationParams<uint8_t>(-63.5, 64);
207   std::pair<float, int32_t> output_quant_param = quantizationParams<uint8_t>(-127, 128);
208
209   Tensor input_tensor =
210     makeInputTensor<DataType::U8>({2, 2, 4, 1}, input_quant_param.first, input_quant_param.second,
211                                   input_data, _memory_manager.get());
212   Tensor filter_tensor =
213     makeInputTensor<DataType::U8>({3, 2, 2, 1}, input_quant_param.first, input_quant_param.second,
214                                   filter_data, _memory_manager.get());
215   Tensor bias_tensor = makeInputTensor<DataType::S32>(
216     {3}, input_quant_param.first * input_quant_param.first, 0, bias_data, _memory_manager.get());
217   Tensor im2col(DataType::U8, Shape({}), {}, "");
218   Tensor output_tensor =
219     makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
220
221   Conv2DParams params{};
222   params.padding = Padding::VALID;
223   params.stride_height = 2;
224   params.stride_width = 2;
225   params.dilation_height_factor = 1;
226   params.dilation_width_factor = 1;
227   params.activation = Activation::NONE;
228
229   Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
230   kernel.configure();
231   _memory_manager->allocate_memory(output_tensor);
232   _memory_manager->allocate_memory(im2col);
233   kernel.execute();
234
235   std::vector<float> ref_output_data{
236     18, 2, 5, // first batch, left
237     18, 2, 5, // first batch, right
238     17, 4, 3, // second batch, left
239     37, 4, 3, // second batch, right
240   };
241   std::vector<int32_t> ref_output_shape{2, 1, 2, 3};
242   EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
243   EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
244 }
245
246 TEST_F(Conv2DTest, Uint8_CWQ)
247 {
248   const int output_channels = 3;
249   std::vector<float> input_data{
250     // First batch
251     1, 1, 1, 1, // row = 1
252     2, 2, 2, 2, // row = 2
253                 // Second batch
254     1, 2, 3, 4, // row = 1
255     1, 2, 3, 4, // row = 2
256   };
257   std::vector<float> filter_data{
258     1,  2,  3,  4, // first 2x2 filter
259     -1, 1,  -1, 1, // second 2x2 filter
260     -1, -1, 1,  1, // third 2x2 filter
261   };
262   std::vector<float> bias_data{1, 2, 3};
263   Shape filter_shape{output_channels, 2, 2, 1};
264
265   std::pair<float, int32_t> input_quant_param = quantizationParams<uint8_t>(0, 4);
266   std::pair<float, int32_t> output_quant_param = quantizationParams<uint8_t>(-127, 128);
267
268   std::vector<std::pair<float, int32_t>> filter_quant_params;
269   filter_quant_params.push_back(quantizationParams<uint8_t>(0, 4));
270   filter_quant_params.push_back(quantizationParams<uint8_t>(-1, 1));
271   filter_quant_params.push_back(quantizationParams<uint8_t>(-1, 1));
272
273   std::vector<float> filter_scales;
274   std::vector<int32_t> filter_zerops;
275   for (auto iter : filter_quant_params)
276   {
277     filter_scales.push_back(iter.first);
278     filter_zerops.push_back(iter.second);
279   }
280
281   std::vector<float> bias_scales;
282   for (int i = 0; i < output_channels; ++i)
283     bias_scales.push_back(filter_quant_params[i].first * input_quant_param.first);
284   std::vector<int32_t> zerop(output_channels, 0);
285
286   Tensor input_tensor =
287     makeInputTensor<DataType::U8>({2, 2, 4, 1}, input_quant_param.first, input_quant_param.second,
288                                   input_data, _memory_manager.get());
289   Tensor filter_tensor = makeInputTensor<DataType::U8>(filter_shape, filter_scales, filter_zerops,
290                                                        0, filter_data, _memory_manager.get());
291   Tensor bias_tensor = makeInputTensor<DataType::S32>({output_channels}, bias_scales, zerop, 0,
292                                                       bias_data, _memory_manager.get());
293   Tensor im2col(DataType::U8, Shape({}), {}, "");
294   Tensor output_tensor =
295     makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
296
297   Conv2DParams params{};
298   params.padding = Padding::VALID;
299   params.stride_height = 2;
300   params.stride_width = 2;
301   params.dilation_height_factor = 1;
302   params.dilation_width_factor = 1;
303   params.activation = Activation::NONE;
304
305   Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
306   kernel.configure();
307   _memory_manager->allocate_memory(output_tensor);
308   _memory_manager->allocate_memory(im2col);
309   kernel.execute();
310
311   std::vector<float> ref_output_data{
312     18, 2, 5, // first batch, left
313     18, 2, 5, // first batch, right
314     17, 4, 3, // second batch, left
315     37, 4, 3, // second batch, right
316   };
317   std::vector<int32_t> ref_output_shape{2, 1, 2, 3};
318   EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
319   EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
320 }
321
322 TEST_F(Conv2DTest, SInt8_CWQ)
323 {
324   const int output_channels = 3;
325   std::vector<float> input_data{
326     // First batch
327     1, 1, 1, 1, // row = 1
328     2, 2, 2, 2, // row = 2
329                 // Second batch
330     1, 2, 3, 4, // row = 1
331     1, 2, 3, 4, // row = 2
332   };
333   std::vector<float> filter_data{
334     1,  2,  3,  4, // first 2x2 filter
335     -1, 1,  -1, 1, // second 2x2 filter
336     -1, -1, 1,  1, // third 2x2 filter
337   };
338   std::vector<float> bias_data{1, 2, 3};
339   Shape filter_shape{output_channels, 2, 2, 1};
340
341   std::pair<float, int32_t> input_quant_param = quantizationParams<int8_t>(0, 4);
342   std::pair<float, int32_t> output_quant_param = quantizationParams<int8_t>(-127, 128);
343
344   std::vector<std::pair<float, int32_t>> filter_quant_params;
345   filter_quant_params.push_back(std::pair<float, int32_t>(0.5, 0));
346   filter_quant_params.push_back(std::pair<float, int32_t>(0.25, 0));
347   filter_quant_params.push_back(std::pair<float, int32_t>(0.125, 0));
348
349   std::vector<float> filter_scales;
350   std::vector<int32_t> filter_zerops;
351   for (auto iter : filter_quant_params)
352   {
353     filter_scales.push_back(iter.first);
354     filter_zerops.push_back(iter.second);
355   }
356
357   std::vector<float> bias_scales;
358   for (int i = 0; i < output_channels; ++i)
359     bias_scales.push_back(filter_quant_params[i].first * input_quant_param.first);
360   std::vector<int32_t> zerop(output_channels, 0);
361
362   Tensor input_tensor =
363     makeInputTensor<DataType::S8>({2, 2, 4, 1}, input_quant_param.first, input_quant_param.second,
364                                   input_data, _memory_manager.get());
365   Tensor filter_tensor = makeInputTensor<DataType::S8>(filter_shape, filter_scales, filter_zerops,
366                                                        0, filter_data, _memory_manager.get());
367   Tensor bias_tensor = makeInputTensor<DataType::S32>({output_channels}, bias_scales, zerop, 0,
368                                                       bias_data, _memory_manager.get());
369   Tensor im2col(DataType::S8, Shape({}), {}, "");
370   Tensor output_tensor =
371     makeOutputTensor(DataType::S8, output_quant_param.first, output_quant_param.second);
372
373   Conv2DParams params{};
374   params.padding = Padding::VALID;
375   params.stride_height = 2;
376   params.stride_width = 2;
377   params.dilation_height_factor = 1;
378   params.dilation_width_factor = 1;
379   params.activation = Activation::NONE;
380
381   Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
382   kernel.configure();
383   _memory_manager->allocate_memory(output_tensor);
384   _memory_manager->allocate_memory(im2col);
385   kernel.execute();
386
387   std::vector<float> ref_output_data{
388     18, 2, 5, // first batch, left
389     18, 2, 5, // first batch, right
390     17, 4, 3, // second batch, left
391     37, 4, 3, // second batch, right
392   };
393   std::vector<int32_t> ref_output_shape{2, 1, 2, 3};
394   EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
395   EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
396 }
397
398 TEST_F(Conv2DTest, SInt16)
399 {
400   Shape input_shape{1, 4, 3, 2};
401   Shape filter_shape{2, 2, 2, 2};
402   Shape bias_shape{2};
403   std::vector<int32_t> ref_output_shape{1, 2, 2, 2};
404
405   std::vector<float> input_data{
406     1,  2,  3,  4,  5,  6,  // row = 0
407     7,  8,  9,  10, 11, 12, // row = 1
408     13, 14, 15, 16, 17, 18, // row = 2
409     19, 20, 21, 22, 23, 24, // row = 3
410   };
411   std::vector<float> filter_data{
412     1,  2,  -3, -4, // out = 0, row = 0
413     -5, 6,  -7, 8,  // out = 1, row = 0
414     4,  -2, 3,  -1, // out = 0, row = 1
415     -8, -6, 7,  5,  // out = 1, row = 1
416   };
417   std::vector<float> bias_data{1, 2};
418   std::vector<float> ref_output_data{
419     11, 16, 7, 20, // row = 0
420     0,  40, 0, 44, // row = 1
421   };
422
423   Tensor input_tensor =
424     makeInputTensor<DataType::S16>(input_shape, 0.25, 0, input_data, _memory_manager.get());
425   Tensor filter_tensor =
426     makeInputTensor<DataType::S16>(filter_shape, 0.2, 0, filter_data, _memory_manager.get());
427   Tensor bias_tensor =
428     makeInputTensor<DataType::S64>(bias_shape, 0.25 * 0.2, 0, bias_data, _memory_manager.get());
429   Tensor im2col(DataType::S16, Shape({}), {}, "");
430   Tensor output_tensor = makeOutputTensor(DataType::S16, 0.5, 0);
431
432   Conv2DParams params{};
433   params.padding = Padding::VALID;
434   params.stride_height = 2;
435   params.stride_width = 1;
436   params.dilation_height_factor = 1;
437   params.dilation_width_factor = 1;
438   params.activation = Activation::RELU;
439
440   Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
441   kernel.configure();
442   _memory_manager->allocate_memory(output_tensor);
443   _memory_manager->allocate_memory(im2col);
444   kernel.execute();
445
446   EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
447   EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
448 }
449
450 TEST_F(Conv2DTest, SInt16_CWQ_weights)
451 {
452   Shape input_shape{1, 2, 2, 2};  // Batch x H x W x C
453   Shape filter_shape{3, 1, 1, 2}; // Out channels x H x W x In Channels
454   Shape bias_shape{3};
455   std::vector<int32_t> ref_output_shape{1, 2, 2, 3};
456
457   std::vector<float> input_data{
458     1, 2, // row = 0, col 0
459     3, 4, // row = 0, col 1
460     5, 6, // row = 1, col 0
461     7, 8, // row = 1, col 1
462   };
463   std::vector<float> filter_data{
464     4, -3, // out = 0
465     1, -3, // out = 1
466     5, -3, // out = 2
467   };
468   std::vector<float> bias_data{1, 10, 5};
469   std::vector<float> ref_output_data{
470     0, 5, 4,  // row 0, col 0
471     1, 1, 8,  // row 0, col 1
472     3, 0, 12, // row 1, col 0
473     5, 0, 16, // row 1, col 1
474   };
475
476   float input_scale = 0.25f;
477   float output_scale = 0.05f;
478   std::vector<float> filter_scales = {0.25f, 0.2f, 0.1f};
479   std::vector<float> bias_scales;
480   for (int i = 0; i < filter_scales.size(); ++i)
481     bias_scales.push_back(filter_scales[i] * input_scale);
482   std::vector<int32_t> zerop = {0, 0, 0};
483
484   Tensor input_tensor =
485     makeInputTensor<DataType::S16>(input_shape, input_scale, 0, input_data, _memory_manager.get());
486   Tensor filter_tensor = makeInputTensor<DataType::S16>(filter_shape, filter_scales, zerop, 0,
487                                                         filter_data, _memory_manager.get());
488   Tensor bias_tensor = makeInputTensor<DataType::S64>(bias_shape, bias_scales, zerop, 0, bias_data,
489                                                       _memory_manager.get());
490   Tensor im2col(DataType::S16, Shape({}), {}, "");
491   Tensor output_tensor = makeOutputTensor(DataType::S16, output_scale, 0);
492
493   Conv2DParams params{};
494   params.padding = Padding::VALID;
495   params.stride_height = 1;
496   params.stride_width = 1;
497   params.dilation_height_factor = 1;
498   params.dilation_width_factor = 1;
499   params.activation = Activation::RELU;
500
501   Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
502   kernel.configure();
503   _memory_manager->allocate_memory(output_tensor);
504   _memory_manager->allocate_memory(im2col);
505   kernel.execute();
506
507   EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
508   EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
509 }
510
511 TEST_F(Conv2DTest, Unsupported_Type_Configure_NEG)
512 {
513   Shape input_shape{1, 4, 3, 2};
514   Shape filter_shape{2, 2, 2, 2};
515   Shape bias_shape{2};
516   std::vector<int32_t> input_data{
517     1,  2,  3,  4,  5,  6,  // row = 0
518     7,  8,  9,  10, 11, 12, // row = 1
519     13, 14, 15, 16, 17, 18, // row = 2
520     19, 20, 21, 22, 23, 24, // row = 3
521   };
522   std::vector<float> filter_data{
523     1,  2,  -3, -4, // out = 0, row = 0
524     -5, 6,  -7, 8,  // out = 1, row = 0
525     4,  -2, 3,  -1, // out = 0, row = 1
526     -8, -6, 7,  5,  // out = 1, row = 1
527   };
528   std::vector<float> bias_data{1, 2};
529   Tensor input_tensor =
530     makeInputTensor<DataType::S32>(input_shape, input_data, _memory_manager.get());
531   Tensor filter_tensor =
532     makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data, _memory_manager.get());
533   Tensor bias_tensor =
534     makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, _memory_manager.get());
535   Tensor im2col(DataType::FLOAT32, Shape({}), {}, "");
536   Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
537
538   Conv2DParams params{};
539   params.padding = Padding::VALID;
540   params.stride_height = 2;
541   params.stride_width = 1;
542   params.dilation_height_factor = 1;
543   params.dilation_width_factor = 1;
544   params.activation = Activation::RELU;
545
546   Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
547   EXPECT_ANY_THROW(kernel.configure());
548 }
549
550 TEST_F(Conv2DTest, Invalid_Bias_Type_NEG)
551 {
552   Shape input_shape{1, 4, 3, 2};
553   Shape filter_shape{2, 2, 2, 2};
554   Shape bias_shape{2};
555   std::vector<float> input_data{
556     1,  2,  3,  4,  5,  6,  // row = 0
557     7,  8,  9,  10, 11, 12, // row = 1
558     13, 14, 15, 16, 17, 18, // row = 2
559     19, 20, 21, 22, 23, 24, // row = 3
560   };
561   std::vector<float> filter_data{
562     1,  2,  -3, -4, // out = 0, row = 0
563     -5, 6,  -7, 8,  // out = 1, row = 0
564     4,  -2, 3,  -1, // out = 0, row = 1
565     -8, -6, 7,  5,  // out = 1, row = 1
566   };
567   std::vector<uint8_t> bias_data{1, 2};
568   Tensor input_tensor =
569     makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
570   Tensor filter_tensor =
571     makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data, _memory_manager.get());
572   Tensor bias_tensor = makeInputTensor<DataType::U8>(bias_shape, bias_data, _memory_manager.get());
573   Tensor im2col(DataType::FLOAT32, Shape({}), {}, "");
574   Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
575
576   Conv2DParams params{};
577   params.padding = Padding::VALID;
578   params.stride_height = 2;
579   params.stride_width = 1;
580   params.dilation_height_factor = 1;
581   params.dilation_width_factor = 1;
582   params.activation = Activation::RELU;
583
584   Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
585   EXPECT_ANY_THROW(kernel.configure());
586 }
587
588 TEST_F(Conv2DTest, Invalid_Bias_Data_NEG)
589 {
590   Shape input_shape{1, 4, 3, 2};
591   Shape filter_shape{2, 2, 2, 2};
592   Shape bias_shape{3};
593   std::vector<float> input_data{
594     1,  2,  3,  4,  5,  6,  // row = 0
595     7,  8,  9,  10, 11, 12, // row = 1
596     13, 14, 15, 16, 17, 18, // row = 2
597     19, 20, 21, 22, 23, 24, // row = 3
598   };
599   std::vector<float> filter_data{
600     1,  2,  -3, -4, // out = 0, row = 0
601     -5, 6,  -7, 8,  // out = 1, row = 0
602     4,  -2, 3,  -1, // out = 0, row = 1
603     -8, -6, 7,  5,  // out = 1, row = 1
604   };
605   std::vector<float> bias_data{1, 2, 3};
606   Tensor input_tensor =
607     makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
608   Tensor filter_tensor =
609     makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data, _memory_manager.get());
610   Tensor bias_tensor =
611     makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, _memory_manager.get());
612   Tensor im2col(DataType::FLOAT32, Shape({}), {}, "");
613   Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
614
615   Conv2DParams params{};
616   params.padding = Padding::VALID;
617   params.stride_height = 2;
618   params.stride_width = 1;
619   params.dilation_height_factor = 1;
620   params.dilation_width_factor = 1;
621   params.activation = Activation::RELU;
622
623   Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
624   EXPECT_ANY_THROW(kernel.configure());
625 }
626
627 TEST_F(Conv2DTest, Invalid_Input_Shape_NEG)
628 {
629   Shape input_shape{1, 4, 6, 1};
630   Shape filter_shape{2, 2, 2, 2};
631   Shape bias_shape{2};
632   std::vector<float> input_data{
633     1,  2,  3,  4,  5,  6,  // row = 0
634     7,  8,  9,  10, 11, 12, // row = 1
635     13, 14, 15, 16, 17, 18, // row = 2
636     19, 20, 21, 22, 23, 24, // row = 3
637   };
638   std::vector<float> filter_data{
639     1,  2,  -3, -4, // out = 0, row = 0
640     -5, 6,  -7, 8,  // out = 1, row = 0
641     4,  -2, 3,  -1, // out = 0, row = 1
642     -8, -6, 7,  5,  // out = 1, row = 1
643   };
644   std::vector<float> bias_data{1, 2};
645   Tensor input_tensor =
646     makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
647   Tensor filter_tensor =
648     makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data, _memory_manager.get());
649   Tensor bias_tensor =
650     makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, _memory_manager.get());
651   Tensor im2col(DataType::FLOAT32, Shape({}), {}, "");
652   Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
653
654   Conv2DParams params{};
655   params.padding = Padding::VALID;
656   params.stride_height = 2;
657   params.stride_width = 1;
658   params.dilation_height_factor = 1;
659   params.dilation_width_factor = 1;
660   params.activation = Activation::RELU;
661
662   Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
663   EXPECT_ANY_THROW(kernel.configure());
664 }
665
666 TEST_F(Conv2DTest, Invalid_fused_act_tanh_NEG)
667 {
668   Shape input_shape{1, 4, 3, 2};
669   Shape filter_shape{2, 2, 2, 2};
670   Shape bias_shape{2};
671   std::vector<float> input_data{
672     1,  2,  3,  4,  5,  6,  // row = 0
673     7,  8,  9,  10, 11, 12, // row = 1
674     13, 14, 15, 16, 17, 18, // row = 2
675     19, 20, 21, 22, 23, 24, // row = 3
676   };
677   std::vector<float> filter_data{
678     1,  2,  -3, -4, // out = 0, row = 0
679     -5, 6,  -7, 8,  // out = 1, row = 0
680     4,  -2, 3,  -1, // out = 0, row = 1
681     -8, -6, 7,  5,  // out = 1, row = 1
682   };
683   std::vector<float> bias_data{1, 2};
684   Tensor input_tensor =
685     makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
686   Tensor filter_tensor =
687     makeInputTensor<DataType::FLOAT32>(filter_shape, filter_data, _memory_manager.get());
688   Tensor bias_tensor =
689     makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, _memory_manager.get());
690   Tensor im2col(DataType::FLOAT32, Shape({}), {}, "");
691   Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
692
693   Conv2DParams params{};
694   params.padding = Padding::VALID;
695   params.stride_height = 2;
696   params.stride_width = 1;
697   params.dilation_height_factor = 1;
698   params.dilation_width_factor = 1;
699   params.activation = Activation::TANH;
700
701   Conv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &im2col, params);
702   EXPECT_ANY_THROW(kernel.configure());
703 }
704
705 } // namespace
706 } // namespace kernels
707 } // namespace luci_interpreter