blob: 6a3400e9cb5250964b68bbeb3a08fba57d14bfbb [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>
Teresa Charlinad1b3d72023-03-14 12:10:28 +000017#include <schema_generated.h>
Sadik Armagan32ca1442020-11-13 17:51:56 +000018#include <tensorflow/lite/version.h>
19
20#include <doctest/doctest.h>
21
22namespace
23{
24
25template <typename T, typename B = float>
26std::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,
Jan Eilers7612bd62021-04-06 17:29:03 +010040 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},
Sadik Armagan32ca1442020-11-13 17:51:56 +000044 float outputQuantScale = 2.0f,
45 int outputQuantOffset = 0,
46 float quantScale = 1.0f,
47 int quantOffset = 0,
Jan Eilers7612bd62021-04-06 17:29:03 +010048 int32_t depth_multiplier = 1,
49 int32_t filterQuantizationDim = 0)
Sadik Armagan32ca1442020-11-13 17:51:56 +000050{
51 using namespace tflite;
52 flatbuffers::FlatBufferBuilder flatBufferBuilder;
53
Ryan OShea238ecd92023-03-07 11:44:23 +000054 std::array<flatbuffers::Offset<tflite::Buffer>, 5> buffers;
55 buffers[0] = CreateBuffer(flatBufferBuilder);
56 buffers[1] = CreateBuffer(flatBufferBuilder);
57 buffers[2] = CreateBuffer(flatBufferBuilder,
Sadik Armagan32ca1442020-11-13 17:51:56 +000058 flatBufferBuilder.CreateVector(reinterpret_cast<const uint8_t*>(filterData.data()),
59 sizeof(T) * filterData.size()));
60
Ryan OShea238ecd92023-03-07 11:44:23 +000061 buffers[3] = CreateBuffer(flatBufferBuilder,
Sadik Armagan32ca1442020-11-13 17:51:56 +000062 flatBufferBuilder.CreateVector(reinterpret_cast<const uint8_t*>(biasData.data()),
63 sizeof(B) * biasData.size()));
Ryan OShea238ecd92023-03-07 11:44:23 +000064 buffers[4] = CreateBuffer(flatBufferBuilder);
Sadik Armagan32ca1442020-11-13 17:51:56 +000065
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 }));
Jan Eilers7612bd62021-04-06 17:29:03 +010078
Sadik Armagan32ca1442020-11-13 17:51:56 +000079 auto filterQuantizationParameters =
Jan Eilers7612bd62021-04-06 17:29:03 +010080 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));
Sadik Armagan32ca1442020-11-13 17:51:56 +000095
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,
Ryan OShea238ecd92023-03-07 11:44:23 +0000101 1,
Sadik Armagan32ca1442020-11-13 17:51:56 +0000102 flatBufferBuilder.CreateString("input"),
103 quantizationParameters);
104 tensors[1] = CreateTensor(flatBufferBuilder,
105 flatBufferBuilder.CreateVector<int32_t>(filterTensorShape.data(),
106 filterTensorShape.size()),
107 tensorType,
Ryan OShea238ecd92023-03-07 11:44:23 +0000108 2,
Sadik Armagan32ca1442020-11-13 17:51:56 +0000109 flatBufferBuilder.CreateString("filter"),
110 filterQuantizationParameters);
111
112 auto biasTensorType = ::tflite::TensorType_FLOAT32;
Jan Eilerseb616122020-11-20 11:59:40 +0000113 if (tensorType == ::tflite::TensorType_INT8 || tensorType == ::tflite::TensorType_UINT8)
Sadik Armagan32ca1442020-11-13 17:51:56 +0000114 {
115 biasTensorType = ::tflite::TensorType_INT32;
116 }
117 tensors[2] = CreateTensor(flatBufferBuilder,
118 flatBufferBuilder.CreateVector<int32_t>(biasTensorShape.data(), biasTensorShape.size()),
119 biasTensorType,
Ryan OShea238ecd92023-03-07 11:44:23 +0000120 3,
Sadik Armagan32ca1442020-11-13 17:51:56 +0000121 flatBufferBuilder.CreateString("bias"),
Jan Eilers7612bd62021-04-06 17:29:03 +0100122 biasQuantizationParameters);
Sadik Armagan32ca1442020-11-13 17:51:56 +0000123 tensors[3] = CreateTensor(flatBufferBuilder,
124 flatBufferBuilder.CreateVector<int32_t>(outputTensorShape.data(),
125 outputTensorShape.size()),
126 tensorType,
Ryan OShea238ecd92023-03-07 11:44:23 +0000127 4,
Sadik Armagan32ca1442020-11-13 17:51:56 +0000128 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
Keith Davis892fafe2020-11-26 17:40:35 +0000159 const std::vector<int> operatorInputs{0, 1, 2};
160 const std::vector<int> operatorOutputs{3};
Sadik Armagan32ca1442020-11-13 17:51:56 +0000161 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
Keith Davis892fafe2020-11-26 17:40:35 +0000169 const std::vector<int> subgraphInputs{0, 1, 2};
170 const std::vector<int> subgraphOutputs{3};
Sadik Armagan32ca1442020-11-13 17:51:56 +0000171 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
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100190 flatBufferBuilder.Finish(flatbufferModel, armnnDelegate::FILE_IDENTIFIER);
Sadik Armagan32ca1442020-11-13 17:51:56 +0000191
192 return std::vector<char>(flatBufferBuilder.GetBufferPointer(),
193 flatBufferBuilder.GetBufferPointer() + flatBufferBuilder.GetSize());
194}
195
196template <typename T, typename B = float>
197void 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 = {},
Jan Eilers7612bd62021-04-06 17:29:03 +0100214 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},
Sadik Armagan32ca1442020-11-13 17:51:56 +0000218 float outputQuantScale = 2.0f,
219 int outputQuantOffset = 0,
220 float quantScale = 1.0f,
221 int quantOffset = 0,
Jan Eilers7612bd62021-04-06 17:29:03 +0100222 int32_t depth_multiplier = 1,
223 int32_t filterQuantizationDim = 3)
Sadik Armagan32ca1442020-11-13 17:51:56 +0000224
225{
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100226 using namespace delegateTestInterpreter;
Sadik Armagan32ca1442020-11-13 17:51:56 +0000227
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,
Jan Eilers7612bd62021-04-06 17:29:03 +0100243 biasScales,
244 biasOffsets,
245 filterScales,
246 filterOffsets,
Sadik Armagan32ca1442020-11-13 17:51:56 +0000247 outputQuantScale,
248 outputQuantOffset,
249 quantScale,
250 quantOffset,
Jan Eilers7612bd62021-04-06 17:29:03 +0100251 depth_multiplier,
252 filterQuantizationDim);
Sadik Armagan32ca1442020-11-13 17:51:56 +0000253
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100254 // 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);
Sadik Armagan32ca1442020-11-13 17:51:56 +0000261
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100262 // 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);
Sadik Armagan32ca1442020-11-13 17:51:56 +0000269
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100270 armnnDelegate::CompareOutputData<T>(tfLiteOutputValues, armnnOutputValues, expectedOutputValues);
271 armnnDelegate::CompareOutputShape(tfLiteOutputShape, armnnOutputShape, outputShape);
Sadik Armagan32ca1442020-11-13 17:51:56 +0000272
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100273 tfLiteInterpreter.Cleanup();
274 armnnInterpreter.Cleanup();
Sadik Armagan32ca1442020-11-13 17:51:56 +0000275}
276
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100277// 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)
279template <typename T, typename B = float>
280std::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;
Ryan OShea238ecd92023-03-07 11:44:23 +0000307 buffers[0] = CreateBuffer(flatBufferBuilder);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100308 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
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100428 flatBufferBuilder.Finish(flatbufferModel, armnnDelegate::FILE_IDENTIFIER);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100429
430 return std::vector<char>(flatBufferBuilder.GetBufferPointer(),
431 flatBufferBuilder.GetBufferPointer() + flatBufferBuilder.GetSize());
432}
433
434template <typename T, typename B = float>
435void 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{
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100461 using namespace delegateTestInterpreter;
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100462
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
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100487 // 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);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100494
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100495 // 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);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100502
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100503 armnnDelegate::CompareOutputShape(tfLiteOutputShape, armnnOutputShape, outputShape);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100504
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100505 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);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100508
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100509 tfLiteInterpreter.Cleanup();
510 armnnInterpreter.Cleanup();
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100511}
512#endif
513
Sadik Armagan32ca1442020-11-13 17:51:56 +0000514template <typename T>
515std::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;
Ryan OShea238ecd92023-03-07 11:44:23 +0000536 buffers[0] = CreateBuffer(flatBufferBuilder);
Sadik Armagan32ca1442020-11-13 17:51:56 +0000537 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
Keith Davis892fafe2020-11-26 17:40:35 +0000596 const std::vector<int> operatorInputs{0, 1, 2};
597 const std::vector<int> operatorOutputs{3};
Sadik Armagan32ca1442020-11-13 17:51:56 +0000598 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
Keith Davis892fafe2020-11-26 17:40:35 +0000606 const std::vector<int> subgraphInputs{0, 1, 2};
607 const std::vector<int> subgraphOutputs{3};
Sadik Armagan32ca1442020-11-13 17:51:56 +0000608 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
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100628 flatBufferBuilder.Finish(flatbufferModel, armnnDelegate::FILE_IDENTIFIER);
Sadik Armagan32ca1442020-11-13 17:51:56 +0000629
630 return std::vector<char>(flatBufferBuilder.GetBufferPointer(),
631 flatBufferBuilder.GetBufferPointer() + flatBufferBuilder.GetSize());
632}
633
634template <typename T>
635void 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{
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100655 using namespace delegateTestInterpreter;
Sadik Armagan32ca1442020-11-13 17:51:56 +0000656
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
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100676 // 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);
Sadik Armagan32ca1442020-11-13 17:51:56 +0000683
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100684 // 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);
Sadik Armagan32ca1442020-11-13 17:51:56 +0000691
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100692 armnnDelegate::CompareOutputData<T>(tfLiteOutputValues, armnnOutputValues, expectedOutputValues);
693 armnnDelegate::CompareOutputShape(tfLiteOutputShape, armnnOutputShape, outputTensorShape);
Sadik Armagan32ca1442020-11-13 17:51:56 +0000694
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100695 tfLiteInterpreter.Cleanup();
696 armnnInterpreter.Cleanup();
Sadik Armagan32ca1442020-11-13 17:51:56 +0000697}
698
699} // anonymous namespace
700
701
702
703