1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "nnrt_utils.h"
17
18 #include <iostream>
19 #include "tensorflow/lite/util.h"
20 #include "tensorflow/lite/builtin_ops.h"
21 #include "tensorflow/lite/context_util.h"
22 #include "tensorflow/lite/minimal_logging.h"
23 #include "tensorflow/lite/kernels/kernel_util.h"
24
25 #include "neural_network_runtime_type.h"
26
27 namespace tflite {
NnrtErrorDescription(int32_t errorCode)28 std::string NnrtErrorDescription(int32_t errorCode)
29 {
30 switch (errorCode) {
31 case OH_NN_SUCCESS:
32 return "OH_NN_SUCCESS";
33 case OH_NN_FAILED:
34 return "OH_NN_FAILED";
35 case OH_NN_INVALID_PARAMETER:
36 return "OH_NN_INVALID_PARAMETER";
37 case OH_NN_MEMORY_ERROR:
38 return "OH_NN_MEMORY_ERROR";
39 case OH_NN_OPERATION_FORBIDDEN:
40 return "OH_NN_OPERATION_FORBIDDEN";
41 case OH_NN_NULL_PTR:
42 return "OH_NN_NULL_PTR";
43 case OH_NN_INVALID_FILE:
44 return "OH_NN_INVALID_FILE";
45 case OH_NN_UNAVALIDABLE_DEVICE:
46 return "OH_NN_UNAVALIDABLE_DEVICE";
47 case OH_NN_INVALID_PATH:
48 return "OH_NN_INVALID_PATH";
49 default:
50 return "Unknown NNRT error code: " + std::to_string(errorCode);
51 }
52 }
53
IsFloat(TfLiteType type)54 bool IsFloat(TfLiteType type)
55 {
56 return type == kTfLiteFloat32;
57 }
58
IsQuantized(TfLiteType type)59 bool IsQuantized(TfLiteType type)
60 {
61 return ((type == kTfLiteUInt8) || (type == kTfLiteInt8));
62 }
63
IsScalarInputSupported(int32_t builtinCode)64 bool IsScalarInputSupported(int32_t builtinCode)
65 {
66 switch (builtinCode) {
67 case kTfLiteBuiltinAdd:
68 case kTfLiteBuiltinMul:
69 case kTfLiteBuiltinSub:
70 case kTfLiteBuiltinDiv:
71 case kTfLiteBuiltinEqual:
72 case kTfLiteBuiltinNotEqual:
73 case kTfLiteBuiltinGreater:
74 case kTfLiteBuiltinGreaterEqual:
75 case kTfLiteBuiltinLess:
76 case kTfLiteBuiltinLessEqual:
77 case kTfLiteBuiltinPow:
78 case kTfLiteBuiltinMaximum:
79 case kTfLiteBuiltinMinimum:
80 case kTfLiteBuiltinPrelu:
81 case kTfLiteBuiltinLeakyRelu:
82 return true;
83 default:
84 return false;
85 }
86 }
87
IsUseTargetDevice(NnrtDelegate::Options delegateOptions,bool excludeNnrtReference)88 bool IsUseTargetDevice(NnrtDelegate::Options delegateOptions, bool excludeNnrtReference)
89 {
90 const std::string& deviceName = delegateOptions.acceleratorName;
91 bool hasSelectedAccelerator = !deviceName.empty();
92 if (!excludeNnrtReference && hasSelectedAccelerator) {
93 if (!deviceName.compare(NNRT_REFERENCE_DEVICE)) {
94 hasSelectedAccelerator = false;
95 }
96 }
97
98 return hasSelectedAccelerator;
99 }
100
GetTargetDevice(TfLiteContext * context,TfLiteDelegate * delegate,const NnrtApi * nnrt,size_t & dev)101 TfLiteStatus GetTargetDevice(TfLiteContext* context, TfLiteDelegate* delegate, const NnrtApi* nnrt, size_t& dev)
102 {
103 TF_LITE_ENSURE_EQ(context, nnrt != nullptr, true);
104 TF_LITE_ENSURE_EQ(context, delegate != nullptr, true);
105
106 NnrtDelegate::Options delegateOptions;
107 TF_LITE_ENSURE_STATUS(NnrtDelegate::GetOptions(delegate, delegateOptions));
108 const std::string& deviceName = delegateOptions.acceleratorName;
109
110 uint32_t numDevices {0};
111 const size_t* alldevicesID {nullptr};
112 RETURN_TFLITE_ERROR_IF_NN_ERROR(nnrt->OH_NNDevice_GetAllDevicesID(&alldevicesID, &numDevices),
113 "Get available device number and deviceID.");
114 if (numDevices == 0) {
115 TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "[NNRT-UTILS] Have no available device.");
116 return kTfLiteError;
117 }
118
119 std::vector<OH_NN_DeviceType> deviceTypes;
120 for (uint32_t i = 0; i < numDevices; ++i) {
121 OH_NN_DeviceType tempDeviceType {OH_NN_ACCELERATOR};
122 RETURN_TFLITE_ERROR_IF_NN_ERROR(nnrt->OH_NNDevice_GetType(alldevicesID[i], &tempDeviceType),
123 "Get available devicesType.");
124 deviceTypes.emplace_back(tempDeviceType);
125 }
126
127 OH_NN_DeviceType deviceType {OH_NN_CPU};
128 std::vector<OH_NN_DeviceType>::iterator pos = std::find(deviceTypes.begin(), deviceTypes.end(), deviceType);
129 if (pos != deviceTypes.end()) {
130 int index = distance(deviceTypes.begin(), pos);
131 dev = alldevicesID[index];
132 } else {
133 TFLITE_LOG_PROD(TFLITE_LOG_ERROR,
134 "[NNRT-UTILS] Cannot find the %s device, please choose another process unit.",
135 deviceName.c_str());
136 return kTfLiteError;
137 }
138
139 return kTfLiteOk;
140 }
141
TransposeDims(TfLiteContext * context,const int32_t * dims,uint32_t dimCount,std::vector<int32_t> destAxis,std::vector<int32_t> & weightDims)142 TfLiteStatus TransposeDims(TfLiteContext* context, const int32_t* dims, uint32_t dimCount,
143 std::vector<int32_t> destAxis, std::vector<int32_t>& weightDims)
144 {
145 TF_LITE_ENSURE_EQ(context, dims != nullptr, true);
146
147 if (dimCount != destAxis.size()) {
148 TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "[NNRT-UTILS] Invalid dimension count %d.", dimCount);
149 return kTfLiteError;
150 }
151
152 for (auto axis : destAxis) {
153 if (axis < 0) {
154 TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "[NNRT-UTILS] Invalid axis %d.", axis);
155 return kTfLiteError;
156 }
157 weightDims.emplace_back(*(dims + axis));
158 }
159
160 return kTfLiteOk;
161 }
162
GetTensorSize(TfLiteContext * context,const int32_t * dims,int32_t dimCount,int64_t & tensorSize)163 TfLiteStatus GetTensorSize(TfLiteContext* context, const int32_t* dims, int32_t dimCount, int64_t& tensorSize)
164 {
165 TF_LITE_ENSURE_EQ(context, dims != nullptr, true);
166
167 if (dimCount != DEPTHWISE_WEIGHT_DIMENSION_COUNT) {
168 TFLITE_LOG_PROD(TFLITE_LOG_ERROR,
169 "[NNRT-UTILS] Dimension count is not equal to destination axis number, should be 4.");
170 return kTfLiteError;
171 }
172
173 tensorSize = 1;
174 for (int32_t i = 0; i < dimCount; ++i) {
175 if (*(dims + i) <= 0) {
176 TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "[NNRT-UTILS] Get invalid dimenision.");
177 return kTfLiteError;
178 }
179 tensorSize *= *(dims + i);
180 }
181
182 return kTfLiteOk;
183 }
184
185 namespace delegate {
186 namespace nnrt {
187 const std::vector<int32_t> ACTIVATE_FUSE_TYPE_LIST = {
188 OH_NN_FUSED_NONE,
189 OH_NN_FUSED_RELU,
190 OH_NN_FUSE_UNSUPPORTED,
191 OH_NN_FUSED_RELU6,
192 OH_NN_FUSE_UNSUPPORTED,
193 OH_NN_FUSE_UNSUPPORTED,
194 OH_NN_FUSE_UNSUPPORTED
195 };
196
197 const unorderedTypeMap TFLITE_TYPE_TO_NNRT_TYPE = {
198 {kTfLiteBuiltinAdd, OH_NN_OPS_ADD},
199 {kTfLiteBuiltinAveragePool2d, OH_NN_OPS_AVG_POOL},
200 {kTfLiteBuiltinConcatenation, OH_NN_OPS_CONCAT},
201 {kTfLiteBuiltinConv2d, OH_NN_OPS_CONV2D},
202 {kTfLiteBuiltinDepthwiseConv2d, OH_NN_OPS_DEPTHWISE_CONV2D_NATIVE},
203 {kTfLiteBuiltinDepthToSpace, OH_NN_UNSUPPORT_OPS},
204 {kTfLiteBuiltinDequantize, OH_NN_OPS_QUANT_DTYPE_CAST},
205 {kTfLiteBuiltinEmbeddingLookup, OH_NN_UNSUPPORT_OPS},
206 {kTfLiteBuiltinFloor, OH_NN_UNSUPPORT_OPS},
207 {kTfLiteBuiltinFullyConnected, OH_NN_OPS_FULL_CONNECTION},
208 {kTfLiteBuiltinHashtableLookup, OH_NN_UNSUPPORT_OPS},
209 {kTfLiteBuiltinL2Normalization, OH_NN_UNSUPPORT_OPS},
210 {kTfLiteBuiltinL2Pool2d, OH_NN_UNSUPPORT_OPS},
211 {kTfLiteBuiltinLocalResponseNormalization, OH_NN_UNSUPPORT_OPS},
212 {kTfLiteBuiltinLogistic, OH_NN_OPS_SIGMOID},
213 {kTfLiteBuiltinLshProjection, OH_NN_UNSUPPORT_OPS},
214 {kTfLiteBuiltinLstm, OH_NN_UNSUPPORT_OPS},
215 {kTfLiteBuiltinMaxPool2d, OH_NN_OPS_MAX_POOL},
216 {kTfLiteBuiltinMul, OH_NN_OPS_MUL},
217 {kTfLiteBuiltinRelu, OH_NN_UNSUPPORT_OPS},
218 {kTfLiteBuiltinReluN1To1, OH_NN_UNSUPPORT_OPS},
219 {kTfLiteBuiltinRelu6, OH_NN_UNSUPPORT_OPS},
220 {kTfLiteBuiltinReshape, OH_NN_OPS_RESHAPE},
221 {kTfLiteBuiltinResizeBilinear, OH_NN_UNSUPPORT_OPS},
222 {kTfLiteBuiltinRnn, OH_NN_UNSUPPORT_OPS},
223 {kTfLiteBuiltinSoftmax, OH_NN_OPS_SOFTMAX},
224 {kTfLiteBuiltinSpaceToDepth, OH_NN_UNSUPPORT_OPS},
225 {kTfLiteBuiltinSvdf, OH_NN_UNSUPPORT_OPS},
226 {kTfLiteBuiltinTanh, OH_NN_UNSUPPORT_OPS},
227 {kTfLiteBuiltinConcatEmbeddings, OH_NN_UNSUPPORT_OPS},
228 {kTfLiteBuiltinSkipGram, OH_NN_UNSUPPORT_OPS},
229 {kTfLiteBuiltinCall, OH_NN_UNSUPPORT_OPS},
230 {kTfLiteBuiltinCustom, OH_NN_UNSUPPORT_OPS},
231 {kTfLiteBuiltinEmbeddingLookupSparse, OH_NN_UNSUPPORT_OPS},
232 {kTfLiteBuiltinPad, OH_NN_OPS_PAD},
233 {kTfLiteBuiltinUnidirectionalSequenceRnn, OH_NN_UNSUPPORT_OPS},
234 {kTfLiteBuiltinGather, OH_NN_UNSUPPORT_OPS},
235 {kTfLiteBuiltinBatchToSpaceNd, OH_NN_UNSUPPORT_OPS},
236 {kTfLiteBuiltinSpaceToBatchNd, OH_NN_UNSUPPORT_OPS},
237 {kTfLiteBuiltinTranspose, OH_NN_UNSUPPORT_OPS},
238 {kTfLiteBuiltinMean, OH_NN_OPS_REDUCE_MEAN},
239 {kTfLiteBuiltinSub, OH_NN_OPS_SUB},
240 {kTfLiteBuiltinDiv, OH_NN_UNSUPPORT_OPS},
241 {kTfLiteBuiltinSqueeze, OH_NN_UNSUPPORT_OPS},
242 {kTfLiteBuiltinUnidirectionalSequenceLstm, OH_NN_UNSUPPORT_OPS},
243 {kTfLiteBuiltinStridedSlice, OH_NN_OPS_STRIDED_SLICE},
244 {kTfLiteBuiltinBidirectionalSequenceRnn, OH_NN_UNSUPPORT_OPS},
245 {kTfLiteBuiltinExp, OH_NN_UNSUPPORT_OPS},
246 {kTfLiteBuiltinTopkV2, OH_NN_UNSUPPORT_OPS},
247 {kTfLiteBuiltinSplit, OH_NN_UNSUPPORT_OPS},
248 {kTfLiteBuiltinLogSoftmax, OH_NN_UNSUPPORT_OPS},
249 {kTfLiteBuiltinDelegate, OH_NN_UNSUPPORT_OPS},
250 {kTfLiteBuiltinBidirectionalSequenceLstm, OH_NN_UNSUPPORT_OPS},
251 {kTfLiteBuiltinCast, OH_NN_UNSUPPORT_OPS},
252 {kTfLiteBuiltinPrelu, OH_NN_UNSUPPORT_OPS},
253 {kTfLiteBuiltinMaximum, OH_NN_UNSUPPORT_OPS},
254 {kTfLiteBuiltinArgMax, OH_NN_UNSUPPORT_OPS},
255 {kTfLiteBuiltinMinimum, OH_NN_UNSUPPORT_OPS},
256 {kTfLiteBuiltinLess, OH_NN_UNSUPPORT_OPS},
257 {kTfLiteBuiltinNeg, OH_NN_UNSUPPORT_OPS},
258 {kTfLiteBuiltinPadv2, OH_NN_UNSUPPORT_OPS},
259 {kTfLiteBuiltinGreater, OH_NN_UNSUPPORT_OPS},
260 {kTfLiteBuiltinGreaterEqual, OH_NN_UNSUPPORT_OPS},
261 {kTfLiteBuiltinLessEqual, OH_NN_UNSUPPORT_OPS},
262 {kTfLiteBuiltinSelect, OH_NN_UNSUPPORT_OPS},
263 {kTfLiteBuiltinSlice, OH_NN_UNSUPPORT_OPS},
264 {kTfLiteBuiltinSin, OH_NN_UNSUPPORT_OPS},
265 {kTfLiteBuiltinTransposeConv, OH_NN_UNSUPPORT_OPS},
266 {kTfLiteBuiltinSparseToDense, OH_NN_UNSUPPORT_OPS},
267 {kTfLiteBuiltinTile, OH_NN_UNSUPPORT_OPS},
268 {kTfLiteBuiltinExpandDims, OH_NN_UNSUPPORT_OPS},
269 {kTfLiteBuiltinEqual, OH_NN_UNSUPPORT_OPS},
270 {kTfLiteBuiltinNotEqual, OH_NN_UNSUPPORT_OPS},
271 {kTfLiteBuiltinLog, OH_NN_UNSUPPORT_OPS},
272 {kTfLiteBuiltinSum, OH_NN_UNSUPPORT_OPS},
273 {kTfLiteBuiltinSqrt, OH_NN_UNSUPPORT_OPS},
274 {kTfLiteBuiltinRsqrt, OH_NN_UNSUPPORT_OPS},
275 {kTfLiteBuiltinShape, OH_NN_OPS_SHAPE},
276 {kTfLiteBuiltinPow, OH_NN_UNSUPPORT_OPS},
277 {kTfLiteBuiltinArgMin, OH_NN_UNSUPPORT_OPS},
278 {kTfLiteBuiltinFakeQuant, OH_NN_UNSUPPORT_OPS},
279 {kTfLiteBuiltinReduceProd, OH_NN_UNSUPPORT_OPS},
280 {kTfLiteBuiltinReduceMax, OH_NN_UNSUPPORT_OPS},
281 {kTfLiteBuiltinPack, OH_NN_OPS_STACK},
282 {kTfLiteBuiltinLogicalOr, OH_NN_UNSUPPORT_OPS},
283 {kTfLiteBuiltinOneHot, OH_NN_UNSUPPORT_OPS},
284 {kTfLiteBuiltinLogicalAnd, OH_NN_UNSUPPORT_OPS},
285 {kTfLiteBuiltinLogicalNot, OH_NN_UNSUPPORT_OPS},
286 {kTfLiteBuiltinUnpack, OH_NN_UNSUPPORT_OPS},
287 {kTfLiteBuiltinReduceMin, OH_NN_UNSUPPORT_OPS},
288 {kTfLiteBuiltinFloorDiv, OH_NN_UNSUPPORT_OPS},
289 {kTfLiteBuiltinReduceAny, OH_NN_UNSUPPORT_OPS},
290 {kTfLiteBuiltinSquare, OH_NN_UNSUPPORT_OPS},
291 {kTfLiteBuiltinZerosLike, OH_NN_UNSUPPORT_OPS},
292 {kTfLiteBuiltinFill, OH_NN_UNSUPPORT_OPS},
293 {kTfLiteBuiltinFloorMod, OH_NN_UNSUPPORT_OPS},
294 {kTfLiteBuiltinRange, OH_NN_UNSUPPORT_OPS},
295 {kTfLiteBuiltinResizeNearestNeighbor, OH_NN_UNSUPPORT_OPS},
296 {kTfLiteBuiltinLeakyRelu, OH_NN_UNSUPPORT_OPS},
297 {kTfLiteBuiltinSquaredDifference, OH_NN_UNSUPPORT_OPS},
298 {kTfLiteBuiltinMirrorPad, OH_NN_UNSUPPORT_OPS},
299 {kTfLiteBuiltinAbs, OH_NN_UNSUPPORT_OPS},
300 {kTfLiteBuiltinSplitV, OH_NN_UNSUPPORT_OPS},
301 {kTfLiteBuiltinUnique, OH_NN_UNSUPPORT_OPS},
302 {kTfLiteBuiltinCeil, OH_NN_UNSUPPORT_OPS},
303 {kTfLiteBuiltinReverseV2, OH_NN_UNSUPPORT_OPS},
304 {kTfLiteBuiltinAddN, OH_NN_UNSUPPORT_OPS},
305 {kTfLiteBuiltinGatherNd, OH_NN_UNSUPPORT_OPS},
306 {kTfLiteBuiltinCos, OH_NN_UNSUPPORT_OPS},
307 {kTfLiteBuiltinWhere, OH_NN_UNSUPPORT_OPS},
308 {kTfLiteBuiltinRank, OH_NN_UNSUPPORT_OPS},
309 {kTfLiteBuiltinElu, OH_NN_UNSUPPORT_OPS},
310 {kTfLiteBuiltinReverseSequence, OH_NN_UNSUPPORT_OPS},
311 {kTfLiteBuiltinMatrixDiag, OH_NN_UNSUPPORT_OPS},
312 {kTfLiteBuiltinQuantize, OH_NN_OPS_QUANT_DTYPE_CAST},
313 {kTfLiteBuiltinMatrixSetDiag, OH_NN_UNSUPPORT_OPS},
314 {kTfLiteBuiltinRound, OH_NN_UNSUPPORT_OPS},
315 {kTfLiteBuiltinHardSwish, OH_NN_OPS_HSWISH},
316 {kTfLiteBuiltinIf, OH_NN_UNSUPPORT_OPS},
317 {kTfLiteBuiltinWhile, OH_NN_UNSUPPORT_OPS},
318 {kTfLiteBuiltinNonMaxSuppressionV4, OH_NN_UNSUPPORT_OPS},
319 {kTfLiteBuiltinNonMaxSuppressionV5, OH_NN_UNSUPPORT_OPS},
320 {kTfLiteBuiltinScatterNd, OH_NN_UNSUPPORT_OPS},
321 {kTfLiteBuiltinSelectV2, OH_NN_UNSUPPORT_OPS},
322 {kTfLiteBuiltinDensify, OH_NN_UNSUPPORT_OPS},
323 {kTfLiteBuiltinSegmentSum, OH_NN_UNSUPPORT_OPS},
324 {kTfLiteBuiltinBatchMatmul, OH_NN_UNSUPPORT_OPS},
325 {kTfLiteBuiltinPlaceholderForGreaterOpCodes, OH_NN_UNSUPPORT_OPS},
326 {kTfLiteBuiltinCumsum, OH_NN_UNSUPPORT_OPS},
327 {kTfLiteBuiltinCallOnce, OH_NN_UNSUPPORT_OPS},
328 {kTfLiteBuiltinBroadcastTo, OH_NN_UNSUPPORT_OPS},
329 {kTfLiteBuiltinRfft2d, OH_NN_UNSUPPORT_OPS},
330 {kTfLiteBuiltinConv3d, OH_NN_UNSUPPORT_OPS},
331 {kTfLiteBuiltinImag, OH_NN_UNSUPPORT_OPS},
332 {kTfLiteBuiltinReal, OH_NN_UNSUPPORT_OPS},
333 {kTfLiteBuiltinComplexAbs, OH_NN_UNSUPPORT_OPS},
334 {kTfLiteBuiltinHashtable, OH_NN_UNSUPPORT_OPS},
335 {kTfLiteBuiltinHashtableFind, OH_NN_UNSUPPORT_OPS},
336 {kTfLiteBuiltinHashtableImport, OH_NN_UNSUPPORT_OPS},
337 {kTfLiteBuiltinHashtableSize, OH_NN_UNSUPPORT_OPS},
338 {kTfLiteBuiltinReduceAll, OH_NN_UNSUPPORT_OPS},
339 {kTfLiteBuiltinConv3dTranspose, OH_NN_UNSUPPORT_OPS},
340 {kTfLiteBuiltinVarHandle, OH_NN_UNSUPPORT_OPS},
341 {kTfLiteBuiltinReadVariable, OH_NN_UNSUPPORT_OPS},
342 {kTfLiteBuiltinAssignVariable, OH_NN_UNSUPPORT_OPS},
343 {kTfLiteBuiltinBroadcastTo, OH_NN_UNSUPPORT_OPS},
344 };
345 } // nnrt
346 } // namespace
347 } // namespace tflite