1 /* Copyright 2016 The TensorFlow Authors. All Rights Reserved.
2
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 "soc_interface.h"
17
18 #include <inttypes.h>
19
20 #include "hexagon_controller.h"
21 #include "hexagon_nn.h"
22 #include "node_data_float.h"
23 #include "tfm_log.h"
24
25 // to demonstrate the performance difference between ION and HLOS memory
26 // for sharing with ADSP.
27 #define USE_ION_MEMORY
28
29 const int64_t FLAG_ENABLE_INCEPTION_DUMMY_BINARY_INPUT = 0x01;
30 const int64_t FLAG_ENABLE_EXPERIMENTAL_DEBUG = 0x02;
31
32 static const int INCEPTION_VERSION = 3;
33
34 static hexagon_nn_input* s_node_inputs_array;
35 static int s_node_inputs_array_index;
36 static int s_node_inputs_array_max_count;
37
38 static hexagon_nn_output* s_node_outputs_array;
39 static int s_node_outputs_array_index;
40 static int s_node_outputs_array_max_count;
41
soc_interface_GetWrapperVersion()42 int soc_interface_GetWrapperVersion() {
43 TFMLOGD("GetWrapperVersion");
44 return hexagon_controller_GetWrapperVersion();
45 }
46
soc_interface_GetSocControllerVersion()47 int soc_interface_GetSocControllerVersion() {
48 TFMLOGD("GetSocControllerVersion");
49 return hexagon_controller_GetHexagonBinaryVersion();
50 }
51
soc_interface_Init()52 bool soc_interface_Init() {
53 TFMLOGD("Init");
54 hexagon_controller_InitHexagonWithMaxAttributes(
55 0, 100, INCEPTION_VERSION /* version */);
56 hexagon_controller_GrowMemorySize();
57 return true;
58 }
59
soc_interface_Finalize()60 bool soc_interface_Finalize() {
61 TFMLOGD("Finalize");
62 hexagon_controller_DeInitHexagon();
63 return true;
64 }
65
soc_interface_ExecuteGraph()66 bool soc_interface_ExecuteGraph() {
67 TFMLOGD("ExecuteGraph");
68 if (hexagon_controller_IsDbgUseInceptionDummyDataEnabled()) {
69 hexagon_controller_InitInputNodeDataToInceptionDummyData(
70 INCEPTION_VERSION /* version */);
71 }
72 const uint32_t graph_id = hexagon_controller_GetTargetGraphId();
73 if (graph_id == 0) {
74 TFMLOGE("Graph id has not been set yet.");
75 return false;
76 }
77 hexagon_controller_ExecuteGraphWithBuffer(graph_id, true);
78 return true;
79 }
80
soc_interface_TeardownGraph()81 bool soc_interface_TeardownGraph() {
82 TFMLOGD("TeardownGraph");
83 const uint32_t graph_id = hexagon_controller_GetTargetGraphId();
84 if (graph_id == 0) {
85 TFMLOGE("Graph id has not been set yet.");
86 return false;
87 }
88 hexagon_controller_Teardown(graph_id);
89 return true;
90 }
91
soc_interface_AllocateInOutNodeBuffers(int input_count,int * input_sizes,int output_count,int * output_sizes)92 bool soc_interface_AllocateInOutNodeBuffers(int input_count, int* input_sizes,
93 int output_count,
94 int* output_sizes) {
95 TFMLOGD("AllocateInOutNodeBuffers");
96 return hexagon_controller_AllocateMultipleNodeDataBuffers(
97 input_count, input_sizes, output_count, output_sizes);
98 }
99
soc_interface_FillInputNodeWithPort(int port,int x,int y,int z,int d,const uint8_t * const buf,uint64_t buf_byte_size)100 bool soc_interface_FillInputNodeWithPort(int port, int x, int y, int z, int d,
101 const uint8_t* const buf,
102 uint64_t buf_byte_size) {
103 TFMLOGD("FillInputNodeWithPort %d", port);
104 struct NodeDataFloat* node_data =
105 hexagon_controller_GetInputNodeDataBuffer(port);
106 if (buf_byte_size > node_data->max_buf_byte_size) {
107 TFMLOGE("buf size exceeds max buf size");
108 return false;
109 }
110 memcpy(node_data->byte_array_data, buf, buf_byte_size);
111 node_data->x = x;
112 node_data->y = y;
113 node_data->z = z;
114 node_data->d = d;
115 node_data->array_byte_size = buf_byte_size;
116 return true;
117 }
118
soc_interface_FillInputNodeFloat(int x,int y,int z,int d,const uint8_t * const buf,uint64_t buf_byte_size)119 bool soc_interface_FillInputNodeFloat(int x, int y, int z, int d,
120 const uint8_t* const buf,
121 uint64_t buf_byte_size) {
122 return soc_interface_FillInputNodeWithPort(
123 /*port=*/0, x, y, z, d, buf, buf_byte_size);
124 }
125
126 // TODO(satok): Remove and use runtime version
soc_interface_ReadOutputNodeWithPort(int port,uint8_t ** buf,uint64_t * buf_byte_size)127 bool soc_interface_ReadOutputNodeWithPort(int port, uint8_t** buf,
128 uint64_t* buf_byte_size) {
129 TFMLOGD("ReadOutputNodeWithPort");
130 int array_byte_size = -1;
131 uint8_t* output_node_data_buffer =
132 hexagon_controller_GetOutputNodeDataBuffer(port, &array_byte_size);
133 if (array_byte_size < 0) {
134 TFMLOGE("Failed to read data.");
135 return false;
136 }
137 *buf = output_node_data_buffer;
138 *buf_byte_size = array_byte_size;
139 return true;
140 }
141
soc_interface_ReadOutputNodeFloat(const char * const node_name,uint8_t ** buf,uint64_t * buf_byte_size)142 bool soc_interface_ReadOutputNodeFloat(const char* const node_name,
143 uint8_t** buf, uint64_t* buf_byte_size) {
144 return soc_interface_ReadOutputNodeWithPort(/*port=*/0, buf, buf_byte_size);
145 }
146
soc_interface_setupDummyGraph(int version)147 bool soc_interface_setupDummyGraph(int version) {
148 TFMLOGD("SetupGraphDummy");
149 const uint32_t graph_id = hexagon_controller_SetupGraph(version);
150 if (graph_id == 0) {
151 TFMLOGE("Failed to setup graph");
152 return false;
153 }
154 hexagon_controller_SetTargetGraphId(graph_id);
155 return true;
156 }
157
soc_interface_AllocateNodeInputAndNodeOutputArray(int total_input_count,int total_output_count)158 bool soc_interface_AllocateNodeInputAndNodeOutputArray(int total_input_count,
159 int total_output_count) {
160 TFMLOGD("Allocate node inputs and node outputs array %d, %d",
161 total_input_count, total_output_count);
162 posix_memalign((void**)&s_node_inputs_array, 128,
163 total_input_count * sizeof(hexagon_nn_input));
164 posix_memalign((void**)&s_node_outputs_array, 128,
165 total_output_count * sizeof(hexagon_nn_output));
166 s_node_inputs_array_index = 0;
167 s_node_outputs_array_index = 0;
168 s_node_inputs_array_max_count = total_input_count;
169 s_node_outputs_array_max_count = total_output_count;
170 return true;
171 }
172
soc_interface_ReleaseNodeInputAndNodeOutputArray()173 bool soc_interface_ReleaseNodeInputAndNodeOutputArray() {
174 TFMLOGD("Release node inputs and node outputs array");
175 free(s_node_inputs_array);
176 free(s_node_outputs_array);
177 return true;
178 }
179
soc_interface_SetOneNodeInputs(int input_count,const int * const node_id,const int * const port)180 void* soc_interface_SetOneNodeInputs(
181 int input_count, const int* const node_id, const int* const port) {
182 if (s_node_inputs_array_index + input_count > s_node_inputs_array_max_count) {
183 TFMLOGE("input count exceeds limit");
184 return 0;
185 }
186 for (int i = 0; i < input_count; ++i) {
187 const int index = s_node_inputs_array_index + i;
188 s_node_inputs_array[index].src_id = node_id[i];
189 s_node_inputs_array[index].output_idx = port[i];
190 }
191 void* retval = (void*)(&s_node_inputs_array[s_node_inputs_array_index]);
192 s_node_inputs_array_index += input_count;
193 return retval;
194 }
195
soc_interface_SetOneNodeOutputs(int output_count,int * max_size)196 void* soc_interface_SetOneNodeOutputs(int output_count, int* max_size) {
197 if (s_node_outputs_array_index + output_count >
198 s_node_outputs_array_max_count) {
199 TFMLOGE("output count exceeds limit");
200 return 0;
201 }
202 for (int i = 0; i < output_count; ++i) {
203 const int index = s_node_outputs_array_index + i;
204 s_node_outputs_array[index].max_size = max_size[i];
205 }
206 void* retval = (void*)(&s_node_outputs_array[s_node_outputs_array_index]);
207 s_node_outputs_array_index += output_count;
208 return retval;
209 }
210
211 // Append const node to the graph
soc_interface_AppendConstNode(const char * const name,int node_id,int batch,int height,int width,int depth,const uint8_t * const data,int data_length)212 bool soc_interface_AppendConstNode(const char* const name, int node_id,
213 int batch, int height, int width, int depth,
214 const uint8_t* const data, int data_length) {
215 const uint32_t graph_id = hexagon_controller_GetTargetGraphId();
216 const int retval = hexagon_controller_AppendConstNode(
217 name, graph_id, node_id, batch, height, width, depth, data, data_length);
218 if (retval != 0) {
219 TFMLOGE("Failed to append const node %d", node_id);
220 return false;
221 }
222 return true;
223 }
224
225 // Append node to the graph
soc_interface_AppendNode(const char * const name,int node_id,int ops_id,int padding_id,const void * const inputs,int inputs_count,const void * const outputs,int outputs_count)226 bool soc_interface_AppendNode(const char* const name, int node_id, int ops_id,
227 int padding_id, const void* const inputs,
228 int inputs_count, const void* const outputs,
229 int outputs_count) {
230 const uint32_t graph_id = hexagon_controller_GetTargetGraphId();
231 const int retval = hexagon_controller_AppendNode(
232 name, graph_id, node_id, ops_id, padding_id, (hexagon_nn_input*)inputs,
233 inputs_count, (hexagon_nn_output*)outputs, outputs_count);
234 if (retval != 0) {
235 TFMLOGE("Failed to append const node %d", node_id);
236 return false;
237 }
238 return true;
239 }
240
241 // Instantiate graph
soc_interface_InstantiateGraph()242 bool soc_interface_InstantiateGraph() {
243 const uint32_t nn_id = hexagon_controller_InstantiateGraph();
244 hexagon_controller_SetTargetGraphId(nn_id);
245 return true;
246 }
247
248 // Construct graph
soc_interface_ConstructGraph()249 bool soc_interface_ConstructGraph() {
250 const uint32_t graph_id = hexagon_controller_GetTargetGraphId();
251 return hexagon_controller_ConstructGraph(graph_id);
252 }
253
soc_interface_SetLogLevel(int log_level)254 void soc_interface_SetLogLevel(int log_level) {
255 SetLogLevel(log_level);
256 }
257
soc_interface_SetDebugFlag(uint64_t flag)258 void soc_interface_SetDebugFlag(uint64_t flag) {
259 TFMLOGI("Set debug flag 0x%" PRIx64, flag);
260 if ((flag & FLAG_ENABLE_INCEPTION_DUMMY_BINARY_INPUT) != 0) {
261 TFMLOGI("Enable always use panda data");
262 hexagon_controller_EnableDbgUseInceptionDummyData(true);
263 } else if ((flag & FLAG_ENABLE_EXPERIMENTAL_DEBUG) != 0) {
264 SetExperimentalDebug();
265 }
266 }
267