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