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 42 int soc_interface_GetWrapperVersion() { 43 TFMLOGD("GetWrapperVersion"); 44 return hexagon_controller_GetWrapperVersion(); 45 } 46 47 int soc_interface_GetSocControllerVersion() { 48 TFMLOGD("GetSocControllerVersion"); 49 return hexagon_controller_GetHexagonBinaryVersion(); 50 } 51 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 60 bool soc_interface_Finalize() { 61 TFMLOGD("Finalize"); 62 hexagon_controller_DeInitHexagon(); 63 return true; 64 } 65 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 249 bool soc_interface_ConstructGraph() { 250 const uint32_t graph_id = hexagon_controller_GetTargetGraphId(); 251 return hexagon_controller_ConstructGraph(graph_id); 252 } 253 254 void soc_interface_SetLogLevel(int log_level) { 255 SetLogLevel(log_level); 256 } 257 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