1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef ANDROID_HARDWARE_V1_0_HEXAGON_MODEL_H
18 #define ANDROID_HARDWARE_V1_0_HEXAGON_MODEL_H
19
20 #include <android/hardware/neuralnetworks/1.0/types.h>
21 #include <atomic>
22 #include <string>
23 #include <vector>
24 #include "CpuExecutor.h"
25 #include "HexagonController.h"
26 #include "HexagonOperations.h"
27 #include "HexagonUtils.h"
28 #include "OperationsUtils.h"
29 #include "hexagon_nn_controller/hexagon_nn_controller.h"
30
31 namespace android {
32 namespace hardware {
33 namespace neuralnetworks {
34 namespace V1_0 {
35 namespace implementation {
36 namespace hexagon {
37
38 using ::android::nn::RunTimePoolInfo;
39 using ::android::nn::Shape;
40
41 using NeuralnetworksModel = ::android::hardware::neuralnetworks::V1_0::Model;
42
43 // runtime operand information
44 struct OperandInfo {
45 // tensor information
46 OperandType type;
47 std::vector<uint32_t> dimensions;
48
49 // (optional) quantization paramters
50 float scale;
51 int32_t zeroPoint;
52
53 // lifetime
54 OperandLifeTime lifetime;
55
56 // data location
57 uint8_t* buffer;
58 uint32_t length;
59
60 // Hexagon nnlib identifiers
61 hexagon_nn_input hexagon_input;
62 hexagon_nn_input hexagon_input_min;
63 hexagon_nn_input hexagon_input_max;
64 hexagon_nn_output hexagon_output;
65 };
66
67 // interface wrapper
68 class Model {
69 public:
70 // methods
71 Model() = delete;
72 Model(const Model&) = delete;
73 Model& operator=(const Model&) = delete;
74 Model(Model&& other);
75 Model& operator=(Model&& other);
76
77 Model(const NeuralnetworksModel& model);
78 ~Model();
79
80 std::string getLog();
81 std::string getGraph();
82
83 // model check
84 const int32_t* getPointer(uint32_t operand);
85 Shape getShape(uint32_t operand);
86 bool setShape(uint32_t operand, const Shape& shape);
87 bool isConstant(uint32_t operand);
88
89 // model prepare types
90 const hexagon_nn_input& getTensor(uint32_t operand);
91 const hexagon_nn_input& getQuantizationMin(uint32_t operand);
92 const hexagon_nn_input& getQuantizationMax(uint32_t operand);
93 hexagon_nn_input createQuantizationValue(uint32_t operand, int32_t quant_value);
94 hexagon_nn_input createConvFilterTensor(uint32_t operand);
95 hexagon_nn_input createDepthwiseFilterTensor(uint32_t operand, int32_t depth_multiplier);
96 hexagon_nn_input createFullyConnectedWeightTensor(uint32_t operand);
97 template <typename Type>
98 Type getScalar(uint32_t operand);
99 op_type getFloatActivation(uint32_t operand);
100 op_type getQuantizedActivation(uint32_t operand);
101 hexagon_nn_padding_type getPadding(uint32_t operand);
102
103 template <typename Type>
104 hexagon_nn_input createTensor(uint32_t B, uint32_t H, uint32_t W, uint32_t D,
105 const std::vector<Type>& values);
106 hexagon_nn_input createShape(uint32_t B, uint32_t H, uint32_t W, uint32_t D);
107 template <typename Type>
108 hexagon_nn_input createValues(const std::vector<Type>& values);
109 template <typename Type>
110 hexagon_nn_input createScalar(Type value);
111
112 // model prepare operations
113 bool addBasicOperation(op_type op, hexagon_nn_padding_type pad,
114 const std::vector<hexagon_nn_input>& inputs,
115 const std::vector<uint32_t>& outputs);
116 bool addFloatOperationWithActivation(op_type op, hexagon_nn_padding_type pad,
117 op_type activation,
118 const std::vector<hexagon_nn_input>& inputs,
119 const std::vector<uint32_t>& outputs);
120 bool addQuant8OperationWithActivation(op_type op, hexagon_nn_padding_type pad,
121 op_type activation,
122 const std::vector<hexagon_nn_input>& inputs,
123 const std::vector<uint32_t>& outputs);
124 bool addFusedFloatOperation(op_type op, hexagon_nn_padding_type pad,
125 const hexagon_nn_input& bias, op_type activation,
126 const std::vector<hexagon_nn_input>& inputs,
127 const std::vector<uint32_t>& outputs);
128 bool addFusedQuant8Operation(op_type op, hexagon_nn_padding_type pad,
129 const std::vector<hexagon_nn_input>& bias, op_type activation,
130 const std::vector<hexagon_nn_input>& inputs,
131 const std::vector<uint32_t>& outputs);
132
133 std::vector<bool> supportedOperations();
134 bool prepare();
135 bool execute(const Request& request);
136
137 private:
138 uint32_t getNextNode();
139 uint32_t addOperationInternal(op_type op, hexagon_nn_padding_type pad,
140 const std::vector<hexagon_nn_input>& inputs,
141 const std::vector<hexagon_nn_output>& outputs);
142 hexagon_nn_input createTensorInternal(uint32_t B, uint32_t H, uint32_t W, uint32_t D,
143 const uint8_t* ptr, size_t size);
144 std::vector<hexagon_nn_input> setupActivationArgs(op_type op);
145 hexagon_nn_input addOperand(uint32_t operand);
146 std::vector<hexagon_nn_output> getHexagonOutputs(const std::vector<uint32_t>& operands);
147 bool registerHexagonInputs(const std::vector<uint32_t>& operands, uint32_t node);
148
149 bool verifyOperations();
150 bool verifyOperands();
151 bool addInputs();
152 bool addOperations();
153 bool addOutputs();
154
155 void clearModel();
156
157 // members
158 hexagon_nn_nn_id mGraphId;
159 uint32_t mNodeCount;
160 bool mCompiled;
161 std::vector<OperandInfo> mOperands;
162 std::vector<Operation> mOperations;
163 std::vector<uint32_t> mInputs;
164 std::vector<uint32_t> mOutputs;
165 std::vector<RunTimePoolInfo> mPools;
166 };
167
168 // template implementations
169
170 template <typename Type>
getScalar(uint32_t operand)171 Type Model::getScalar(uint32_t operand) {
172 return *reinterpret_cast<const Type*>(mOperands[operand].buffer);
173 }
174
175 template <typename Type>
createTensor(uint32_t B,uint32_t H,uint32_t W,uint32_t D,const std::vector<Type> & values)176 hexagon_nn_input Model::createTensor(uint32_t B, uint32_t H, uint32_t W, uint32_t D,
177 const std::vector<Type>& values) {
178 return createTensorInternal(B, H, W, D, reinterpret_cast<const uint8_t*>(values.data()),
179 values.size() * sizeof(Type));
180 }
181
182 template <typename Type>
createValues(const std::vector<Type> & values)183 hexagon_nn_input Model::createValues(const std::vector<Type>& values) {
184 return createTensor(1, 1, 1, values.size(), values);
185 }
186
187 template <typename Type>
createScalar(Type value)188 hexagon_nn_input Model::createScalar(Type value) {
189 return createTensorInternal(1, 1, 1, 1, reinterpret_cast<uint8_t*>(&value), sizeof(Type));
190 }
191
192 } // namespace hexagon
193 } // namespace implementation
194 } // namespace V1_0
195 } // namespace neuralnetworks
196 } // namespace hardware
197 } // namespace android
198
199 #endif // ANDROID_HARDWARE_V1_0_HEXAGON_MODEL_H
200