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, &paramIndices, &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