blob: 076925afac186994c71fbdfc4a36408b0b445965 [file] [log] [blame]
David Monahan1670b0c2020-11-18 14:40:27 +00001//
Colm Donelan7bcae3c2024-01-22 10:07:14 +00002// Copyright © 2020, 2023-2024 Arm Ltd and Contributors. All rights reserved.
David Monahan1670b0c2020-11-18 14:40:27 +00003// SPDX-License-Identifier: MIT
4//
5
6#pragma once
7
8#include "TestUtils.hpp"
9
10#include <armnn_delegate.hpp>
Matthew Sloyanebe392d2023-03-30 10:12:08 +010011#include <DelegateTestInterpreter.hpp>
David Monahan1670b0c2020-11-18 14:40:27 +000012
David Monahan1670b0c2020-11-18 14:40:27 +000013#include <tensorflow/lite/version.h>
14
David Monahan1670b0c2020-11-18 14:40:27 +000015namespace
16{
17
Matthew Sloyan3504e422023-05-03 13:53:02 +010018std::vector<char> CreateReshapeTfLiteModel(
Ryan OShea238ecd92023-03-07 11:44:23 +000019 tflite::BuiltinOperator redefineOperatorCode,
20 tflite::TensorType tensorType,
21 const std::vector<int32_t>& inputTensorShape,
22 const std::vector<int32_t>& outputTensorShape,
23 const std::vector<int32_t>& targetShape,
24 bool useOption = true,
25 float quantScale = 1.0f,
26 int quantOffset = 0)
David Monahan1670b0c2020-11-18 14:40:27 +000027{
28 using namespace tflite;
29 flatbuffers::FlatBufferBuilder flatBufferBuilder;
30 std::vector<flatbuffers::Offset<tflite::Buffer>> buffers;
Ryan OShea238ecd92023-03-07 11:44:23 +000031 buffers.push_back(CreateBuffer(flatBufferBuilder));
32 buffers.push_back(CreateBuffer(flatBufferBuilder));
David Monahan1670b0c2020-11-18 14:40:27 +000033
34 auto quantizationParameters =
Ryan OShea238ecd92023-03-07 11:44:23 +000035 CreateQuantizationParameters(flatBufferBuilder,
36 0,
37 0,
38 flatBufferBuilder.CreateVector<float>({ quantScale }),
39 flatBufferBuilder.CreateVector<int64_t>({ quantOffset }));
David Monahan1670b0c2020-11-18 14:40:27 +000040
41 auto inputTensor = CreateTensor(flatBufferBuilder,
42 flatBufferBuilder.CreateVector<int32_t>(inputTensorShape.data(),
43 inputTensorShape.size()),
44 tensorType,
Ryan OShea238ecd92023-03-07 11:44:23 +000045 1,
David Monahan1670b0c2020-11-18 14:40:27 +000046 flatBufferBuilder.CreateString("input"),
47 quantizationParameters);
48
David Monahan1670b0c2020-11-18 14:40:27 +000049 std::vector<flatbuffers::Offset<Tensor>> tensors;
50 std::vector<int32_t> operatorInputs;
51 std::vector<int> subgraphInputs;
52 flatbuffers::Offset<void> operatorBuiltinOptions;
53
54 if (useOption)
55 {
Ryan OShea238ecd92023-03-07 11:44:23 +000056 buffers.push_back(CreateBuffer(flatBufferBuilder));
57 auto outputTensor = CreateTensor(flatBufferBuilder,
58 flatBufferBuilder.CreateVector<int32_t>(outputTensorShape.data(),
59 outputTensorShape.size()),
60 tensorType,
61 2,
62 flatBufferBuilder.CreateString("output"),
63 quantizationParameters);
David Monahan1670b0c2020-11-18 14:40:27 +000064 tensors = { inputTensor, outputTensor};
Keith Davis892fafe2020-11-26 17:40:35 +000065 operatorInputs = {0};
66 subgraphInputs = {0};
David Monahan1670b0c2020-11-18 14:40:27 +000067 operatorBuiltinOptions = CreateReshapeOptions(
Ryan OShea238ecd92023-03-07 11:44:23 +000068 flatBufferBuilder,
69 flatBufferBuilder.CreateVector(targetShape.data(), targetShape.size())).Union();
David Monahan1670b0c2020-11-18 14:40:27 +000070 }
71 else
72 {
73 buffers.push_back(
Ryan OShea238ecd92023-03-07 11:44:23 +000074 CreateBuffer(flatBufferBuilder,
75 flatBufferBuilder.CreateVector(reinterpret_cast<const uint8_t*>(targetShape.data()),
76 sizeof(int32_t) * targetShape.size())));
David Monahan1670b0c2020-11-18 14:40:27 +000077 int32_t size = static_cast<int32_t>(targetShape.size());
78 auto shapeTensor = CreateTensor(flatBufferBuilder,
79 flatBufferBuilder.CreateVector<int32_t>( { size } ),
80 tflite::TensorType_INT32,
81 2,
82 flatBufferBuilder.CreateString("shape"));
Ryan OShea238ecd92023-03-07 11:44:23 +000083
84 buffers.push_back(CreateBuffer(flatBufferBuilder));
85 auto outputTensor = CreateTensor(flatBufferBuilder,
86 flatBufferBuilder.CreateVector<int32_t>(outputTensorShape.data(),
87 outputTensorShape.size()),
88 tensorType,
89 3,
90 flatBufferBuilder.CreateString("output"),
91 quantizationParameters);
92
David Monahan1670b0c2020-11-18 14:40:27 +000093 tensors = { inputTensor, outputTensor, shapeTensor };
Keith Davis892fafe2020-11-26 17:40:35 +000094 operatorInputs = {0, 2};
95 subgraphInputs = {0, 2};
David Monahan1670b0c2020-11-18 14:40:27 +000096 operatorBuiltinOptions = CreateReshapeOptions(flatBufferBuilder).Union();
97 }
98
99 // create operator
100 tflite::BuiltinOptions operatorBuiltinOptionsType = BuiltinOptions_ReshapeOptions;
101
Keith Davis892fafe2020-11-26 17:40:35 +0000102 const std::vector<int32_t> operatorOutputs{1};
David Monahan1670b0c2020-11-18 14:40:27 +0000103 flatbuffers::Offset <Operator> redefineOperator =
Ryan OShea238ecd92023-03-07 11:44:23 +0000104 CreateOperator(flatBufferBuilder,
105 0,
106 flatBufferBuilder.CreateVector<int32_t>(operatorInputs.data(), operatorInputs.size()),
107 flatBufferBuilder.CreateVector<int32_t>(operatorOutputs.data(), operatorOutputs.size()),
108 operatorBuiltinOptionsType,
109 operatorBuiltinOptions);
David Monahan1670b0c2020-11-18 14:40:27 +0000110
Keith Davis892fafe2020-11-26 17:40:35 +0000111 const std::vector<int> subgraphOutputs{1};
David Monahan1670b0c2020-11-18 14:40:27 +0000112 flatbuffers::Offset <SubGraph> subgraph =
Ryan OShea238ecd92023-03-07 11:44:23 +0000113 CreateSubGraph(flatBufferBuilder,
114 flatBufferBuilder.CreateVector(tensors.data(), tensors.size()),
115 flatBufferBuilder.CreateVector<int32_t>(subgraphInputs.data(), subgraphInputs.size()),
116 flatBufferBuilder.CreateVector<int32_t>(subgraphOutputs.data(), subgraphOutputs.size()),
117 flatBufferBuilder.CreateVector(&redefineOperator, 1));
David Monahan1670b0c2020-11-18 14:40:27 +0000118
119 flatbuffers::Offset <flatbuffers::String> modelDescription =
Ryan OShea238ecd92023-03-07 11:44:23 +0000120 flatBufferBuilder.CreateString("ArmnnDelegate: Reshape Operator Model");
David Monahan1670b0c2020-11-18 14:40:27 +0000121 flatbuffers::Offset <OperatorCode> operatorCode = CreateOperatorCode(flatBufferBuilder,
122 redefineOperatorCode);
123
124 flatbuffers::Offset <Model> flatbufferModel =
Ryan OShea238ecd92023-03-07 11:44:23 +0000125 CreateModel(flatBufferBuilder,
126 TFLITE_SCHEMA_VERSION,
127 flatBufferBuilder.CreateVector(&operatorCode, 1),
128 flatBufferBuilder.CreateVector(&subgraph, 1),
129 modelDescription,
130 flatBufferBuilder.CreateVector(buffers.data(), buffers.size()));
David Monahan1670b0c2020-11-18 14:40:27 +0000131
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100132 flatBufferBuilder.Finish(flatbufferModel, armnnDelegate::FILE_IDENTIFIER);
David Monahan1670b0c2020-11-18 14:40:27 +0000133
134 return std::vector<char>(flatBufferBuilder.GetBufferPointer(),
135 flatBufferBuilder.GetBufferPointer() + flatBufferBuilder.GetSize());
136}
137
Matthew Sloyan3504e422023-05-03 13:53:02 +0100138std::vector<char> CreateRedefineTfLiteModel(
139 tflite::BuiltinOperator redefineOperatorCode,
140 tflite::TensorType tensorType,
141 const std::vector<int32_t>& inputTensorShape,
142 const std::vector<int32_t>& outputTensorShape,
143 const std::vector<int32_t>& squeezeOrAxisData,
144 float quantScale = 1.0f,
145 int quantOffset = 0)
146{
147 using namespace tflite;
148 flatbuffers::FlatBufferBuilder flatBufferBuilder;
149 std::vector<flatbuffers::Offset<tflite::Buffer>> buffers;
150 buffers.push_back(CreateBuffer(flatBufferBuilder));
151 buffers.push_back(CreateBuffer(flatBufferBuilder));
152
153 auto quantizationParameters =
154 CreateQuantizationParameters(flatBufferBuilder,
155 0,
156 0,
157 flatBufferBuilder.CreateVector<float>({ quantScale }),
158 flatBufferBuilder.CreateVector<int64_t>({ quantOffset }));
159
160 auto inputTensor = CreateTensor(flatBufferBuilder,
161 flatBufferBuilder.CreateVector<int32_t>(inputTensorShape.data(),
162 inputTensorShape.size()),
163 tensorType,
164 1,
165 flatBufferBuilder.CreateString("input"),
166 quantizationParameters);
167
168 std::vector<flatbuffers::Offset<Tensor>> tensors;
169 std::vector<int32_t> operatorInputs;
170 std::vector<int> subgraphInputs;
171 flatbuffers::Offset<void> operatorBuiltinOptions;
172 tflite::BuiltinOptions operatorBuiltinOptionsType = BuiltinOptions_SqueezeOptions;
173
174 if (redefineOperatorCode == tflite::BuiltinOperator_SQUEEZE)
175 {
176 buffers.push_back(CreateBuffer(flatBufferBuilder));
177 auto outputTensor = CreateTensor(flatBufferBuilder,
178 flatBufferBuilder.CreateVector<int32_t>(outputTensorShape.data(),
179 outputTensorShape.size()),
180 tensorType,
181 2,
182 flatBufferBuilder.CreateString("output"),
183 quantizationParameters);
184 tensors = { inputTensor, outputTensor};
185 operatorInputs = {0};
186 subgraphInputs = {0};
187 operatorBuiltinOptions =
188 CreateSqueezeOptions(flatBufferBuilder,
189 flatBufferBuilder.CreateVector(squeezeOrAxisData.data(),
190 squeezeOrAxisData.size())).Union();
191
192 operatorBuiltinOptionsType = BuiltinOptions_SqueezeOptions;
193 }
194 else if (redefineOperatorCode == tflite::BuiltinOperator_EXPAND_DIMS)
195 {
196 buffers.push_back(
197 CreateBuffer(flatBufferBuilder,
198 flatBufferBuilder.CreateVector(reinterpret_cast<const uint8_t*>(squeezeOrAxisData.data()),
199 sizeof(int32_t) * squeezeOrAxisData.size())));
200 auto shapeTensor = CreateTensor(flatBufferBuilder,
201 flatBufferBuilder.CreateVector<int32_t>( { 1 } ),
202 tflite::TensorType_INT32,
203 2,
204 flatBufferBuilder.CreateString("axis"));
205
206 buffers.push_back(CreateBuffer(flatBufferBuilder));
207 auto outputTensor = CreateTensor(flatBufferBuilder,
208 flatBufferBuilder.CreateVector<int32_t>(outputTensorShape.data(),
209 outputTensorShape.size()),
210 tensorType,
211 3,
212 flatBufferBuilder.CreateString("output"),
213 quantizationParameters);
214
215 tensors = { inputTensor, outputTensor, shapeTensor };
216 operatorInputs = {0, 2};
217 subgraphInputs = {0, 2};
218 operatorBuiltinOptions = CreateExpandDimsOptions(flatBufferBuilder).Union();
219
220 operatorBuiltinOptionsType = BuiltinOptions_ExpandDimsOptions;
221 }
222
223 const std::vector<int32_t> operatorOutputs{1};
224 flatbuffers::Offset <Operator> redefineOperator =
225 CreateOperator(flatBufferBuilder,
226 0,
227 flatBufferBuilder.CreateVector<int32_t>(operatorInputs.data(), operatorInputs.size()),
228 flatBufferBuilder.CreateVector<int32_t>(operatorOutputs.data(), operatorOutputs.size()),
229 operatorBuiltinOptionsType,
230 operatorBuiltinOptions);
231
232 const std::vector<int> subgraphOutputs{1};
233 flatbuffers::Offset <SubGraph> subgraph =
234 CreateSubGraph(flatBufferBuilder,
235 flatBufferBuilder.CreateVector(tensors.data(), tensors.size()),
236 flatBufferBuilder.CreateVector<int32_t>(subgraphInputs.data(), subgraphInputs.size()),
237 flatBufferBuilder.CreateVector<int32_t>(subgraphOutputs.data(), subgraphOutputs.size()),
238 flatBufferBuilder.CreateVector(&redefineOperator, 1));
239
240 flatbuffers::Offset <flatbuffers::String> modelDescription =
241 flatBufferBuilder.CreateString("ArmnnDelegate: Redefine Operator Model");
242 flatbuffers::Offset <OperatorCode> operatorCode = CreateOperatorCode(flatBufferBuilder,
243 redefineOperatorCode);
244
245 flatbuffers::Offset <Model> flatbufferModel =
246 CreateModel(flatBufferBuilder,
247 TFLITE_SCHEMA_VERSION,
248 flatBufferBuilder.CreateVector(&operatorCode, 1),
249 flatBufferBuilder.CreateVector(&subgraph, 1),
250 modelDescription,
251 flatBufferBuilder.CreateVector(buffers.data(), buffers.size()));
252
253 flatBufferBuilder.Finish(flatbufferModel, armnnDelegate::FILE_IDENTIFIER);
254
255 return std::vector<char>(flatBufferBuilder.GetBufferPointer(),
256 flatBufferBuilder.GetBufferPointer() + flatBufferBuilder.GetSize());
257}
258
David Monahan1670b0c2020-11-18 14:40:27 +0000259template <typename T>
260void RedefineTest(tflite::BuiltinOperator redefineOperatorCode,
261 tflite::TensorType tensorType,
David Monahan1670b0c2020-11-18 14:40:27 +0000262 const std::vector<int32_t>& inputShape,
Narumol Prangnawarat4cf0fe32020-12-18 16:13:06 +0000263 std::vector<int32_t>& outputShape,
David Monahan1670b0c2020-11-18 14:40:27 +0000264 std::vector<T>& inputValues,
265 std::vector<T>& expectedOutputValues,
Matthew Sloyan3504e422023-05-03 13:53:02 +0100266 std::vector<int32_t>& additionalData,
David Monahan1670b0c2020-11-18 14:40:27 +0000267 bool useOption = true,
Colm Donelan7bcae3c2024-01-22 10:07:14 +0000268 const std::vector<armnn::BackendId>& backends = {},
David Monahan1670b0c2020-11-18 14:40:27 +0000269 float quantScale = 1.0f,
270 int quantOffset = 0)
271{
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100272 using namespace delegateTestInterpreter;
Matthew Sloyan3504e422023-05-03 13:53:02 +0100273
274 std::vector<char> modelBuffer;
275 if (redefineOperatorCode == tflite::BuiltinOperator_EXPAND_DIMS)
276 {
277 modelBuffer = CreateRedefineTfLiteModel(redefineOperatorCode,
278 tensorType,
279 inputShape,
280 outputShape,
281 additionalData,
282 quantScale,
283 quantOffset);
284 }
285 else if (redefineOperatorCode == tflite::BuiltinOperator_RESHAPE)
286 {
287 modelBuffer = CreateReshapeTfLiteModel(redefineOperatorCode,
288 tensorType,
289 inputShape,
290 outputShape,
291 additionalData,
292 useOption,
293 quantScale,
294 quantOffset);
295 }
296 else if (redefineOperatorCode == tflite::BuiltinOperator_SQUEEZE)
297 {
298 modelBuffer = CreateRedefineTfLiteModel(redefineOperatorCode,
299 tensorType,
300 inputShape,
301 outputShape,
302 additionalData,
303 quantScale,
304 quantOffset);
305 }
David Monahan1670b0c2020-11-18 14:40:27 +0000306
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100307 // Setup interpreter with just TFLite Runtime.
308 auto tfLiteInterpreter = DelegateTestInterpreter(modelBuffer);
309 CHECK(tfLiteInterpreter.AllocateTensors() == kTfLiteOk);
310 CHECK(tfLiteInterpreter.FillInputTensor<T>(inputValues, 0) == kTfLiteOk);
311 CHECK(tfLiteInterpreter.Invoke() == kTfLiteOk);
312 std::vector<T> tfLiteOutputValues = tfLiteInterpreter.GetOutputResult<T>(0);
313 std::vector<int32_t> tfLiteOutputShape = tfLiteInterpreter.GetOutputShape(0);
David Monahan1670b0c2020-11-18 14:40:27 +0000314
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100315 // Setup interpreter with Arm NN Delegate applied.
Colm Donelan7bcae3c2024-01-22 10:07:14 +0000316 auto armnnInterpreter = DelegateTestInterpreter(modelBuffer, CaptureAvailableBackends(backends));
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100317 CHECK(armnnInterpreter.AllocateTensors() == kTfLiteOk);
318 CHECK(armnnInterpreter.FillInputTensor<T>(inputValues, 0) == kTfLiteOk);
319 CHECK(armnnInterpreter.Invoke() == kTfLiteOk);
320 std::vector<T> armnnOutputValues = armnnInterpreter.GetOutputResult<T>(0);
321 std::vector<int32_t> armnnOutputShape = armnnInterpreter.GetOutputShape(0);
David Monahan1670b0c2020-11-18 14:40:27 +0000322
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100323 armnnDelegate::CompareOutputData<T>(tfLiteOutputValues, armnnOutputValues, expectedOutputValues);
324 armnnDelegate::CompareOutputShape(tfLiteOutputShape, armnnOutputShape, outputShape);
David Monahan1670b0c2020-11-18 14:40:27 +0000325
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100326 tfLiteInterpreter.Cleanup();
327 armnnInterpreter.Cleanup();
David Monahan1670b0c2020-11-18 14:40:27 +0000328}
329
330} // anonymous namespace