1 /* Copyright 2020 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/all_ops_resolver.h"
19 #include "tensorflow/lite/micro/kernels/kernel_runner.h"
20 #include "tensorflow/lite/micro/kernels/micro_ops.h"
21 #include "tensorflow/lite/micro/test_helpers.h"
22 #include "tensorflow/lite/micro/testing/micro_test.h"
23
24 namespace tflite {
25 namespace testing {
26 namespace {
27
28 constexpr int kRunPeriod = 2;
29
30 // TODO(b/149795762): Add this to TfLiteStatus enum.
31 constexpr int kTfLiteAbort = -9;
32
33 } // namespace
34 } // namespace testing
35 } // namespace tflite
36
37 TF_LITE_MICRO_TESTS_BEGIN
38
TF_LITE_MICRO_TEST(OutputTensorLength4)39 TF_LITE_MICRO_TEST(OutputTensorLength4) {
40 constexpr int depth = 3;
41 constexpr int num_slots = 4;
42 int8_t input_data[depth];
43 int8_t output_data[depth * num_slots];
44
45 memset(output_data, 0, sizeof(output_data));
46
47 // There are four input dimensions - [1, 1, 1, depth].
48 const int input_dims[] = {4, 1, 1, 1, depth};
49 // There are four output dimensions - [1, num_slots, 1, depth].
50 const int output_dims[] = {4, 1, num_slots, 1, depth};
51
52 TfLiteIntArray* input_tensor_dims =
53 tflite::testing::IntArrayFromInts(input_dims);
54 TfLiteIntArray* output_tensor_dims =
55 tflite::testing::IntArrayFromInts(output_dims);
56
57 const int output_dims_count = tflite::ElementCount(*output_tensor_dims);
58
59 constexpr int inputs_size = 2;
60 constexpr int outputs_size = 1;
61 constexpr int tensors_size = inputs_size + outputs_size;
62 TfLiteTensor tensors[tensors_size] = {
63 tflite::testing::CreateQuantizedTensor(input_data, input_tensor_dims, 1,
64 0),
65 tflite::testing::CreateQuantizedTensor(output_data, output_tensor_dims, 1,
66 0),
67 };
68
69 // There is one input - tensor 0.
70 const int inputs_array_data[] = {1, 0};
71 TfLiteIntArray* inputs_array =
72 tflite::testing::IntArrayFromInts(inputs_array_data);
73 // There is one output - tensor 1.
74 const int outputs_array_data[] = {1, 1};
75 TfLiteIntArray* outputs_array =
76 tflite::testing::IntArrayFromInts(outputs_array_data);
77
78 const TfLiteRegistration* registration =
79 tflite::ops::micro::Register_CIRCULAR_BUFFER();
80 tflite::micro::KernelRunner runner = tflite::micro::KernelRunner(
81 *registration, tensors, tensors_size, inputs_array, outputs_array,
82 /*builtin_data=*/nullptr);
83 TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
84
85 const int8_t goldens[5][16] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3},
86 {0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6},
87 {0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
88 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
89 {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}};
90
91 // Expect the circular buffer to run every other invoke for 4xN output.
92 for (int i = 0; i < 5; i++) {
93 for (int j = 0; j < depth; j++) {
94 input_data[j] = i * depth + j + 1;
95 }
96 TfLiteStatus status = runner.Invoke();
97
98 for (int j = 0; j < output_dims_count; ++j) {
99 TF_LITE_MICRO_EXPECT_EQ(goldens[i][j], output_data[j]);
100 }
101
102 // Every kRunPeriod iterations, the circular buffer should return kTfLiteOk.
103 if (i % tflite::testing::kRunPeriod == tflite::testing::kRunPeriod - 1) {
104 TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, status);
105 } else {
106 TF_LITE_MICRO_EXPECT_EQ(tflite::testing::kTfLiteAbort, status);
107 }
108 }
109 }
110
TF_LITE_MICRO_TEST(OutputTensorLength5)111 TF_LITE_MICRO_TEST(OutputTensorLength5) {
112 constexpr int depth = 4;
113 constexpr int num_slots = 5;
114 int8_t input_data[depth];
115 int8_t output_data[depth * num_slots];
116
117 memset(output_data, 0, sizeof(output_data));
118 const int input_dims[] = {4, 1, 1, 1, depth};
119 const int output_dims[] = {4, 1, num_slots, 1, depth};
120 TfLiteIntArray* input_tensor_dims =
121 tflite::testing::IntArrayFromInts(input_dims);
122 TfLiteIntArray* output_tensor_dims =
123 tflite::testing::IntArrayFromInts(output_dims);
124
125 const int output_dims_count = tflite::ElementCount(*output_tensor_dims);
126
127 constexpr int inputs_size = 2;
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_tensor_dims, 1,
132 0),
133 tflite::testing::CreateQuantizedTensor(output_data, output_tensor_dims, 1,
134 0),
135 };
136
137 // There is one input - tensor 0.
138 const int inputs_array_data[] = {1, 0};
139 TfLiteIntArray* inputs_array =
140 tflite::testing::IntArrayFromInts(inputs_array_data);
141 // There is one output - tensor 1.
142 const int outputs_array_data[] = {1, 1};
143 TfLiteIntArray* outputs_array =
144 tflite::testing::IntArrayFromInts(outputs_array_data);
145
146 const TfLiteRegistration* registration =
147 tflite::ops::micro::Register_CIRCULAR_BUFFER();
148 tflite::micro::KernelRunner runner = tflite::micro::KernelRunner(
149 *registration, tensors, tensors_size, inputs_array, outputs_array,
150 /*builtin_data=*/nullptr);
151 TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
152
153 const int8_t goldens[6][20] = {
154 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4},
155 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8},
156 {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
157 {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
158 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
159 {5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
160 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}};
161
162 // Expect circular buffer to run every cycle for 5xN output.
163 for (int i = 0; i < 6; i++) {
164 for (int j = 0; j < depth; j++) {
165 input_data[j] = i * depth + j + 1;
166 }
167 TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
168
169 for (int j = 0; j < output_dims_count; ++j) {
170 TF_LITE_MICRO_EXPECT_EQ(goldens[i][j], output_data[j]);
171 }
172 }
173 }
174
175 TF_LITE_MICRO_TESTS_END
176