xref: /aosp_15_r20/external/executorch/backends/mediatek/runtime/NeuronExecutor.cpp (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
1 /*
2  * Copyright (c) 2024 MediaTek Inc.
3  *
4  * Licensed under the BSD License (the "License"); you may not use this file
5  * except in compliance with the License. See the license file in the root
6  * directory of this source tree for more details.
7  */
8 
9 #include "NeuronExecutor.h"
10 #include "NeuronLog.h"
11 #include "api/NeuronAdapter.h"
12 
13 #include <string>
14 #include <vector>
15 
16 #define RESTORE_DLA_EXTENSION_OPERAND_TYPE 0x0100
17 #define RESTORE_DLA_EXTENSION_OPERATION_TYPE 0x0000
18 #define RESTORE_DLA_EXTENSION_NAME "com.mediatek.compiled_network"
19 
20 namespace executorch {
21 namespace backends {
22 namespace neuron {
23 
NeuronExecutor()24 NeuronExecutor::NeuronExecutor(){};
25 
LoadFromCompiledNetwork(const void * buffer,size_t size,int inputCount,int outputCount,std::string & runtimeOption)26 int NeuronExecutor::LoadFromCompiledNetwork(
27     const void* buffer,
28     size_t size,
29     int inputCount,
30     int outputCount,
31     std::string& runtimeOption) {
32   NeuronModel* model = nullptr;
33   NeuronCompilation* compilation = nullptr;
34   NeuronExecution* execution = nullptr;
35 
36   std::vector<NeuronOperandType> mInputOperand;
37   std::vector<NeuronOperandType> mOutputOperand;
38   // ---------------------------Model------------------------------------
39   int err = NEURON_NO_ERROR;
40   err |= NeuronModel_create(&model);
41   CHECK_NO_ERROR(err);
42 
43   mModel = std::unique_ptr<NeuronModel, NeuronDeleter>(model);
44 
45   std::vector<uint32_t> input_op_number;
46   // fake input, the real outputs are loaded by compiled network.
47   NeuronOperandType fakeInputOperandType{
48       .type = NEURON_TENSOR_FLOAT32,
49       .dimensionCount = 0,
50       .scale = 0.0f,
51       .zeroPoint = 0,
52   };
53 
54   for (int i = 0; i < inputCount; i++) {
55     mInputOperand.push_back(fakeInputOperandType);
56   }
57   for (int i = 0; i < mInputOperand.size(); i++) {
58     err |= NeuronModel_addOperand(model, &mInputOperand[i]);
59     input_op_number.emplace_back(i);
60   }
61 
62   int32_t operandType = 0;
63   const uint16_t network_operand_restore_data =
64       RESTORE_DLA_EXTENSION_OPERAND_TYPE;
65   const char* extensionRestoreCompiledNetwork = RESTORE_DLA_EXTENSION_NAME;
66   err |= NeuronModel_getExtensionOperandType(
67       model,
68       extensionRestoreCompiledNetwork,
69       network_operand_restore_data,
70       &operandType);
71   CHECK_NO_ERROR(err);
72 
73   NeuronOperandType extenOperandType{
74       .type = operandType,
75       .dimensionCount = 0,
76       .scale = 0.0f,
77       .zeroPoint = 0,
78   };
79 
80   err |= NeuronModel_addOperand(model, &extenOperandType);
81   CHECK_NO_ERROR(err);
82   input_op_number.emplace_back(input_op_number.size());
83 
84   // fake output, the real outputs are loaded by compiled network.
85   NeuronOperandType fakeOutputOperandType{
86       .type = NEURON_TENSOR_FLOAT32,
87       .dimensionCount = 0,
88       .scale = 0.0f,
89       .zeroPoint = 0,
90   };
91 
92   for (int i = 0; i < outputCount; i++) {
93     mOutputOperand.push_back(fakeOutputOperandType);
94   }
95 
96   std::vector<uint32_t> output_op_number;
97   for (int i = 0; i < mOutputOperand.size(); i++) {
98     err |= NeuronModel_addOperand(model, &mOutputOperand[i]);
99     output_op_number.emplace_back(i + input_op_number.size());
100   }
101 
102   CHECK_NO_ERROR(err);
103 
104   err |=
105       NeuronModel_setOperandValue(model, input_op_number.back(), buffer, size);
106 
107   int32_t operationType = 0;
108   const uint16_t network_operation_type_restore =
109       RESTORE_DLA_EXTENSION_OPERATION_TYPE;
110   err |= NeuronModel_getExtensionOperationType(
111       model,
112       extensionRestoreCompiledNetwork,
113       network_operation_type_restore,
114       &operationType);
115 
116   CHECK_NO_ERROR(err);
117 
118   // Add extension operation
119   err |= NeuronModel_addOperation(
120       model,
121       (NeuronOperationType)operationType,
122       input_op_number.size(),
123       input_op_number.data(),
124       output_op_number.size(),
125       output_op_number.data());
126 
127   CHECK_NO_ERROR(err);
128 
129   // Identify input and output
130   err |= NeuronModel_identifyInputsAndOutputs(
131       model,
132       input_op_number.size() - 1,
133       input_op_number.data(),
134       output_op_number.size(),
135       output_op_number.data());
136 
137   CHECK_NO_ERROR(err);
138 
139   err |= NeuronModel_finish(model);
140   CHECK_NO_ERROR(err);
141   // ---------------------------Compilation------------------------------------
142   // err = NeuronCompilation_e(model, &compilation) != NEURON_NO_ERROR;
143   err = NeuronCompilation_createWithOptions(
144       model, &compilation, runtimeOption.c_str());
145   CHECK_NO_ERROR(err);
146 
147   mCompilation = std::unique_ptr<NeuronCompilation, NeuronDeleter>(compilation);
148 
149   err |=
150       NeuronCompilation_setPreference(compilation, NEURON_PREFER_TURBO_BOOST);
151   err |= NeuronCompilation_setPriority(compilation, NEURON_PRIORITY_HIGH);
152   CHECK_NO_ERROR(err);
153 
154   err = NeuronCompilation_finish(compilation);
155   CHECK_NO_ERROR(err);
156 
157   // ---------------------------Execution------------------------------------
158   // Create Neuron executor instance.
159   err = NeuronExecution_create(compilation, &execution);
160   CHECK_NO_ERROR(err);
161   mExecution = std::unique_ptr<NeuronExecution, NeuronDeleter>(execution);
162 
163   return NEURON_NO_ERROR;
164 }
165 
166 } // namespace neuron
167 } // namespace backends
168 } // namespace executorch
169