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