From 035f1324bfcd19b7e4f4205c0e4d4cc2d2e089e2 Mon Sep 17 00:00:00 2001 From: Bin Li Date: Wed, 6 Nov 2019 19:50:19 +0800 Subject: [PATCH] Integrate hexnn wrapper and support unsigned PD --- include/mace/public/mace.h | 12 ++ .../runtime/hexagon/hexagon_dsp_wrapper.cc | 109 +++++++----------- .../runtime/hexagon/hexagon_dsp_wrapper.h | 2 + mace/libmace/mace.cc | 65 +++++++++-- mace/tools/mace_run.cc | 3 + third_party/nnlib/BUILD.bazel | 1 + .../nnlib/arm64-v8a/libhexagon_controller.so | Bin 38704 -> 52712 bytes .../armeabi-v7a/libhexagon_controller.so | Bin 26704 -> 40552 bytes third_party/nnlib/hexagon_nn.h | 77 +++++++++---- third_party/nnlib/hexnn_dsp_controller.h | 53 +++++++++ third_party/nnlib/license.txt | 2 +- third_party/nnlib/ops.h | 2 +- 12 files changed, 228 insertions(+), 98 deletions(-) create mode 100644 third_party/nnlib/hexnn_dsp_controller.h diff --git a/include/mace/public/mace.h b/include/mace/public/mace.h index d2c76866..7018fc53 100644 --- a/include/mace/public/mace.h +++ b/include/mace/public/mace.h @@ -328,6 +328,18 @@ class MACE_API MaceEngineConfig { MaceStatus SetCPUThreadPolicy(int num_threads_hint, CPUAffinityPolicy policy); + /// \brief Set Hexagon NN to run on unsigned PD + /// + /// Caution: This function must be called before any Hexagon related + /// functions and it should only be called once. + /// Starting in the SM8150 family, signature-free dynamic module offload is + /// enabled on cDSP in a low-rights process (Unsigned PD). A success from this + /// function allows the clients to offload the dynamic shared object to cDSP + /// without signing. However, some older cDSP firmware may not work due to + /// access limitations. + /// \return MaceStatus::MACE_SUCCESS for success, other for failure. + MaceStatus SetHexagonToUnsignedPD(); + /// \brief Set Hexagon DSP power parameters /// /// Caution: this function may hurt performance if improper diff --git a/mace/core/runtime/hexagon/hexagon_dsp_wrapper.cc b/mace/core/runtime/hexagon/hexagon_dsp_wrapper.cc index cdde2786..e76c20f4 100644 --- a/mace/core/runtime/hexagon/hexagon_dsp_wrapper.cc +++ b/mace/core/runtime/hexagon/hexagon_dsp_wrapper.cc @@ -29,6 +29,7 @@ #include "mace/port/env.h" #include "mace/utils/memory.h" #include "third_party/nnlib/hexagon_nn.h" +#include "third_party/nnlib/hexnn_dsp_controller.h" namespace mace { @@ -106,6 +107,8 @@ hexagon_nn_corner_type TransformCornerType(HexagonNNCornerType corner) { } // namespace HexagonDSPWrapper::HexagonDSPWrapper() { + hexnn_controller_init(); + std::string env_log_execute_time_str; GetEnv("MACE_DSP_LOG_EXECUTE_TIME", &env_log_execute_time_str); if (env_log_execute_time_str.empty()) { @@ -115,6 +118,9 @@ HexagonDSPWrapper::HexagonDSPWrapper() { } } +HexagonDSPWrapper::~HexagonDSPWrapper() { + hexnn_controller_deinit(); +} int HexagonDSPWrapper::GetVersion() { int version; @@ -122,6 +128,14 @@ int HexagonDSPWrapper::GetVersion() { return version; } +bool HexagonDSPWrapper::RequestUnsignedPD() { + int ret = hexnn_controller_request_unsigned_pd(); + if (ret != 0) { + LOG(WARNING) << "Request unsigned PD failed: " << ret; + } + return ret == 0; +} + bool HexagonDSPWrapper::SetPower(HexagonNNCornerType corner, bool dcvs_enable, int latency) { @@ -129,6 +143,9 @@ bool HexagonDSPWrapper::SetPower(HexagonNNCornerType corner, dcvs_enable ? NN_DCVS_ENABLE : NN_DCVS_DISABLE, static_cast(std::max(0, latency))); + if (ret != 0) { + LOG(WARNING) << "Hexagon set power failed: " << ret; + } return ret == 0; } @@ -157,7 +174,6 @@ bool HexagonDSPWrapper::SetupGraph(const NetDef &net_def, int64_t t0 = NowMicros(); // const node - std::vector const_node_list; for (const ConstTensor &const_tensor : net_def.tensors()) { std::vector tensor_shape(const_tensor.dims().begin(), const_tensor.dims().end()); @@ -165,48 +181,32 @@ bool HexagonDSPWrapper::SetupGraph(const NetDef &net_def, tensor_shape.insert(tensor_shape.begin(), 1); } - hexagon_nn_const_node const_node; - const_node.node_id = node_id(const_tensor.node_id()); - const_node.tensor.batches = tensor_shape[0]; - const_node.tensor.height = tensor_shape[1]; - const_node.tensor.width = tensor_shape[2]; - const_node.tensor.depth = tensor_shape[3]; - + unsigned char *data; + int data_len; if (const_tensor.data_type() == DataType::DT_INT32 && const_tensor.data_size() == 0) { - const_node.tensor.data = NULL; - const_node.tensor.dataLen = 0; + data = NULL; + data_len = 0; } else { - const_node.tensor.data = - const_cast(model_data + const_tensor.offset()); - const_node.tensor.dataLen = const_tensor.data_size() * - GetEnumTypeSize(const_tensor.data_type()); - } - const_node_list.push_back(const_node); - // 255 is magic number: why fastrpc limits sequence length to that? - if (const_node_list.size() >= 250) { - MACE_CHECK( - hexagon_nn_append_const_node_list(nn_id_, const_node_list.data(), - const_node_list.size()) == 0, - "append const node error"); - const_node_list.clear(); + data = const_cast(model_data + const_tensor.offset()); + data_len = + const_tensor.data_size() * GetEnumTypeSize(const_tensor.data_type()); } - } - - if (!const_node_list.empty()) { MACE_CHECK( - hexagon_nn_append_const_node_list(nn_id_, const_node_list.data(), - const_node_list.size()) == 0, + hexagon_nn_append_const_node(nn_id_, + node_id(const_tensor.node_id()), + tensor_shape[0], + tensor_shape[1], + tensor_shape[2], + tensor_shape[3], + data, + data_len) == 0, "append const node error"); } - const_node_list.clear(); // op node OpMap op_map; op_map.Init(); - std::vector op_node_list; - std::vector> cached_inputs; - std::vector> cached_outputs; std::vector inputs; std::vector outputs; @@ -233,40 +233,18 @@ bool HexagonDSPWrapper::SetupGraph(const NetDef &net_def, outputs[i].zero_offset = 0; outputs[i].stepsize = 0; } - cached_inputs.push_back(inputs); - cached_outputs.push_back(outputs); - - hexagon_nn_padding_type padding_type = - static_cast(op.padding()); - - hexagon_nn_op_node op_node; - op_node.node_id = node_id(op.node_id()); - op_node.operation = op_id; - op_node.padding = padding_type; - op_node.inputs = cached_inputs.back().data(); - op_node.inputsLen = inputs.size(); - op_node.outputs = cached_outputs.back().data(); - op_node.outputsLen = outputs.size(); - - op_node_list.push_back(op_node); - if (op_node_list.size() >= 125) { - MACE_CHECK(hexagon_nn_append_node_list(nn_id_, op_node_list.data(), - op_node_list.size()) == 0, - "append node error"); - op_node_list.clear(); - cached_inputs.clear(); - cached_outputs.clear(); - } - } - - if (!op_node_list.empty()) { - MACE_CHECK(hexagon_nn_append_node_list(nn_id_, op_node_list.data(), - op_node_list.size()) == 0, + auto padding_type = static_cast(op.padding()); + + MACE_CHECK(hexagon_nn_append_node(nn_id_, + node_id(op.node_id()), + op_id, + padding_type, + inputs.data(), + inputs.size(), + outputs.data(), + outputs.size()) == 0, "append node error"); } - op_node_list.clear(); - cached_inputs.clear(); - cached_outputs.clear(); // input info num_inputs_ = net_def.input_info_size(); @@ -372,7 +350,8 @@ void HexagonDSPWrapper::GetPerfInfo() { std::vector> run_order_data; for (unsigned int i = 0; i < n_items; ++i) { unsigned int node_id = perf_info[i].node_id; - unsigned int node_type_id = perf_info[i].node_type; + unsigned int node_type_id = 0; + hexagon_nn_get_nodetype(nn_id_, node_id, &node_type_id); node_id_counters[node_id] = ((static_cast(perf_info[i].counter_hi) << 32) + perf_info[i].counter_lo) * diff --git a/mace/core/runtime/hexagon/hexagon_dsp_wrapper.h b/mace/core/runtime/hexagon/hexagon_dsp_wrapper.h index 1c0c4635..831d163f 100644 --- a/mace/core/runtime/hexagon/hexagon_dsp_wrapper.h +++ b/mace/core/runtime/hexagon/hexagon_dsp_wrapper.h @@ -28,6 +28,7 @@ namespace mace { class HexagonDSPWrapper : public HexagonControlWrapper { public: HexagonDSPWrapper(); + ~HexagonDSPWrapper(); int GetVersion() override; bool Config() override; @@ -49,6 +50,7 @@ class HexagonDSPWrapper : public HexagonControlWrapper { static bool SetPower(HexagonNNCornerType corner, bool dcvs_enable, int latency); + static bool RequestUnsignedPD(); private: uint64_t GetLastExecuteCycles(); diff --git a/mace/libmace/mace.cc b/mace/libmace/mace.cc index 51c53097..eb79da6f 100644 --- a/mace/libmace/mace.cc +++ b/mace/libmace/mace.cc @@ -192,6 +192,8 @@ class MaceEngineConfig::Impl { MaceStatus SetCPUThreadPolicy(int num_threads_hint, CPUAffinityPolicy policy); + MaceStatus SetHexagonToUnsignedPD(); + MaceStatus SetHexagonPower(HexagonNNCornerType corner, bool dcvs_enable, int latency); @@ -220,6 +222,18 @@ class MaceEngineConfig::Impl { return gpu_perf_hint_; } + inline HexagonNNCornerType hexagon_corner() const { + return hexagon_corner_; + } + + inline bool hexagon_dcvs_enable() const { + return hexagon_dcvs_enable_; + } + + inline int hexagon_latency() const { + return hexagon_latency_; + } + private: DeviceType device_type_; int num_threads_; @@ -227,6 +241,9 @@ class MaceEngineConfig::Impl { std::shared_ptr gpu_context_; GPUPriorityHint gpu_priority_hint_; GPUPerfHint gpu_perf_hint_; + HexagonNNCornerType hexagon_corner_; + bool hexagon_dcvs_enable_; + int hexagon_latency_; }; MaceEngineConfig::Impl::Impl(const DeviceType device_type) @@ -235,13 +252,10 @@ MaceEngineConfig::Impl::Impl(const DeviceType device_type) cpu_affinity_policy_(CPUAffinityPolicy::AFFINITY_NONE), gpu_context_(nullptr), gpu_priority_hint_(GPUPriorityHint::PRIORITY_LOW), - gpu_perf_hint_(GPUPerfHint::PERF_NORMAL) { -#ifdef MACE_ENABLE_HEXAGON - if (!HexagonDSPWrapper::SetPower(HEXAGON_NN_CORNER_TURBO, true, 100)) { - LOG(WARNING) << "Hexagon set default clocks failed!"; - } -#endif -} + gpu_perf_hint_(GPUPerfHint::PERF_NORMAL), + hexagon_corner_(HexagonNNCornerType::HEXAGON_NN_CORNER_TURBO), + hexagon_dcvs_enable_(true), + hexagon_latency_(100) {} MaceStatus MaceEngineConfig::Impl::SetGPUContext( std::shared_ptr context) { @@ -265,13 +279,21 @@ MaceStatus MaceEngineConfig::Impl::SetCPUThreadPolicy( return MaceStatus::MACE_SUCCESS; } +MaceStatus MaceEngineConfig::Impl::SetHexagonToUnsignedPD() { + bool ret = false; +#ifdef MACE_ENABLE_HEXAGON + ret = HexagonDSPWrapper::RequestUnsignedPD(); +#endif + return ret ? MaceStatus::MACE_SUCCESS : MaceStatus::MACE_RUNTIME_ERROR; +} + MaceStatus MaceEngineConfig::Impl::SetHexagonPower( HexagonNNCornerType corner, bool dcvs_enable, int latency) { - MACE_UNUSED(corner); - MACE_UNUSED(dcvs_enable); - MACE_UNUSED(latency); + hexagon_corner_ = corner; + hexagon_dcvs_enable_ = dcvs_enable; + hexagon_latency_ = latency; bool ret = false; #ifdef MACE_ENABLE_HEXAGON ret = HexagonDSPWrapper::SetPower(corner, dcvs_enable, latency); @@ -302,6 +324,10 @@ MaceStatus MaceEngineConfig::SetCPUThreadPolicy( return impl_->SetCPUThreadPolicy(num_threads_hint, policy); } +MaceStatus MaceEngineConfig::SetHexagonToUnsignedPD() { + return impl_->SetHexagonToUnsignedPD(); +} + MaceStatus MaceEngineConfig::SetHexagonPower( HexagonNNCornerType corner, bool dcvs_enable, @@ -434,6 +460,11 @@ class MaceEngine::Impl { std::map input_info_map_; std::map output_info_map_; std::unique_ptr thread_pool_; +#ifdef MACE_ENABLE_HEXAGON + HexagonNNCornerType hexagon_corner_; + bool hexagon_dcvs_enable_; + int hexagon_latency_; +#endif #if defined(MACE_ENABLE_HEXAGON) || defined(MACE_ENABLE_HTA) std::unique_ptr hexagon_controller_; #endif @@ -454,8 +485,13 @@ MaceEngine::Impl::Impl(const MaceEngineConfig &config) is_quantized_model_(false), thread_pool_(new utils::ThreadPool(config.impl_->num_threads(), config.impl_->cpu_affinity_policy())) +#ifdef MACE_ENABLE_HEXAGON + , hexagon_corner_(config.impl_->hexagon_corner()) + , hexagon_dcvs_enable_(config.impl_->hexagon_dcvs_enable()) + , hexagon_latency_(config.impl_->hexagon_latency()) +#endif #if defined(MACE_ENABLE_HEXAGON) || defined(MACE_ENABLE_HTA) -, hexagon_controller_(nullptr) + , hexagon_controller_(nullptr) #endif #ifdef MACE_ENABLE_APU , apu_controller_(nullptr) @@ -554,6 +590,13 @@ MaceStatus MaceEngine::Impl::Init( output_tensor->set_data_format(DataFormat::NHWC); #endif } +#ifdef MACE_ENABLE_HEXAGON + if (device_type_ == HEXAGON) { + HexagonDSPWrapper::SetPower(hexagon_corner_, + hexagon_dcvs_enable_, + hexagon_latency_); + } +#endif #if defined(MACE_ENABLE_HEXAGON) || defined(MACE_ENABLE_HTA) if (device_type_ == HEXAGON || device_type_ == HTA) { hexagon_controller_ = CreateHexagonControlWrapper(device_.get()); diff --git a/mace/tools/mace_run.cc b/mace/tools/mace_run.cc index e135e5ed..55f29317 100644 --- a/mace/tools/mace_run.cc +++ b/mace/tools/mace_run.cc @@ -197,6 +197,9 @@ bool RunModel(const std::string &model_name, } #endif // MACE_ENABLE_OPENCL #ifdef MACE_ENABLE_HEXAGON + // SetHexagonToUnsignedPD() can be called for 8150 family(with new cDSP + // firmware) or 8250 family above to run hexagon nn on unsigned PD. + // config.SetHexagonToUnsignedPD(); config.SetHexagonPower(HEXAGON_NN_CORNER_TURBO, true, 100); #endif std::unique_ptr model_graph_data = diff --git a/third_party/nnlib/BUILD.bazel b/third_party/nnlib/BUILD.bazel index 488b0500..38521738 100644 --- a/third_party/nnlib/BUILD.bazel +++ b/third_party/nnlib/BUILD.bazel @@ -20,6 +20,7 @@ cc_library( ]), hdrs = [ "hexagon_nn.h", + "hexnn_dsp_controller.h", "ops.h", ], visibility = ["//visibility:public"], diff --git a/third_party/nnlib/arm64-v8a/libhexagon_controller.so b/third_party/nnlib/arm64-v8a/libhexagon_controller.so index 2509a78001d9b4490051617ffa4e895f4da85ca8..29a8003625daa2865f7a8dddbef2bedd812f44ab 100755 GIT binary patch literal 52712 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 diff --git a/third_party/nnlib/armeabi-v7a/libhexagon_controller.so b/third_party/nnlib/armeabi-v7a/libhexagon_controller.so index 13d6f92188f3118773db0014976d22c45110ced8..977c25d69cc46d0dba59e71ab45071299ebfbeb1 100755 GIT binary patch literal 40552 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 diff --git a/third_party/nnlib/hexagon_nn.h b/third_party/nnlib/hexagon_nn.h index d225d6b6..cd371c4d 100644 --- a/third_party/nnlib/hexagon_nn.h +++ b/third_party/nnlib/hexagon_nn.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted (subject to the limitations in the @@ -87,13 +87,15 @@ struct hexagon_nn_output { typedef struct hexagon_nn_perfinfo hexagon_nn_perfinfo; struct hexagon_nn_perfinfo { unsigned int node_id; - unsigned int node_type; unsigned int executions; - unsigned int unused; unsigned int counter_lo; unsigned int counter_hi; }; typedef int hexagon_nn_nn_id; +typedef struct hexagon_nn_initinfo hexagon_nn_initinfo; +struct hexagon_nn_initinfo { + int priority; +}; enum hexagon_nn_padding_type { NN_PAD_NA, NN_PAD_SAME, @@ -133,7 +135,47 @@ struct hexagon_nn_tensordef { unsigned int data_valid_len; unsigned int unused; }; +enum hexagon_nn_execute_result { + NN_EXECUTE_SUCCESS, + NN_EXECUTE_ERROR, + NN_EXECUTE_BUFFER_SIZE_ERROR, + _32BIT_PLACEHOLDER_hexagon_nn_execute_result = 0x7fffffff +}; +typedef enum hexagon_nn_execute_result hexagon_nn_execute_result; +typedef struct hexagon_nn_execute_info hexagon_nn_execute_info; +struct hexagon_nn_execute_info { + hexagon_nn_execute_result result; + unsigned char* extraInfo; + int extraInfoLen; + unsigned int extraInfoValidLen; +}; +enum hexagon_nn_option_type { + NN_OPTION_NOSUCHOPTION, + NN_OPTION_SCALAR_THREADS, + NN_OPTION_HVX_THREADS, + NN_OPTION_VTCM_REQ, + NN_OPTION_ENABLE_GRAPH_PRINT, + NN_OPTION_ENABLE_TENSOR_PRINT, + NN_OPTION_TENSOR_PRINT_FILTER, + NN_OPTION_HAP_MEM_GROW_SIZE, + NN_OPTION_ENABLE_CONST_PRINT, + NN_OPTION_LASTPLUSONE, + _32BIT_PLACEHOLDER_hexagon_nn_option_type = 0x7fffffff +}; +typedef enum hexagon_nn_option_type hexagon_nn_option_type; +typedef struct hexagon_nn_uint_option hexagon_nn_uint_option; +struct hexagon_nn_uint_option { + unsigned int option_id; + unsigned int uint_value; +}; +typedef struct hexagon_nn_string_option hexagon_nn_string_option; +struct hexagon_nn_string_option { + unsigned int option_id; + char string_data[256]; +}; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_config)(void) __QAIC_HEADER_ATTRIBUTE; +__QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_config_with_options)(const hexagon_nn_uint_option* uint_options, int uint_optionsLen, const hexagon_nn_string_option* string_options, int string_optionsLen) __QAIC_HEADER_ATTRIBUTE; +__QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_graph_config)(hexagon_nn_nn_id id, const hexagon_nn_uint_option* uint_options, int uint_optionsLen, const hexagon_nn_string_option* string_options, int string_optionsLen) __QAIC_HEADER_ATTRIBUTE; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_get_dsp_offset)(unsigned int* libhexagon_addr, unsigned int* fastrpc_shell_addr) __QAIC_HEADER_ATTRIBUTE; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_init)(hexagon_nn_nn_id* g) __QAIC_HEADER_ATTRIBUTE; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_set_debug_level)(hexagon_nn_nn_id id, int level) __QAIC_HEADER_ATTRIBUTE; @@ -143,26 +185,12 @@ __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_append_node)(hexagon_nn_nn_id __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_append_const_node)(hexagon_nn_nn_id id, unsigned int node_id, unsigned int batches, unsigned int height, unsigned int width, unsigned int depth, const unsigned char* data, int dataLen) __QAIC_HEADER_ATTRIBUTE; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_append_empty_const_node)(hexagon_nn_nn_id id, unsigned int node_id, unsigned int batches, unsigned int height, unsigned int width, unsigned int depth, unsigned int size) __QAIC_HEADER_ATTRIBUTE; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_populate_const_node)(hexagon_nn_nn_id id, unsigned int node_id, const unsigned char* data, int dataLen, unsigned int target_offset) __QAIC_HEADER_ATTRIBUTE; -typedef struct hexagon_nn_op_node hexagon_nn_op_node; -struct hexagon_nn_op_node { - unsigned int node_id; - unsigned int operation; - hexagon_nn_padding_type padding; - hexagon_nn_input* inputs; - int inputsLen; - hexagon_nn_output* outputs; - int outputsLen; -}; -typedef struct hexagon_nn_const_node hexagon_nn_const_node; -struct hexagon_nn_const_node { - unsigned int node_id; - hexagon_nn_tensordef tensor; -}; -__QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_append_node_list)(hexagon_nn_nn_id id, const hexagon_nn_op_node* ops, int opsLen) __QAIC_HEADER_ATTRIBUTE; -__QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_append_const_node_list)(hexagon_nn_nn_id id, const hexagon_nn_const_node* consts, int constsLen) __QAIC_HEADER_ATTRIBUTE; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_prepare)(hexagon_nn_nn_id id) __QAIC_HEADER_ATTRIBUTE; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_execute)(hexagon_nn_nn_id id, unsigned int batches_in, unsigned int height_in, unsigned int width_in, unsigned int depth_in, const unsigned char* data_in, int data_inLen, unsigned int* batches_out, unsigned int* height_out, unsigned int* width_out, unsigned int* depth_out, unsigned char* data_out, int data_outLen, unsigned int* data_len_out) __QAIC_HEADER_ATTRIBUTE; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_teardown)(hexagon_nn_nn_id id) __QAIC_HEADER_ATTRIBUTE; +__QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_variable_read)(hexagon_nn_nn_id id, unsigned int node_id, int output_index, unsigned int* batches_out, unsigned int* height_out, unsigned int* width_out, unsigned int* depth_out, unsigned char* data_out, int data_outLen, unsigned int* data_len_out) __QAIC_HEADER_ATTRIBUTE; +__QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_variable_write)(hexagon_nn_nn_id id, unsigned int node_id, int output_index, unsigned int batches, unsigned int height, unsigned int width, unsigned int depth, const unsigned char* data_in, int data_inLen) __QAIC_HEADER_ATTRIBUTE; +__QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_variable_write_flat)(hexagon_nn_nn_id id, unsigned int node_id, int output_index, const unsigned char* data_in, int data_inLen) __QAIC_HEADER_ATTRIBUTE; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_set_powersave_level)(unsigned int level) __QAIC_HEADER_ATTRIBUTE; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_set_powersave_details)(hexagon_nn_corner_type corner, hexagon_nn_dcvs_type dcvs, unsigned int latency) __QAIC_HEADER_ATTRIBUTE; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_set_clocks)(hexagon_nn_corner_type corner, hexagon_nn_dcvs_type dcvs, unsigned int latency) __QAIC_HEADER_ATTRIBUTE; @@ -173,10 +201,19 @@ __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_last_execution_cycles)(hexagon __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_version)(int* ver) __QAIC_HEADER_ATTRIBUTE; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_op_name_to_id)(const char* name, unsigned int* node_id) __QAIC_HEADER_ATTRIBUTE; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_op_id_to_name)(unsigned int node_id, char* name, int nameLen) __QAIC_HEADER_ATTRIBUTE; +__QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_get_num_nodes_in_graph)(hexagon_nn_nn_id id, unsigned int* num_nodes) __QAIC_HEADER_ATTRIBUTE; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_disable_dcvs)(void) __QAIC_HEADER_ATTRIBUTE; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_GetHexagonBinaryVersion)(int* ver) __QAIC_HEADER_ATTRIBUTE; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_PrintLog)(const unsigned char* buf, int bufLen) __QAIC_HEADER_ATTRIBUTE; __QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_execute_new)(hexagon_nn_nn_id id, const hexagon_nn_tensordef* inputs, int inputsLen, hexagon_nn_tensordef* outputs, int outputsLen) __QAIC_HEADER_ATTRIBUTE; +__QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_execute_with_info)(hexagon_nn_nn_id id, const hexagon_nn_tensordef* inputs, int inputsLen, hexagon_nn_tensordef* outputs, int outputsLen, hexagon_nn_execute_info* execute_info) __QAIC_HEADER_ATTRIBUTE; +__QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_init_with_info)(hexagon_nn_nn_id* g, const hexagon_nn_initinfo* info) __QAIC_HEADER_ATTRIBUTE; +__QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_get_nodetype)(hexagon_nn_nn_id graph_id, hexagon_nn_nn_id node_id, unsigned int* node_type) __QAIC_HEADER_ATTRIBUTE; +__QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_multi_execution_cycles)(hexagon_nn_nn_id id, unsigned int* cycles_lo, unsigned int* cycles_hi) __QAIC_HEADER_ATTRIBUTE; +__QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_get_power)(int type) __QAIC_HEADER_ATTRIBUTE; +__QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_set_graph_option)(hexagon_nn_nn_id id, const char* name, int value) __QAIC_HEADER_ATTRIBUTE; +__QAIC_HEADER_EXPORT int __QAIC_HEADER(hexagon_nn_populate_graph)(hexagon_nn_nn_id id, const unsigned char* graph_data, int graph_dataLen) __QAIC_HEADER_ATTRIBUTE; + #ifdef __cplusplus } #endif diff --git a/third_party/nnlib/hexnn_dsp_controller.h b/third_party/nnlib/hexnn_dsp_controller.h new file mode 100644 index 00000000..671a6c68 --- /dev/null +++ b/third_party/nnlib/hexnn_dsp_controller.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted (subject to the limitations in the + * disclaimer below) provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE + * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT + * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef THIRD_PARTY_NNLIB_HEXNN_DSP_CONTROLLER_H_ +#define THIRD_PARTY_NNLIB_HEXNN_DSP_CONTROLLER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +int hexnn_controller_request_unsigned_pd(); + +int hexnn_controller_init(); + +int hexnn_controller_deinit(); + +#ifdef __cplusplus +} +#endif + +#endif // THIRD_PARTY_NNLIB_HEXNN_DSP_CONTROLLER_H_ diff --git a/third_party/nnlib/license.txt b/third_party/nnlib/license.txt index d5c3aa96..624e16e8 100644 --- a/third_party/nnlib/license.txt +++ b/third_party/nnlib/license.txt @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted (subject to the limitations in the diff --git a/third_party/nnlib/ops.h b/third_party/nnlib/ops.h index 4aedd258..252171df 100644 --- a/third_party/nnlib/ops.h +++ b/third_party/nnlib/ops.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted (subject to the limitations in the -- GitLab