1 /* Copyright 2019 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/micro/kernels/kernel_runner.h"
19 #include "tensorflow/lite/micro/test_helpers.h"
20 #include "tensorflow/lite/micro/testing/micro_test.h"
21
22 namespace tflite {
23 namespace testing {
24 namespace {
25
26 const int flat_size_simple = 4;
27 const float scale_simple = 0.01;
28 const int dims_simple[] = {4, 1, 2, 2, 1};
29 const float input1_simple[] = {-0.8, 0.2, 0.9, 0.7};
30 const float input2_simple[] = {0.6, 0.4, 0.9, 0.8};
31 const float golden_simple[] = {-0.48, 0.08, 0.81, 0.56};
32 const float golden_simple_relu[] = {0.0, 0.08, 0.81, 0.56};
33
34 const int flat_size_broadcast = 6;
35 const float input_scale_broadcast = 0.05f;
36 const float output_scale_broadcast = 0.01f;
37 const int dims_broadcast[] = {4, 1, 3, 1, 2};
38 const int dims_scalar_broadcast[] = {1, 1};
39 const float input1_broadcast[] = {-2.0, 0.2, 0.7, 0.8, 1.1, 2.0};
40 const float input2_broadcast[] = {0.1};
41 const float golden_broadcast[] = {-0.2, 0.02, 0.07, 0.08, 0.11, 0.2};
42 const float golden_broadcast_relu[] = {0, 0.02, 0.07, 0.08, 0.11, 0.2};
43
44 template <typename T>
ValidateMulGoldens(TfLiteTensor * tensors,int tensors_size,TfLiteFusedActivation activation,const T * golden,int output_len,float tolerance,T * output)45 void ValidateMulGoldens(TfLiteTensor* tensors, int tensors_size,
46 TfLiteFusedActivation activation, const T* golden,
47 int output_len, float tolerance, T* output) {
48 TfLiteMulParams builtin_data = {
49 .activation = activation,
50 };
51
52 int inputs_array_data[] = {2, 0, 1};
53 TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
54 int outputs_array_data[] = {1, 2};
55 TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
56
57 const TfLiteRegistration registration = tflite::ops::micro::Register_MUL();
58 micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array,
59 outputs_array,
60 reinterpret_cast<void*>(&builtin_data));
61
62 TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
63 TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
64
65 for (int i = 0; i < output_len; i++) {
66 TF_LITE_MICRO_EXPECT_NEAR(golden[i], output[i], tolerance);
67 }
68 }
69
TestMulFloat(const int * input1_dims_data,const float * input1_data,const int * input2_dims_data,const float * input2_data,const int * output_dims_data,const float * golden,float * output_data,TfLiteFusedActivation activation)70 void TestMulFloat(const int* input1_dims_data, const float* input1_data,
71 const int* input2_dims_data, const float* input2_data,
72 const int* output_dims_data, const float* golden,
73 float* output_data, TfLiteFusedActivation activation) {
74 TfLiteIntArray* input1_dims = IntArrayFromInts(input1_dims_data);
75 TfLiteIntArray* input2_dims = IntArrayFromInts(input2_dims_data);
76 TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
77 const int output_dims_count = ElementCount(*output_dims);
78
79 constexpr int inputs_size = 2;
80 constexpr int outputs_size = 1;
81 constexpr int tensors_size = inputs_size + outputs_size;
82 TfLiteTensor tensors[tensors_size] = {
83 CreateTensor(input1_data, input1_dims),
84 CreateTensor(input2_data, input2_dims),
85 CreateTensor(output_data, output_dims),
86 };
87
88 ValidateMulGoldens(tensors, tensors_size, activation, golden,
89 output_dims_count, 1e-5, output_data);
90 }
91
92 template <typename T>
TestMulQuantized(const int * input1_dims_data,const float * input1_data,T * input1_quantized,const int * input2_dims_data,const float * input2_data,T * input2_quantized,const float input_scale,const int input_zero_point,const int * output_dims_data,const float * golden,T * golden_quantized,const float output_scale,const int output_zero_point,T * output_data,TfLiteFusedActivation activation)93 void TestMulQuantized(const int* input1_dims_data, const float* input1_data,
94 T* input1_quantized, const int* input2_dims_data,
95 const float* input2_data, T* input2_quantized,
96 const float input_scale, const int input_zero_point,
97 const int* output_dims_data, const float* golden,
98 T* golden_quantized, const float output_scale,
99 const int output_zero_point, T* output_data,
100 TfLiteFusedActivation activation) {
101 TfLiteIntArray* input1_dims = IntArrayFromInts(input1_dims_data);
102 TfLiteIntArray* input2_dims = IntArrayFromInts(input2_dims_data);
103 TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
104 const int output_dims_count = ElementCount(*output_dims);
105
106 constexpr int inputs_size = 2;
107 constexpr int outputs_size = 1;
108 constexpr int tensors_size = inputs_size + outputs_size;
109 TfLiteTensor tensors[tensors_size] = {
110 CreateQuantizedTensor(input1_data, input1_quantized, input1_dims,
111 input_scale, input_zero_point),
112 CreateQuantizedTensor(input2_data, input2_quantized, input2_dims,
113 input_scale, input_zero_point),
114 CreateQuantizedTensor(output_data, output_dims, output_scale,
115 output_zero_point)};
116
117 Quantize(golden, golden_quantized, output_dims_count, output_scale,
118 output_zero_point);
119
120 ValidateMulGoldens(tensors, tensors_size, activation, golden_quantized,
121 output_dims_count, 1.0f, output_data);
122 }
123
124 } // namespace
125
126 } // namespace testing
127 } // namespace tflite
128
129 TF_LITE_MICRO_TESTS_BEGIN
130
TF_LITE_MICRO_TEST(SimpleFloatNoAcativationShouldMatchGolden)131 TF_LITE_MICRO_TEST(SimpleFloatNoAcativationShouldMatchGolden) {
132 float output_data[tflite::testing::flat_size_simple];
133
134 tflite::testing::TestMulFloat(
135 tflite::testing::dims_simple, tflite::testing::input1_simple,
136 tflite::testing::dims_simple, tflite::testing::input2_simple,
137 tflite::testing::dims_simple, tflite::testing::golden_simple, output_data,
138 kTfLiteActNone);
139 }
140
TF_LITE_MICRO_TEST(SimpleFloatReluShouldMatchGolden)141 TF_LITE_MICRO_TEST(SimpleFloatReluShouldMatchGolden) {
142 float output_data[tflite::testing::flat_size_simple];
143
144 tflite::testing::TestMulFloat(
145 tflite::testing::dims_simple, tflite::testing::input1_simple,
146 tflite::testing::dims_simple, tflite::testing::input2_simple,
147 tflite::testing::dims_simple, tflite::testing::golden_simple_relu,
148 output_data, kTfLiteActRelu);
149 }
150
TF_LITE_MICRO_TEST(SimpleInt8NoAcativationShouldMatchGolden)151 TF_LITE_MICRO_TEST(SimpleInt8NoAcativationShouldMatchGolden) {
152 int8_t input1_quantized[tflite::testing::flat_size_simple];
153 int8_t input2_quantized[tflite::testing::flat_size_simple];
154 int8_t golden_quantized[tflite::testing::flat_size_simple];
155 int8_t output_data[tflite::testing::flat_size_simple];
156
157 tflite::testing::TestMulQuantized(
158 tflite::testing::dims_simple, tflite::testing::input1_simple,
159 input1_quantized, tflite::testing::dims_simple,
160 tflite::testing::input2_simple, input2_quantized,
161 tflite::testing::scale_simple, 0, tflite::testing::dims_simple,
162 tflite::testing::golden_simple, golden_quantized,
163 tflite::testing::scale_simple, 0, output_data, kTfLiteActNone);
164 }
165
TF_LITE_MICRO_TEST(SimpleUInt8NoAcativationShouldMatchGolden)166 TF_LITE_MICRO_TEST(SimpleUInt8NoAcativationShouldMatchGolden) {
167 uint8_t input1_quantized[tflite::testing::flat_size_simple];
168 uint8_t input2_quantized[tflite::testing::flat_size_simple];
169 uint8_t golden_quantized[tflite::testing::flat_size_simple];
170 uint8_t output_data[tflite::testing::flat_size_simple];
171
172 tflite::testing::TestMulQuantized(
173 tflite::testing::dims_simple, tflite::testing::input1_simple,
174 input1_quantized, tflite::testing::dims_simple,
175 tflite::testing::input2_simple, input2_quantized,
176 tflite::testing::scale_simple, 128, tflite::testing::dims_simple,
177 tflite::testing::golden_simple, golden_quantized,
178 tflite::testing::scale_simple, 128, output_data, kTfLiteActNone);
179 }
180
TF_LITE_MICRO_TEST(BroadcastFloatNoActivationShouldMatchGolden)181 TF_LITE_MICRO_TEST(BroadcastFloatNoActivationShouldMatchGolden) {
182 float output_data[tflite::testing::flat_size_broadcast];
183
184 tflite::testing::TestMulFloat(
185 tflite::testing::dims_broadcast, tflite::testing::input1_broadcast,
186 tflite::testing::dims_scalar_broadcast, tflite::testing::input2_broadcast,
187 tflite::testing::dims_broadcast, tflite::testing::golden_broadcast,
188 output_data, kTfLiteActNone);
189 }
190
TF_LITE_MICRO_TEST(BroadcastFloatReluShouldMatchGolden)191 TF_LITE_MICRO_TEST(BroadcastFloatReluShouldMatchGolden) {
192 float output_data[tflite::testing::flat_size_broadcast];
193
194 tflite::testing::TestMulFloat(
195 tflite::testing::dims_broadcast, tflite::testing::input1_broadcast,
196 tflite::testing::dims_scalar_broadcast, tflite::testing::input2_broadcast,
197 tflite::testing::dims_broadcast, tflite::testing::golden_broadcast_relu,
198 output_data, kTfLiteActRelu);
199 }
200
TF_LITE_MICRO_TEST(BroadcastInt8NoAcativationShouldMatchGolden)201 TF_LITE_MICRO_TEST(BroadcastInt8NoAcativationShouldMatchGolden) {
202 int8_t input1_quantized[tflite::testing::flat_size_broadcast];
203 int8_t input2_quantized[tflite::testing::flat_size_broadcast];
204 int8_t golden_quantized[tflite::testing::flat_size_broadcast];
205 int8_t output_data[tflite::testing::flat_size_broadcast];
206
207 tflite::testing::TestMulQuantized(
208 tflite::testing::dims_broadcast, tflite::testing::input1_broadcast,
209 input1_quantized, tflite::testing::dims_scalar_broadcast,
210 tflite::testing::input2_broadcast, input2_quantized,
211 tflite::testing::input_scale_broadcast, 0,
212 tflite::testing::dims_broadcast, tflite::testing::golden_broadcast,
213 golden_quantized, tflite::testing::output_scale_broadcast, 0, output_data,
214 kTfLiteActNone);
215 }
216
TF_LITE_MICRO_TEST(BroadcastUInt8NoAcativationShouldMatchGolden)217 TF_LITE_MICRO_TEST(BroadcastUInt8NoAcativationShouldMatchGolden) {
218 uint8_t input1_quantized[tflite::testing::flat_size_broadcast];
219 uint8_t input2_quantized[1];
220 uint8_t golden_quantized[tflite::testing::flat_size_broadcast];
221 uint8_t output_data[tflite::testing::flat_size_broadcast];
222
223 tflite::testing::TestMulQuantized(
224 tflite::testing::dims_broadcast, tflite::testing::input1_broadcast,
225 input1_quantized, tflite::testing::dims_scalar_broadcast,
226 tflite::testing::input2_broadcast, input2_quantized,
227 tflite::testing::input_scale_broadcast, 128,
228 tflite::testing::dims_broadcast, tflite::testing::golden_broadcast,
229 golden_quantized, tflite::testing::output_scale_broadcast, 128,
230 output_data, kTfLiteActNone);
231 }
232
233 TF_LITE_MICRO_TESTS_END
234