• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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