1 /* Copyright 2019 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 #include "tensorflow/lite/delegates/hexagon/hexagon_delegate.h"
16
17 #include <memory>
18 #include <string>
19 #include <utility>
20 #include <vector>
21
22 #include "tensorflow/lite/c/common.h"
23 #include "tensorflow/lite/context_util.h"
24 #include "tensorflow/lite/delegates/hexagon/hexagon_delegate_kernel.h"
25 #include "tensorflow/lite/delegates/hexagon/hexagon_implementation.h"
26 #include "tensorflow/lite/delegates/hexagon/utils.h"
27 #include "tensorflow/lite/delegates/utils/simple_delegate.h"
28 #include "tensorflow/lite/minimal_logging.h"
29
30 namespace tflite {
31 namespace {
32 // Should be > 0. > 16 causes problems.
33 constexpr int kMaxHexagonGraphs = 4;
34 constexpr int kMaxMaxHexagonGraphs = 16;
35 constexpr int kMinNodesPerHexagonGraph = 2;
36
37 class HexagonDelegate : public SimpleDelegateInterface {
38 public:
HexagonDelegate(const TfLiteHexagonDelegateOptions * params)39 explicit HexagonDelegate(const TfLiteHexagonDelegateOptions* params)
40 : params_(params != nullptr ? *params
41 : TfLiteHexagonDelegateOptions({0})) {
42 if (params_.max_delegated_partitions <= 0) {
43 params_.max_delegated_partitions = kMaxHexagonGraphs;
44 } else if (params_.max_delegated_partitions > kMaxMaxHexagonGraphs) {
45 TFLITE_LOG_PROD(tflite::TFLITE_LOG_WARNING,
46 "Hexagon delegate: cannot have this many %d partitions, "
47 "and will cap to at most %d partitions.\n",
48 params_.max_delegated_partitions, kMaxMaxHexagonGraphs);
49 params_.max_delegated_partitions = kMaxMaxHexagonGraphs;
50 }
51 if (params_.min_nodes_per_partition <= 0) {
52 params_.min_nodes_per_partition = kMinNodesPerHexagonGraph;
53 }
54 }
55
IsNodeSupportedByDelegate(const TfLiteRegistration * registration,const TfLiteNode * node,TfLiteContext * context) const56 bool IsNodeSupportedByDelegate(const TfLiteRegistration* registration,
57 const TfLiteNode* node,
58 TfLiteContext* context) const override {
59 return IsNodeSupportedByHexagon(registration, node, context);
60 }
61
Initialize(TfLiteContext * context)62 TfLiteStatus Initialize(TfLiteContext* context) override { return kTfLiteOk; }
63
Name() const64 const char* Name() const override { return "TfLiteHexagonDelegate"; }
65
CreateDelegateKernelInterface()66 std::unique_ptr<SimpleDelegateKernelInterface> CreateDelegateKernelInterface()
67 override {
68 return std::make_unique<HexagonDelegateKernel>(params_);
69 }
70
DelegateOptions() const71 SimpleDelegateInterface::Options DelegateOptions() const override {
72 auto options = SimpleDelegateInterface::Options();
73 options.max_delegated_partitions = params_.max_delegated_partitions;
74 options.min_nodes_per_partition = params_.min_nodes_per_partition;
75 return options;
76 }
77
VerifyDelegate()78 bool VerifyDelegate() {
79 auto* hexagon_nn = HexagonNNImplementation();
80 if (hexagon_nn == nullptr) {
81 return false;
82 }
83 if (hexagon_nn->hexagon_nn_version != nullptr &&
84 hexagon_nn->hexagon_nn_hexagon_interface_version) {
85 int hexagon_nn_version = -1;
86 int hexagon_interface_version =
87 hexagon_nn->hexagon_nn_hexagon_interface_version();
88 if (hexagon_nn->hexagon_nn_version(&hexagon_nn_version) != 0) {
89 TFLITE_LOG_PROD(tflite::TFLITE_LOG_WARNING,
90 "Failed to fetch Hexagon NN version. This might be "
91 "because you're using incompatible versions of "
92 "libhexagon_interface and libhexagon_nn_skel. "
93 "You must use compatible versions. "
94 "Refer to Tensorflow Lite Hexagon Delegate Guide.");
95 return false;
96 }
97 if (hexagon_nn_version != hexagon_interface_version) {
98 TFLITE_LOG_PROD(
99 tflite::TFLITE_LOG_WARNING,
100 "Incompatible versions between interface library and "
101 "libhexagon_skel %d vs %d. You must use compatible versions. "
102 "Refer to Tensorflow Lite Hexagon Delegate Guide.",
103 hexagon_interface_version, hexagon_nn_version);
104 return false;
105 }
106 }
107 return hexagon_nn->hexagon_nn_is_device_supported &&
108 hexagon_nn->hexagon_nn_is_device_supported();
109 }
110
111 private:
112 TfLiteHexagonDelegateOptions params_;
113 };
114
115 } // namespace
116 } // namespace tflite
117
TfLiteHexagonDelegateCreate(const TfLiteHexagonDelegateOptions * options)118 TfLiteDelegate* TfLiteHexagonDelegateCreate(
119 const TfLiteHexagonDelegateOptions* options) {
120 auto hexagon_delegate_interface =
121 std::make_unique<tflite::HexagonDelegate>(options);
122 if (!hexagon_delegate_interface->VerifyDelegate()) {
123 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO,
124 "Hexagon Delegate is not supported.\n");
125 return nullptr;
126 }
127 auto* initialized_delegate =
128 tflite::TfLiteDelegateFactory::CreateSimpleDelegate(
129 std::move(hexagon_delegate_interface));
130 if (options->enable_dynamic_batch_size) {
131 initialized_delegate->flags |= kTfLiteDelegateFlagsAllowDynamicTensors;
132 }
133 return initialized_delegate;
134 }
135
TfLiteHexagonDelegateOptionsDefault()136 TfLiteHexagonDelegateOptions TfLiteHexagonDelegateOptionsDefault() {
137 TfLiteHexagonDelegateOptions result{0};
138 return result;
139 }
140
TfLiteHexagonDelegateDelete(TfLiteDelegate * delegate)141 void TfLiteHexagonDelegateDelete(TfLiteDelegate* delegate) {
142 tflite::TfLiteDelegateFactory::DeleteSimpleDelegate(delegate);
143 }
144
TfLiteHexagonInit()145 void TfLiteHexagonInit() { tflite::HexagonDelegateKernel::InitState(); }
146
TfLiteHexagonInitWithPath(const char * lib_directory_path)147 void TfLiteHexagonInitWithPath(const char* lib_directory_path) {
148 if (lib_directory_path != nullptr) {
149 std::string env_var_value = lib_directory_path;
150 env_var_value += ";/system/lib/rfsa/adsp;/system/vendor/lib/rfsa/adsp;/dsp";
151 setenv("ADSP_LIBRARY_PATH", env_var_value.c_str(), 1 /* overwrite */);
152 }
153 tflite::HexagonDelegateKernel::InitState();
154 }
TfLiteHexagonTearDown()155 void TfLiteHexagonTearDown() { tflite::HexagonDelegateKernel::Teardown(); }
156