• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #include "tensorflow/lite/c/builtin_op_data.h"
17 #include "tensorflow/lite/c/common.h"
18 #include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
19 #include "tensorflow/lite/micro/kernels/kernel_runner.h"
20 #include "tensorflow/lite/micro/test_helpers.h"
21 #include "tensorflow/lite/micro/testing/micro_test.h"
22 
23 namespace tflite {
24 namespace testing {
25 namespace {
26 
27 #if !defined(XTENSA)  // Needed to avoid build errors from unused variables.
28 constexpr int kMaxFilterChannels = 64;
29 constexpr int kMaxBiasChannels = 64;
30 #endif  // !defined(XTENSA)
31 
32 // Index of the output tensor in context->tensors, specific to
33 // DepthwiseConv.
34 constexpr int kOutputTensorIndex = 3;
35 
36 // Creates a DepthwiseConv opeerator, calls it with the provided input tensors
37 // and some defaults parameters, and compares the output with
38 // expected_output_data.
39 //
40 // The tensors parameter contains both the input tensors as well as a
41 // preallocated output tensor into which the output is stored.
42 template <typename T>
ValidateDepthwiseConvGoldens(const T * expected_output_data,int output_length,TfLiteDepthwiseConvParams * conv_params,float tolerance,int tensors_size,TfLiteTensor * tensors)43 TfLiteStatus ValidateDepthwiseConvGoldens(
44     const T* expected_output_data, int output_length,
45     TfLiteDepthwiseConvParams* conv_params, float tolerance, int tensors_size,
46     TfLiteTensor* tensors) {
47   int inputs_array_data[] = {3, 0, 1, 2};
48   TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
49   int outputs_array_data[] = {1, 3};
50   TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
51 
52   const TfLiteRegistration registration = Register_DEPTHWISE_CONV_2D();
53   micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array,
54                              outputs_array,
55                              reinterpret_cast<void*>(conv_params));
56 
57   int input_depth = tensors[0].dims->data[3];
58   int output_depth = tensors[1].dims->data[3];
59   int depth_mul = output_depth / input_depth;
60 
61   conv_params->padding = kTfLitePaddingValid;
62   conv_params->stride_height = 1;
63   conv_params->stride_width = 1;
64   conv_params->depth_multiplier = depth_mul;
65 
66   const char* init_data = reinterpret_cast<const char*>(conv_params);
67 
68   // TODO(b/154240825): Use a test macro here which fails and returns.
69   TfLiteStatus status = runner.InitAndPrepare(init_data);
70   if (status != kTfLiteOk) {
71     return status;
72   }
73   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
74 
75   const T* output_data = tflite::GetTensorData<T>(&tensors[kOutputTensorIndex]);
76   for (int i = 0; i < output_length; ++i) {
77     TF_LITE_MICRO_EXPECT_NEAR(expected_output_data[i], output_data[i],
78                               tolerance);
79   }
80   return kTfLiteOk;
81 }
82 
83 #if !defined(XTENSA)  // Needed to avoid build errors from unsused functions.
TestDepthwiseConvFloat(const int * input_dims_data,const float * input_data,const int * filter_dims_data,const float * filter_data,const int * bias_dims_data,const float * bias_data,const float * expected_output_data,const int * output_dims_data,TfLiteDepthwiseConvParams * conv_params,float * output_data)84 void TestDepthwiseConvFloat(const int* input_dims_data, const float* input_data,
85                             const int* filter_dims_data,
86                             const float* filter_data, const int* bias_dims_data,
87                             const float* bias_data,
88                             const float* expected_output_data,
89                             const int* output_dims_data,
90                             TfLiteDepthwiseConvParams* conv_params,
91                             float* output_data) {
92   TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data);
93   TfLiteIntArray* filter_dims = IntArrayFromInts(filter_dims_data);
94   TfLiteIntArray* bias_dims = IntArrayFromInts(bias_dims_data);
95   TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
96   const int output_dims_count = ElementCount(*output_dims);
97 
98   constexpr int inputs_size = 3;
99   constexpr int outputs_size = 1;
100   constexpr int tensors_size = inputs_size + outputs_size;
101   TfLiteTensor tensors[tensors_size] = {
102       CreateTensor(input_data, input_dims),
103       CreateTensor(filter_data, filter_dims),
104       CreateTensor(bias_data, bias_dims),
105       CreateTensor(output_data, output_dims),
106   };
107 
108   ValidateDepthwiseConvGoldens(expected_output_data, output_dims_count,
109                                conv_params, 1e-5, tensors_size, tensors);
110 }
111 
TestDepthwiseConvQuantizedPerLayer(const int * input_dims_data,const float * input_data,uint8_t * input_quantized,float input_scale,int input_zero_point,const int * filter_dims_data,const float * filter_data,uint8_t * filter_quantized,float filter_scale,int filter_zero_point,const int * bias_dims_data,const float * bias_data,int32_t * bias_quantized,const float * golden,uint8_t * golden_quantized,const int * output_dims_data,uint8_t * output_data,float output_scale,int output_zero_point,TfLiteDepthwiseConvParams * conv_params)112 void TestDepthwiseConvQuantizedPerLayer(
113     const int* input_dims_data, const float* input_data,
114     uint8_t* input_quantized, float input_scale, int input_zero_point,
115     const int* filter_dims_data, const float* filter_data,
116     uint8_t* filter_quantized, float filter_scale, int filter_zero_point,
117     const int* bias_dims_data, const float* bias_data, int32_t* bias_quantized,
118     const float* golden, uint8_t* golden_quantized, const int* output_dims_data,
119     uint8_t* output_data, float output_scale, int output_zero_point,
120     TfLiteDepthwiseConvParams* conv_params) {
121   TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data);
122   TfLiteIntArray* filter_dims = IntArrayFromInts(filter_dims_data);
123   TfLiteIntArray* bias_dims = IntArrayFromInts(bias_dims_data);
124   TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
125   const int output_dims_count = ElementCount(*output_dims);
126 
127   constexpr int inputs_size = 3;
128   constexpr int outputs_size = 1;
129   constexpr int tensors_size = inputs_size + outputs_size;
130   TfLiteTensor tensors[tensors_size] = {
131       tflite::testing::CreateQuantizedTensor(input_data, input_quantized,
132                                              input_dims, input_scale,
133                                              input_zero_point),
134       tflite::testing::CreateQuantizedTensor(filter_data, filter_quantized,
135                                              filter_dims, filter_scale,
136                                              filter_zero_point),
137       tflite::testing::CreateQuantizedBiasTensor(
138           bias_data, bias_quantized, bias_dims, input_scale, filter_scale),
139       tflite::testing::CreateQuantizedTensor(output_data, output_dims,
140                                              output_scale, output_zero_point),
141   };
142 
143   // TODO(njeff): Affine Quantization Params should be set on tensor creation.
144   float filter_scales[] = {1, filter_scale};
145   int filter_zero_points[] = {1, 128};
146   TfLiteAffineQuantization filter_quant = {FloatArrayFromFloats(filter_scales),
147                                            IntArrayFromInts(filter_zero_points),
148                                            0};
149   tensors[1].quantization = {kTfLiteAffineQuantization, &filter_quant};
150 
151   float bias_scales[] = {1, filter_scale * input_scale};
152   int bias_zero_points[] = {1, 128};
153   TfLiteAffineQuantization bias_quant = {FloatArrayFromFloats(bias_scales),
154                                          IntArrayFromInts(bias_zero_points), 0};
155   tensors[2].quantization = {kTfLiteAffineQuantization, &bias_quant};
156 
157   Quantize(golden, golden_quantized, output_dims_count, output_scale,
158            output_zero_point);
159   ValidateDepthwiseConvGoldens(golden_quantized, output_dims_count, conv_params,
160                                1.0, tensors_size, tensors);
161 }
162 
TestDepthwiseConvQuantizedPerChannel(const int * input_dims_data,const float * input_data,int8_t * input_quantized,float input_scale,int input_zero_point,const int * filter_dims_data,const float * filter_data,int8_t * filter_data_quantized,const int * bias_dims_data,const float * bias_data,int32_t * bias_data_quantized,const int * output_dims_data,const float * expected_output_data,int8_t * expected_output_data_quantized,int8_t * output_data,float output_scale,int output_zero_point,TfLiteDepthwiseConvParams * conv_params)163 void TestDepthwiseConvQuantizedPerChannel(
164     const int* input_dims_data, const float* input_data,
165     int8_t* input_quantized, float input_scale, int input_zero_point,
166     const int* filter_dims_data, const float* filter_data,
167     int8_t* filter_data_quantized, const int* bias_dims_data,
168     const float* bias_data, int32_t* bias_data_quantized,
169     const int* output_dims_data, const float* expected_output_data,
170     int8_t* expected_output_data_quantized, int8_t* output_data,
171     float output_scale, int output_zero_point,
172     TfLiteDepthwiseConvParams* conv_params) {
173   TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data);
174   TfLiteIntArray* filter_dims = IntArrayFromInts(filter_dims_data);
175   TfLiteIntArray* bias_dims = IntArrayFromInts(bias_dims_data);
176   TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
177   const int output_dims_count = ElementCount(*output_dims);
178 
179   int filter_zero_points[kMaxFilterChannels];
180   float filter_scales[kMaxFilterChannels];
181   int bias_zero_points[kMaxBiasChannels];
182   float bias_scales[kMaxBiasChannels];
183   TfLiteAffineQuantization filter_quant;
184   TfLiteAffineQuantization bias_quant;
185   TfLiteTensor input_tensor = CreateQuantizedTensor(
186       input_data, input_quantized, input_dims, input_scale, input_zero_point);
187   TfLiteTensor filter_tensor = CreateSymmetricPerChannelQuantizedTensor(
188       filter_data, filter_data_quantized, filter_dims, filter_scales,
189       filter_zero_points, &filter_quant, 3 /* quantized dimension */
190   );
191   TfLiteTensor bias_tensor = CreatePerChannelQuantizedBiasTensor(
192       bias_data, bias_data_quantized, bias_dims, input_scale, &filter_scales[1],
193       bias_scales, bias_zero_points, &bias_quant, 3 /* quantized dimension */
194   );
195   TfLiteTensor output_tensor = CreateQuantizedTensor(
196       output_data, output_dims, output_scale, input_zero_point);
197 
198   // TODO(njeff): Affine Quantization Params should be set on tensor creation.
199   float input_scales[] = {1, input_scale};
200   int input_zero_points[] = {1, input_zero_point};
201   TfLiteAffineQuantization input_quant = {FloatArrayFromFloats(input_scales),
202                                           IntArrayFromInts(input_zero_points),
203                                           0};
204   input_tensor.quantization = {kTfLiteAffineQuantization, &input_quant};
205 
206   float output_scales[] = {1, output_scale};
207   int output_zero_points[] = {1, output_zero_point};
208   TfLiteAffineQuantization output_quant = {FloatArrayFromFloats(output_scales),
209                                            IntArrayFromInts(output_zero_points),
210                                            0};
211   output_tensor.quantization = {kTfLiteAffineQuantization, &output_quant};
212 
213   constexpr int inputs_size = 3;
214   constexpr int outputs_size = 1;
215   constexpr int tensors_size = inputs_size + outputs_size;
216   TfLiteTensor tensors[tensors_size] = {
217       input_tensor,
218       filter_tensor,
219       bias_tensor,
220       output_tensor,
221   };
222 
223   Quantize(expected_output_data, expected_output_data_quantized,
224            output_dims_count, output_scale, output_zero_point);
225 
226   TF_LITE_MICRO_EXPECT_EQ(
227       kTfLiteOk, ValidateDepthwiseConvGoldens(expected_output_data_quantized,
228                                               output_dims_count, conv_params,
229                                               1.0, tensors_size, tensors));
230 }
231 
232 #endif  // !defined(XTENSA)
233 
234 }  // namespace
235 }  // namespace testing
236 }  // namespace tflite
237 
238 TF_LITE_MICRO_TESTS_BEGIN
239 
240 #if !defined(XTENSA)  // TODO(b/170322965): xtensa kernels are less general than
241                       // reference kernels and we ifdef out test cases that are
242                       // currently known to fail.
TF_LITE_MICRO_TEST(SimpleTest)243 TF_LITE_MICRO_TEST(SimpleTest) {
244   const int input_shape[] = {4, 1, 3, 2, 2};
245   const float input_values[] = {1, 2, 7, 8, 3, 4, 9, 10, 5, 6, 11, 12};
246   const int filter_shape[] = {4, 1, 2, 2, 4};
247   const float filter_values[] = {1, 2, 3, 4, -9, 10,  -11, 12,
248                                  5, 6, 7, 8, 13, -14, 15,  -16};
249   const int bias_shape[] = {4, 1, 1, 1, 4};
250   const float bias_values[] = {1, 2, 3, 4};
251   const float golden[] = {
252       71, -34, 99, -20, 91, -26, 127, -4,
253   };
254   const int output_shape[] = {4, 1, 2, 1, 4};
255   const int output_dims_count = 8;
256   float output_data[output_dims_count];
257 
258   TfLiteDepthwiseConvParams conv_params;
259   conv_params.activation = kTfLiteActNone;
260   conv_params.dilation_width_factor = 1;
261   conv_params.dilation_height_factor = 1;
262 
263   tflite::testing::TestDepthwiseConvFloat(
264       input_shape, input_values, filter_shape, filter_values, bias_shape,
265       bias_values, golden, output_shape, &conv_params, output_data);
266 }
267 
TF_LITE_MICRO_TEST(SimpleTestQuantized)268 TF_LITE_MICRO_TEST(SimpleTestQuantized) {
269   const int input_elements = 12;
270   const int input_shape[] = {4, 1, 3, 2, 2};
271   const float input_values[] = {1, 2, 7, 8, 3, 4, 9, 10, 5, 6, 11, 12};
272   const int filter_elements = 16;
273   const int filter_shape[] = {4, 1, 2, 2, 4};
274   const float filter_values[] = {1, 2, 3, 4, -9, 10,  -11, 12,
275                                  5, 6, 7, 8, 13, -14, 15,  -16};
276   const int bias_elements = 4;
277   const int bias_shape[] = {4, 1, 1, 1, 4};
278   const int output_elements = 8;
279   const float bias_values[] = {1, 2, 3, 4};
280   const float golden[] = {
281       71, -34, 99, -20, 91, -26, 127, -4,
282   };
283   const int output_shape[] = {4, 1, 2, 1, 4};
284 
285   const float input_scale = 0.5f;
286   const int input_zero_point = 128;
287   const float filter_scale = 0.5f;
288   const int filter_zero_point = 128;
289   const float output_scale = 1.0f;
290   const int output_zero_point = 128;
291 
292   uint8_t input_quantized[input_elements];
293   uint8_t filter_quantized[filter_elements];
294   int32_t bias_quantized[bias_elements];
295   uint8_t golden_quantized[output_elements];
296   uint8_t output_data[output_elements];
297 
298   TfLiteDepthwiseConvParams conv_params;
299   conv_params.activation = kTfLiteActNone;
300   conv_params.dilation_width_factor = 1;
301   conv_params.dilation_height_factor = 1;
302 
303   tflite::testing::TestDepthwiseConvQuantizedPerLayer(
304       input_shape, input_values, input_quantized, input_scale, input_zero_point,
305       filter_shape, filter_values, filter_quantized, filter_scale,
306       filter_zero_point, bias_shape, bias_values, bias_quantized, golden,
307       golden_quantized, output_shape, output_data, output_scale,
308       output_zero_point, &conv_params);
309 }
310 
TF_LITE_MICRO_TEST(SimpleTestDilatedQuantized)311 TF_LITE_MICRO_TEST(SimpleTestDilatedQuantized) {
312   const int input_elements = 48;
313   const int input_shape[] = {4, 1, 4, 6, 2};
314   const float input_values[] = {1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,   // h = 0
315                                 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4,   // h = 1
316                                 1, 2, 3, 4, 5, 6, 2, 6, 2, 4, 4, 2,   // h = 2
317                                 3, 2, 6, 5, 1, 4, 1, 2, 1, 4, 6, 3};  // h = 3
318   const int filter_elements = 16;
319   const int filter_shape[] = {4, 1, 2, 2, 4};
320   const float filter_values[] = {1, 2, 3, 4, -9, 10,  -11, 12,
321                                  5, 6, 7, 8, 13, -14, 15,  -16};
322   const int bias_elements = 4;
323   const int bias_shape[] = {4, 1, 1, 1, 4};
324   const int output_elements = 24;
325   const float bias_values[] = {1, 2, 3, 4};
326   const float golden[] = {
327       15, 2,  88, -48, 25, 14, 72, 0,  61, -2,  56, 48,  // h = 0
328       -4, 52, 12, 48,  11, 70, 63, 40, 51, -30, 41, 48   // h = 1
329   };
330   const int output_shape[] = {4, 1, 2, 3, 4};
331 
332   const float input_scale = 0.5f;
333   const int input_zero_point = 128;
334   const float filter_scale = 0.5f;
335   const int filter_zero_point = 128;
336   const float output_scale = 1.0f;
337   const int output_zero_point = 128;
338 
339   uint8_t input_quantized[input_elements];
340   uint8_t filter_quantized[filter_elements];
341   int32_t bias_quantized[bias_elements];
342   uint8_t golden_quantized[output_elements];
343   uint8_t output_data[output_elements];
344 
345   TfLiteDepthwiseConvParams conv_params;
346   conv_params.activation = kTfLiteActNone;
347   conv_params.dilation_width_factor = 3;
348   conv_params.dilation_height_factor = 2;
349 
350   tflite::testing::TestDepthwiseConvQuantizedPerLayer(
351       input_shape, input_values, input_quantized, input_scale, input_zero_point,
352       filter_shape, filter_values, filter_quantized, filter_scale,
353       filter_zero_point, bias_shape, bias_values, bias_quantized, golden,
354       golden_quantized, output_shape, output_data, output_scale,
355       output_zero_point, &conv_params);
356 }
357 
TF_LITE_MICRO_TEST(SimpleTestRelu)358 TF_LITE_MICRO_TEST(SimpleTestRelu) {
359   const int input_shape[] = {4, 1, 3, 2, 2};
360   const float input_values[] = {1, 2, 7, 8, 3, 4, 9, 10, 5, 6, 11, 12};
361   const int filter_shape[] = {4, 1, 2, 2, 4};
362   const float filter_values[] = {1, 2, 3, 4, -9, 10,  -11, 12,
363                                  5, 6, 7, 8, 13, -14, 15,  -16};
364   const int bias_shape[] = {4, 1, 1, 1, 4};
365   const float bias_values[] = {1, 2, 3, 4};
366   const int output_shape[] = {4, 1, 2, 1, 4};
367   const int output_dims_count = 8;
368   const float golden_relu[] = {71, 0, 99, 0, 91, 0, 127, 0};
369   float output_data[output_dims_count];
370 
371   TfLiteDepthwiseConvParams conv_params;
372   conv_params.activation = kTfLiteActRelu;
373   conv_params.dilation_width_factor = 1;
374   conv_params.dilation_height_factor = 1;
375 
376   tflite::testing::TestDepthwiseConvFloat(
377       input_shape, input_values, filter_shape, filter_values, bias_shape,
378       bias_values, golden_relu, output_shape, &conv_params, output_data);
379 }
380 
TF_LITE_MICRO_TEST(SimpleTestReluQuantized)381 TF_LITE_MICRO_TEST(SimpleTestReluQuantized) {
382   const int input_elements = 12;
383   const int input_shape[] = {4, 1, 3, 2, 2};
384   const float input_values[] = {1, 2, 7, 8, 3, 4, 9, 10, 5, 6, 11, 12};
385   const int filter_elements = 16;
386   const int filter_shape[] = {4, 1, 2, 2, 4};
387   const float filter_values[] = {1, 2, 3, 4, -9, 10,  -11, 12,
388                                  5, 6, 7, 8, 13, -14, 15,  -16};
389   const int bias_elements = 4;
390   const int bias_shape[] = {4, 1, 1, 1, 4};
391   const int output_elements = 8;
392   const float bias_values[] = {1, 2, 3, 4};
393   const int output_shape[] = {4, 1, 2, 1, 4};
394   const float golden_relu[] = {71, 0, 99, 0, 91, 0, 127, 0};
395 
396   const float input_scale = 0.5f;
397   const int input_zero_point = 128;
398   const float filter_scale = 0.5f;
399   const int filter_zero_point = 128;
400   const float output_scale = 1.0f;
401   const int output_zero_point = 128;
402 
403   uint8_t input_quantized[input_elements];
404   uint8_t filter_quantized[filter_elements];
405   int32_t bias_quantized[bias_elements];
406   uint8_t golden_quantized[output_elements];
407   uint8_t output_data[output_elements];
408 
409   TfLiteDepthwiseConvParams conv_params;
410   conv_params.activation = kTfLiteActRelu;
411   conv_params.dilation_width_factor = 1;
412   conv_params.dilation_height_factor = 1;
413 
414   tflite::testing::TestDepthwiseConvQuantizedPerLayer(
415       input_shape, input_values, input_quantized, input_scale, input_zero_point,
416       filter_shape, filter_values, filter_quantized, filter_scale,
417       filter_zero_point, bias_shape, bias_values, bias_quantized, golden_relu,
418       golden_quantized, output_shape, output_data, output_scale,
419       output_zero_point, &conv_params);
420 }
421 
TF_LITE_MICRO_TEST(SimpleTestQuantizedOptimizedFilterWidth)422 TF_LITE_MICRO_TEST(SimpleTestQuantizedOptimizedFilterWidth) {
423   const int input_elements = 12;
424   const float input_values[] = {1, 2, 7, 8, 3, 4, 9, 10, 5, 6, 11, 12};
425   const int filter_elements = 16;
426   const float filter_values[] = {1, 2, 3, 4, -9, 10,  -11, 12,
427                                  5, 6, 7, 8, 13, -14, 15,  -16};
428   const int bias_elements = 4;
429   const float bias_values[] = {1, 2, 3, 4};
430   const int output_dims_count = 9;
431   const int input_shape[] = {4, 1, 1, 9, 1};
432   const int filter_shape[] = {4, 2, 1, 8, 1};
433   const int bias_shape[] = {1, 1};
434   const float goldens[] = {
435       92, 56, 12, 22, 33, 72, 44, 20, 5,
436   };
437   const int output_shape[] = {4, 1, 1, 9, 1};
438 
439   const float input_scale = 1.0f;
440   const int input_zero_point = 128;
441   const float filter_scale = 0.5f;
442   const int filter_zero_point = 128;
443   const float output_scale = 1.0f;
444   const int output_zero_point = 128;
445 
446   uint8_t input_quantized[input_elements];
447   uint8_t filter_quantized[filter_elements];
448   int32_t bias_quantized[bias_elements];
449   uint8_t golden_quantized[output_dims_count];
450   uint8_t output_data[output_dims_count];
451 
452   TfLiteDepthwiseConvParams conv_params;
453   conv_params.activation = kTfLiteActNone;
454   conv_params.dilation_width_factor = 1;
455   conv_params.dilation_height_factor = 1;
456 
457   tflite::testing::TestDepthwiseConvQuantizedPerLayer(
458       input_shape, input_values, input_quantized, input_scale, input_zero_point,
459       filter_shape, filter_values, filter_quantized, filter_scale,
460       filter_zero_point, bias_shape, bias_values, bias_quantized, goldens,
461       golden_quantized, output_shape, output_data, output_scale,
462       output_zero_point, &conv_params);
463 }
464 
TF_LITE_MICRO_TEST(SimpleTestQuantizedPerChannel)465 TF_LITE_MICRO_TEST(SimpleTestQuantizedPerChannel) {
466   const int input_elements = 12;
467   const int input_shape[] = {4, 1, 3, 2, 2};
468   const float input_values[] = {1, 2, 7, 8, 3, 4, 9, 10, 5, 6, 11, 12};
469   const int filter_elements = 16;
470   const int filter_shape[] = {4, 1, 2, 2, 4};
471   const float filter_values[] = {1, 2, 3, 4, -9, 10,  -11, 12,
472                                  5, 6, 7, 8, 13, -14, 15,  -16};
473   const int bias_elements = 4;
474   const int bias_shape[] = {4, 1, 1, 1, 4};
475   const int output_elements = 8;
476   const float bias_values[] = {1, 2, 3, 4};
477   const float golden[] = {
478       71, -34, 99, -20, 91, -26, 127, -4,
479   };
480   const int output_shape[] = {4, 1, 2, 1, 4};
481   const int output_dims_count = 8;
482   int8_t output_data[output_dims_count];
483 
484   const float input_scale = 0.5;
485   const float output_scale = 1.0f;
486   const int input_zero_point = 0;
487   const int output_zero_point = 0;
488 
489   int8_t input_quantized[input_elements];
490   int8_t filter_quantized[filter_elements];
491   int32_t bias_quantized[bias_elements];
492   int8_t golden_quantized[output_elements];
493 
494   TfLiteDepthwiseConvParams conv_params;
495   conv_params.activation = kTfLiteActNone;
496   conv_params.dilation_width_factor = 1;
497   conv_params.dilation_height_factor = 1;
498 
499   tflite::testing::TestDepthwiseConvQuantizedPerChannel(
500       input_shape, input_values, input_quantized, input_scale, input_zero_point,
501       filter_shape, filter_values, filter_quantized, bias_shape, bias_values,
502       bias_quantized, output_shape, golden, golden_quantized, output_data,
503       output_scale, output_zero_point, &conv_params);
504 }
505 
TF_LITE_MICRO_TEST(SimpleTestQuantizedPerChannelDepthMultiplier1)506 TF_LITE_MICRO_TEST(SimpleTestQuantizedPerChannelDepthMultiplier1) {
507   const int input_elements = 12;
508   const int input_shape[] = {4, 1, 3, 2, 2};
509   const float input_values[] = {1, 2, 7, 8, 3, 4, 9, 10, 5, 6, 11, 12};
510   const int filter_elements = 8;
511   const int filter_shape[] = {4, 1, 2, 2, 2};
512   const float filter_values[] = {1, 2, 3, 4, -9, 10, -11, 12};
513   const int bias_elements = 2;
514   const int bias_shape[] = {4, 1, 1, 1, 2};
515   const int output_elements = 4;
516   const float bias_values[] = {1, 2};
517   const float golden[] = {
518       -103,
519       127,
520       -128,
521       127,
522   };
523   const int output_shape[] = {4, 1, 2, 1, 2};
524   const int output_dims_count = 4;
525   int8_t output_data[output_dims_count];
526 
527   const float input_scale = 1.0f;
528   const float output_scale = 1.0f;
529   const int input_zero_point = 0;
530   const int output_zero_point = 0;
531 
532   int8_t input_quantized[input_elements];
533   int8_t filter_quantized[filter_elements];
534   int32_t bias_quantized[bias_elements];
535   int8_t golden_quantized[output_elements];
536 
537   TfLiteDepthwiseConvParams conv_params;
538   conv_params.activation = kTfLiteActNone;
539   conv_params.dilation_width_factor = 1;
540   conv_params.dilation_height_factor = 1;
541 
542   tflite::testing::TestDepthwiseConvQuantizedPerChannel(
543       input_shape, input_values, input_quantized, input_scale, input_zero_point,
544       filter_shape, filter_values, filter_quantized, bias_shape, bias_values,
545       bias_quantized, output_shape, golden, golden_quantized, output_data,
546       output_scale, output_zero_point, &conv_params);
547 }
548 
TF_LITE_MICRO_TEST(TestQuantizedPerChannelDepthMultiplier1Relu6)549 TF_LITE_MICRO_TEST(TestQuantizedPerChannelDepthMultiplier1Relu6) {
550   const int input_elements = 24;
551   const int input_shape[] = {4, 1, 3, 2, 4};
552   const float input_values[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
553                                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
554   const int filter_elements = 16;
555   const int filter_shape[] = {4, 1, 2, 2, 4};
556   const float filter_values[] = {0,  1, 8,   -2, -1, 2, -10, 0,
557                                  -1, 3, -18, 0,  0,  4, 20,  -3};
558   const int bias_elements = 4;
559   const int bias_shape[] = {4, 1, 1, 1, 4};
560   const int output_elements = 8;
561   const float bias_values[] = {1, 2, 3, 4};
562   const float golden[] = {
563       0, 6, 3, 0, 0, 6, 3, 0,
564   };
565   const int output_shape[] = {4, 1, 2, 1, 4};
566   int8_t output_data[output_elements];
567 
568   const float input_scale = 0.023529f;
569   const float output_scale = 0.023529f;
570   const int input_zero_point = -128;
571   const int output_zero_point = -128;
572 
573   int8_t input_quantized[input_elements];
574   int8_t filter_quantized[filter_elements];
575   int32_t bias_quantized[bias_elements];
576   int8_t golden_quantized[output_elements];
577 
578   TfLiteDepthwiseConvParams conv_params;
579   conv_params.activation = kTfLiteActRelu6;
580   conv_params.dilation_width_factor = 1;
581   conv_params.dilation_height_factor = 1;
582 
583   tflite::testing::TestDepthwiseConvQuantizedPerChannel(
584       input_shape, input_values, input_quantized, input_scale, input_zero_point,
585       filter_shape, filter_values, filter_quantized, bias_shape, bias_values,
586       bias_quantized, output_shape, golden, golden_quantized, output_data,
587       output_scale, output_zero_point, &conv_params);
588 }
589 
TF_LITE_MICRO_TEST(SimpleTestDilatedQuantizedPerChannel)590 TF_LITE_MICRO_TEST(SimpleTestDilatedQuantizedPerChannel) {
591   const int input_elements = 48;
592   const int input_shape[] = {4, 1, 4, 6, 2};
593   const float input_values[] = {1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,   // h = 0
594                                 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4,   // h = 1
595                                 1, 2, 3, 4, 5, 6, 2, 6, 2, 4, 4, 2,   // h = 2
596                                 3, 2, 6, 5, 1, 4, 1, 2, 1, 4, 6, 3};  // h = 3
597   const int filter_elements = 16;
598   const int filter_shape[] = {4, 1, 2, 2, 4};
599   const float filter_values[] = {1, 2, 3, 4, -9, 10,  -11, 12,
600                                  5, 6, 7, 8, 13, -14, 15,  -16};
601   const int bias_elements = 4;
602   const int bias_shape[] = {4, 1, 1, 1, 4};
603   const int output_elements = 24;
604   const float bias_values[] = {1, 2, 3, 4};
605   const float golden[] = {
606       15, 2,  88, -48, 25, 14, 72, 0,  61, -2,  56, 48,  // h = 0
607       -4, 52, 12, 48,  11, 70, 63, 40, 51, -30, 41, 48   // h = 1
608   };
609   const int output_shape[] = {4, 1, 2, 3, 4};
610   int8_t output_data[output_elements];
611 
612   const float input_scale = 0.5;
613   const float output_scale = 1.0f;
614   const int input_zero_point = 0;
615   const int output_zero_point = 0;
616 
617   int8_t input_quantized[input_elements];
618   int8_t filter_quantized[filter_elements];
619   int32_t bias_quantized[bias_elements];
620   int8_t golden_quantized[output_elements];
621 
622   TfLiteDepthwiseConvParams conv_params;
623   conv_params.activation = kTfLiteActNone;
624   conv_params.dilation_width_factor = 3;
625   conv_params.dilation_height_factor = 2;
626 
627   tflite::testing::TestDepthwiseConvQuantizedPerChannel(
628       input_shape, input_values, input_quantized, input_scale, input_zero_point,
629       filter_shape, filter_values, filter_quantized, bias_shape, bias_values,
630       bias_quantized, output_shape, golden, golden_quantized, output_data,
631       output_scale, output_zero_point, &conv_params);
632 }
633 
TF_LITE_MICRO_TEST(TestQuantizedPerChannelCompareWithFloat)634 TF_LITE_MICRO_TEST(TestQuantizedPerChannelCompareWithFloat) {
635   const int input_dims[] = {4, 1, 2, 3, 2};
636   const float input_data[] = {3, 2, 1, -1, -2, -3, 4, 3, 2, -2, -3, -4};
637   const int filter_dims[] = {4, 1, 2, 2, 4};
638   const float filter_data[] = {1, 2, 3, 4, 3, 4, 5, 6, 7, 8, 5, 6, 3, 4, 1, 2};
639   const int bias_dims[] = {4, 1, 1, 1, 4};
640   const float bias_data[] = {3, -2, 4, 6};
641   const int output_dims[] = {4, 1, 1, 2, 4};
642   const float golden[] = {43, 48, 18, 22, 3, -4, -28, -36};
643 
644   const int input_size = 12;
645   const int filter_size = 16;
646   const int output_size = 8;
647   const int bias_size = 4;
648   int8_t input_quantized[input_size];
649   int8_t filter_quantized[filter_size];
650   int32_t bias_quantized[bias_size];
651   int8_t golden_quantized[output_size];
652   int8_t output_data[output_size];
653   float output_float[output_size];
654 
655   const float input_scale = 0.5;
656   const float output_scale = 1.0;
657   const int input_zero_point = 0;
658   const int output_zero_point = 0;
659 
660   TfLiteDepthwiseConvParams conv_params;
661   conv_params.activation = kTfLiteActNone;
662   conv_params.dilation_width_factor = 1;
663   conv_params.dilation_height_factor = 1;
664 
665   tflite::testing::TestDepthwiseConvQuantizedPerChannel(
666       input_dims, input_data, input_quantized, input_scale, input_zero_point,
667       filter_dims, filter_data, filter_quantized, bias_dims, bias_data,
668       bias_quantized, output_dims, golden, golden_quantized, output_data,
669       output_scale, output_zero_point, &conv_params);
670 
671   tflite::testing::TestDepthwiseConvFloat(
672       input_dims, input_data, filter_dims, filter_data, bias_dims, bias_data,
673       golden, output_dims, &conv_params, output_float);
674 }
675 
TF_LITE_MICRO_TEST(PerChannelBroadcastQuantizationParams)676 TF_LITE_MICRO_TEST(PerChannelBroadcastQuantizationParams) {
677   const float input_scale = 1.0f;
678   const float filter_scale = 1.0f;
679   const float output_scale = 1.0f;
680 
681   const int input_elements = 12;
682   const int input_shape[] = {4, 1, 3, 2, 2};
683   const float input_values[] = {1, 2, 7, 8, 3, 4, 9, 10, 5, 6, 11, 12};
684   const int filter_elements = 16;
685   const int filter_shape[] = {4, 1, 2, 2, 4};
686   const float filter_values[] = {1, 2, 3, 4, -9, 10,  -11, 12,
687                                  5, 6, 7, 8, 13, -14, 15,  -16};
688   const int bias_elements = 4;
689   const int bias_shape[] = {4, 1, 1, 1, 4};
690   const int output_elements = 8;
691   const float bias_values[] = {1, 2, 3, 4};
692   const float golden[] = {
693       71, -34, 99, -20, 91, -26, 127, -4,
694   };
695   const int output_shape[] = {4, 1, 2, 1, 4};
696   const int output_dims_count = 8;
697   int8_t output_data[output_dims_count];
698 
699   int8_t input_quantized[input_elements];
700   int8_t filter_quantized[filter_elements];
701   int32_t bias_quantized[bias_elements];
702   int8_t golden_quantized[output_elements];
703 
704   TfLiteIntArray* input_dims = tflite::testing::IntArrayFromInts(input_shape);
705   TfLiteIntArray* filter_dims = tflite::testing::IntArrayFromInts(filter_shape);
706   TfLiteIntArray* bias_dims = tflite::testing::IntArrayFromInts(bias_shape);
707   TfLiteIntArray* output_dims = tflite::testing::IntArrayFromInts(output_shape);
708 
709   // Create per-layer quantized int8_t input tensor.
710   TfLiteTensor input_tensor = tflite::testing::CreateQuantizedTensor(
711       input_values, input_quantized, input_dims, input_scale, 0);
712   int input_zero_points[2] = {1, 0};
713   float input_scales[2] = {1, input_scale};
714   TfLiteAffineQuantization input_quant = {
715       tflite::testing::FloatArrayFromFloats(input_scales),
716       tflite::testing::IntArrayFromInts(input_zero_points), 0};
717   input_tensor.quantization = {kTfLiteAffineQuantization, &input_quant};
718 
719   // Create per-layer quantized int8_t filter tensor.
720   TfLiteTensor filter_tensor = tflite::testing::CreateQuantizedTensor(
721       filter_values, filter_quantized, filter_dims, filter_scale, 0);
722   int filter_zero_points[2] = {1, 0};
723   float filter_scales[2] = {1, filter_scale};
724   TfLiteAffineQuantization filter_quant = {
725       tflite::testing::FloatArrayFromFloats(filter_scales),
726       tflite::testing::IntArrayFromInts(filter_zero_points), 0};
727   filter_tensor.quantization = {kTfLiteAffineQuantization, &filter_quant};
728 
729   // Create per-layer quantized int32_t bias tensor.
730   tflite::SymmetricQuantize(bias_values, bias_quantized, bias_elements,
731                             input_scale * output_scale);
732   TfLiteTensor bias_tensor =
733       tflite::testing::CreateTensor(bias_quantized, bias_dims);
734 
735   int bias_zero_points[2] = {1, 0};
736   float bias_scales[2] = {1, input_scale * filter_scale};
737   TfLiteAffineQuantization bias_quant = {
738       tflite::testing::FloatArrayFromFloats(bias_scales),
739       tflite::testing::IntArrayFromInts(bias_zero_points), 0};
740   bias_tensor.quantization = {kTfLiteAffineQuantization, &bias_quant};
741 
742   // Create per-layer quantized int8_t output tensor.
743   TfLiteTensor output_tensor = tflite::testing::CreateQuantizedTensor(
744       output_data, output_dims, output_scale, 0);
745   int output_zero_points[2] = {1, 0};
746   float output_scales[2] = {1, output_scale};
747   TfLiteAffineQuantization output_quant = {
748       tflite::testing::FloatArrayFromFloats(output_scales),
749       tflite::testing::IntArrayFromInts(output_zero_points), 0};
750   output_tensor.quantization = {kTfLiteAffineQuantization, &output_quant};
751 
752   constexpr int inputs_size = 3;
753   constexpr int outputs_size = 1;
754   constexpr int tensors_size = inputs_size + outputs_size;
755   TfLiteTensor tensors[tensors_size] = {
756       input_tensor,
757       filter_tensor,
758       bias_tensor,
759       output_tensor,
760   };
761 
762   tflite::Quantize(golden, golden_quantized, output_dims_count, output_scale,
763                    0);
764 
765   TfLiteDepthwiseConvParams conv_params;
766   conv_params.activation = kTfLiteActNone;
767   conv_params.dilation_width_factor = 1;
768   conv_params.dilation_height_factor = 1;
769 
770   TF_LITE_MICRO_EXPECT_EQ(
771       kTfLiteOk, tflite::testing::ValidateDepthwiseConvGoldens(
772                      golden_quantized, output_dims_count, &conv_params, 1e-5,
773                      tensors_size, tensors));
774 }
775 
776 #endif  // !defined(XTENSA)
777 
TF_LITE_MICRO_TEST(FilterDimsNotMatchingAffineQuantization)778 TF_LITE_MICRO_TEST(FilterDimsNotMatchingAffineQuantization) {
779   const int input_shape[] = {4, 1, 2, 3, 2};
780   const float input_data[] = {3, 2, 1, -1, -2, -3, 4, 3, 2, -2, -3, -4};
781   const int filter_shape[] = {4, 1, 2, 2, 4};
782   const float filter_data[] = {1, 2, 3, 4, 3, 4, 5, 6, 7, 8, 5, 6, 3, 4, 1, 2};
783   const int bias_shape[] = {4, 1, 1, 1, 4};
784   const float bias_data[] = {3, -2, 4, 6};
785   const int output_shape[] = {4, 1, 1, 2, 4};
786 
787   const int input_size = 12;
788   const int filter_size = 16;
789   const int output_size = 8;
790   const int bias_size = 4;
791   int8_t input_quantized[input_size];
792   int8_t filter_quantized[filter_size];
793   int32_t bias_quantized[bias_size];
794   int8_t golden_quantized[output_size];
795   int zero_points[bias_size + 1];
796   float scales[bias_size + 1];
797   int8_t output_data[output_size];
798 
799   const float input_scale = 0.5;
800   const float output_scale = 1.0;
801   const int input_zero_point = 0;
802   const int output_zero_point = 0;
803 
804   TfLiteIntArray* input_dims = tflite::testing::IntArrayFromInts(input_shape);
805   TfLiteIntArray* filter_dims = tflite::testing::IntArrayFromInts(filter_shape);
806   TfLiteIntArray* bias_dims = tflite::testing::IntArrayFromInts(bias_shape);
807   TfLiteIntArray* output_dims = tflite::testing::IntArrayFromInts(output_shape);
808 
809   int filter_zero_points[5];
810   float filter_scales[5];
811   TfLiteAffineQuantization filter_quant;
812   TfLiteAffineQuantization bias_quant;
813   TfLiteTensor input_tensor = tflite::testing::CreateQuantizedTensor(
814       input_data, input_quantized, input_dims, input_scale, input_zero_point);
815   TfLiteTensor filter_tensor =
816       tflite::testing::CreateSymmetricPerChannelQuantizedTensor(
817           filter_data, filter_quantized, filter_dims, filter_scales,
818           filter_zero_points, &filter_quant, 0 /* quantized dimension */);
819   TfLiteTensor bias_tensor =
820       tflite::testing::CreatePerChannelQuantizedBiasTensor(
821           bias_data, bias_quantized, bias_dims, input_scale, &filter_scales[1],
822           scales, zero_points, &bias_quant, 0);
823   TfLiteTensor output_tensor = tflite::testing::CreateQuantizedTensor(
824       output_data, output_dims, output_scale, output_zero_point);
825 
826   float input_scales[] = {1, input_scale};
827   int input_zero_points[] = {1, input_zero_point};
828   TfLiteAffineQuantization input_quant = {
829       tflite::testing::FloatArrayFromFloats(input_scales),
830       tflite::testing::IntArrayFromInts(input_zero_points), 0};
831   input_tensor.quantization = {kTfLiteAffineQuantization, &input_quant};
832 
833   constexpr int inputs_size = 3;
834   constexpr int outputs_size = 1;
835   constexpr int tensors_size = inputs_size + outputs_size;
836   TfLiteTensor tensors[tensors_size] = {
837       input_tensor,
838       filter_tensor,
839       bias_tensor,
840       output_tensor,
841   };
842 
843   TfLiteDepthwiseConvParams conv_params;
844   conv_params.activation = kTfLiteActNone;
845   conv_params.dilation_width_factor = 1;
846   conv_params.dilation_height_factor = 1;
847 
848   // Set filter quant to mismatched dimension.
849   TfLiteAffineQuantization* quant = reinterpret_cast<TfLiteAffineQuantization*>(
850       filter_tensor.quantization.params);
851   quant->scale->size = 2;
852   TF_LITE_MICRO_EXPECT_EQ(kTfLiteError,
853                           tflite::testing::ValidateDepthwiseConvGoldens(
854                               golden_quantized, output_size, &conv_params, 1e-5,
855                               tensors_size, tensors));
856 
857   // Set scale back to correct dimension, and make zero point array too short.
858   quant->scale->size = filter_shape[0];
859   quant->zero_point->size = 2;
860   TF_LITE_MICRO_EXPECT_EQ(kTfLiteError,
861                           tflite::testing::ValidateDepthwiseConvGoldens(
862                               golden_quantized, output_size, &conv_params, 1e-5,
863                               tensors_size, tensors));
864 }
865 
TF_LITE_MICRO_TEST(Int8Input32x4Filter32x4ShouldMatchGolden)866 TF_LITE_MICRO_TEST(Int8Input32x4Filter32x4ShouldMatchGolden) {
867   const int input_elements = 32 * 4;
868   const int filter_elements = 32 * 4;
869   const int bias_elements = 32;
870   const int output_elements = 32;
871   const int input_shape[] = {4, 1, 4, 1, 32};
872   const int filter_shape[] = {4, 1, 4, 1, 32};
873   const int bias_shape[] = {1, 32};
874   const int output_shape[] = {4, 1, 1, 1, 32};
875   const float input_values[] = {
876       11.0589, 10.8824, 11.1766, 11.5295, 10.8236, 9.5295, 9.5295, 10.0001,
877       11.2354, 10.8824, 9.1765,  9.0589,  9.6471,  8.9412, 7.9412, 9.0001,
878       9.3530,  7.5295,  9.2354,  9.5883,  7.5883,  8.1765, 7.5883, 9.2942,
879       9.1177,  8.5883,  8.2354,  8.6471,  8.0589,  8.0001, 7.4118, 7.3530,
880       11.0001, 11.1177, 11.0589, 11.2354, 10.5883, 9.2942, 9.2942, 10.1177,
881       11.2354, 10.8824, 8.9412,  8.8236,  9.2354,  8.8824, 7.0001, 9.1177,
882       9.5883,  8.2354,  9.1765,  9.5295,  7.4118,  8.5883, 8.1177, 9.1765,
883       9.0001,  9.0589,  8.9412,  8.2942,  7.8824,  8.4118, 7.2942, 7.2354,
884       10.4118, 10.8824, 11.1177, 11.0001, 10.0001, 9.7060, 9.7648, 10.1766,
885       11.1766, 10.6471, 8.6471,  8.5295,  9.5295,  9.0001, 7.0001, 9.4118,
886       9.8236,  8.0001,  9.2354,  9.5883,  7.5295,  9.0001, 8.5295, 9.0589,
887       8.9412,  9.1177,  8.9412,  8.0001,  8.0589,  8.8824, 7.0589, 7.3530,
888       11.3530, 11.0589, 10.7060, 10.7648, 9.9413,  9.1177, 9.1177, 9.7648,
889       10.7060, 10.2354, 8.5883,  8.8236,  9.7648,  9.2942, 7.5295, 9.2354,
890       9.7060,  8.1177,  9.2942,  9.5883,  7.7648,  9.6471, 9.1177, 9.4707,
891       9.3530,  8.8236,  8.5295,  8.0589,  8.6471,  9.5883, 7.4118, 7.5883};
892   const float filter_values[] = {
893       -0.1617, -0.1948, 0.1419,  -0.2311, -0.0891, 0.1551,  0.0033,  0.3037,
894       -0.1683, 0.1353,  0.1518,  -0.1683, -0.1386, 0.1452,  0.1816,  0.1716,
895       -0.1948, 0.2080,  0.2245,  -0.1981, -0.2410, 0.1849,  0.1981,  0.1584,
896       0.2509,  0.1783,  -0.2146, -0.1518, 0.2080,  -0.2872, 0.2014,  0.2476,
897       -0.4126, -0.0561, -0.3235, -0.0594, -0.0957, 0.2014,  -0.1056, 0.1386,
898       -0.2542, -0.1617, 0.1287,  -0.1816, -0.0363, 0.1419,  -0.0594, 0.2344,
899       -0.0099, 0.4192,  0.1287,  -0.2311, -0.2212, -0.0528, -0.2080, 0.1816,
900       -0.1452, 0.1221,  0.1254,  -0.1056, -0.0759, 0.1221,  0.1023,  0.1485,
901       0.2707,  0.1716,  -0.1882, -0.1783, 0.1650,  -0.2740, 0.1915,  0.2080,
902       -0.2971, -0.2575, -0.3169, 0.0198,  -0.0231, 0.2410,  -0.0429, 0.0660,
903       -0.1816, 0.1981,  0.2014,  -0.1386, -0.1915, 0.1716,  0.1320,  0.1419,
904       0.1320,  0.1353,  -0.1386, -0.1716, 0.1320,  -0.1650, 0.1386,  0.0825,
905       -0.1419, -0.1023, 0.1783,  0.0462,  0.2047,  -0.2179, -0.1518, -0.1551,
906       0.1518,  0.3334,  0.3103,  -0.2047, -0.2047, -0.0957, -0.1650, 0.1221,
907       0.0990,  0.1353,  -0.1617, -0.1485, 0.1650,  -0.1816, 0.1518,  0.1254,
908       -0.0363, -0.1254, 0.1386,  0.0429,  0.2113,  -0.2839, -0.1056, -0.2278};
909   const float bias_values[] = {
910       0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,
911       0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,
912       0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,
913       0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000};
914   const float golden[] = {
915       -5.1194, -2.0075, -2.1751, -4.7958, 1.7073,  -1.2963, -0.4641, 5.0416,
916       -6.4424, 0.3836,  2.4684,  -4.7643, -3.8913, 3.8382,  -0.5164, 5.4304,
917       -2.7400, 7.7016,  3.6115,  -6.8545, -3.6290, 0.8509,  2.3247,  5.6117,
918       1.8215,  2.7645,  -0.7032, -3.2156, 3.9689,  -5.4583, 2.4346,  1.7731};
919 
920   // Quantization Parameters.  All scales except output are 1.0, and all zero
921   // points are 0. This direct-maps the values to floating point and makes it
922   // easy to reson about them.
923   const float input_scale = 0.058824;
924   const float filter_scale = 0.003301;
925   const float output_scale = 0.092596;
926   const int input_zero_point = -128;
927   const int output_zero_point = 0;
928 
929   TfLiteIntArray* input_dims = tflite::testing::IntArrayFromInts(input_shape);
930   TfLiteIntArray* filter_dims = tflite::testing::IntArrayFromInts(filter_shape);
931   TfLiteIntArray* bias_dims = tflite::testing::IntArrayFromInts(bias_shape);
932   TfLiteIntArray* output_dims = tflite::testing::IntArrayFromInts(output_shape);
933 
934   // Create per-tensor quantized int8_t input tensor.
935   int8_t input_quantized[input_elements];
936   TfLiteTensor input_tensor = tflite::testing::CreateQuantizedTensor(
937       input_values, input_quantized, input_dims, input_scale, input_zero_point);
938 
939   // Set zero point and scale arrays with a single element for each.
940   int input_zero_points[] = {1, input_zero_point};
941   float input_scales[] = {1, input_scale};
942   TfLiteAffineQuantization input_quant = {
943       tflite::testing::FloatArrayFromFloats(input_scales),
944       tflite::testing::IntArrayFromInts(input_zero_points), 0};
945   input_tensor.quantization = {kTfLiteAffineQuantization, &input_quant};
946 
947   // Create per-tensor quantized int8_t filter tensor.
948   int8_t filter_quantized[filter_elements];
949   TfLiteTensor filter_tensor = tflite::testing::CreateQuantizedTensor(
950       filter_values, filter_quantized, filter_dims, filter_scale, 0);
951 
952   // Set zero point and scale arrays with a single element for each.
953   int filter_zero_points[] = {1, 0};
954   float filter_scales[] = {1, filter_scale};
955   TfLiteAffineQuantization filter_quant = {
956       tflite::testing::FloatArrayFromFloats(filter_scales),
957       tflite::testing::IntArrayFromInts(filter_zero_points), 0};
958   filter_tensor.quantization = {kTfLiteAffineQuantization, &filter_quant};
959 
960   // Create per-tensor quantized int32_t bias tensor.
961   int32_t bias_quantized[bias_elements];
962   // See https://www.tensorflow.org/lite/performance/quantization_spec for a
963   // detailed explanation of why bias scale is input_scale * filter_scale.
964   tflite::SymmetricQuantize(bias_values, bias_quantized, bias_elements,
965                             input_scale * output_scale);
966   TfLiteTensor bias_tensor =
967       tflite::testing::CreateTensor(bias_quantized, bias_dims);
968 
969   // Set zero point and scale arrays with a single element for each.
970   int bias_zero_points[] = {1, 0};
971   float bias_scales[] = {1, input_scale * filter_scale};
972   TfLiteAffineQuantization bias_quant = {
973       tflite::testing::FloatArrayFromFloats(bias_scales),
974       tflite::testing::IntArrayFromInts(bias_zero_points), 0};
975   bias_tensor.quantization = {kTfLiteAffineQuantization, &bias_quant};
976 
977   // Create per-tensor quantized int8_t output tensor.
978   int8_t output_quantized[output_elements];
979   TfLiteTensor output_tensor = tflite::testing::CreateQuantizedTensor(
980       output_quantized, output_dims, output_scale, output_zero_point);
981 
982   // Set zero point and scale arrays with a single element for each.
983   int output_zero_points[] = {1, output_zero_point};
984   float output_scales[] = {1, output_scale};
985   TfLiteAffineQuantization output_quant = {
986       tflite::testing::FloatArrayFromFloats(output_scales),
987       tflite::testing::IntArrayFromInts(output_zero_points), 0};
988   output_tensor.quantization = {kTfLiteAffineQuantization, &output_quant};
989 
990   // The 3 inputs include the input, filter and bias tensors.
991   constexpr int kInputsSize = 3;
992   constexpr int kOutputsSize = 1;
993   constexpr int kTensorsSize = kInputsSize + kOutputsSize;
994   TfLiteTensor tensors[kTensorsSize] = {
995       input_tensor,
996       filter_tensor,
997       bias_tensor,
998       output_tensor,
999   };
1000 
1001   int8_t golden_quantized[output_elements];
1002   tflite::Quantize(golden, golden_quantized, output_elements, output_scale, 0);
1003 
1004   // Errors due to quantization should not exceed 1.
1005   constexpr int kQuantizationTolerance = 1;
1006 
1007   TfLiteDepthwiseConvParams conv_params;
1008   conv_params.activation = kTfLiteActNone;
1009   conv_params.dilation_width_factor = 1;
1010   conv_params.dilation_height_factor = 1;
1011   tflite::testing::ValidateDepthwiseConvGoldens(
1012       golden_quantized, output_elements, &conv_params, kQuantizationTolerance,
1013       kTensorsSize, tensors);
1014 }
1015 
1016 TF_LITE_MICRO_TESTS_END
1017