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/micro/memory_helpers.h"
17 
18 #include "tensorflow/lite/micro/micro_error_reporter.h"
19 #include "tensorflow/lite/micro/test_helpers.h"
20 #include "tensorflow/lite/micro/testing/micro_test.h"
21 
22 namespace {
23 
24 // This just needs to be big enough to handle the array of 5 ints allocated
25 // in TestAllocateOutputDimensionsFromInput below.
26 const int kGlobalPersistentBufferLength = 100;
27 char global_persistent_buffer[kGlobalPersistentBufferLength];
28 
29 // Only need to handle a single allocation at a time for output dimensions
30 // in TestAllocateOutputDimensionsFromInput.
FakeAllocatePersistentBuffer(TfLiteContext * context,size_t bytes)31 void* FakeAllocatePersistentBuffer(TfLiteContext* context, size_t bytes) {
32   return reinterpret_cast<void*>(global_persistent_buffer);
33 }
34 
35 }  // namespace
36 
37 TF_LITE_MICRO_TESTS_BEGIN
38 
TF_LITE_MICRO_TEST(TestAlignPointerUp)39 TF_LITE_MICRO_TEST(TestAlignPointerUp) {
40   uint8_t* input0 = reinterpret_cast<uint8_t*>(0);
41 
42   uint8_t* input0_aligned1 = tflite::AlignPointerUp(input0, 1);
43   TF_LITE_MICRO_EXPECT(input0 == input0_aligned1);
44 
45   uint8_t* input0_aligned2 = tflite::AlignPointerUp(input0, 2);
46   TF_LITE_MICRO_EXPECT(input0 == input0_aligned2);
47 
48   uint8_t* input0_aligned3 = tflite::AlignPointerUp(input0, 3);
49   TF_LITE_MICRO_EXPECT(input0 == input0_aligned3);
50 
51   uint8_t* input0_aligned16 = tflite::AlignPointerUp(input0, 16);
52   TF_LITE_MICRO_EXPECT(input0 == input0_aligned16);
53 
54   uint8_t* input23 = reinterpret_cast<uint8_t*>(23);
55 
56   uint8_t* input23_aligned1 = tflite::AlignPointerUp(input23, 1);
57   TF_LITE_MICRO_EXPECT(input23 == input23_aligned1);
58 
59   uint8_t* input23_aligned2 = tflite::AlignPointerUp(input23, 2);
60   uint8_t* expected23_aligned2 = reinterpret_cast<uint8_t*>(24);
61   TF_LITE_MICRO_EXPECT(expected23_aligned2 == input23_aligned2);
62 
63   uint8_t* input23_aligned3 = tflite::AlignPointerUp(input23, 3);
64   uint8_t* expected23_aligned3 = reinterpret_cast<uint8_t*>(24);
65   TF_LITE_MICRO_EXPECT(expected23_aligned3 == input23_aligned3);
66 
67   uint8_t* input23_aligned16 = tflite::AlignPointerUp(input23, 16);
68   uint8_t* expected23_aligned16 = reinterpret_cast<uint8_t*>(32);
69   TF_LITE_MICRO_EXPECT(expected23_aligned16 == input23_aligned16);
70 }
71 
TF_LITE_MICRO_TEST(TestAlignPointerDown)72 TF_LITE_MICRO_TEST(TestAlignPointerDown) {
73   uint8_t* input0 = reinterpret_cast<uint8_t*>(0);
74 
75   uint8_t* input0_aligned1 = tflite::AlignPointerDown(input0, 1);
76   TF_LITE_MICRO_EXPECT(input0 == input0_aligned1);
77 
78   uint8_t* input0_aligned2 = tflite::AlignPointerDown(input0, 2);
79   TF_LITE_MICRO_EXPECT(input0 == input0_aligned2);
80 
81   uint8_t* input0_aligned3 = tflite::AlignPointerDown(input0, 3);
82   TF_LITE_MICRO_EXPECT(input0 == input0_aligned3);
83 
84   uint8_t* input0_aligned16 = tflite::AlignPointerDown(input0, 16);
85   TF_LITE_MICRO_EXPECT(input0 == input0_aligned16);
86 
87   uint8_t* input23 = reinterpret_cast<uint8_t*>(23);
88 
89   uint8_t* input23_aligned1 = tflite::AlignPointerDown(input23, 1);
90   TF_LITE_MICRO_EXPECT(input23 == input23_aligned1);
91 
92   uint8_t* input23_aligned2 = tflite::AlignPointerDown(input23, 2);
93   uint8_t* expected23_aligned2 = reinterpret_cast<uint8_t*>(22);
94   TF_LITE_MICRO_EXPECT(expected23_aligned2 == input23_aligned2);
95 
96   uint8_t* input23_aligned3 = tflite::AlignPointerDown(input23, 3);
97   uint8_t* expected23_aligned3 = reinterpret_cast<uint8_t*>(21);
98   TF_LITE_MICRO_EXPECT(expected23_aligned3 == input23_aligned3);
99 
100   uint8_t* input23_aligned16 = tflite::AlignPointerDown(input23, 16);
101   uint8_t* expected23_aligned16 = reinterpret_cast<uint8_t*>(16);
102   TF_LITE_MICRO_EXPECT(expected23_aligned16 == input23_aligned16);
103 }
104 
TF_LITE_MICRO_TEST(TestAlignSizeUp)105 TF_LITE_MICRO_TEST(TestAlignSizeUp) {
106   TF_LITE_MICRO_EXPECT_EQ(static_cast<size_t>(1), tflite::AlignSizeUp(1, 1));
107   TF_LITE_MICRO_EXPECT_EQ(static_cast<size_t>(2), tflite::AlignSizeUp(1, 2));
108   TF_LITE_MICRO_EXPECT_EQ(static_cast<size_t>(3), tflite::AlignSizeUp(1, 3));
109   TF_LITE_MICRO_EXPECT_EQ(static_cast<size_t>(16), tflite::AlignSizeUp(1, 16));
110 
111   TF_LITE_MICRO_EXPECT_EQ(static_cast<size_t>(23), tflite::AlignSizeUp(23, 1));
112   TF_LITE_MICRO_EXPECT_EQ(static_cast<size_t>(24), tflite::AlignSizeUp(23, 2));
113   TF_LITE_MICRO_EXPECT_EQ(static_cast<size_t>(24), tflite::AlignSizeUp(23, 3));
114   TF_LITE_MICRO_EXPECT_EQ(static_cast<size_t>(32), tflite::AlignSizeUp(23, 16));
115 }
116 
TF_LITE_MICRO_TEST(TestTypeSizeOf)117 TF_LITE_MICRO_TEST(TestTypeSizeOf) {
118   size_t size;
119   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk,
120                           tflite::TfLiteTypeSizeOf(kTfLiteFloat16, &size));
121   TF_LITE_MICRO_EXPECT_EQ(sizeof(int16_t), size);
122 
123   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk,
124                           tflite::TfLiteTypeSizeOf(kTfLiteFloat32, &size));
125   TF_LITE_MICRO_EXPECT_EQ(sizeof(float), size);
126 
127   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk,
128                           tflite::TfLiteTypeSizeOf(kTfLiteFloat64, &size));
129   TF_LITE_MICRO_EXPECT_EQ(sizeof(double), size);
130 
131   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk,
132                           tflite::TfLiteTypeSizeOf(kTfLiteInt16, &size));
133   TF_LITE_MICRO_EXPECT_EQ(sizeof(int16_t), size);
134 
135   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk,
136                           tflite::TfLiteTypeSizeOf(kTfLiteInt32, &size));
137   TF_LITE_MICRO_EXPECT_EQ(sizeof(int32_t), size);
138 
139   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk,
140                           tflite::TfLiteTypeSizeOf(kTfLiteUInt32, &size));
141   TF_LITE_MICRO_EXPECT_EQ(sizeof(uint32_t), size);
142 
143   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk,
144                           tflite::TfLiteTypeSizeOf(kTfLiteUInt8, &size));
145   TF_LITE_MICRO_EXPECT_EQ(sizeof(uint8_t), size);
146 
147   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk,
148                           tflite::TfLiteTypeSizeOf(kTfLiteInt8, &size));
149   TF_LITE_MICRO_EXPECT_EQ(sizeof(int8_t), size);
150 
151   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk,
152                           tflite::TfLiteTypeSizeOf(kTfLiteInt64, &size));
153   TF_LITE_MICRO_EXPECT_EQ(sizeof(int64_t), size);
154 
155   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk,
156                           tflite::TfLiteTypeSizeOf(kTfLiteUInt64, &size));
157   TF_LITE_MICRO_EXPECT_EQ(sizeof(uint64_t), size);
158 
159   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk,
160                           tflite::TfLiteTypeSizeOf(kTfLiteBool, &size));
161   TF_LITE_MICRO_EXPECT_EQ(sizeof(bool), size);
162 
163   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk,
164                           tflite::TfLiteTypeSizeOf(kTfLiteComplex64, &size));
165   TF_LITE_MICRO_EXPECT_EQ(sizeof(float) * 2, size);
166 
167   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk,
168                           tflite::TfLiteTypeSizeOf(kTfLiteComplex128, &size));
169   TF_LITE_MICRO_EXPECT_EQ(sizeof(double) * 2, size);
170 
171   TF_LITE_MICRO_EXPECT_NE(
172       kTfLiteOk, tflite::TfLiteTypeSizeOf(static_cast<TfLiteType>(-1), &size));
173 }
174 
TF_LITE_MICRO_TEST(TestBytesRequiredForTensor)175 TF_LITE_MICRO_TEST(TestBytesRequiredForTensor) {
176   const tflite::Tensor* tensor100 =
177       tflite::testing::Create1dFlatbufferTensor(100);
178   size_t bytes;
179   size_t type_size;
180   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, tflite::BytesRequiredForTensor(
181                                          *tensor100, &bytes, &type_size,
182                                          tflite::GetMicroErrorReporter()));
183   TF_LITE_MICRO_EXPECT_EQ(static_cast<size_t>(400), bytes);
184   TF_LITE_MICRO_EXPECT_EQ(static_cast<size_t>(4), type_size);
185 
186   const tflite::Tensor* tensor200 =
187       tflite::testing::Create1dFlatbufferTensor(200);
188   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, tflite::BytesRequiredForTensor(
189                                          *tensor200, &bytes, &type_size,
190                                          tflite::GetMicroErrorReporter()));
191   TF_LITE_MICRO_EXPECT_EQ(static_cast<size_t>(800), bytes);
192   TF_LITE_MICRO_EXPECT_EQ(static_cast<size_t>(4), type_size);
193 }
194 
TF_LITE_MICRO_TEST(TestAllocateOutputDimensionsFromInput)195 TF_LITE_MICRO_TEST(TestAllocateOutputDimensionsFromInput) {
196   constexpr int kDimsLen = 4;
197   int input1_dims[] = {1, 1};
198   int input2_dims[] = {kDimsLen, 5, 5, 5, 5};
199   int output_dims[] = {0, 0, 0, 0, 0};
200   TfLiteTensor input_tensor1 = tflite::testing::CreateTensor<int32_t>(
201       nullptr, tflite::testing::IntArrayFromInts(input1_dims));
202   TfLiteTensor input_tensor2 = tflite::testing::CreateTensor<int32_t>(
203       nullptr, tflite::testing::IntArrayFromInts(input2_dims));
204   TfLiteTensor output_tensor = tflite::testing::CreateTensor<int32_t>(
205       nullptr, tflite::testing::IntArrayFromInts(output_dims));
206   TfLiteContext context;
207   // Only need to allocate space for output_tensor.dims.  Use a simple
208   // fake allocator.
209   context.AllocatePersistentBuffer = FakeAllocatePersistentBuffer;
210 
211   TF_LITE_MICRO_EXPECT_EQ(
212       kTfLiteOk, tflite::AllocateOutputDimensionsFromInput(
213                      &context, &input_tensor1, &input_tensor2, &output_tensor));
214 
215   TF_LITE_MICRO_EXPECT_EQ(output_tensor.bytes, input_tensor2.bytes);
216   for (int i = 0; i < kDimsLen; i++) {
217     TF_LITE_MICRO_EXPECT_EQ(input_tensor2.dims->data[i],
218                             output_tensor.dims->data[i]);
219     // Reset output dims for next iteration.
220     output_tensor.dims->data[i] = 0;
221   }
222   // Output tensor size must be 0 to allocate output dimensions from input.
223   output_tensor.dims->size = 0;
224   TF_LITE_MICRO_EXPECT_EQ(
225       kTfLiteOk, tflite::AllocateOutputDimensionsFromInput(
226                      &context, &input_tensor2, &input_tensor1, &output_tensor));
227   for (int i = 0; i < kDimsLen; i++) {
228     TF_LITE_MICRO_EXPECT_EQ(input_tensor2.dims->data[i],
229                             output_tensor.dims->data[i]);
230   }
231   TF_LITE_MICRO_EXPECT_EQ(output_tensor.bytes, input_tensor2.bytes);
232 }
233 TF_LITE_MICRO_TESTS_END
234