xref: /aosp_15_r20/external/tensorflow/tensorflow/lite/delegates/hexagon/hexagon_delegate.cc (revision b6fb3261f9314811a0f4371741dbb8839866f948)
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