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