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