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 #define LOG_TAG "android.hardware.neuralnetworks@1.0-impl-hvx"
18 
19 #include "HexagonController.h"
20 
21 #define LOAD_HEXAGON_FUNCTION(name) \
22     mFn_##name = loadFunction<hexagon_nn_controller_##name##_fn>("hexagon_nn_controller_" #name);
23 
24 #define CLOSE_HEXAGON_FUNCTION(name) mFn_##name = nullptr;
25 
26 #define FOR_EACH_FUNCTION(MACRO)   \
27     MACRO(init)                    \
28     MACRO(getlog)                  \
29     MACRO(snpprint)                \
30     MACRO(set_debug_level)         \
31     MACRO(prepare)                 \
32     MACRO(append_node)             \
33     MACRO(append_const_node)       \
34     MACRO(execute_new)             \
35     MACRO(execute)                 \
36     MACRO(teardown)                \
37     MACRO(get_perfinfo)            \
38     MACRO(reset_perfinfo)          \
39     MACRO(version)                 \
40     MACRO(last_execution_cycles)   \
41     MACRO(GetHexagonBinaryVersion) \
42     MACRO(PrintLog)                \
43     MACRO(op_name_to_id)           \
44     MACRO(op_id_to_name)           \
45     MACRO(disable_dcvs)            \
46     MACRO(set_powersave_level)     \
47     MACRO(config)                  \
48     MACRO(get_dsp_offset)          \
49     MACRO(boost)                   \
50     MACRO(slow)
51 
52 #define CONTROLLER_CHECK(function, ...)    \
53     if (mFn_##function == nullptr) {       \
54         return -1;                         \
55     }                                      \
56     int err = mFn_##function(__VA_ARGS__); \
57     if (err != 0) {                        \
58         return err;                        \
59     }                                      \
60     return 0;
61 
62 namespace android {
63 namespace hardware {
64 namespace neuralnetworks {
65 namespace V1_0 {
66 namespace implementation {
67 namespace hexagon {
68 
69 const char Controller::kFilename[] = "libhexagon_nn_controller.so";
70 
Controller()71 Controller::Controller() {
72     openNnlib();
73 }
74 
~Controller()75 Controller::~Controller() {
76     closeNnlib();
77 }
78 
openNnlib()79 bool Controller::openNnlib() {
80     mHandle = dlopen(kFilename, RTLD_LAZY | RTLD_LOCAL);
81     HEXAGON_SOFT_ASSERT_NE(mHandle, 0,
82                            "FAILED TO LOAD LIBRARY " /* << kFilename << ": " << dlerror()*/);
83     FOR_EACH_FUNCTION(LOAD_HEXAGON_FUNCTION)
84     return true;
85 }
86 
closeNnlib()87 bool Controller::closeNnlib() {
88     FOR_EACH_FUNCTION(CLOSE_HEXAGON_FUNCTION)
89     if (mHandle != nullptr) {
90         int err = dlclose(mHandle);
91         mHandle = nullptr;
92         HEXAGON_SOFT_ASSERT_EQ(err, 0, "FAILED TO CLOSE LIBRARY " << kFilename);
93     }
94     return true;
95 }
96 
resetNnlib()97 bool Controller::resetNnlib() {
98     return closeNnlib() && openNnlib();
99 }
100 
getInstance()101 Controller& Controller::getInstance() {
102     static Controller instance{};
103     return instance;
104 }
105 
init(hexagon_nn_nn_id * g)106 int Controller::init(hexagon_nn_nn_id* g) {
107     CONTROLLER_CHECK(init, g);
108 }
109 
getlog(hexagon_nn_nn_id id,unsigned char * buf,uint32_t length)110 int Controller::getlog(hexagon_nn_nn_id id, unsigned char* buf, uint32_t length) {
111     CONTROLLER_CHECK(getlog, id, buf, length);
112 }
113 
snpprint(hexagon_nn_nn_id id,unsigned char * buf,uint32_t length)114 int Controller::snpprint(hexagon_nn_nn_id id, unsigned char* buf, uint32_t length) {
115     CONTROLLER_CHECK(snpprint, id, buf, length);
116 }
117 
set_debug_level(hexagon_nn_nn_id id,int level)118 int Controller::set_debug_level(hexagon_nn_nn_id id, int level) {
119     CONTROLLER_CHECK(set_debug_level, id, level);
120 }
121 
prepare(hexagon_nn_nn_id id)122 int Controller::prepare(hexagon_nn_nn_id id) {
123     CONTROLLER_CHECK(prepare, id);
124 }
125 
append_node(hexagon_nn_nn_id id,uint32_t node_id,op_type operation,hexagon_nn_padding_type padding,const hexagon_nn_input * inputs,uint32_t num_inputs,const hexagon_nn_output * outputs,uint32_t num_outputs)126 int Controller::append_node(hexagon_nn_nn_id id, uint32_t node_id, op_type operation,
127                             hexagon_nn_padding_type padding, const hexagon_nn_input* inputs,
128                             uint32_t num_inputs, const hexagon_nn_output* outputs,
129                             uint32_t num_outputs) {
130     CONTROLLER_CHECK(append_node, id, node_id, operation, padding, inputs, num_inputs, outputs,
131                      num_outputs);
132 }
133 
append_const_node(hexagon_nn_nn_id id,uint32_t node_id,uint32_t batches,uint32_t height,uint32_t width,uint32_t depth,const uint8_t * data,uint32_t data_len)134 int Controller::append_const_node(hexagon_nn_nn_id id, uint32_t node_id, uint32_t batches,
135                                   uint32_t height, uint32_t width, uint32_t depth,
136                                   const uint8_t* data, uint32_t data_len) {
137     CONTROLLER_CHECK(append_const_node, id, node_id, batches, height, width, depth, data, data_len);
138 }
139 
execute_new(hexagon_nn_nn_id id,const hexagon_nn_tensordef * inputs,uint32_t n_inputs,hexagon_nn_tensordef * outputs,uint32_t n_outputs)140 int Controller::execute_new(hexagon_nn_nn_id id, const hexagon_nn_tensordef* inputs,
141                             uint32_t n_inputs, hexagon_nn_tensordef* outputs, uint32_t n_outputs) {
142     CONTROLLER_CHECK(execute_new, id, inputs, n_inputs, outputs, n_outputs);
143 }
144 
execute(hexagon_nn_nn_id id,uint32_t batches_in,uint32_t height_in,uint32_t width_in,uint32_t depth_in,const uint8_t * data_in,uint32_t data_len_in,uint32_t * batches_out,uint32_t * height_out,uint32_t * width_out,uint32_t * depth_out,uint8_t * data_out,uint32_t data_out_max,uint32_t * data_out_size)145 int Controller::execute(hexagon_nn_nn_id id, uint32_t batches_in, uint32_t height_in,
146                         uint32_t width_in, uint32_t depth_in, const uint8_t* data_in,
147                         uint32_t data_len_in, uint32_t* batches_out, uint32_t* height_out,
148                         uint32_t* width_out, uint32_t* depth_out, uint8_t* data_out,
149                         uint32_t data_out_max, uint32_t* data_out_size) {
150     CONTROLLER_CHECK(execute, id, batches_in, height_in, width_in, depth_in, data_in, data_len_in,
151                      batches_out, height_out, width_out, depth_out, data_out, data_out_max,
152                      data_out_size);
153 }
154 
teardown(hexagon_nn_nn_id id)155 int Controller::teardown(hexagon_nn_nn_id id) {
156     CONTROLLER_CHECK(teardown, id);
157 }
158 
get_perfinfo(hexagon_nn_nn_id id,hexagon_nn_perfinfo * info_out,unsigned int info_out_len,unsigned int * n_items_out)159 int Controller::get_perfinfo(hexagon_nn_nn_id id, hexagon_nn_perfinfo* info_out,
160                              unsigned int info_out_len, unsigned int* n_items_out) {
161     CONTROLLER_CHECK(get_perfinfo, id, info_out, info_out_len, n_items_out);
162 }
163 
reset_perfinfo(hexagon_nn_nn_id id,uint32_t event)164 int Controller::reset_perfinfo(hexagon_nn_nn_id id, uint32_t event) {
165     CONTROLLER_CHECK(reset_perfinfo, id, event);
166 }
167 
version(int * ver)168 int Controller::version(int* ver) {
169     CONTROLLER_CHECK(version, ver);
170 }
171 
last_execution_cycles(hexagon_nn_nn_id id,unsigned int * cycles_lo,unsigned int * cycles_hi)172 int Controller::last_execution_cycles(hexagon_nn_nn_id id, unsigned int* cycles_lo,
173                                       unsigned int* cycles_hi) {
174     CONTROLLER_CHECK(last_execution_cycles, id, cycles_lo, cycles_hi);
175 }
176 
GetHexagonBinaryVersion(int * ver)177 int Controller::GetHexagonBinaryVersion(int* ver) {
178     CONTROLLER_CHECK(GetHexagonBinaryVersion, ver);
179 }
180 
PrintLog(const uint8_t * data_in,unsigned int data_in_len)181 int Controller::PrintLog(const uint8_t* data_in, unsigned int data_in_len) {
182     CONTROLLER_CHECK(PrintLog, data_in, data_in_len);
183 }
184 
op_name_to_id(const char * name,unsigned int * id)185 int Controller::op_name_to_id(const char* name, unsigned int* id) {
186     CONTROLLER_CHECK(op_name_to_id, name, id);
187 }
188 
op_id_to_name(const unsigned int id,char * name,int name_len)189 int Controller::op_id_to_name(const unsigned int id, char* name, int name_len) {
190     CONTROLLER_CHECK(op_id_to_name, id, name, name_len);
191 }
192 
disable_dcvs()193 int Controller::disable_dcvs() {
194     CONTROLLER_CHECK(disable_dcvs);
195 }
196 
set_powersave_level(unsigned int level)197 int Controller::set_powersave_level(unsigned int level) {
198     CONTROLLER_CHECK(set_powersave_level, level);
199 }
200 
config()201 int Controller::config() {
202     CONTROLLER_CHECK(config);
203 }
204 
get_dsp_offset()205 unsigned int Controller::get_dsp_offset() {
206     CONTROLLER_CHECK(get_dsp_offset);
207 }
208 
boost(int bus_usage)209 int Controller::boost(int bus_usage) {
210     CONTROLLER_CHECK(boost, bus_usage);
211 }
212 
slow()213 int Controller::slow() {
214     CONTROLLER_CHECK(slow);
215 }
216 
217 }  // namespace hexagon
218 }  // namespace implementation
219 }  // namespace V1_0
220 }  // namespace neuralnetworks
221 }  // namespace hardware
222 }  // namespace android
223