1 /*
2 * Copyright (c) 2022-2023 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 "interfaces/innerkits/c/neural_network_runtime_inner.h"
17 #include "interfaces/kits/c/neural_network_runtime/neural_network_runtime.h"
18
19 #include "compilation.h"
20 #include "executor.h"
21 #include "inner_model.h"
22 #include "common/log.h"
23 #include "quant_param.h"
24 #include "validation.h"
25
26 using namespace OHOS::NeuralNetworkRuntime;
27
28 #define NNRT_API __attribute__((visibility("default")))
29
OH_NNQuantParam_Create()30 NNRT_API NN_QuantParam *OH_NNQuantParam_Create()
31 {
32 auto* quantParamImpl = new (std::nothrow) QuantParams();
33 if (quantParamImpl == nullptr) {
34 LOGE("OH_NNQuantParam_Create failed, please check whether it has enough memory.");
35 return nullptr;
36 }
37
38 return (NN_QuantParam*)(quantParamImpl);
39 }
40
OH_NNQuantParam_SetScales(NN_QuantParam * quantParams,const double * scales,size_t quantNum)41 NNRT_API OH_NN_ReturnCode OH_NNQuantParam_SetScales(NN_QuantParam* quantParams, const double* scales, size_t quantNum)
42 {
43 if (quantParams == nullptr) {
44 LOGE("OH_NNQuantParam_SetScales failed, passed nullptr to quantParams.");
45 return OH_NN_INVALID_PARAMETER;
46 }
47
48 if (scales == nullptr) {
49 LOGE("OH_NNQuantParam_SetScales failed, passed nullptr to scales.");
50 return OH_NN_INVALID_PARAMETER;
51 }
52
53 if (quantNum == 0) {
54 LOGE("OH_NNQuantParam_SetScales failed, passed 0 to quantNum.");
55 return OH_NN_INVALID_PARAMETER;
56 }
57
58 auto* quantParamImpl = reinterpret_cast<QuantParams*>(quantParams);
59 std::vector<double> scaleVector(scales, scales + quantNum);
60 quantParamImpl->SetScales(scaleVector);
61
62 return OH_NN_SUCCESS;
63 }
64
OH_NNQuantParam_SetZeroPoints(NN_QuantParam * quantParams,const int32_t * zeroPoints,size_t quantNum)65 NNRT_API OH_NN_ReturnCode OH_NNQuantParam_SetZeroPoints(NN_QuantParam* quantParams,
66 const int32_t* zeroPoints,
67 size_t quantNum)
68 {
69 if (quantParams == nullptr) {
70 LOGE("OH_NNQuantParam_SetZeroPoints failed, passed nullptr to quantParams.");
71 return OH_NN_INVALID_PARAMETER;
72 }
73
74 if (zeroPoints == nullptr) {
75 LOGE("OH_NNQuantParam_SetZeroPoints failed, passed nullptr to zeroPoints.");
76 return OH_NN_INVALID_PARAMETER;
77 }
78
79 if (quantNum == 0) {
80 LOGE("OH_NNQuantParam_SetZeroPoints failed, passed 0 to quantNum.");
81 return OH_NN_INVALID_PARAMETER;
82 }
83
84 auto* quantParamImpl = reinterpret_cast<QuantParams*>(quantParams);
85 std::vector<int32_t> zeroPointVector(zeroPoints, zeroPoints + quantNum);
86 quantParamImpl->SetZeroPoints(zeroPointVector);
87
88 return OH_NN_SUCCESS;
89 }
90
OH_NNQuantParam_SetNumBits(NN_QuantParam * quantParams,const uint32_t * numBits,size_t quantNum)91 OH_NN_ReturnCode OH_NNQuantParam_SetNumBits(NN_QuantParam* quantParams, const uint32_t* numBits, size_t quantNum)
92 {
93 if (quantParams == nullptr) {
94 LOGE("OH_NNQuantParam_SetNumBits failed, passed nullptr to quantParams.");
95 return OH_NN_INVALID_PARAMETER;
96 }
97
98 if (numBits == nullptr) {
99 LOGE("OH_NNQuantParam_SetNumBits failed, passed nullptr to numBits.");
100 return OH_NN_INVALID_PARAMETER;
101 }
102
103 if (quantNum == 0) {
104 LOGE("OH_NNQuantParam_SetNumBits failed, passed 0 to quantNum.");
105 return OH_NN_INVALID_PARAMETER;
106 }
107
108 auto* quantParamImpl = reinterpret_cast<QuantParams*>(quantParams);
109 std::vector<uint32_t> numBitVector(numBits, numBits + quantNum);
110 quantParamImpl->SetNumBits(numBitVector);
111
112 return OH_NN_SUCCESS;
113 }
114
OH_NNQuantParam_Destroy(NN_QuantParam ** quantParams)115 OH_NN_ReturnCode OH_NNQuantParam_Destroy(NN_QuantParam** quantParams)
116 {
117 if (quantParams == nullptr) {
118 LOGE("OH_NNQuantParam_Destroy failed, passed nullptr to quantParams.");
119 return OH_NN_INVALID_PARAMETER;
120 }
121
122 if (*quantParams == nullptr) {
123 LOGW("OH_NNQuantParam_Destroy failed, passed nullptr to *quantParams.");
124 return OH_NN_INVALID_PARAMETER;
125 }
126
127 auto* quantParamImpl = reinterpret_cast<QuantParams*>(*quantParams);
128 delete quantParamImpl;
129 *quantParams = nullptr;
130
131 return OH_NN_SUCCESS;
132 }
133
OH_NNModel_AddTensorToModel(OH_NNModel * model,const NN_TensorDesc * tensorDesc)134 OH_NN_ReturnCode OH_NNModel_AddTensorToModel(OH_NNModel* model, const NN_TensorDesc* tensorDesc)
135 {
136 if (model == nullptr) {
137 LOGE("OH_NNModel_AddTensorToModel failed, passed nullptr to model.");
138 return OH_NN_INVALID_PARAMETER;
139 }
140
141 if (tensorDesc == nullptr) {
142 LOGE("OH_NNModel_AddTensorToModel failed, passed nullptr to tensorDesc.");
143 return OH_NN_INVALID_PARAMETER;
144 }
145
146 auto* innerModel = reinterpret_cast<OHOS::NeuralNetworkRuntime::InnerModel*>(model);
147 OH_NN_ReturnCode returnCode = innerModel->AddTensorDesc(tensorDesc);
148 if (returnCode != OH_NN_SUCCESS) {
149 LOGE("OH_NNModel_AddTensorToModel failed, error happened when adding tensor to model.");
150 }
151
152 return returnCode;
153 }
154
OH_NNModel_SetTensorQuantParams(OH_NNModel * model,uint32_t index,NN_QuantParam * quantParam)155 OH_NN_ReturnCode OH_NNModel_SetTensorQuantParams(OH_NNModel* model, uint32_t index, NN_QuantParam* quantParam)
156 {
157 if (model == nullptr) {
158 LOGE("OH_NNModel_SetTensorQuantParams failed, passed nullptr to model.");
159 return OH_NN_INVALID_PARAMETER;
160 }
161
162 if (quantParam == nullptr) {
163 LOGE("OH_NNModel_SetTensorQuantParams failed, passed nullptr to quantParam.");
164 return OH_NN_INVALID_PARAMETER;
165 }
166
167 auto* innerModel = reinterpret_cast<OHOS::NeuralNetworkRuntime::InnerModel*>(model);
168 OH_NN_ReturnCode returnCode = innerModel->SetTensorQuantParam((uint32_t)(index), quantParam);
169 if (returnCode != OH_NN_SUCCESS) {
170 LOGE("OH_NNModel_SetTensorQuantParams failed, error happened when setting tensor quantParam.");
171 }
172
173 return returnCode;
174 }
175
OH_NNModel_SetTensorType(OH_NNModel * model,uint32_t index,OH_NN_TensorType tensorType)176 OH_NN_ReturnCode OH_NNModel_SetTensorType(OH_NNModel* model, uint32_t index, OH_NN_TensorType tensorType)
177 {
178 if (model == nullptr) {
179 LOGE("OH_NNModel_SetTensorType failed, passed nullptr to model.");
180 return OH_NN_INVALID_PARAMETER;
181 }
182
183 if (!Validation::ValidateTensorType(tensorType)) {
184 LOGE("OH_NNModel_SetTensorType failed, invalid tensor type.");
185 return OH_NN_INVALID_PARAMETER;
186 }
187
188 auto* innerModel = reinterpret_cast<OHOS::NeuralNetworkRuntime::InnerModel*>(model);
189 OH_NN_ReturnCode returnCode = innerModel->SetTensorType((uint32_t)(index), tensorType);
190 if (returnCode != OH_NN_SUCCESS) {
191 LOGE("OH_NNModel_SetTensorType failed, error happened when setting tensor type.");
192 }
193
194 return returnCode;
195 }
196
OH_NNModel_Construct(void)197 NNRT_API OH_NNModel *OH_NNModel_Construct(void)
198 {
199 InnerModel *innerModel = new(std::nothrow) InnerModel();
200 if (innerModel == nullptr) {
201 LOGE("OH_NNModel_Construct failed, please check whether it has enough memory.");
202 return nullptr;
203 }
204
205 OH_NNModel *nnModel = reinterpret_cast<OH_NNModel*>(innerModel);
206 return nnModel;
207 }
208
OH_NNModel_AddOperation(OH_NNModel * model,OH_NN_OperationType op,const OH_NN_UInt32Array * paramIndices,const OH_NN_UInt32Array * inputIndices,const OH_NN_UInt32Array * outputIndices)209 NNRT_API OH_NN_ReturnCode OH_NNModel_AddOperation(OH_NNModel *model,
210 OH_NN_OperationType op,
211 const OH_NN_UInt32Array *paramIndices,
212 const OH_NN_UInt32Array *inputIndices,
213 const OH_NN_UInt32Array *outputIndices)
214 {
215 if (model == nullptr) {
216 LOGE("OH_NNModel_AddOperation failed, passed nullptr to model.");
217 return OH_NN_INVALID_PARAMETER;
218 }
219
220 if (paramIndices == nullptr) {
221 LOGE("OH_NNModel_AddOperation failed, passed nullptr to paramIndices.");
222 return OH_NN_INVALID_PARAMETER;
223 }
224
225 if (inputIndices == nullptr) {
226 LOGE("OH_NNModel_AddOperation failed, passed nullptr to inputIndices.");
227 return OH_NN_INVALID_PARAMETER;
228 }
229
230 if (outputIndices == nullptr) {
231 LOGE("OH_NNModel_AddOperation failed, passed nullptr to outputIndices.");
232 return OH_NN_INVALID_PARAMETER;
233 }
234
235 InnerModel *innerModel = reinterpret_cast<InnerModel*>(model);
236 return innerModel->AddOperation(op, *paramIndices, *inputIndices, *outputIndices);
237 }
238
OH_NNModel_SetTensorData(OH_NNModel * model,uint32_t index,const void * dataBuffer,size_t length)239 NNRT_API OH_NN_ReturnCode OH_NNModel_SetTensorData(OH_NNModel *model,
240 uint32_t index,
241 const void *dataBuffer,
242 size_t length)
243 {
244 if (model == nullptr) {
245 LOGE("OH_NNModel_SetTensorData failed, passed nullptr to model.");
246 return OH_NN_INVALID_PARAMETER;
247 }
248
249 if (dataBuffer == nullptr) {
250 LOGE("OH_NNModel_SetTensorData failed, passed nullptr to dataBuffer, which has no effect.");
251 return OH_NN_INVALID_PARAMETER;
252 }
253
254 if (length == 0) {
255 LOGE("OH_NNModel_SetTensorData failed, passed dataBuffer with length 0, which has no effect.");
256 return OH_NN_INVALID_PARAMETER;
257 }
258
259 InnerModel *innerModel = reinterpret_cast<InnerModel*>(model);
260 return innerModel->SetTensorValue(index, dataBuffer, length);
261 }
262
OH_NNModel_SpecifyInputsAndOutputs(OH_NNModel * model,const OH_NN_UInt32Array * inputIndices,const OH_NN_UInt32Array * outputIndices)263 NNRT_API OH_NN_ReturnCode OH_NNModel_SpecifyInputsAndOutputs(OH_NNModel *model,
264 const OH_NN_UInt32Array *inputIndices,
265 const OH_NN_UInt32Array *outputIndices)
266 {
267 if (model == nullptr) {
268 LOGE("OH_NNModel_SpecifyInputsAndOutputs failed, passed nullptr to model.");
269 return OH_NN_INVALID_PARAMETER;
270 }
271
272 if (inputIndices == nullptr) {
273 LOGE("OH_NNModel_SpecifyInputsAndOutputs failed, passed nullptr to inputIndices.");
274 return OH_NN_INVALID_PARAMETER;
275 }
276
277 if (outputIndices == nullptr) {
278 LOGE("OH_NNModel_SpecifyInputsAndOutputs failed, passed nullptr to outputIndices.");
279 return OH_NN_INVALID_PARAMETER;
280 }
281
282 InnerModel *innerModel = reinterpret_cast<InnerModel*>(model);
283 return innerModel->SpecifyInputsAndOutputs(*inputIndices, *outputIndices);
284 }
285
OH_NNModel_Finish(OH_NNModel * model)286 NNRT_API OH_NN_ReturnCode OH_NNModel_Finish(OH_NNModel *model)
287 {
288 if (model == nullptr) {
289 LOGE("OH_NNModel_Finish failed, passed nullptr to model.");
290 return OH_NN_INVALID_PARAMETER;
291 }
292
293 InnerModel *innerModel = reinterpret_cast<InnerModel*>(model);
294 return innerModel->Build();
295 }
296
OH_NNModel_BuildFromLiteGraph(OH_NNModel * model,const void * liteGraph)297 NNRT_API OH_NN_ReturnCode OH_NNModel_BuildFromLiteGraph(OH_NNModel *model, const void *liteGraph)
298 {
299 if (model == nullptr) {
300 LOGE("OH_NNModel_BuildFromLiteGraph failed, passed nullptr to model.");
301 return OH_NN_INVALID_PARAMETER;
302 }
303
304 if (liteGraph == nullptr) {
305 LOGE("OH_NNModel_BuildFromLiteGraph failed, passed nullptr to liteGraph.");
306 return OH_NN_INVALID_PARAMETER;
307 }
308
309 auto *pLiteGraph = static_cast<const mindspore::lite::LiteGraph*>(liteGraph);
310 InnerModel *innerModel = reinterpret_cast<InnerModel*>(model);
311
312 // Once the innerModel built from the liteGraph successfully, the innerModel
313 // owns the liteGraph, in which case, the invoker should not delete
314 // the liteGraph actively. Otherwise, the invoker still has the ownership.
315 return innerModel->BuildFromLiteGraph(pLiteGraph);
316 }
317
OH_NNModel_BuildFromMetaGraph(OH_NNModel * model,const void * metaGraph,const OH_NN_Extension * extensions,size_t extensionSize)318 NNRT_API OH_NN_ReturnCode OH_NNModel_BuildFromMetaGraph(OH_NNModel *model, const void *metaGraph,
319 const OH_NN_Extension *extensions, size_t extensionSize)
320 {
321 if (model == nullptr) {
322 LOGE("OH_NNModel_BuildFromMetaGraph failed, passed nullptr to model.");
323 return OH_NN_INVALID_PARAMETER;
324 }
325
326 if (metaGraph == nullptr) {
327 LOGE("OH_NNModel_BuildFromMetaGraph failed, passed nullptr to metaGraph.");
328 return OH_NN_INVALID_PARAMETER;
329 }
330
331 Buffer buffer;
332 std::string modelName;
333 for (size_t i = 0; i < extensionSize; ++i) {
334 std::string name = extensions[i].name;
335 if (name == "QuantBuffer") {
336 buffer.data = extensions[i].value;
337 buffer.length = extensions[i].valueSize;
338 } else if (name == "ModelName") {
339 modelName.assign(extensions[i].value, extensions[i].value + extensions[i].valueSize);
340 }
341 }
342
343 InnerModel *innerModel = reinterpret_cast<InnerModel*>(model);
344 return innerModel->BuildFromMetaGraph(metaGraph, buffer, modelName);
345 }
346
OH_NNModel_SetInputsAndOutputsInfo(OH_NNModel * model,const OH_NN_TensorInfo * inputsInfo,size_t inputSize,const OH_NN_TensorInfo * outputsInfo,size_t outputSize)347 NNRT_API OH_NN_ReturnCode OH_NNModel_SetInputsAndOutputsInfo(OH_NNModel *model, const OH_NN_TensorInfo *inputsInfo,
348 size_t inputSize, const OH_NN_TensorInfo *outputsInfo, size_t outputSize)
349 {
350 if (model == nullptr) {
351 LOGE("OH_NNModel_SetInputsAndOutputsInfo failed, passed nullptr to model.");
352 return OH_NN_INVALID_PARAMETER;
353 }
354
355 if ((inputsInfo == nullptr) || (inputSize == 0)) {
356 LOGE("OH_NNModel_SetInputsAndOutputsInfo failed, inputsInfo is empty.");
357 return OH_NN_INVALID_PARAMETER;
358 }
359
360 if ((outputsInfo == nullptr) || (outputSize == 0)) {
361 LOGE("OH_NNModel_SetInputsAndOutputsInfo failed, outputsInfo is empty.");
362 return OH_NN_INVALID_PARAMETER;
363 }
364
365 InnerModel *innerModel = reinterpret_cast<InnerModel*>(model);
366 return innerModel->SetInputsAndOutputsInfo(inputsInfo, inputSize, outputsInfo, outputSize);
367 }
368
OH_NNModel_Destroy(OH_NNModel ** model)369 NNRT_API void OH_NNModel_Destroy(OH_NNModel **model)
370 {
371 if (model == nullptr) {
372 LOGW("OH_NNModel_Destroy has no effect, passed nullptr to model.");
373 return;
374 }
375
376 if (*model == nullptr) {
377 LOGW("OH_NNModel_Destroy has no effect, passed nullptr to *model.");
378 return;
379 }
380
381 InnerModel *innerModel = reinterpret_cast<InnerModel*>(*model);
382 delete innerModel;
383 *model = nullptr;
384 }
385
OH_NNModel_GetAvailableOperations(OH_NNModel * model,size_t deviceID,const bool ** isAvailable,uint32_t * opCount)386 NNRT_API OH_NN_ReturnCode OH_NNModel_GetAvailableOperations(OH_NNModel *model,
387 size_t deviceID,
388 const bool **isAvailable,
389 uint32_t *opCount)
390 {
391 if (model == nullptr) {
392 LOGE("OH_NNModel_GetAvailableOperations failed, passed nullptr to model.");
393 return OH_NN_INVALID_PARAMETER;
394 }
395
396 if (isAvailable == nullptr) {
397 LOGE("OH_NNModel_GetAvailableOperations failed, passed nullptr to isAvailable.");
398 return OH_NN_INVALID_PARAMETER;
399 }
400
401 if (*isAvailable != nullptr) {
402 LOGE("OH_NNModel_GetAvailableOperations failed, *isAvailable is not nullptr.");
403 return OH_NN_INVALID_PARAMETER;
404 }
405
406 if (opCount == nullptr) {
407 LOGE("OH_NNModel_GetAvailableOperations failed, passed nullptr to opCount.");
408 return OH_NN_INVALID_PARAMETER;
409 }
410
411 InnerModel *innerModel = reinterpret_cast<InnerModel*>(model);
412 return innerModel->GetSupportedOperations(deviceID, isAvailable, *opCount);
413 }