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 #define __STDC_WANT_LIB_EXT1__ 1
16
17 #include "nnrt_op_builder.h"
18
19 #include <cstring>
20
21 #include "neural_network_runtime.h"
22 #include "tensorflow/lite/util.h"
23 #include "tensorflow/lite/context_util.h"
24
25 #include "nnrt_utils.h"
26
27 namespace tflite {
28 namespace delegate {
29 namespace nnrt {
30 constexpr int32_t SCALAR_TENSOR_RANK = 1;
31 constexpr int32_t ADDZEROS_BIAS_INDEX = -1;
32 constexpr int32_t UNSPECIFIED_DIMENSION_VALUE = -1;
33 const std::vector<int32_t> DEPTHWISE_TRANSPOSE_AXISS = { 3, 1, 2, 0 };
34
NnrtOpBuilder(const NnrtApi * nnrt,NnrtOpBuilderArgs & opBuilderArgs)35 NnrtOpBuilder::NnrtOpBuilder(const NnrtApi* nnrt, NnrtOpBuilderArgs& opBuilderArgs)
36 : m_nnrt(nnrt),
37 m_context(opBuilderArgs.context),
38 m_pTensorMapping(opBuilderArgs.pTensorMapping),
39 m_nnModel(opBuilderArgs.nnModel),
40 m_allowDynamicDimensions(opBuilderArgs.delegateOptions.allowDynamicDimensions)
41 {
42 // Map Op func pointer
43 MapBuiltinCodeToFunc();
44
45 // Get model inputs
46 for (int32_t i : TfLiteIntArrayView(opBuilderArgs.inputTensors)) {
47 // Constant tensors are not NNRT inputs.
48 if (i != kTfLiteOptionalTensor && opBuilderArgs.context->tensors[i].allocation_type != kTfLiteMmapRo) {
49 m_inputs.emplace_back(i);
50 }
51 }
52 }
53
AddZerosBias(const NnrtOpMappingArgs & mappingArgs,int32_t inputId,int32_t filterId,int32_t channelNum)54 TfLiteStatus NnrtOpBuilder::AddZerosBias(const NnrtOpMappingArgs& mappingArgs, int32_t inputId, int32_t filterId,
55 int32_t channelNum)
56 {
57 int32_t biasIndex = ADDZEROS_BIAS_INDEX;
58 mappingArgs.context->AddTensors(mappingArgs.context, 1, &biasIndex);
59 TfLiteTensor* biasTensor = &mappingArgs.context->tensors[biasIndex];
60 const auto inputType = mappingArgs.context->tensors[inputId].type;
61
62 if (inputType == kTfLiteFloat32) {
63 biasTensor->type = kTfLiteFloat32;
64 } else {
65 biasTensor->type = kTfLiteInt32;
66 }
67
68 // Create an array with a required bias shape and resize the bias tensor.
69 TfLiteIntArray* biasShape = TfLiteIntArrayCreate(1); // 1-dimension
70 biasShape->data[0] = channelNum;
71 biasTensor->allocation_type = kTfLiteDynamic;
72 mappingArgs.context->ResizeTensor(mappingArgs.context, biasTensor, biasShape);
73
74 // Set tensor's values to zeroes and add it using AddVector*, so that the values are copied to NNRT.
75 #ifdef __STDC_LIB_EXT1__
76 if (inputType == kTfLiteFloat32) {
77 memset_s(biasTensor->data.f, biasTensor->bytes, 0, channelNum * sizeof(float));
78 TF_LITE_ENSURE_STATUS(mappingArgs.builder->AddVectorFloat32Tensor(biasTensor->data.f, channelNum,
79 OH_NN_TENSOR));
80 } else {
81 memset_s(biasTensor->data.i32, biasTensor->bytes, 0, channelNum * sizeof(int32_t));
82 const TfLiteTensor& inputTensor = mappingArgs.context->tensors[inputId];
83 const TfLiteTensor& filterTensor = mappingArgs.context->tensors[filterId];
84
85 // NNRT requires bias scale to be a product of an input scale and a filter scale.
86 biasTensor->params.scale = inputTensor.params.scale * filterTensor.params.scale;
87 TF_LITE_ENSURE_STATUS(mappingArgs.builder->AddVectorInt32Tensor(biasTensor->data.i32, channelNum,
88 OH_NN_TENSOR));
89 }
90 #endif
91
92 return kTfLiteOk;
93 }
94
AddBasicComputeParams(const NnrtOpMappingArgs & mappingArgs,int32_t builtinCode)95 TfLiteStatus NnrtOpBuilder::AddBasicComputeParams(const NnrtOpMappingArgs& mappingArgs, int32_t builtinCode)
96 {
97 if (builtinCode == kTfLiteBuiltinAdd) {
98 auto builtin = reinterpret_cast<TfLiteAddParams*>(mappingArgs.node->builtin_data);
99 TF_LITE_ENSURE_STATUS(AddActivateParamsInOperator<TfLiteAddParams>(mappingArgs, builtin, builtinCode,
100 OH_NN_ADD_ACTIVATIONTYPE));
101 } else if (builtinCode == kTfLiteBuiltinMul) {
102 auto builtin = reinterpret_cast<TfLiteMulParams*>(mappingArgs.node->builtin_data);
103 TF_LITE_ENSURE_STATUS(AddActivateParamsInOperator<TfLiteMulParams>(mappingArgs, builtin, builtinCode,
104 OH_NN_MUL_ACTIVATION_TYPE));
105 } else if (builtinCode == kTfLiteBuiltinSub) {
106 auto builtin = reinterpret_cast<TfLiteSubParams*>(mappingArgs.node->builtin_data);
107 TF_LITE_ENSURE_STATUS(AddActivateParamsInOperator<TfLiteSubParams>(mappingArgs, builtin, builtinCode,
108 OH_NN_SUB_ACTIVATIONTYPE));
109 } else {
110 TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "[NNRT-OPBUILDER] unsupportted basic compute type %d.", builtinCode);
111 return kTfLiteError;
112 }
113
114 return kTfLiteOk;
115 }
116
AddAvgPoolingParams(const NnrtOpMappingArgs & mappingArgs,int32_t builtinCode)117 TfLiteStatus NnrtOpBuilder::AddAvgPoolingParams(const NnrtOpMappingArgs& mappingArgs, int32_t builtinCode)
118 {
119 auto builtin = reinterpret_cast<TfLitePoolParams*>(mappingArgs.node->builtin_data);
120 std::vector<int64_t> kernel = { static_cast<int64_t>(builtin->filter_height),
121 static_cast<int64_t>(builtin->filter_width) };
122 std::vector<int64_t> stride = { static_cast<int64_t>(builtin->stride_height),
123 static_cast<int64_t>(builtin->stride_width) };
124
125 mappingArgs.builder->AddVectorInt64Tensor(kernel.data(), kernel.size(), OH_NN_AVG_POOL_KERNEL_SIZE);
126 mappingArgs.builder->AddVectorInt64Tensor(stride.data(), stride.size(), OH_NN_AVG_POOL_STRIDE);
127 TF_LITE_ENSURE_STATUS(AddPadParamsInOperator<TfLitePoolParams>(mappingArgs, builtin, builtinCode,
128 OH_NN_AVG_POOL_PAD_MODE));
129 TF_LITE_ENSURE_STATUS(AddActivateParamsInOperator<TfLitePoolParams>(mappingArgs, builtin, builtinCode,
130 OH_NN_AVG_POOL_ACTIVATION_TYPE));
131
132 return kTfLiteOk;
133 }
134
AddMaxPoolingParams(const NnrtOpMappingArgs & mappingArgs,int32_t builtinCode)135 TfLiteStatus NnrtOpBuilder::AddMaxPoolingParams(const NnrtOpMappingArgs& mappingArgs, int32_t builtinCode)
136 {
137 auto builtin = reinterpret_cast<TfLitePoolParams*>(mappingArgs.node->builtin_data);
138 std::vector<int64_t> kernel = { static_cast<int64_t>(builtin->filter_height),
139 static_cast<int64_t>(builtin->filter_width) };
140 std::vector<int64_t> stride = { static_cast<int64_t>(builtin->stride_height),
141 static_cast<int64_t>(builtin->stride_width) };
142
143 mappingArgs.builder->AddVectorInt64Tensor(kernel.data(), kernel.size(), OH_NN_MAX_POOL_KERNEL_SIZE);
144 mappingArgs.builder->AddVectorInt64Tensor(stride.data(), stride.size(), OH_NN_MAX_POOL_STRIDE);
145 TF_LITE_ENSURE_STATUS(AddPadParamsInOperator<TfLitePoolParams>(mappingArgs, builtin, builtinCode,
146 OH_NN_MAX_POOL_PAD_MODE));
147 TF_LITE_ENSURE_STATUS(AddActivateParamsInOperator<TfLitePoolParams>(mappingArgs, builtin, builtinCode,
148 OH_NN_MAX_POOL_ACTIVATION_TYPE));
149
150 return kTfLiteOk;
151 }
152
AddFullConnectedParams(const NnrtOpMappingArgs & mappingArgs,int32_t builtinCode)153 TfLiteStatus NnrtOpBuilder::AddFullConnectedParams(const NnrtOpMappingArgs& mappingArgs, int32_t builtinCode)
154 {
155 // IF bias is not presented, bias input index will be -1.
156 const bool isBiasPresent =
157 (mappingArgs.node->inputs->size == 3) && (mappingArgs.node->inputs->data[2] != kTfLiteOptionalTensor);
158
159 if (!isBiasPresent) {
160 const int32_t inputTensorId = mappingArgs.node->inputs->data[0]; // kInputTensor
161 const int32_t filterTensorId = mappingArgs.node->inputs->data[1]; // kWeightsTensor
162 const int32_t numUnits = mappingArgs.context->tensors[filterTensorId].dims->data[0]; // bias channel num
163 TF_LITE_ENSURE_STATUS(AddZerosBias(mappingArgs, inputTensorId, filterTensorId, numUnits));
164 }
165
166 auto builtin = reinterpret_cast<TfLiteFullyConnectedParams*>(mappingArgs.node->builtin_data);
167 TF_LITE_ENSURE_STATUS(AddActivateParamsInOperator<TfLiteFullyConnectedParams>(mappingArgs, builtin, builtinCode,
168 OH_NN_FULL_CONNECTION_ACTIVATIONTYPE));
169
170 return kTfLiteOk;
171 }
172
AddConcatenationParams(const NnrtOpMappingArgs & mappingArgs,int32_t builtinCode)173 TfLiteStatus NnrtOpBuilder::AddConcatenationParams(const NnrtOpMappingArgs& mappingArgs, int32_t builtinCode)
174 {
175 auto builtin = reinterpret_cast<TfLiteConcatenationParams*>(mappingArgs.node->builtin_data);
176 const int64_t axis = static_cast<int64_t>(builtin->axis);
177 mappingArgs.builder->AddScalarInt64Tensor(axis, OH_NN_CONCAT_AXIS);
178
179 return kTfLiteOk;
180 }
181
AddSoftmaxParams(const NnrtOpMappingArgs & mappingArgs,int32_t builtinCode)182 TfLiteStatus NnrtOpBuilder::AddSoftmaxParams(const NnrtOpMappingArgs& mappingArgs, int32_t builtinCode)
183 {
184 auto builtin = reinterpret_cast<TfLiteSoftmaxParams*>(mappingArgs.node->builtin_data);
185 const int64_t axis = static_cast<int64_t>(builtin->beta);
186 mappingArgs.builder->AddScalarInt64Tensor(axis, OH_NN_SOFTMAX_AXIS);
187
188 return kTfLiteOk;
189 }
190
AddQuantizeParams(const NnrtOpMappingArgs & mappingArgs,int32_t builtinCode)191 TfLiteStatus NnrtOpBuilder::AddQuantizeParams(const NnrtOpMappingArgs& mappingArgs, int32_t builtinCode)
192 {
193 OH_NN_DataType nnType {OH_NN_FLOAT32};
194
195 int32_t inputIndex = mappingArgs.node->inputs->data[0];
196 m_pTensorMapping->ConvertType(m_context, inputIndex, 0, nnType);
197 mappingArgs.builder->AddScalarInt64Tensor(static_cast<int64_t>(nnType), OH_NN_QUANT_DTYPE_CAST_SRC_T);
198
199 int32_t outputIndex = mappingArgs.node->outputs->data[0];
200 m_pTensorMapping->ConvertType(m_context, outputIndex, 0, nnType);
201 mappingArgs.builder->AddScalarInt64Tensor(static_cast<int64_t>(nnType), OH_NN_QUANT_DTYPE_CAST_DST_T);
202
203 return kTfLiteOk;
204 }
205
AddPackParams(const NnrtOpMappingArgs & mappingArgs,int32_t builtinCode)206 TfLiteStatus NnrtOpBuilder::AddPackParams(const NnrtOpMappingArgs& mappingArgs, int32_t builtinCode)
207 {
208 auto builtin = reinterpret_cast<TfLitePackParams*>(mappingArgs.node->builtin_data);
209 const int64_t axis = static_cast<int64_t>(builtin->axis);
210 mappingArgs.builder->AddScalarInt64Tensor(axis, OH_NN_STACK_AXIS);
211
212 return kTfLiteOk;
213 }
214
AddPadParams(const NnrtOpMappingArgs & mappingArgs,int32_t builtinCode)215 TfLiteStatus NnrtOpBuilder::AddPadParams(const NnrtOpMappingArgs& mappingArgs, int32_t builtinCode)
216 {
217 float padValue = 0.0;
218 mappingArgs.builder->AddScalarFloat32Tensor(padValue, OH_NN_PAD_CONSTANT_VALUE);
219 return kTfLiteOk;
220 }
221
AddReduceMeanParams(const NnrtOpMappingArgs & mappingArgs,int32_t builtinCode)222 TfLiteStatus NnrtOpBuilder::AddReduceMeanParams(const NnrtOpMappingArgs& mappingArgs, int32_t builtinCode)
223 {
224 auto builtin = reinterpret_cast<TfLiteReducerParams*>(mappingArgs.node->builtin_data);
225 const int32_t keepDims = (builtin->keep_dims);
226 mappingArgs.builder->AddScalarBoolTensor(keepDims, OH_NN_REDUCE_MEAN_KEEP_DIMS);
227
228 return kTfLiteOk;
229 }
230
AddStridedSliceParams(const NnrtOpMappingArgs & mappingArgs,int32_t builtinCode)231 TfLiteStatus NnrtOpBuilder::AddStridedSliceParams(const NnrtOpMappingArgs& mappingArgs, int32_t builtinCode)
232 {
233 auto builtin = reinterpret_cast<TfLiteStridedSliceParams*>(mappingArgs.node->builtin_data);
234 mappingArgs.builder->AddScalarInt64Tensor(static_cast<int64_t>(builtin->begin_mask),
235 OH_NN_STRIDED_SLICE_BEGIN_MASK);
236 mappingArgs.builder->AddScalarInt64Tensor(static_cast<int64_t>(builtin->end_mask),
237 OH_NN_STRIDED_SLICE_END_MASK);
238 mappingArgs.builder->AddScalarInt64Tensor(static_cast<int64_t>(builtin->ellipsis_mask),
239 OH_NN_STRIDED_SLICE_ELLIPSIS_MASK);
240 mappingArgs.builder->AddScalarInt64Tensor(static_cast<int64_t>(builtin->new_axis_mask),
241 OH_NN_STRIDED_SLICE_NEW_AXIS_MASK);
242 mappingArgs.builder->AddScalarInt64Tensor(static_cast<int64_t>(builtin->shrink_axis_mask),
243 OH_NN_STRIDED_SLICE_SHRINK_AXIS_MASK);
244
245 return kTfLiteOk;
246 }
247
AddReshapeParams(const NnrtOpMappingArgs & mappingArgs,int32_t builtinCode)248 TfLiteStatus NnrtOpBuilder::AddReshapeParams(const NnrtOpMappingArgs& mappingArgs, int32_t builtinCode)
249 {
250 if (mappingArgs.node->inputs->size == 1) {
251 auto builtin = reinterpret_cast<TfLiteReshapeParams*>(mappingArgs.node->builtin_data);
252 int32_t numDimensions = builtin->num_dimensions;
253 std::vector<int32_t> outputShape(numDimensions);
254 for (int32_t i = 0; i < numDimensions; ++i) {
255 outputShape[i] = builtin->shape[i];
256 }
257 mappingArgs.builder->AddVectorInt32Tensor(outputShape.data(), outputShape.size(), OH_NN_TENSOR);
258 }
259
260 return kTfLiteOk;
261 }
262
AddConv2DParams(const NnrtOpMappingArgs & mappingArgs,int32_t builtinCode)263 TfLiteStatus NnrtOpBuilder::AddConv2DParams(const NnrtOpMappingArgs& mappingArgs, int32_t builtinCode)
264 {
265 auto builtin = reinterpret_cast<TfLiteConvParams*>(mappingArgs.node->builtin_data);
266 std::vector<int64_t> stride = { static_cast<int64_t>(builtin->stride_height),
267 static_cast<int64_t>(builtin->stride_width) };
268 std::vector<int64_t> dilation = { static_cast<int64_t>(builtin->dilation_height_factor),
269 static_cast<int64_t>(builtin->dilation_width_factor) };
270 int64_t groupNum = 1;
271
272 mappingArgs.builder->AddVectorInt64Tensor(stride.data(), stride.size(), OH_NN_CONV2D_STRIDES);
273 mappingArgs.builder->AddVectorInt64Tensor(dilation.data(), dilation.size(), OH_NN_CONV2D_DILATION);
274
275 TF_LITE_ENSURE_STATUS(AddPadParamsInOperator<TfLiteConvParams>(mappingArgs, builtin, builtinCode,
276 OH_NN_CONV2D_PAD_MODE));
277 mappingArgs.builder->AddScalarInt64Tensor(groupNum, OH_NN_CONV2D_GROUP);
278 TF_LITE_ENSURE_STATUS(AddActivateParamsInOperator<TfLiteConvParams>(mappingArgs, builtin, builtinCode,
279 OH_NN_CONV2D_ACTIVATION_TYPE));
280
281 return kTfLiteOk;
282 }
283
AddDepthwiseConv2DParams(const NnrtOpMappingArgs & mappingArgs,int32_t builtinCode)284 TfLiteStatus NnrtOpBuilder::AddDepthwiseConv2DParams(const NnrtOpMappingArgs& mappingArgs, int32_t builtinCode)
285 {
286 auto builtin = reinterpret_cast<TfLiteDepthwiseConvParams*>(mappingArgs.node->builtin_data);
287 std::vector<int64_t> stride = { static_cast<int64_t>(builtin->stride_height),
288 static_cast<int64_t>(builtin->stride_width) };
289 std::vector<int64_t> dilation = { static_cast<int64_t>(builtin->dilation_height_factor),
290 static_cast<int64_t>(builtin->dilation_width_factor) };
291 TF_LITE_ENSURE_STATUS(mappingArgs.builder->AddVectorInt64Tensor(stride.data(), stride.size(),
292 OH_NN_DEPTHWISE_CONV2D_NATIVE_STRIDES));
293 TF_LITE_ENSURE_STATUS(mappingArgs.builder->AddVectorInt64Tensor(dilation.data(), dilation.size(),
294 OH_NN_DEPTHWISE_CONV2D_NATIVE_DILATION));
295 TF_LITE_ENSURE_STATUS(AddPadParamsInOperator<TfLiteDepthwiseConvParams>(mappingArgs, builtin, builtinCode,
296 OH_NN_DEPTHWISE_CONV2D_NATIVE_PAD));
297 TF_LITE_ENSURE_STATUS(AddActivateParamsInOperator<TfLiteDepthwiseConvParams>(mappingArgs, builtin, builtinCode,
298 OH_NN_DEPTHWISE_CONV2D_NATIVE_ACTIVATION_TYPE));
299 return kTfLiteOk;
300 }
301
FinalizeAddOperation(OH_NN_OperationType type,int32_t liteNodeIndex)302 TfLiteStatus NnrtOpBuilder::FinalizeAddOperation(OH_NN_OperationType type, int32_t liteNodeIndex)
303 {
304 // Actually add a NN API Operation
305 OH_NN_UInt32Array inputIndices;
306 OH_NN_UInt32Array outputIndices;
307 OH_NN_UInt32Array paramIndices;
308 inputIndices.data = m_augmentedInputs.data();
309 inputIndices.size = static_cast<uint32_t>(m_augmentedInputs.size());
310 outputIndices.data = m_augmentedOutputs.data();
311 outputIndices.size = static_cast<uint32_t>(m_augmentedOutputs.size());
312 paramIndices.size = static_cast<uint32_t>(m_augmentedParams.size());
313
314 paramIndices.data = (m_augmentedParams.size() == 0) ? nullptr : m_augmentedParams.data();
315
316 RETURN_TFLITE_ERROR_IF_NN_ERROR(m_nnrt->OH_NNModel_AddOperation(m_nnModel,
317 type, ¶mIndices, &inputIndices, &outputIndices), "adding operation");
318
319 m_augmentedInputs.clear();
320 m_augmentedOutputs.clear();
321 m_augmentedParams.clear();
322
323 return kTfLiteOk;
324 }
325
AddTensor(int32_t tensorIndex,int32_t builtinCode,std::vector<uint32_t> & indices,int32_t tensorFlags)326 TfLiteStatus NnrtOpBuilder::AddTensor(int32_t tensorIndex, int32_t builtinCode, std::vector<uint32_t>& indices,
327 int32_t tensorFlags)
328 {
329 int32_t nnTensorIndex = m_pTensorMapping->LiteIndexToNn(tensorIndex);
330 if (nnTensorIndex != INVALID_INDEX) {
331 indices.emplace_back(nnTensorIndex);
332 return kTfLiteOk;
333 }
334
335 // Parameters needed for new type.
336 TfLiteTensor* tensor = &(m_context->tensors[tensorIndex]);
337 if (kTfLiteNoType == tensor->type) {
338 indices.emplace_back(INVALID_INDEX);
339 return kTfLiteOk;
340 }
341
342 TF_LITE_ENSURE_STATUS(AddTensor(tensorIndex, builtinCode, tensorFlags, nnTensorIndex));
343
344 indices.emplace_back(nnTensorIndex);
345
346 return kTfLiteOk;
347 }
348
AddTensor(int32_t tensorIndex,int32_t builtinCode,int32_t tensorFlags,int32_t & nnTensorIndex)349 TfLiteStatus NnrtOpBuilder::AddTensor(int32_t tensorIndex, int32_t builtinCode, int32_t tensorFlags,
350 int32_t& nnTensorIndex)
351 {
352 TfLiteTensor* tensor = &(m_context->tensors[tensorIndex]);
353 const bool scalarAsTensor = tensorFlags & NN_TENSOR_FLAG_SCALAR_AS_TENSOR;
354 OH_NN_Tensor nnTensor;
355 OH_NN_QuantParam nnQuantParam;
356 std::vector<int32_t> weightDims;
357 void* tensorData = tensor->data.data;
358 std::vector<int8_t> depthwiseTensorData;
359 TF_LITE_ENSURE_STATUS(ConstructNNTensor(tensorIndex, builtinCode, scalarAsTensor, nnQuantParam, nnTensor));
360
361 // For depth-wise conv operator, we should transpose weight tensor to adapt NN tensor format.
362 if ((builtinCode == kTfLiteBuiltinDepthwiseConv2d) && (tensor->allocation_type == kTfLiteMmapRo) &&
363 (nnTensor.dimensionCount == DEPTHWISE_WEIGHT_DIMENSION_COUNT)) {
364 size_t typeBytes = 0;
365 int64_t tensorSize = 0;
366 TF_LITE_ENSURE_STATUS(GetSizeOfType(m_context, tensor->type, &typeBytes));
367 TF_LITE_ENSURE_STATUS(GetTensorSize(m_context, nnTensor.dimensions, nnTensor.dimensionCount, tensorSize));
368
369 depthwiseTensorData.assign(tensorSize * typeBytes, 0);
370 TfLiteStatus retCode = TransposeDepthwiseTensor(tensorIndex, nnTensor, weightDims, depthwiseTensorData);
371 if (retCode != kTfLiteOk) {
372 TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "[NNRT-OPBUILDER] Fail to transpose depthwise tensor.");
373 return kTfLiteError;
374 }
375 tensorData = static_cast<void*>(depthwiseTensorData.data());
376 }
377
378 int32_t nnRet = m_nnrt->OH_NNModel_AddTensor(m_nnModel, &nnTensor);
379 if (nnRet != OH_NN_SUCCESS) {
380 TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "[NNRT-OPBUILDER] Fail to add nnTensor to NN model.");
381 return kTfLiteError;
382 }
383
384 // Allocate a new tensor index
385 nnTensorIndex = m_pTensorMapping->AddNewNnTensorIndex(tensorIndex);
386 if (tensor->allocation_type == kTfLiteMmapRo) {
387 nnRet = m_nnrt->OH_NNModel_SetTensorData(m_nnModel, nnTensorIndex,
388 tensorData, tensor->bytes);
389 if (nnRet != OH_NN_SUCCESS) {
390 TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "[NNRT-OPBUILDER] Fail to setting new nnTensor value.");
391 return kTfLiteError;
392 }
393 }
394
395 return kTfLiteOk;
396 }
397
TransposeDepthwiseTensor(int32_t tensorIndex,OH_NN_Tensor & nnTensor,std::vector<int32_t> & weightDims,std::vector<int8_t> & tensorData)398 TfLiteStatus NnrtOpBuilder::TransposeDepthwiseTensor(int32_t tensorIndex, OH_NN_Tensor& nnTensor,
399 std::vector<int32_t>& weightDims, std::vector<int8_t>& tensorData)
400 {
401 const int32_t* tensorDims = nnTensor.dimensions;
402 uint32_t tensorRank = nnTensor.dimensionCount;
403
404 // For Depth-wise Convolution, NNRT choose to Transpose dimension with [3, 1, 2, 0]
405 TF_LITE_ENSURE_STATUS(TransposeDims(m_context, tensorDims, tensorRank, DEPTHWISE_TRANSPOSE_AXISS, weightDims));
406 nnTensor.dimensions = weightDims.data();
407
408 TfLiteTensor* tensor = &(m_context->tensors[tensorIndex]);
409 if (tensor->type == kTfLiteFloat32) {
410 TF_LITE_ENSURE_STATUS(
411 TransposeTensor(m_context, tensorIndex, tensorDims, reinterpret_cast<float*>(tensorData.data())));
412 } else if (tensor->type == kTfLiteInt32) {
413 TF_LITE_ENSURE_STATUS(
414 TransposeTensor(m_context, tensorIndex, tensorDims, reinterpret_cast<int32_t*>(tensorData.data())));
415 } else if (tensor->type == kTfLiteInt8) {
416 TF_LITE_ENSURE_STATUS(
417 TransposeTensor(m_context, tensorIndex, tensorDims, reinterpret_cast<int8_t*>(tensorData.data())));
418 } else if (tensor->type == kTfLiteUInt8) {
419 TF_LITE_ENSURE_STATUS(
420 TransposeTensor(m_context, tensorIndex, tensorDims, reinterpret_cast<uint8_t*>(tensorData.data())));
421 } else {
422 TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "[NNRT-OPBUILDER] unsupportted weight tensor type %d.", tensor->type);
423 return kTfLiteError;
424 }
425
426 return kTfLiteOk;
427 }
428
ConstructNNTensor(int32_t tensorIndex,int32_t builtinCode,int32_t tensorFlags,OH_NN_QuantParam & nnQuantParam,OH_NN_Tensor & nnTensor)429 TfLiteStatus NnrtOpBuilder::ConstructNNTensor(int32_t tensorIndex, int32_t builtinCode, int32_t tensorFlags,
430 OH_NN_QuantParam& nnQuantParam, OH_NN_Tensor& nnTensor)
431 {
432 OH_NN_DataType nnType {OH_NN_UNKNOWN};
433 TF_LITE_ENSURE_STATUS(m_pTensorMapping->ConvertType(m_context, tensorIndex, tensorFlags, nnType));
434 TF_LITE_ENSURE_STATUS(m_pTensorMapping->ConvertQuantParams(m_context, tensorIndex, nnQuantParam));
435
436 TfLiteTensor* tensor = &(m_context->tensors[tensorIndex]);
437 uint32_t tensorRank = static_cast<uint32_t>(tensor->dims->size);
438 m_dimsUnspecified.assign(tensorRank, UNSPECIFIED_DIMENSION_VALUE);
439
440 int32_t* tensorDims = (m_allowDynamicDimensions && (tensor->allocation_type != kTfLiteMmapRo) &&
441 std::find(m_inputs.begin(), m_inputs.end(), tensorIndex) != m_inputs.end()) ?
442 reinterpret_cast<int32_t*>(m_dimsUnspecified.data()) :
443 tensor->dims->data;
444
445 const bool scalarAsTensor = tensorFlags & NN_TENSOR_FLAG_SCALAR_AS_TENSOR;
446 if (scalarAsTensor && tensorRank == 0) {
447 tensorRank = SCALAR_TENSOR_RANK; // Use rank 1, shape {1} nnTensor for TFLite scalar tensors.
448 tensorDims = const_cast<int32_t*>(&SCALAR_TENSOR_RANK);
449 }
450
451 if (tensorRank == 0) {
452 // if the tensorRank is 0, the dimension ptr must be nullptr.
453 tensorDims = nullptr;
454 }
455
456 nnTensor.dataType = nnType;
457 nnTensor.dimensionCount = tensorRank;
458 nnTensor.dimensions = tensorDims;
459 nnTensor.quantParam = nnQuantParam.quantCount ? &nnQuantParam : nullptr;
460 nnTensor.type = OH_NN_TENSOR;
461
462 return kTfLiteOk;
463 }
464
AddOpFuncParams(const NnrtOpMappingArgs & mappingArgs,int32_t builtinCode)465 TfLiteStatus NnrtOpBuilder::AddOpFuncParams(const NnrtOpMappingArgs& mappingArgs, int32_t builtinCode)
466 {
467 if (!m_keyToOpFunc.count(builtinCode)) {
468 TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "[NNRT-OPBUILDER] unsupportted Op builtinCode : %d.", builtinCode);
469 return kTfLiteError;
470 }
471
472 OpFuncPtr pfunc = m_keyToOpFunc[builtinCode];
473 return (this->*pfunc)(mappingArgs, builtinCode);
474 }
475
MapBuiltinCodeToFunc()476 TfLiteStatus NnrtOpBuilder::MapBuiltinCodeToFunc()
477 {
478 m_keyToOpFunc[kTfLiteBuiltinAdd] = &NnrtOpBuilder::AddBasicComputeParams;
479 m_keyToOpFunc[kTfLiteBuiltinAveragePool2d] = &NnrtOpBuilder::AddAvgPoolingParams;
480 m_keyToOpFunc[kTfLiteBuiltinConcatenation] = &NnrtOpBuilder::AddConcatenationParams;
481 m_keyToOpFunc[kTfLiteBuiltinConv2d] = &NnrtOpBuilder::AddConv2DParams;
482 m_keyToOpFunc[kTfLiteBuiltinDepthwiseConv2d] = &NnrtOpBuilder::AddDepthwiseConv2DParams;
483 m_keyToOpFunc[kTfLiteBuiltinDequantize] = &NnrtOpBuilder::AddQuantizeParams;
484 m_keyToOpFunc[kTfLiteBuiltinFullyConnected] = &NnrtOpBuilder::AddFullConnectedParams;
485 m_keyToOpFunc[kTfLiteBuiltinMaxPool2d] = &NnrtOpBuilder::AddMaxPoolingParams;
486 m_keyToOpFunc[kTfLiteBuiltinMul] = &NnrtOpBuilder::AddBasicComputeParams;
487 m_keyToOpFunc[kTfLiteBuiltinSub] = &NnrtOpBuilder::AddBasicComputeParams;
488 m_keyToOpFunc[kTfLiteBuiltinReshape] = &NnrtOpBuilder::AddReshapeParams;
489 m_keyToOpFunc[kTfLiteBuiltinSoftmax] = &NnrtOpBuilder::AddSoftmaxParams;
490 m_keyToOpFunc[kTfLiteBuiltinStridedSlice] = &NnrtOpBuilder::AddStridedSliceParams;
491 m_keyToOpFunc[kTfLiteBuiltinPack] = &NnrtOpBuilder::AddPackParams;
492 m_keyToOpFunc[kTfLiteBuiltinPad] = &NnrtOpBuilder::AddPadParams;
493 m_keyToOpFunc[kTfLiteBuiltinMean] = &NnrtOpBuilder::AddReduceMeanParams;
494 m_keyToOpFunc[kTfLiteBuiltinQuantize] = &NnrtOpBuilder::AddQuantizeParams;
495 m_keyToOpFunc[kTfLiteBuiltinHardSwish] = &NnrtOpBuilder::AddDefaultOpParams;
496 m_keyToOpFunc[kTfLiteBuiltinShape] = &NnrtOpBuilder::AddDefaultOpParams;
497 m_keyToOpFunc[kTfLiteBuiltinLogistic] = &NnrtOpBuilder::AddDefaultOpParams;
498
499 return kTfLiteOk;
500 }
501 } // namespace nnrt
502 } // namespace delegate
503 } // namespace tflite