text: /*
   * Copyright (C) 2017 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  #define LOG_TAG "android.hardware.neuralnetworks@1.0-impl-hvx"
  
  #include "HexagonController.h"
  
  #define LOAD_HEXAGON_FUNCTION(name) \
      mFn_##name = loadFunction<hexagon_nn_controller_##name##_fn>("hexagon_nn_controller_" #name);
  
  #define CLOSE_HEXAGON_FUNCTION(name) mFn_##name = nullptr;
  
  #define FOR_EACH_FUNCTION(MACRO)   \
      MACRO(init)                    \
      MACRO(getlog)                  \
      MACRO(snpprint)                \
      MACRO(set_debug_level)         \
      MACRO(prepare)                 \
      MACRO(append_node)             \
      MACRO(append_const_node)       \
      MACRO(execute_new)             \
      MACRO(execute)                 \
      MACRO(teardown)                \
      MACRO(get_perfinfo)            \
      MACRO(reset_perfinfo)          \
      MACRO(version)                 \
      MACRO(last_execution_cycles)   \
      MACRO(GetHexagonBinaryVersion) \
      MACRO(PrintLog)                \
      MACRO(op_name_to_id)           \
      MACRO(op_id_to_name)           \
      MACRO(disable_dcvs)            \
      MACRO(set_powersave_level)     \
      MACRO(config)                  \
      MACRO(get_dsp_offset)          \
      MACRO(boost)                   \
      MACRO(slow)
  
  #define CONTROLLER_CHECK(function, ...)    \
      if (mFn_##function == nullptr) {       \
          return -1;                         \
      }                                      \
      int err = mFn_##function(__VA_ARGS__); \
      if (err != 0) {                        \
          return err;                        \
      }                                      \
      return 0;
  
  namespace android {
  namespace hardware {
  namespace neuralnetworks {
  namespace V1_0 {
  namespace implementation {
  namespace hexagon {
  
  const char Controller::kFilename[] = "libhexagon_nn_controller.so";
  
  Controller::Controller() {
      openNnlib();
  }
  
  Controller::~Controller() {
      closeNnlib();
  }
  
  bool Controller::openNnlib() {
      mHandle = dlopen(kFilename, RTLD_LAZY | RTLD_LOCAL);
      HEXAGON_SOFT_ASSERT_NE(mHandle, 0,
                             "FAILED TO LOAD LIBRARY " /* << kFilename << ": " << dlerror()*/);
      FOR_EACH_FUNCTION(LOAD_HEXAGON_FUNCTION)
      return true;
  }
  
  bool Controller::closeNnlib() {
      FOR_EACH_FUNCTION(CLOSE_HEXAGON_FUNCTION)
      if (mHandle != nullptr) {
          int err = dlclose(mHandle);
          mHandle = nullptr;
          HEXAGON_SOFT_ASSERT_EQ(err, 0, "FAILED TO CLOSE LIBRARY " << kFilename);
      }
      return true;
  }
  
  bool Controller::resetNnlib() {
      return closeNnlib() && openNnlib();
  }
  
  Controller& Controller::getInstance() {
      static Controller instance{};
      return instance;
  }
  
  int Controller::init(hexagon_nn_nn_id* g) {
      CONTROLLER_CHECK(init, g);
  }
  
  int Controller::getlog(hexagon_nn_nn_id id, unsigned char* buf, uint32_t length) {
      CONTROLLER_CHECK(getlog, id, buf, length);
  }
  
  int Controller::snpprint(hexagon_nn_nn_id id, unsigned char* buf, uint32_t length) {
      CONTROLLER_CHECK(snpprint, id, buf, length);
  }
  
  int Controller::set_debug_level(hexagon_nn_nn_id id, int level) {
      CONTROLLER_CHECK(set_debug_level, id, level);
  }
  
  int Controller::prepare(hexagon_nn_nn_id id) {
      CONTROLLER_CHECK(prepare, id);
  }
  
  int Controller::append_node(hexagon_nn_nn_id id, uint32_t node_id, op_type operation,
                              hexagon_nn_padding_type padding, const hexagon_nn_input* inputs,
                              uint32_t num_inputs, const hexagon_nn_output* outputs,
                              uint32_t num_outputs) {
      CONTROLLER_CHECK(append_node, id, node_id, operation, padding, inputs, num_inputs, outputs,
                       num_outputs);
  }
  
  int Controller::append_const_node(hexagon_nn_nn_id id, uint32_t node_id, uint32_t batches,
                                    uint32_t height, uint32_t width, uint32_t depth,
                                    const uint8_t* data, uint32_t data_len) {
      CONTROLLER_CHECK(append_const_node, id, node_id, batches, height, width, depth, data, data_len);
  }
  
  int Controller::execute_new(hexagon_nn_nn_id id, const hexagon_nn_tensordef* inputs,
                              uint32_t n_inputs, hexagon_nn_tensordef* outputs, uint32_t n_outputs) {
      CONTROLLER_CHECK(execute_new, id, inputs, n_inputs, outputs, n_outputs);
  }
  
  int Controller::execute(hexagon_nn_nn_id id, uint32_t batches_in, uint32_t height_in,
                          uint32_t width_in, uint32_t depth_in, const uint8_t* data_in,
                          uint32_t data_len_in, uint32_t* batches_out, uint32_t* height_out,
                          uint32_t* width_out, uint32_t* depth_out, uint8_t* data_out,
                          uint32_t data_out_max, uint32_t* data_out_size) {
      CONTROLLER_CHECK(execute, id, batches_in, height_in, width_in, depth_in, data_in, data_len_in,
                       batches_out, height_out, width_out, depth_out, data_out, data_out_max,
                       data_out_size);
  }
  
  int Controller::teardown(hexagon_nn_nn_id id) {
      CONTROLLER_CHECK(teardown, id);
  }
  
  int Controller::get_perfinfo(hexagon_nn_nn_id id, hexagon_nn_perfinfo* info_out,
                               unsigned int info_out_len, unsigned int* n_items_out) {
      CONTROLLER_CHECK(get_perfinfo, id, info_out, info_out_len, n_items_out);
  }
  
  int Controller::reset_perfinfo(hexagon_nn_nn_id id, uint32_t event) {
      CONTROLLER_CHECK(reset_perfinfo, id, event);
  }
  
  int Controller::version(int* ver) {
      CONTROLLER_CHECK(version, ver);
  }
  
  int Controller::last_execution_cycles(hexagon_nn_nn_id id, unsigned int* cycles_lo,
                                        unsigned int* cycles_hi) {
      CONTROLLER_CHECK(last_execution_cycles, id, cycles_lo, cycles_hi);
  }
  
  int Controller::GetHexagonBinaryVersion(int* ver) {
      CONTROLLER_CHECK(GetHexagonBinaryVersion, ver);
  }
  
  int Controller::PrintLog(const uint8_t* data_in, unsigned int data_in_len) {
      CONTROLLER_CHECK(PrintLog, data_in, data_in_len);
  }
  
  int Controller::op_name_to_id(const char* name, unsigned int* id) {
      CONTROLLER_CHECK(op_name_to_id, name, id);
  }
  
  int Controller::op_id_to_name(const unsigned int id, char* name, int name_len) {
      CONTROLLER_CHECK(op_id_to_name, id, name, name_len);
  }
  
  int Controller::disable_dcvs() {
      CONTROLLER_CHECK(disable_dcvs);
  }
  
  int Controller::set_powersave_level(unsigned int level) {
      CONTROLLER_CHECK(set_powersave_level, level);
  }
  
  int Controller::config() {
      CONTROLLER_CHECK(config);
  }
  
  unsigned int Controller::get_dsp_offset() {
      CONTROLLER_CHECK(get_dsp_offset);
  }
  
  int Controller::boost(int bus_usage) {
      CONTROLLER_CHECK(boost, bus_usage);
  }
  
  int Controller::slow() {
      CONTROLLER_CHECK(slow);
  }
  
  }  // namespace hexagon
  }  // namespace implementation
  }  // namespace V1_0
  }  // namespace neuralnetworks
  }  // namespace hardware
  }  // namespace android
  