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 #ifndef TENSORFLOW_LITE_DELEGATES_NNRT_UTILS_H
17 #define TENSORFLOW_LITE_DELEGATES_NNRT_UTILS_H
18
19 #include <map>
20 #include <vector>
21 #include <unordered_map>
22
23 #include "nnrt_delegate.h"
24
25 namespace tflite {
26 constexpr int32_t DEPTHWISE_WEIGHT_BATCH_DIMENSION = 0;
27 constexpr int32_t DEPTHWISE_WEIGHT_HEIGHT_DIMENSION = 1;
28 constexpr int32_t DEPTHWISE_WEIGHT_WIDTH_DIMENSION = 2;
29 constexpr int32_t DEPTHWISE_WEIGHT_CHANNEL_DIMENSION = 3;
30 constexpr int32_t DEPTHWISE_WEIGHT_DIMENSION_COUNT = 4;
31 const std::string NNRT_REFERENCE_DEVICE = "nnrt-reference";
32
33 // Bit mask for tensor flags.
34 enum BIT_MASK {
35 NN_TENSOR_FLAG_SCALAR_AS_TENSOR = 1U << 0,
36 NN_TENSOR_FLAG_INT8_CONVERSION = 1U << 1,
37 NN_TENSOR_FLAG_USE_INT8_ASYMM_SIGNED = 1U << 2,
38 NN_TENSOR_FLAG_FORCE_PER_CHANNEL = 1U << 3,
39 NN_TENSOR_FLAG_HALF_TO_FLOAT_CONVERSION = 1U << 4,
40 };
41
42 // Returns the enum name corresponding to the given error code if the given
43 // value corresponds to an of the error codes in the enumeration above or
44 // an message with the unknown code.
45 // LINT.IfChange(NnrtErrorDescription)
46 extern std::string NnrtErrorDescription(int32_t errorCode);
47
48 #define RETURN_TFLITE_ERROR_IF_NN_ERROR(code, callDesc) \
49 do { \
50 if ((code) != OH_NN_SUCCESS) { \
51 const auto errorDesc = NnrtErrorDescription((code)); \
52 TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "NN API returned error %s at line %d while %s.\n", \
53 errorDesc.c_str(), __LINE__, (callDesc)); \
54 return kTfLiteError; \
55 } \
56 } while (0)
57
58 #define RETURN_TFLITE_ERROR_IF_NN_ERROR_FOR_TENSOR(code, callDesc, pTensor) \
59 do { \
60 if ((code) != OH_NN_SUCCESS) { \
61 const auto errorDesc = NnrtErrorDescription((code)); \
62 TFLITE_LOG_PROD(TFLITE_LOG_ERROR, \
63 "NN API returned error %s at line %d while %s for tensor '%s'.\n", errorDesc.c_str(), \
64 __LINE__, (callDesc), (pTensor)->name ? (pTensor)->name : "no-name"); \
65 return kTfLiteError; \
66 } \
67 } while (0)
68
69 // Return true if type is kTfLiteFloat32.
70 extern bool IsFloat(TfLiteType type);
71
72 // Return true if type is kTfLiteUInt8 or kTfLiteInt8.
73 extern bool IsQuantized(TfLiteType type);
74
75 // Return true if the operator supports scalar data as input.
76 extern bool IsScalarInputSupported(int32_t builtinCode);
77
78 // Returns true if this delegate is configured to use a specific set of devices.
79 // If the acceleratorName in the delegate options is equal to "nnrt-reference"
80 // this method will return true only if the excludeNnrtReference is true.
81 extern bool IsUseTargetDevice(
82 NnrtDelegate::Options delegateOptions, bool excludeNnrtReference = false);
83
84 // Fills the given result vector with the list of devices the given delegate
85 // is referring to.
86 // There are three possible results,
87 // - An empty array (not the full list of available accelerators,
88 // for efficiency reasons) if no accelerator is chosen and the
89 // disallowNnrtCpu delegate option is false.
90 // - A single element array with the target processor, if an accelerator name
91 // is specified in the delegate options.
92 // - The target available device on device.
93 extern TfLiteStatus GetTargetDevice(TfLiteContext* context, TfLiteDelegate* delegate,
94 const NnrtApi* nnrt, size_t& dev);
95
96 // Transpose demension following fixed axis.
97 // If exist -1 in destAxis, return kTfLiteError.
98 extern TfLiteStatus TransposeDims(TfLiteContext* context, const int32_t* dims, uint32_t dimCount,
99 std::vector<int32_t> destAxis, std::vector<int32_t>& weightDims);
100
101 // Get Tensor size by byte.
102 // Calculate Tesnorsize by mul all dimension in dims.
103 // Return kTfLiteError if element dimension is less 0.
104 extern TfLiteStatus GetTensorSize(TfLiteContext* context, const int32_t* dims, int32_t dimCount, int64_t& tensorSize);
105
106 // Transpose dimension for Tensor.
107 // Only change NHWC format tensor to CHWN format tensor, and
108 // the capacity of result vec must equal to input tensor size.
109 template <class T>
TransposeTensor(TfLiteContext * context,int32_t tensorIndex,const int32_t * dims,T * transposeTensor)110 TfLiteStatus TransposeTensor(TfLiteContext* context, int32_t tensorIndex, const int32_t* dims,
111 T* transposeTensor)
112 {
113 TF_LITE_ENSURE_EQ(context, dims != nullptr, true);
114
115 // NHWC -> CHWN
116 TfLiteTensor* tensor = &(context->tensors[tensorIndex]);
117 const T* tensorData = reinterpret_cast<T*>(tensor->data.data);
118 const int32_t batch = dims[DEPTHWISE_WEIGHT_BATCH_DIMENSION];
119 const int32_t height = dims[DEPTHWISE_WEIGHT_HEIGHT_DIMENSION];
120 const int32_t width = dims[DEPTHWISE_WEIGHT_WIDTH_DIMENSION];
121 const int32_t channel = dims[DEPTHWISE_WEIGHT_CHANNEL_DIMENSION];
122
123 for (int32_t c = 0; c < channel; ++c) {
124 for (int32_t j = 0; j < height * width; ++j) {
125 for (int32_t n = 0; n < batch; ++n) {
126 int32_t newPos = c * (height * width) * batch + j * batch + n;
127 int32_t orgPos = n * (height * width) * channel + j * channel + c;
128 *(transposeTensor + newPos) = *(tensorData + orgPos);
129 }
130 }
131 }
132
133 return kTfLiteOk;
134 };
135
136 namespace delegate {
137 namespace nnrt {
138 using unorderedTypeMap = std::unordered_map<int32_t, int32_t>;
139
140 extern const std::vector<int32_t> ACTIVATE_FUSE_TYPE_LIST;
141
142 extern const unorderedTypeMap TFLITE_TYPE_TO_NNRT_TYPE;
143
144 const int32_t INVALID_INDEX = -1;
145
146 const int32_t OH_NN_UNSUPPORT_OPS = -1;
147
148 const int32_t OH_NN_FUSE_UNSUPPORTED = -1;
149 } // namespace nnrt
150 } // namespace delegate
151 } // namespace tflite
152
153 #endif // TENSORFLOW_LITE_DELEGATES_NNRT_UTILS_H
154