xref: /aosp_15_r20/external/armnn/delegate/test/ConvolutionTestHelper.hpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
1 //
2 // Copyright © 2020, 2023 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #pragma once
7 
8 #include "TestUtils.hpp"
9 
10 #include <armnn_delegate.hpp>
11 #include <DelegateTestInterpreter.hpp>
12 
13 #include <flatbuffers/flatbuffers.h>
14 #include <tensorflow/lite/interpreter.h>
15 #include <tensorflow/lite/kernels/register.h>
16 #include <tensorflow/lite/model.h>
17 #include <schema_generated.h>
18 #include <tensorflow/lite/version.h>
19 
20 #include <doctest/doctest.h>
21 
22 namespace
23 {
24 
25 template <typename T, typename B = float>
CreateConv2dTfLiteModel(tflite::BuiltinOperator convolutionOperatorCode,tflite::TensorType tensorType,uint32_t strideX,uint32_t strideY,uint32_t dilationX,uint32_t dilationY,tflite::Padding padding,tflite::ActivationFunctionType fused_activation_function,const std::vector<int32_t> & inputTensorShape,const std::vector<int32_t> & filterTensorShape,const std::vector<int32_t> & biasTensorShape,const std::vector<int32_t> & outputTensorShape,const std::vector<T> & filterData,const std::vector<B> & biasData,const std::vector<float> biasScales={1.0f},const std::vector<int64_t> biasOffsets={0},const std::vector<float> filterScales={1.0f},const std::vector<int64_t> filterOffsets={0},float outputQuantScale=2.0f,int outputQuantOffset=0,float quantScale=1.0f,int quantOffset=0,int32_t depth_multiplier=1,int32_t filterQuantizationDim=0)26 std::vector<char> CreateConv2dTfLiteModel(tflite::BuiltinOperator convolutionOperatorCode,
27                                           tflite::TensorType tensorType,
28                                           uint32_t strideX,
29                                           uint32_t strideY,
30                                           uint32_t dilationX,
31                                           uint32_t dilationY,
32                                           tflite::Padding padding,
33                                           tflite::ActivationFunctionType fused_activation_function,
34                                           const std::vector <int32_t>& inputTensorShape,
35                                           const std::vector <int32_t>& filterTensorShape,
36                                           const std::vector <int32_t>& biasTensorShape,
37                                           const std::vector <int32_t>& outputTensorShape,
38                                           const std::vector <T>& filterData,
39                                           const std::vector <B>& biasData,
40                                           const std::vector<float> biasScales = {1.0f},
41                                           const std::vector<int64_t> biasOffsets = {0},
42                                           const std::vector<float> filterScales = {1.0f},
43                                           const std::vector<int64_t> filterOffsets = {0},
44                                           float outputQuantScale = 2.0f,
45                                           int outputQuantOffset = 0,
46                                           float quantScale = 1.0f,
47                                           int quantOffset = 0,
48                                           int32_t depth_multiplier = 1,
49                                           int32_t filterQuantizationDim = 0)
50 {
51     using namespace tflite;
52     flatbuffers::FlatBufferBuilder flatBufferBuilder;
53 
54     std::array<flatbuffers::Offset<tflite::Buffer>, 5> buffers;
55     buffers[0] = CreateBuffer(flatBufferBuilder);
56     buffers[1] = CreateBuffer(flatBufferBuilder);
57     buffers[2] = CreateBuffer(flatBufferBuilder,
58                               flatBufferBuilder.CreateVector(reinterpret_cast<const uint8_t*>(filterData.data()),
59                                                              sizeof(T) * filterData.size()));
60 
61     buffers[3] = CreateBuffer(flatBufferBuilder,
62                               flatBufferBuilder.CreateVector(reinterpret_cast<const uint8_t*>(biasData.data()),
63                                                              sizeof(B) * biasData.size()));
64     buffers[4] = CreateBuffer(flatBufferBuilder);
65 
66     auto quantizationParameters =
67         CreateQuantizationParameters(flatBufferBuilder,
68                                      0,
69                                      0,
70                                      flatBufferBuilder.CreateVector<float>({ quantScale }),
71                                      flatBufferBuilder.CreateVector<int64_t>({ quantOffset }));
72     auto outputQuantizationParameters =
73         CreateQuantizationParameters(flatBufferBuilder,
74                                      0,
75                                      0,
76                                      flatBufferBuilder.CreateVector<float>({ outputQuantScale }),
77                                      flatBufferBuilder.CreateVector<int64_t>({ outputQuantOffset }));
78 
79     auto filterQuantizationParameters =
80             CreateQuantizationParameters(flatBufferBuilder,
81                                          0,
82                                          0,
83                                          flatBufferBuilder.CreateVector<float>(filterScales),
84                                          flatBufferBuilder.CreateVector<int64_t>(filterOffsets),
85                                          tflite::QuantizationDetails_NONE,
86                                          0,
87                                          filterQuantizationDim);
88 
89     auto biasQuantizationParameters =
90             CreateQuantizationParameters(flatBufferBuilder,
91                                          0,
92                                          0,
93                                          flatBufferBuilder.CreateVector<float>(biasScales),
94                                          flatBufferBuilder.CreateVector<int64_t>(biasOffsets));
95 
96     std::array<flatbuffers::Offset<Tensor>, 4> tensors;
97     tensors[0] = CreateTensor(flatBufferBuilder,
98                               flatBufferBuilder.CreateVector<int32_t>(inputTensorShape.data(),
99                                                                       inputTensorShape.size()),
100                               tensorType,
101                               1,
102                               flatBufferBuilder.CreateString("input"),
103                               quantizationParameters);
104     tensors[1] = CreateTensor(flatBufferBuilder,
105                               flatBufferBuilder.CreateVector<int32_t>(filterTensorShape.data(),
106                                                                       filterTensorShape.size()),
107                               tensorType,
108                               2,
109                               flatBufferBuilder.CreateString("filter"),
110                               filterQuantizationParameters);
111 
112     auto biasTensorType = ::tflite::TensorType_FLOAT32;
113     if (tensorType == ::tflite::TensorType_INT8 || tensorType == ::tflite::TensorType_UINT8)
114     {
115         biasTensorType = ::tflite::TensorType_INT32;
116     }
117     tensors[2] = CreateTensor(flatBufferBuilder,
118                               flatBufferBuilder.CreateVector<int32_t>(biasTensorShape.data(), biasTensorShape.size()),
119                               biasTensorType,
120                               3,
121                               flatBufferBuilder.CreateString("bias"),
122                               biasQuantizationParameters);
123     tensors[3] = CreateTensor(flatBufferBuilder,
124                               flatBufferBuilder.CreateVector<int32_t>(outputTensorShape.data(),
125                                                                       outputTensorShape.size()),
126                               tensorType,
127                               4,
128                               flatBufferBuilder.CreateString("output"),
129                               outputQuantizationParameters);
130 
131     flatbuffers::Offset<void> operatorBuiltinOptions;
132     tflite::BuiltinOptions operatorBuiltinOptionsType;
133 
134     if(convolutionOperatorCode == tflite::BuiltinOperator_DEPTHWISE_CONV_2D)
135     {
136         operatorBuiltinOptionsType = tflite::BuiltinOptions_DepthwiseConv2DOptions;
137         operatorBuiltinOptions = CreateDepthwiseConv2DOptions(flatBufferBuilder,
138                                                               padding,
139                                                               strideX,
140                                                               strideY,
141                                                               depth_multiplier,
142                                                               fused_activation_function,
143                                                               dilationX,
144                                                               dilationY).Union();
145     }
146     if(convolutionOperatorCode == tflite::BuiltinOperator_CONV_2D)
147     {
148         operatorBuiltinOptionsType = tflite::BuiltinOptions_Conv2DOptions;
149         operatorBuiltinOptions = CreateConv2DOptions(flatBufferBuilder,
150                                                      padding,
151                                                      strideX,
152                                                      strideY,
153                                                      fused_activation_function,
154                                                      dilationX,
155                                                      dilationY).Union();
156     }
157 
158     // create operator
159     const std::vector<int> operatorInputs{0, 1, 2};
160     const std::vector<int> operatorOutputs{3};
161     flatbuffers::Offset <Operator> convolutionOperator =
162         CreateOperator(flatBufferBuilder,
163                        0,
164                        flatBufferBuilder.CreateVector<int32_t>(operatorInputs.data(), operatorInputs.size()),
165                        flatBufferBuilder.CreateVector<int32_t>(operatorOutputs.data(), operatorOutputs.size()),
166                        operatorBuiltinOptionsType,
167                        operatorBuiltinOptions);
168 
169     const std::vector<int> subgraphInputs{0, 1, 2};
170     const std::vector<int> subgraphOutputs{3};
171     flatbuffers::Offset <SubGraph> subgraph =
172         CreateSubGraph(flatBufferBuilder,
173                        flatBufferBuilder.CreateVector(tensors.data(), tensors.size()),
174                        flatBufferBuilder.CreateVector<int32_t>(subgraphInputs.data(), subgraphInputs.size()),
175                        flatBufferBuilder.CreateVector<int32_t>(subgraphOutputs.data(), subgraphOutputs.size()),
176                        flatBufferBuilder.CreateVector(&convolutionOperator, 1));
177 
178     flatbuffers::Offset <flatbuffers::String> modelDescription =
179         flatBufferBuilder.CreateString("ArmnnDelegate: Convolution2d Operator Model");
180     flatbuffers::Offset <OperatorCode> operatorCode = CreateOperatorCode(flatBufferBuilder, convolutionOperatorCode);
181 
182     flatbuffers::Offset <Model> flatbufferModel =
183         CreateModel(flatBufferBuilder,
184                     TFLITE_SCHEMA_VERSION,
185                     flatBufferBuilder.CreateVector(&operatorCode, 1),
186                     flatBufferBuilder.CreateVector(&subgraph, 1),
187                     modelDescription,
188                     flatBufferBuilder.CreateVector(buffers.data(), buffers.size()));
189 
190     flatBufferBuilder.Finish(flatbufferModel, armnnDelegate::FILE_IDENTIFIER);
191 
192     return std::vector<char>(flatBufferBuilder.GetBufferPointer(),
193                              flatBufferBuilder.GetBufferPointer() + flatBufferBuilder.GetSize());
194 }
195 
196 template <typename T, typename B = float>
ConvolutionTest(tflite::BuiltinOperator convolutionOperatorCode,tflite::TensorType tensorType,uint32_t strideX,uint32_t strideY,uint32_t dilationX,uint32_t dilationY,tflite::Padding padding,tflite::ActivationFunctionType fused_activation_function,std::vector<armnn::BackendId> & backends,std::vector<int32_t> & inputShape,std::vector<int32_t> & filterShape,std::vector<int32_t> & outputShape,std::vector<T> & inputValues,std::vector<T> & filterValues,std::vector<T> & expectedOutputValues,const std::vector<int32_t> & biasShape={},const std::vector<B> & biasValues={},const std::vector<float> biasScales={1.0f},const std::vector<int64_t> biasOffsets={0},const std::vector<float> filterScales={1.0f},const std::vector<int64_t> filterOffsets={0},float outputQuantScale=2.0f,int outputQuantOffset=0,float quantScale=1.0f,int quantOffset=0,int32_t depth_multiplier=1,int32_t filterQuantizationDim=3)197 void ConvolutionTest(tflite::BuiltinOperator convolutionOperatorCode,
198                      tflite::TensorType tensorType,
199                      uint32_t strideX,
200                      uint32_t strideY,
201                      uint32_t dilationX,
202                      uint32_t dilationY,
203                      tflite::Padding padding,
204                      tflite::ActivationFunctionType fused_activation_function,
205                      std::vector<armnn::BackendId>& backends,
206                      std::vector<int32_t>& inputShape,
207                      std::vector<int32_t>& filterShape,
208                      std::vector<int32_t>& outputShape,
209                      std::vector<T>& inputValues,
210                      std::vector<T>& filterValues,
211                      std::vector<T>& expectedOutputValues,
212                      const std::vector<int32_t>& biasShape = {},
213                      const std::vector<B>& biasValues = {},
214                      const std::vector<float> biasScales = {1.0f},
215                      const std::vector<int64_t> biasOffsets = {0},
216                      const std::vector<float> filterScales = {1.0f},
217                      const std::vector<int64_t> filterOffsets = {0},
218                      float outputQuantScale = 2.0f,
219                      int outputQuantOffset = 0,
220                      float quantScale = 1.0f,
221                      int quantOffset = 0,
222                      int32_t depth_multiplier = 1,
223                      int32_t filterQuantizationDim = 3)
224 
225 {
226     using namespace delegateTestInterpreter;
227 
228     std::vector<char> modelBuffer;
229     modelBuffer = CreateConv2dTfLiteModel(convolutionOperatorCode,
230                                           tensorType,
231                                           strideX,
232                                           strideY,
233                                           dilationX,
234                                           dilationY,
235                                           padding,
236                                           fused_activation_function,
237                                           inputShape,
238                                           filterShape,
239                                           biasShape,
240                                           outputShape,
241                                           filterValues,
242                                           biasValues,
243                                           biasScales,
244                                           biasOffsets,
245                                           filterScales,
246                                           filterOffsets,
247                                           outputQuantScale,
248                                           outputQuantOffset,
249                                           quantScale,
250                                           quantOffset,
251                                           depth_multiplier,
252                                           filterQuantizationDim);
253 
254     // Setup interpreter with just TFLite Runtime.
255     auto tfLiteInterpreter = DelegateTestInterpreter(modelBuffer);
256     CHECK(tfLiteInterpreter.AllocateTensors() == kTfLiteOk);
257     CHECK(tfLiteInterpreter.FillInputTensor<T>(inputValues, 0) == kTfLiteOk);
258     CHECK(tfLiteInterpreter.Invoke() == kTfLiteOk);
259     std::vector<T>       tfLiteOutputValues = tfLiteInterpreter.GetOutputResult<T>(0);
260     std::vector<int32_t> tfLiteOutputShape  = tfLiteInterpreter.GetOutputShape(0);
261 
262     // Setup interpreter with Arm NN Delegate applied.
263     auto armnnInterpreter = DelegateTestInterpreter(modelBuffer, backends);
264     CHECK(armnnInterpreter.AllocateTensors() == kTfLiteOk);
265     CHECK(armnnInterpreter.FillInputTensor<T>(inputValues, 0) == kTfLiteOk);
266     CHECK(armnnInterpreter.Invoke() == kTfLiteOk);
267     std::vector<T>       armnnOutputValues = armnnInterpreter.GetOutputResult<T>(0);
268     std::vector<int32_t> armnnOutputShape  = armnnInterpreter.GetOutputShape(0);
269 
270     armnnDelegate::CompareOutputData<T>(tfLiteOutputValues, armnnOutputValues, expectedOutputValues);
271     armnnDelegate::CompareOutputShape(tfLiteOutputShape, armnnOutputShape, outputShape);
272 
273     tfLiteInterpreter.Cleanup();
274     armnnInterpreter.Cleanup();
275 }
276 
277 // Conv3d is only correctly supported for external delegates from TF Lite v2.6, as there was a breaking bug in v2.5.
278 #if defined(ARMNN_POST_TFLITE_2_5)
279 template <typename T, typename B = float>
CreateConv3dTfLiteModel(tflite::BuiltinOperator convolutionOperatorCode,tflite::TensorType tensorType,std::vector<uint32_t> strides,std::vector<uint32_t> dilation,tflite::Padding padding,tflite::ActivationFunctionType fused_activation_function,const std::vector<int32_t> & inputTensorShape,const std::vector<int32_t> & filterTensorShape,const std::vector<int32_t> & biasTensorShape,const std::vector<int32_t> & outputTensorShape,const std::vector<T> & filterData,const std::vector<B> & biasData,const std::vector<float> biasScales={1.0f},const std::vector<int64_t> biasOffsets={0},const std::vector<float> filterScales={1.0f},const std::vector<int64_t> filterOffsets={0},float outputQuantScale=2.0f,int outputQuantOffset=0,float quantScale=1.0f,int quantOffset=0,int32_t depth_multiplier=1,int32_t filterQuantizationDim=0)280 std::vector<char> CreateConv3dTfLiteModel(tflite::BuiltinOperator convolutionOperatorCode,
281                                           tflite::TensorType tensorType,
282                                           std::vector<uint32_t> strides,
283                                           std::vector<uint32_t> dilation,
284                                           tflite::Padding padding,
285                                           tflite::ActivationFunctionType fused_activation_function,
286                                           const std::vector<int32_t>& inputTensorShape,
287                                           const std::vector<int32_t>& filterTensorShape,
288                                           const std::vector<int32_t>& biasTensorShape,
289                                           const std::vector<int32_t>& outputTensorShape,
290                                           const std::vector<T>& filterData,
291                                           const std::vector<B>& biasData,
292                                           const std::vector<float> biasScales = {1.0f},
293                                           const std::vector<int64_t> biasOffsets = {0},
294                                           const std::vector<float> filterScales = {1.0f},
295                                           const std::vector<int64_t> filterOffsets = {0},
296                                           float outputQuantScale = 2.0f,
297                                           int outputQuantOffset = 0,
298                                           float quantScale = 1.0f,
299                                           int quantOffset = 0,
300                                           int32_t depth_multiplier = 1,
301                                           int32_t filterQuantizationDim = 0)
302 {
303     using namespace tflite;
304     flatbuffers::FlatBufferBuilder flatBufferBuilder;
305 
306     std::array<flatbuffers::Offset<tflite::Buffer>, 3> buffers;
307     buffers[0] = CreateBuffer(flatBufferBuilder);
308     buffers[1] = CreateBuffer(flatBufferBuilder,
309                               flatBufferBuilder.CreateVector(reinterpret_cast<const uint8_t*>(filterData.data()),
310                                                              sizeof(T) * filterData.size()));
311 
312     buffers[2] = CreateBuffer(flatBufferBuilder,
313                               flatBufferBuilder.CreateVector(reinterpret_cast<const uint8_t*>(biasData.data()),
314                                                              sizeof(B) * biasData.size()));
315 
316     auto quantizationParameters =
317             CreateQuantizationParameters(flatBufferBuilder,
318                                          0,
319                                          0,
320                                          flatBufferBuilder.CreateVector<float>({ quantScale }),
321                                          flatBufferBuilder.CreateVector<int64_t>({ quantOffset }));
322     auto outputQuantizationParameters =
323             CreateQuantizationParameters(flatBufferBuilder,
324                                          0,
325                                          0,
326                                          flatBufferBuilder.CreateVector<float>({ outputQuantScale }),
327                                          flatBufferBuilder.CreateVector<int64_t>({ outputQuantOffset }));
328 
329     auto filterQuantizationParameters =
330             CreateQuantizationParameters(flatBufferBuilder,
331                                          0,
332                                          0,
333                                          flatBufferBuilder.CreateVector<float>(filterScales),
334                                          flatBufferBuilder.CreateVector<int64_t>(filterOffsets),
335                                          tflite::QuantizationDetails_NONE,
336                                          0,
337                                          filterQuantizationDim);
338 
339     auto biasQuantizationParameters =
340             CreateQuantizationParameters(flatBufferBuilder,
341                                          0,
342                                          0,
343                                          flatBufferBuilder.CreateVector<float>(biasScales),
344                                          flatBufferBuilder.CreateVector<int64_t>(biasOffsets));
345 
346     std::array<flatbuffers::Offset<Tensor>, 4> tensors;
347     tensors[0] = CreateTensor(flatBufferBuilder,
348                               flatBufferBuilder.CreateVector<int32_t>(inputTensorShape.data(),
349                                                                       inputTensorShape.size()),
350                               tensorType,
351                               0,
352                               flatBufferBuilder.CreateString("input"),
353                               quantizationParameters);
354     tensors[1] = CreateTensor(flatBufferBuilder,
355                               flatBufferBuilder.CreateVector<int32_t>(filterTensorShape.data(),
356                                                                       filterTensorShape.size()),
357                               tensorType,
358                               1,
359                               flatBufferBuilder.CreateString("filter"),
360                               filterQuantizationParameters);
361 
362     auto biasTensorType = ::tflite::TensorType_FLOAT32;
363     if (tensorType == ::tflite::TensorType_INT8 || tensorType == ::tflite::TensorType_UINT8)
364     {
365         biasTensorType = ::tflite::TensorType_INT32;
366     }
367     tensors[2] = CreateTensor(flatBufferBuilder,
368                               flatBufferBuilder.CreateVector<int32_t>(biasTensorShape.data(), biasTensorShape.size()),
369                               biasTensorType,
370                               2,
371                               flatBufferBuilder.CreateString("bias"),
372                               biasQuantizationParameters);
373     tensors[3] = CreateTensor(flatBufferBuilder,
374                               flatBufferBuilder.CreateVector<int32_t>(outputTensorShape.data(),
375                                                                       outputTensorShape.size()),
376                               tensorType,
377                               0,
378                               flatBufferBuilder.CreateString("output"),
379                               outputQuantizationParameters);
380 
381     tflite::BuiltinOptions operatorBuiltinOptionsType = tflite::BuiltinOptions_Conv3DOptions;
382     flatbuffers::Offset<void> operatorBuiltinOptions = CreateConv3DOptions(flatBufferBuilder,
383                                                                            padding,
384                                                                            strides[2], // Depth
385                                                                            strides[0], // Width
386                                                                            strides[1], // Height
387                                                                            fused_activation_function,
388                                                                            dilation[2],
389                                                                            dilation[0],
390                                                                            dilation[1]).Union();
391 
392     // Create operator
393     const std::vector<int> operatorInputs{0, 1, 2};
394     const std::vector<int> operatorOutputs{3};
395     flatbuffers::Offset <Operator> convolutionOperator =
396             CreateOperator(flatBufferBuilder,
397                            0,
398                            flatBufferBuilder.CreateVector<int32_t>(operatorInputs.data(), operatorInputs.size()),
399                            flatBufferBuilder.CreateVector<int32_t>(operatorOutputs.data(), operatorOutputs.size()),
400                            operatorBuiltinOptionsType,
401                            operatorBuiltinOptions);
402 
403     const std::vector<int> subgraphInputs{0, 1, 2};
404     const std::vector<int> subgraphOutputs{3};
405     flatbuffers::Offset <SubGraph> subgraph =
406             CreateSubGraph(flatBufferBuilder,
407                            flatBufferBuilder.CreateVector(tensors.data(), tensors.size()),
408                            flatBufferBuilder.CreateVector<int32_t>(subgraphInputs.data(), subgraphInputs.size()),
409                            flatBufferBuilder.CreateVector<int32_t>(subgraphOutputs.data(), subgraphOutputs.size()),
410                            flatBufferBuilder.CreateVector(&convolutionOperator, 1));
411 
412     flatbuffers::Offset <flatbuffers::String> modelDescription =
413             flatBufferBuilder.CreateString("ArmnnDelegate: Convolution 3d Operator Model");
414 
415     // If using an operator with a code greater than 127 then the enum value should be passed as the fifth
416     // parameter rather than the second like in other tests.
417     flatbuffers::Offset <OperatorCode> operatorCode =
418             CreateOperatorCode(flatBufferBuilder, 0, 0, 1, tflite::BuiltinOperator_CONV_3D);
419 
420     flatbuffers::Offset <Model> flatbufferModel =
421             CreateModel(flatBufferBuilder,
422                         TFLITE_SCHEMA_VERSION,
423                         flatBufferBuilder.CreateVector(&operatorCode, 1),
424                         flatBufferBuilder.CreateVector(&subgraph, 1),
425                         modelDescription,
426                         flatBufferBuilder.CreateVector(buffers.data(), buffers.size()));
427 
428     flatBufferBuilder.Finish(flatbufferModel, armnnDelegate::FILE_IDENTIFIER);
429 
430     return std::vector<char>(flatBufferBuilder.GetBufferPointer(),
431                              flatBufferBuilder.GetBufferPointer() + flatBufferBuilder.GetSize());
432 }
433 
434 template <typename T, typename B = float>
Convolution3dTest(tflite::BuiltinOperator convolutionOperatorCode,tflite::TensorType tensorType,std::vector<uint32_t> strides,std::vector<uint32_t> dilation,tflite::Padding padding,tflite::ActivationFunctionType fused_activation_function,std::vector<armnn::BackendId> & backends,std::vector<int32_t> & inputShape,std::vector<int32_t> & filterShape,std::vector<int32_t> & outputShape,std::vector<T> & inputValues,std::vector<T> & filterValues,std::vector<T> & expectedOutputValues,const std::vector<int32_t> & biasShape={},const std::vector<B> & biasValues={},const std::vector<float> biasScales={1.0f},const std::vector<int64_t> biasOffsets={0},const std::vector<float> filterScales={1.0f},const std::vector<int64_t> filterOffsets={0},float outputQuantScale=2.0f,int outputQuantOffset=0,float quantScale=1.0f,int quantOffset=0,int32_t depth_multiplier=1,int32_t filterQuantizationDim=3)435 void Convolution3dTest(tflite::BuiltinOperator convolutionOperatorCode,
436                        tflite::TensorType tensorType,
437                        std::vector<uint32_t> strides,
438                        std::vector<uint32_t> dilation,
439                        tflite::Padding padding,
440                        tflite::ActivationFunctionType fused_activation_function,
441                        std::vector<armnn::BackendId>& backends,
442                        std::vector<int32_t>& inputShape,
443                        std::vector<int32_t>& filterShape,
444                        std::vector<int32_t>& outputShape,
445                        std::vector<T>& inputValues,
446                        std::vector<T>& filterValues,
447                        std::vector<T>& expectedOutputValues,
448                        const std::vector<int32_t>& biasShape = {},
449                        const std::vector<B>& biasValues = {},
450                        const std::vector<float> biasScales = {1.0f},
451                        const std::vector<int64_t> biasOffsets = {0},
452                        const std::vector<float> filterScales = {1.0f},
453                        const std::vector<int64_t> filterOffsets = {0},
454                        float outputQuantScale = 2.0f,
455                        int outputQuantOffset = 0,
456                        float quantScale = 1.0f,
457                        int quantOffset = 0,
458                        int32_t depth_multiplier = 1,
459                        int32_t filterQuantizationDim = 3)
460 {
461     using namespace delegateTestInterpreter;
462 
463     std::vector<char> modelBuffer;
464     modelBuffer = CreateConv3dTfLiteModel(convolutionOperatorCode,
465                                           tensorType,
466                                           strides,
467                                           dilation,
468                                           padding,
469                                           fused_activation_function,
470                                           inputShape,
471                                           filterShape,
472                                           biasShape,
473                                           outputShape,
474                                           filterValues,
475                                           biasValues,
476                                           biasScales,
477                                           biasOffsets,
478                                           filterScales,
479                                           filterOffsets,
480                                           outputQuantScale,
481                                           outputQuantOffset,
482                                           quantScale,
483                                           quantOffset,
484                                           depth_multiplier,
485                                           filterQuantizationDim);
486 
487     // Setup interpreter with just TFLite Runtime.
488     auto tfLiteInterpreter = DelegateTestInterpreter(modelBuffer);
489     CHECK(tfLiteInterpreter.AllocateTensors() == kTfLiteOk);
490     CHECK(tfLiteInterpreter.FillInputTensor<T>(inputValues, 0) == kTfLiteOk);
491     CHECK(tfLiteInterpreter.Invoke() == kTfLiteOk);
492     std::vector<T>       tfLiteOutputValues = tfLiteInterpreter.GetOutputResult<T>(0);
493     std::vector<int32_t> tfLiteOutputShape  = tfLiteInterpreter.GetOutputShape(0);
494 
495     // Setup interpreter with Arm NN Delegate applied.
496     auto armnnInterpreter = DelegateTestInterpreter(modelBuffer, backends);
497     CHECK(armnnInterpreter.AllocateTensors() == kTfLiteOk);
498     CHECK(armnnInterpreter.FillInputTensor<T>(inputValues, 0) == kTfLiteOk);
499     CHECK(armnnInterpreter.Invoke() == kTfLiteOk);
500     std::vector<T>       armnnOutputValues = armnnInterpreter.GetOutputResult<T>(0);
501     std::vector<int32_t> armnnOutputShape  = armnnInterpreter.GetOutputShape(0);
502 
503     armnnDelegate::CompareOutputShape(tfLiteOutputShape, armnnOutputShape, outputShape);
504 
505     armnnDelegate::CompareData(expectedOutputValues.data(), armnnOutputValues.data(), expectedOutputValues.size(), 1);
506     armnnDelegate::CompareData(expectedOutputValues.data(), tfLiteOutputValues.data(), expectedOutputValues.size(), 1);
507     armnnDelegate::CompareData(tfLiteOutputValues.data(), armnnOutputValues.data(), expectedOutputValues.size(), 1);
508 
509     tfLiteInterpreter.Cleanup();
510     armnnInterpreter.Cleanup();
511 }
512 #endif
513 
514 template <typename T>
CreateTransposeConvTfLiteModel(tflite::TensorType tensorType,uint32_t strideX,uint32_t strideY,tflite::Padding padding,const std::vector<int32_t> & transposeTensorShape,const std::vector<int32_t> & filterTensorShape,const std::vector<int32_t> & inputTensorShape,const std::vector<int32_t> & outputTensorShape,const std::vector<int32_t> & transposeData,const std::vector<T> & filterData,float filterScale=1.0f,int filterOffset=0,float outputQuantScale=2.0f,int outputQuantOffset=0,float quantScale=1.0f,int quantOffset=0)515 std::vector<char> CreateTransposeConvTfLiteModel(tflite::TensorType tensorType,
516                                                  uint32_t strideX,
517                                                  uint32_t strideY,
518                                                  tflite::Padding padding,
519                                                  const std::vector <int32_t>& transposeTensorShape,
520                                                  const std::vector <int32_t>& filterTensorShape,
521                                                  const std::vector <int32_t>& inputTensorShape,
522                                                  const std::vector <int32_t>& outputTensorShape,
523                                                  const std::vector <int32_t>& transposeData,
524                                                  const std::vector <T>& filterData,
525                                                  float filterScale = 1.0f,
526                                                  int filterOffset = 0,
527                                                  float outputQuantScale = 2.0f,
528                                                  int outputQuantOffset = 0,
529                                                  float quantScale = 1.0f,
530                                                  int quantOffset = 0)
531 {
532     using namespace tflite;
533     flatbuffers::FlatBufferBuilder flatBufferBuilder;
534 
535     std::array<flatbuffers::Offset<tflite::Buffer>, 3> buffers;
536     buffers[0] = CreateBuffer(flatBufferBuilder);
537     buffers[1] = CreateBuffer(flatBufferBuilder,
538                               flatBufferBuilder.CreateVector(reinterpret_cast<const uint8_t*>(transposeData.data()),
539                                                              sizeof(int32_t) * transposeData.size()));
540     buffers[2] = CreateBuffer(flatBufferBuilder,
541                               flatBufferBuilder.CreateVector(reinterpret_cast<const uint8_t*>(filterData.data()),
542                                                              sizeof(T) * filterData.size()));
543 
544     auto quantizationParameters =
545         CreateQuantizationParameters(flatBufferBuilder,
546                                      0,
547                                      0,
548                                      flatBufferBuilder.CreateVector<float>({ quantScale }),
549                                      flatBufferBuilder.CreateVector<int64_t>({ quantOffset }));
550     auto outputQuantizationParameters =
551         CreateQuantizationParameters(flatBufferBuilder,
552                                      0,
553                                      0,
554                                      flatBufferBuilder.CreateVector<float>({ outputQuantScale }),
555                                      flatBufferBuilder.CreateVector<int64_t>({ outputQuantOffset }));
556     auto filterQuantizationParameters =
557         CreateQuantizationParameters(flatBufferBuilder,
558                                      0,
559                                      0,
560                                      flatBufferBuilder.CreateVector<float>({ filterScale }),
561                                      flatBufferBuilder.CreateVector<int64_t>({ filterOffset }));
562 
563     std::array<flatbuffers::Offset<Tensor>, 4> tensors;
564     tensors[0] = CreateTensor(flatBufferBuilder,
565                               flatBufferBuilder.CreateVector<int32_t>(transposeTensorShape.data(),
566                               transposeTensorShape.size()),
567                               tflite::TensorType_INT32,
568                               1);
569     tensors[1] = CreateTensor(flatBufferBuilder,
570                               flatBufferBuilder.CreateVector<int32_t>(filterTensorShape.data(),
571                               filterTensorShape.size()),
572                               tensorType,
573                               2,
574                               flatBufferBuilder.CreateString("filter"),
575                               filterQuantizationParameters);
576     tensors[2] = CreateTensor(flatBufferBuilder,
577                               flatBufferBuilder.CreateVector<int32_t>(inputTensorShape.data(),
578                               inputTensorShape.size()),
579                               tensorType,
580                               0,
581                               flatBufferBuilder.CreateString("input"),
582                               quantizationParameters);
583     tensors[3] = CreateTensor(flatBufferBuilder,
584                               flatBufferBuilder.CreateVector<int32_t>(outputTensorShape.data(),
585                               outputTensorShape.size()),
586                               tensorType,
587                               0,
588                               flatBufferBuilder.CreateString("output"),
589                               outputQuantizationParameters);
590 
591     tflite::BuiltinOptions operatorBuiltinOptionsType = tflite::BuiltinOptions_TransposeConvOptions;
592     flatbuffers::Offset<void> operatorBuiltinOptions =
593         CreateTransposeConvOptions(flatBufferBuilder, padding, strideX, strideY).Union();
594 
595     // create operator
596     const std::vector<int> operatorInputs{0, 1, 2};
597     const std::vector<int> operatorOutputs{3};
598     flatbuffers::Offset <Operator> convolutionOperator =
599         CreateOperator(flatBufferBuilder,
600                        0,
601                        flatBufferBuilder.CreateVector<int32_t>(operatorInputs.data(), operatorInputs.size()),
602                        flatBufferBuilder.CreateVector<int32_t>(operatorOutputs.data(), operatorOutputs.size()),
603                        operatorBuiltinOptionsType,
604                        operatorBuiltinOptions);
605 
606     const std::vector<int> subgraphInputs{0, 1, 2};
607     const std::vector<int> subgraphOutputs{3};
608     flatbuffers::Offset <SubGraph> subgraph =
609         CreateSubGraph(flatBufferBuilder,
610                        flatBufferBuilder.CreateVector(tensors.data(), tensors.size()),
611                        flatBufferBuilder.CreateVector<int32_t>(subgraphInputs.data(), subgraphInputs.size()),
612                        flatBufferBuilder.CreateVector<int32_t>(subgraphOutputs.data(), subgraphOutputs.size()),
613                        flatBufferBuilder.CreateVector(&convolutionOperator, 1));
614 
615     flatbuffers::Offset <flatbuffers::String> modelDescription =
616         flatBufferBuilder.CreateString("ArmnnDelegate: TransposeConv Operator Model");
617     flatbuffers::Offset <OperatorCode> operatorCode =
618         CreateOperatorCode(flatBufferBuilder, tflite::BuiltinOperator_TRANSPOSE_CONV);
619 
620     flatbuffers::Offset <Model> flatbufferModel =
621         CreateModel(flatBufferBuilder,
622                     TFLITE_SCHEMA_VERSION,
623                     flatBufferBuilder.CreateVector(&operatorCode, 1),
624                     flatBufferBuilder.CreateVector(&subgraph, 1),
625                     modelDescription,
626                     flatBufferBuilder.CreateVector(buffers.data(), buffers.size()));
627 
628     flatBufferBuilder.Finish(flatbufferModel, armnnDelegate::FILE_IDENTIFIER);
629 
630     return std::vector<char>(flatBufferBuilder.GetBufferPointer(),
631                              flatBufferBuilder.GetBufferPointer() + flatBufferBuilder.GetSize());
632 }
633 
634 template <typename T>
TransposeConvTest(std::vector<armnn::BackendId> & backends,tflite::TensorType tensorType,uint32_t strideX,uint32_t strideY,tflite::Padding padding,const std::vector<int32_t> & transposeTensorShape,const std::vector<int32_t> & filterTensorShape,const std::vector<int32_t> & inputTensorShape,const std::vector<int32_t> & outputTensorShape,const std::vector<int32_t> & transposeData,const std::vector<T> & filterData,std::vector<T> & inputValues,std::vector<T> & expectedOutputValues,float filterScale=1.0f,int filterOffset=0,float outputQuantScale=1.0f,int outputQuantOffset=0,float quantScale=1.0f,int quantOffset=0)635 void TransposeConvTest(std::vector<armnn::BackendId>& backends,
636                        tflite::TensorType tensorType,
637                        uint32_t strideX,
638                        uint32_t strideY,
639                        tflite::Padding padding,
640                        const std::vector <int32_t>& transposeTensorShape,
641                        const std::vector <int32_t>& filterTensorShape,
642                        const std::vector <int32_t>& inputTensorShape,
643                        const std::vector <int32_t>& outputTensorShape,
644                        const std::vector <int32_t>& transposeData,
645                        const std::vector <T>& filterData,
646                        std::vector<T>& inputValues,
647                        std::vector<T>& expectedOutputValues,
648                        float filterScale = 1.0f,
649                        int filterOffset = 0,
650                        float outputQuantScale = 1.0f,
651                        int outputQuantOffset = 0,
652                        float quantScale = 1.0f,
653                        int quantOffset = 0)
654 {
655     using namespace delegateTestInterpreter;
656 
657     std::vector<char> modelBuffer;
658     modelBuffer = CreateTransposeConvTfLiteModel<T>(tensorType,
659                                                     strideX,
660                                                     strideY,
661                                                     padding,
662                                                     transposeTensorShape,
663                                                     filterTensorShape,
664                                                     inputTensorShape,
665                                                     outputTensorShape,
666                                                     transposeData,
667                                                     filterData,
668                                                     filterScale,
669                                                     filterOffset,
670                                                     outputQuantScale,
671                                                     outputQuantOffset,
672                                                     quantScale,
673                                                     quantOffset);
674 
675 
676     // Setup interpreter with just TFLite Runtime.
677     auto tfLiteInterpreter = DelegateTestInterpreter(modelBuffer);
678     CHECK(tfLiteInterpreter.AllocateTensors() == kTfLiteOk);
679     CHECK(tfLiteInterpreter.FillInputTensor<T>(inputValues, 2) == kTfLiteOk);
680     CHECK(tfLiteInterpreter.Invoke() == kTfLiteOk);
681     std::vector<T>       tfLiteOutputValues = tfLiteInterpreter.GetOutputResult<T>(0);
682     std::vector<int32_t> tfLiteOutputShape  = tfLiteInterpreter.GetOutputShape(0);
683 
684     // Setup interpreter with Arm NN Delegate applied.
685     auto armnnInterpreter = DelegateTestInterpreter(modelBuffer, backends);
686     CHECK(armnnInterpreter.AllocateTensors() == kTfLiteOk);
687     CHECK(armnnInterpreter.FillInputTensor<T>(inputValues, 2) == kTfLiteOk);
688     CHECK(armnnInterpreter.Invoke() == kTfLiteOk);
689     std::vector<T>       armnnOutputValues = armnnInterpreter.GetOutputResult<T>(0);
690     std::vector<int32_t> armnnOutputShape  = armnnInterpreter.GetOutputShape(0);
691 
692     armnnDelegate::CompareOutputData<T>(tfLiteOutputValues, armnnOutputValues, expectedOutputValues);
693     armnnDelegate::CompareOutputShape(tfLiteOutputShape, armnnOutputShape, outputTensorShape);
694 
695     tfLiteInterpreter.Cleanup();
696     armnnInterpreter.Cleanup();
697 }
698 
699 } // anonymous namespace
700 
701 
702 
703 
704