From 6f0eec9d09d29fa0b044bbb0d86e2c8a5e5bbe59 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=D0=A0=D0=BE=D0=BC=D0=B0=D0=BD=20=D0=9C=D0=B8=D1=85=D0=B0?= =?utf8?q?=D0=B9=D0=BB=D0=BE=D0=B2=D0=B8=D1=87=20=D0=A0=D1=83=D1=81=D1=8F?= =?utf8?q?=D0=B5=D0=B2/AI=20Tools=20Lab=20/SRR/Staff=20Engineer/=EC=82=BC?= =?utf8?q?=EC=84=B1=EC=A0=84=EC=9E=90?= Date: Wed, 22 Aug 2018 09:52:50 +0300 Subject: [PATCH] Implement compiler driver and redesign plugin system (#1103) * improve command line parser a little bit * implement compiler driver * redesign plugin system: - eliminate redundant classes - search plugin by predefined paths - adapt cmake build system: installation of targets * Remove redundant headers * Set plugin name dependent on OS target * Eliminate dependencies from nncc_foundation and nncc_core libraries Signed-off-by: Roman Rusyaev --- contrib/nnc/CMakeLists.txt | 59 ++++++++- contrib/nnc/examples/plugin_example/CMakeLists.txt | 2 - .../nnc/examples/plugin_example/samplePlugin.cpp | 3 +- contrib/nnc/include/Definitions.h.in | 44 +++++++ contrib/nnc/include/Driver.h | 50 ++++++++ contrib/nnc/include/Options.h | 35 +++--- contrib/nnc/include/module/AbstractModule.h | 39 ------ contrib/nnc/include/module/BackendModule.h | 29 ----- contrib/nnc/include/module/FrontendModule.h | 29 ----- contrib/nnc/include/module/plugin/PluginManager.h | 49 -------- contrib/nnc/include/module/plugin/PluginProxy.h | 61 --------- contrib/nnc/include/module/plugin/shared_library.h | 38 ------ .../libs/backend/interpreter/core/CMakeLists.txt | 2 +- .../libs/backend/interpreter/plugin/CMakeLists.txt | 3 + .../plugin/include/interpreter_plugin.h | 1 - .../interpreter/plugin/src/interpreter_plugin.cpp | 9 +- .../libs/backend/interpreter/test/CMakeLists.txt | 2 +- contrib/nnc/libs/backend/soft/CMakeLists.txt | 6 +- contrib/nnc/libs/backend/soft/src/c_backend.cpp | 4 +- contrib/nnc/libs/backend/soft/src/cpp_backend.cpp | 4 +- contrib/nnc/libs/backend/soft/src/soft_backend.cpp | 2 - contrib/nnc/libs/core/CMakeLists.txt | 3 +- contrib/nnc/libs/frontend/CMakeLists.txt | 1 - contrib/nnc/libs/frontend/caffe/CMakeLists.txt | 4 +- .../nnc/libs/frontend/caffe/src/caffe_plugin.cpp | 3 +- contrib/nnc/libs/frontend/tflite/CMakeLists.txt | 8 +- .../nnc/libs/frontend/tflite/src/tflite_plugin.cpp | 3 +- contrib/nnc/libs/plugin/CMakeLists.txt | 3 +- contrib/nnc/libs/plugin/include/ConfigException.h | 29 ----- contrib/nnc/libs/plugin/include/PluginException.h | 19 +-- contrib/nnc/libs/plugin/include/PluginInstance.h | 22 ++-- contrib/nnc/libs/plugin/include/PluginManager.h | 62 +++++++++ contrib/nnc/libs/plugin/include/PluginProxy.h | 79 ++++++++++++ contrib/nnc/libs/plugin/include/shared_library.h | 125 ++++++++++++++++++ contrib/nnc/libs/plugin/src/ConfigException.cpp | 21 ---- contrib/nnc/libs/plugin/src/PluginException.cpp | 19 --- contrib/nnc/libs/plugin/src/PluginManager.cpp | 65 ++++++++++ contrib/nnc/libs/plugin/src/PluginProxy.cpp | 66 ++++++++++ contrib/nnc/src/Driver.cpp | 101 +++++++++++++++ contrib/nnc/src/Options.cpp | 77 +++++++----- contrib/nnc/src/main.cpp | 58 ++++----- contrib/nnc/src/module/AbstractModule.cpp | 46 ------- contrib/nnc/src/module/BackendModule.cpp | 20 --- contrib/nnc/src/module/FrontendModule.cpp | 20 --- contrib/nnc/src/module/plugin/PluginManager.cpp | 139 --------------------- contrib/nnc/src/module/plugin/PluginProxy.cpp | 76 ----------- contrib/nnc/src/module/plugin/shared_library.cpp | 75 ----------- contrib/nnc/support/CMakeLists.txt | 3 +- contrib/nnc/support/include/CommandLine.h | 65 ++-------- contrib/nnc/support/src/CommandLine.cpp | 115 ++++++++++++++++- contrib/nnc/unittests/core/CMakeLists.txt | 2 +- contrib/nnc/unittests/module/BackendModule.cpp | 13 -- contrib/nnc/unittests/module/CMakeLists.txt | 2 +- contrib/nnc/unittests/module/PluginManager.cpp | 77 ++---------- contrib/nnc/unittests/module/PluginProxy.cpp | 8 +- contrib/nnc/unittests/module/shared_library.cpp | 14 ++- contrib/nnc/unittests/plugin_core/CMakeLists.txt | 2 +- .../nnc/unittests/plugin_core/ConfigException.cpp | 40 ------ .../nnc/unittests/plugin_core/PluginException.cpp | 11 +- contrib/nnc/unittests/soft_backend/CMakeLists.txt | 2 +- contrib/nnc/unittests/soft_backend/generator.cpp | 6 +- 61 files changed, 954 insertions(+), 1021 deletions(-) create mode 100644 contrib/nnc/include/Definitions.h.in create mode 100644 contrib/nnc/include/Driver.h delete mode 100644 contrib/nnc/include/module/AbstractModule.h delete mode 100644 contrib/nnc/include/module/BackendModule.h delete mode 100644 contrib/nnc/include/module/FrontendModule.h delete mode 100644 contrib/nnc/include/module/plugin/PluginManager.h delete mode 100644 contrib/nnc/include/module/plugin/PluginProxy.h delete mode 100644 contrib/nnc/include/module/plugin/shared_library.h delete mode 100644 contrib/nnc/libs/plugin/include/ConfigException.h create mode 100644 contrib/nnc/libs/plugin/include/PluginManager.h create mode 100644 contrib/nnc/libs/plugin/include/PluginProxy.h create mode 100644 contrib/nnc/libs/plugin/include/shared_library.h delete mode 100644 contrib/nnc/libs/plugin/src/ConfigException.cpp delete mode 100644 contrib/nnc/libs/plugin/src/PluginException.cpp create mode 100644 contrib/nnc/libs/plugin/src/PluginManager.cpp create mode 100644 contrib/nnc/libs/plugin/src/PluginProxy.cpp create mode 100644 contrib/nnc/src/Driver.cpp delete mode 100644 contrib/nnc/src/module/AbstractModule.cpp delete mode 100644 contrib/nnc/src/module/BackendModule.cpp delete mode 100644 contrib/nnc/src/module/FrontendModule.cpp delete mode 100644 contrib/nnc/src/module/plugin/PluginManager.cpp delete mode 100644 contrib/nnc/src/module/plugin/PluginProxy.cpp delete mode 100644 contrib/nnc/src/module/plugin/shared_library.cpp delete mode 100644 contrib/nnc/unittests/module/BackendModule.cpp delete mode 100644 contrib/nnc/unittests/plugin_core/ConfigException.cpp diff --git a/contrib/nnc/CMakeLists.txt b/contrib/nnc/CMakeLists.txt index 2afc659..b649a95 100644 --- a/contrib/nnc/CMakeLists.txt +++ b/contrib/nnc/CMakeLists.txt @@ -6,12 +6,53 @@ include(soft_backend) file(GLOB_RECURSE HEADERS "include/*.h") file(GLOB_RECURSE SOURCES "src/*.cpp") set(MAIN "src/main.cpp") -set(OPTIONS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/Options.cpp") +set(OPTIONS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/Options.cpp) list(REMOVE_ITEM SOURCES ${MAIN}) list(REMOVE_ITEM SOURCES ${OPTIONS_SRC}) include_directories(include) +# +# Variables that uses inside compiler via configure_file +# +### +set(NNC_INSTALL_PATH ${CMAKE_INSTALL_PREFIX}) # root path of installation directory +set(NNC_INSTALL_LIB_PATH ${NNC_INSTALL_PATH}/lib) # directory that contains other directories with shared library +set(NNC_INSTALL_PLUGIN_PATH ${NNC_INSTALL_LIB_PATH}/plugin) # path to where plugins will be located +set(NNC_INSTALL_CORE_PATH ${NNC_INSTALL_LIB_PATH}/core) # path to where common part of nnc will be located +# +# plugins names +# +# NOTE. If names of plugins are changed then these +# variables will have to be also chagned +if (APPLE) + set(LIB_SUFFIX ".dylib") +else() + set(LIB_SUFFIX ".so") +endif() + +set(NNC_CAFFE_PLUGIN_NAME "libcaffe_importer${LIB_SUFFIX}") +set(NNC_TFLITE_PLUGIN_NAME "libtflite_import${LIB_SUFFIX}") +set(NNC_SOFT_CPP_PLUGIN_NAME "libsoft_backend_cpp${LIB_SUFFIX}") +set(NNC_SOFT_C_PLUGIN_NAME "libsoft_backend_c${LIB_SUFFIX}") +set(NNC_INTERPRETER_NAME "libnnc_interpreter_plugin${LIB_SUFFIX}") +### + +# +# functions +# +function(install_nnc_plugin) + install(TARGETS ${ARGV} DESTINATION ${NNC_INSTALL_PLUGIN_PATH}) + set_target_properties(${ARGV} PROPERTIES INSTALL_RPATH ${NNC_INSTALL_CORE_PATH}) +endfunction(install_nnc_plugin) + +function(install_common_library) + install(TARGETS ${ARGV} DESTINATION ${NNC_INSTALL_CORE_PATH}) +endfunction(install_common_library) +# +# end functions +# + # Used by unit tests set(NNC_SOFT_BACKEND_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libs/backend/soft) set(NNC_INTERPRETER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libs/backend/interpreter) @@ -21,16 +62,16 @@ set(NNC_SUPPORT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/support) # Plugin module library add_nncc_library(nnc_module SHARED ${HEADERS} ${SOURCES}) -target_link_libraries(nnc_module PRIVATE nnc_support nncc_core nncc_foundation nnc_plugin_core dl) +target_link_libraries(nnc_module PRIVATE nnc_support nnc_plugin_core dl) target_include_directories(nnc_module PUBLIC include) +install_common_library(nnc_module) # add supprot header files include_directories(support/include) -include_directories(include) # nnc executable add_executable(nnc ${MAIN} ${OPTIONS_SRC}) -target_link_libraries(nnc PRIVATE nnc_support nnc_module nncc_core nncc_foundation nnc_plugin_core dl) +target_link_libraries(nnc PRIVATE nnc_support nnc_module nnc_plugin_core dl) target_include_directories(nnc PUBLIC include) add_subdirectory(support) @@ -38,3 +79,13 @@ add_subdirectory(libs) add_subdirectory(examples) add_subdirectory(unittests) add_subdirectory(tests) + +# configure file that contains extern definitions +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/Definitions.h.in + ${CMAKE_CURRENT_BINARY_DIR}/include/Definitions.h) +include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) + +# install nnc +install(TARGETS nnc DESTINATION bin) +set_target_properties(nnc PROPERTIES INSTALL_RPATH ${NNC_INSTALL_CORE_PATH}) + diff --git a/contrib/nnc/examples/plugin_example/CMakeLists.txt b/contrib/nnc/examples/plugin_example/CMakeLists.txt index dc0219a..011fc20 100644 --- a/contrib/nnc/examples/plugin_example/CMakeLists.txt +++ b/contrib/nnc/examples/plugin_example/CMakeLists.txt @@ -5,9 +5,7 @@ add_library(some_parser SHARED ${PL_EXAMPLE_PARSE_SRC} ${PL_EXAMPLE_PARSE_H}) add_library(some_parser_second SHARED ${PL_EXAMPLE_PARSE_SRC} ${PL_EXAMPLE_PARSE_H}) target_link_libraries(some_parser PRIVATE nnc_plugin_core) -target_link_libraries(some_parser PRIVATE nncc_foundation) target_link_libraries(some_parser PRIVATE nnc_core) target_link_libraries(some_parser_second PRIVATE nnc_plugin_core) -target_link_libraries(some_parser_second PRIVATE nncc_foundation) target_link_libraries(some_parser_second PRIVATE nnc_core) diff --git a/contrib/nnc/examples/plugin_example/samplePlugin.cpp b/contrib/nnc/examples/plugin_example/samplePlugin.cpp index 6f295a3..4de82b5 100644 --- a/contrib/nnc/examples/plugin_example/samplePlugin.cpp +++ b/contrib/nnc/examples/plugin_example/samplePlugin.cpp @@ -3,7 +3,6 @@ #include #include "PluginInstance.h" #include "PluginException.h" -#include "ConfigException.h" using namespace nncc::contrib::plugin; @@ -36,7 +35,7 @@ void *SamplePluginInstance::execute(void *data) return data; } -extern "C" AbstractPluginInstance *get_instance() +extern "C" Plugin *get_instance() { // FIXME: it's necessary to make this printing via debugging system (see issue #893) //std::cout << std::endl << "!!! plugin (" << pluginName << ") " << __func__ << std::endl; diff --git a/contrib/nnc/include/Definitions.h.in b/contrib/nnc/include/Definitions.h.in new file mode 100644 index 0000000..f5c0cf8 --- /dev/null +++ b/contrib/nnc/include/Definitions.h.in @@ -0,0 +1,44 @@ +#ifndef NNCC_DEFINITIONS_H +#define NNCC_DEFINITIONS_H + +/** + * This file contains external definitions that defined by cmake build system + * All definitions of this file must start from `NNC` prefix e.g. `NNC_ROOT_PATH` + */ + +/** + * @breif absolute path to installation directory of *nnc* project + */ +#define NNC_ROOT_PATH "@NNC_INSTALL_PATH@" + +/** + * @breif absolute path to directory contains plugins + */ +#define NNC_PLUGINS_PATH "@NNC_INSTALL_PLUGIN_PATH@" + +/** + * @brief name of CAFFE frontend plugin + */ +#define NNC_FRONTEND_CAFFE_NAME "@NNC_CAFFE_PLUGIN_NAME@" + +/** + * @brief name of TensorFlow Lite frontend plugin + */ +#define NNC_FRONTEND_TFLITE_NAME "@NNC_TFLITE_PLUGIN_NAME@" + +/** + * @brief name of Soft backend plugin which generates C source code + */ +#define NNC_BACKEND_SOFT_C_NAME "@NNC_SOFT_C_PLUGIN_NAME@" + +/** + * @brief name of Soft backend plugin which generates C++ source code + */ +#define NNC_BACKEND_SOFT_CPP_NAME "@NNC_SOFT_CPP_PLUGIN_NAME@" + +/** + * @brief name of Interpreter plugin + */ +#define NNC_BACKEND_INTERPRETER_NAME "@NNC_INTERPRETER_NAME@" + +#endif //NNCC_DEFINITIONS_H diff --git a/contrib/nnc/include/Driver.h b/contrib/nnc/include/Driver.h new file mode 100644 index 0000000..7cb41d6 --- /dev/null +++ b/contrib/nnc/include/Driver.h @@ -0,0 +1,50 @@ +#ifndef NNCC_DRIVER_H +#define NNCC_DRIVER_H + +#include + +namespace nncc +{ +namespace contrib +{ + +/** + * @brief exceptions description class for compiler driver + */ +class DriverException +{ +public: + DriverException() = default; + DriverException(const DriverException &) noexcept {}; + ~DriverException() = default; + + explicit DriverException(const std::string &reason) : _reason(reason) {} + + /** + * @brief get message describes reason why exception was thrown + */ + const std::string &reason() const { return _reason; } + +private: + std::string _reason; // message contains the reason of the error +}; + +/** + * @brief Compiler Driver manages the whole pipeline compilation process + */ +class Driver +{ +public: + /** + * @brief main method to run compiler driver + * @throw DriverException if errors occurred in driver + * PluginException if errors occurred in plugins + */ + static void runDriver(); + +}; + +} // contrib +} // nncc + +#endif //NNCC_DRIVER_H diff --git a/contrib/nnc/include/Options.h b/contrib/nnc/include/Options.h index 16d808a..8b99c4b 100644 --- a/contrib/nnc/include/Options.h +++ b/contrib/nnc/include/Options.h @@ -12,29 +12,36 @@ namespace clopt { /** - * @breif options for compiler driver + * Options for compiler driver */ -extern Option pluginsPath; -extern Option pluginVerbose; +extern Option pluginVerbose; // print additional info about plugins +extern Option caffeFrontend; // frontend for CAFFE AI framework +extern Option tflFrontend; // frontend for TensorFlow Lite AI framework + +// valid values for target option +#define NNC_TARGET_X86_CPP "x86-c++" +#define NNC_TARGET_INTERPRETER "interpreter" +extern Option target; // kind of target for which compiler generates code extern Option debugMode; extern Option debugZones; /** - * @brief frontend options + * Frontend options */ -extern Option inputFile; +extern Option inputFile; // file contains model of specific AI framework /** - * @brief options for backend + * Options for backend */ -// soft backend -extern Option artifactDir; -extern Option artifactName; - -// interpreter -extern Option interFileName; -extern Option interInNode; -extern Option interOutNode; +extern Option artifactDir; // output directory for artifact +extern Option artifactName; // name of artifact + +/** + * Options for interpreter + */ +extern Option interInputData; // input data for model +extern Option interInNode; // name of input node in computational graph +extern Option interOutNode; // name of output node in computational graph } // namespace clopt } // namespace contrib diff --git a/contrib/nnc/include/module/AbstractModule.h b/contrib/nnc/include/module/AbstractModule.h deleted file mode 100644 index c6ec51a..0000000 --- a/contrib/nnc/include/module/AbstractModule.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef __ABSTRACT_MODULE_H__ -#define __ABSTRACT_MODULE_H__ - -#include - -#include "module/plugin/PluginProxy.h" - -namespace nncc -{ -namespace contrib -{ -namespace module -{ - -class AbstractModule -{ -public: - AbstractModule(const AbstractModule &) = delete; - AbstractModule &operator=(const AbstractModule &) = delete; - - void registerPlugin(std::shared_ptr &pl); - virtual void *execute(void *data); - - friend std::ostream &operator<<(std::ostream &st, const AbstractModule &m); - -protected: - AbstractModule(); - virtual ~AbstractModule(); - -private: - std::shared_ptr _activePlugin; - std::vector> _plugins; -}; - -} // namespace module -} // namespace contrib -} // namespace nncc - -#endif /* __ABSTRACT_MODULE_H__ */ diff --git a/contrib/nnc/include/module/BackendModule.h b/contrib/nnc/include/module/BackendModule.h deleted file mode 100644 index b8e14db..0000000 --- a/contrib/nnc/include/module/BackendModule.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __BACKEND_MODULE_H__ -#define __BACKEND_MODULE_H__ - -#include "module/AbstractModule.h" - -namespace nncc -{ -namespace contrib -{ -namespace module -{ - -class BackendModule : public AbstractModule -{ -public: - static BackendModule &getInstance(); - BackendModule &operator=(const BackendModule &) = delete; - BackendModule(const BackendModule &) = delete; - -private: - BackendModule(); - ~BackendModule(); -}; - -} // namespace module -} // namespace contrib -} // namespace nncc - -#endif // __BACKEND_MODULE_H__ diff --git a/contrib/nnc/include/module/FrontendModule.h b/contrib/nnc/include/module/FrontendModule.h deleted file mode 100644 index 1effe0d..0000000 --- a/contrib/nnc/include/module/FrontendModule.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __FRONTEND_MODULE_H__ -#define __FRONTEND_MODULE_H__ - -#include "module/AbstractModule.h" - -namespace nncc -{ -namespace contrib -{ -namespace module -{ - -class FrontendModule : public AbstractModule -{ -public: - static FrontendModule &getInstance(); - FrontendModule &operator=(const FrontendModule &) = delete; - FrontendModule(const FrontendModule &) = delete; - -private: - FrontendModule(); - ~FrontendModule(); -}; - -} // namespace module -} // namespace contrib -} // namespace nncc - -#endif // __FRONTEND_MODULE_H__ diff --git a/contrib/nnc/include/module/plugin/PluginManager.h b/contrib/nnc/include/module/plugin/PluginManager.h deleted file mode 100644 index 5a34758..0000000 --- a/contrib/nnc/include/module/plugin/PluginManager.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef __PLUGIN_MANAGER_H__ -#define __PLUGIN_MANAGER_H__ - -#include - -#include "PluginProxy.h" -#include "module/AbstractModule.h" - -namespace nncc -{ -namespace contrib -{ -namespace module -{ -namespace plugin -{ - -class PluginManagerException : public foundation::Exception -{ -public: - PluginManagerException() = delete; - explicit PluginManagerException(const std::string &info); - PluginManagerException(Exception &e, const std::string &info); -}; - -class PluginManager -{ -public: - void loadPlugins(); - static PluginManager &getInstance(); - - friend std::ostream &operator<<(std::ostream &st, const PluginManager &mod); - -private: - // only for singleton - PluginManager() = default; - - std::vector getPluginPathList(); - - std::vector _modules; - std::vector> _plugins; -}; - -} // namespace plugin -} // namespace module -} // namespace contrib -} // namespace nncc - -#endif // __PLUGIN_MANAGER_H__ diff --git a/contrib/nnc/include/module/plugin/PluginProxy.h b/contrib/nnc/include/module/plugin/PluginProxy.h deleted file mode 100644 index bfbd1e9..0000000 --- a/contrib/nnc/include/module/plugin/PluginProxy.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef __PLUGIN_PROXY_H__ -#define __PLUGIN_PROXY_H__ - -#include -#include -#include - -#include "shared_library.h" -#include "PluginException.h" -#include "PluginInstance.h" - -namespace nncc -{ -namespace contrib -{ -namespace module -{ -namespace plugin -{ - -class PluginProxy -{ -public: - PluginProxy() = delete; - static std::shared_ptr create(const std::string &pluginPath); - virtual ~PluginProxy(); - - const std::string &getPluginPath() const; - const std::string &getPluginName() const; - - /** - * @breif singleton method to get plugin instance - * @return pointer to plugin instance (this pointer mustn't be freed) - */ - contrib::plugin::AbstractPluginInstance *getPluginInstance(); - -public: - static const std::string getInstanceFuncName; - -private: - explicit PluginProxy(const std::string &pluginPath); - - void init() noexcept(false); - void *getFuncAddr(const std::string &func_name) noexcept(false); - friend std::ostream &operator<<(std::ostream &st, const PluginProxy &pl); - -private: - typedef contrib::plugin::AbstractPluginInstance *(*get_instance_t)(); - - contrib::plugin::AbstractPluginInstance *_pluginInstance; - std::shared_ptr _lib; - get_instance_t _getInstance; - std::string _pluginName; -}; - -} // namespace plugin -} // namespace module -} // namespace contrib -} // namespace nncc - -#endif /* __PLUGIN_PROXY_H__ */ diff --git a/contrib/nnc/include/module/plugin/shared_library.h b/contrib/nnc/include/module/plugin/shared_library.h deleted file mode 100644 index b56a404..0000000 --- a/contrib/nnc/include/module/plugin/shared_library.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include -#include - -namespace nncc -{ -namespace contrib -{ -namespace module -{ -namespace plugin -{ - -class SharedLibrary -{ -public: - explicit SharedLibrary(const std::string &fullPath); - - void *findFunc(const std::string &funcName); - const std::string& getPath() const; - - -private: - bool loadLibrary(); - -private: - std::string _path; - void *_handle; - bool _isLoaded; -}; - -std::ostream &operator<<(std::ostream &st, const SharedLibrary &lib); - -} // namespase plugin -} // namespace module -} // namespace contrib -} // namespace nncc diff --git a/contrib/nnc/libs/backend/interpreter/core/CMakeLists.txt b/contrib/nnc/libs/backend/interpreter/core/CMakeLists.txt index 0a48817..00d3dcd 100644 --- a/contrib/nnc/libs/backend/interpreter/core/CMakeLists.txt +++ b/contrib/nnc/libs/backend/interpreter/core/CMakeLists.txt @@ -1,5 +1,5 @@ file(GLOB_RECURSE interp_core_src ./*.cpp ./*.h) add_library(nnc_interpreter_core STATIC ${interp_core_src}) -target_link_libraries(nnc_interpreter_core PUBLIC nncc_core nnc_core) +target_link_libraries(nnc_interpreter_core PUBLIC nnc_core) target_include_directories(nnc_interpreter_core PUBLIC include) set_target_properties(nnc_interpreter_core PROPERTIES POSITION_INDEPENDENT_CODE ON) diff --git a/contrib/nnc/libs/backend/interpreter/plugin/CMakeLists.txt b/contrib/nnc/libs/backend/interpreter/plugin/CMakeLists.txt index 9d3a49b..95ccbbb 100644 --- a/contrib/nnc/libs/backend/interpreter/plugin/CMakeLists.txt +++ b/contrib/nnc/libs/backend/interpreter/plugin/CMakeLists.txt @@ -2,3 +2,6 @@ file(GLOB_RECURSE interp_plugin_src ./*.cpp ./*.h) add_library(nnc_interpreter_plugin SHARED ${interp_plugin_src}) target_link_libraries(nnc_interpreter_plugin PRIVATE nnc_interpreter_core nnc_plugin_core) target_include_directories(nnc_interpreter_plugin PUBLIC include) + +# install interpreter library +install_nnc_plugin(nnc_interpreter_plugin) diff --git a/contrib/nnc/libs/backend/interpreter/plugin/include/interpreter_plugin.h b/contrib/nnc/libs/backend/interpreter/plugin/include/interpreter_plugin.h index 3c1437e..3ace3c7 100644 --- a/contrib/nnc/libs/backend/interpreter/plugin/include/interpreter_plugin.h +++ b/contrib/nnc/libs/backend/interpreter/plugin/include/interpreter_plugin.h @@ -5,7 +5,6 @@ #include "PluginInstance.h" #include "PluginException.h" -#include "ConfigException.h" #include "nnc/core/linalg/TensorVariant.h" #include "nnc/core/linalg/Shape.h" diff --git a/contrib/nnc/libs/backend/interpreter/plugin/src/interpreter_plugin.cpp b/contrib/nnc/libs/backend/interpreter/plugin/src/interpreter_plugin.cpp index b69aa57..2b333b7 100644 --- a/contrib/nnc/libs/backend/interpreter/plugin/src/interpreter_plugin.cpp +++ b/contrib/nnc/libs/backend/interpreter/plugin/src/interpreter_plugin.cpp @@ -2,7 +2,8 @@ #include #include #include -#include + +#include "Options.h" #include "PluginInstance.h" @@ -69,7 +70,7 @@ void *InterpreterPlugin::execute(void *data) { TensorVariant InterpreterPlugin::loadInput(const Shape &shape) { - auto f = fopen(clopt::interFileName.c_str(), "rb"); + auto f = fopen(clopt::interInputData.c_str(), "rb"); assert(f && "Cannot open file"); fseek(f, 0L, SEEK_END); @@ -79,7 +80,7 @@ TensorVariant InterpreterPlugin::loadInput(const Shape &shape) // Check size if (len != tensorSize) { std::stringstream info; - info << "Wrong input file size <" << clopt::interFileName << "> = " << len << ". Should be :" << tensorSize; + info << "Wrong input file size <" << clopt::interInputData << "> = " << len << ". Should be :" << tensorSize; throw PluginException(info.str()); } @@ -102,7 +103,7 @@ InterpreterPlugin::~InterpreterPlugin() } // namespace contrib } // namespace nncc -extern "C" nncc::contrib::backend::interpreter::plugin::AbstractPluginInstance *get_instance() { +extern "C" nncc::contrib::backend::interpreter::plugin::Plugin *get_instance() { return &nncc::contrib::backend::interpreter::plugin::InterpreterPlugin::getInstance(); } diff --git a/contrib/nnc/libs/backend/interpreter/test/CMakeLists.txt b/contrib/nnc/libs/backend/interpreter/test/CMakeLists.txt index 8db47d6..6c43c4f 100644 --- a/contrib/nnc/libs/backend/interpreter/test/CMakeLists.txt +++ b/contrib/nnc/libs/backend/interpreter/test/CMakeLists.txt @@ -27,5 +27,5 @@ target_include_directories(interpreter_op_test PRIVATE ${FB_GEN_INCLUDE_DIRS}) target_include_directories(interpreter_op_test PRIVATE include) target_link_libraries(interpreter_op_test PRIVATE gtest flatbuffers - nnc_core nncc_core nnc_interpreter_core + nnc_core nnc_interpreter_core nn_import_common) diff --git a/contrib/nnc/libs/backend/soft/CMakeLists.txt b/contrib/nnc/libs/backend/soft/CMakeLists.txt index 37413d9..6de26da 100644 --- a/contrib/nnc/libs/backend/soft/CMakeLists.txt +++ b/contrib/nnc/libs/backend/soft/CMakeLists.txt @@ -13,7 +13,6 @@ add_library(soft_backend_common STATIC ${SOFT_BACKEND_COMMON_SOURCES} ${SOFT_GEN set_property(TARGET soft_backend_common PROPERTY POSITION_INDEPENDENT_CODE ON) target_include_directories(soft_backend_common PUBLIC include) target_include_directories(soft_backend_common PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) -target_link_libraries(soft_backend_common PRIVATE nncc_core) target_link_libraries(soft_backend_common PRIVATE nnc_plugin_core) target_link_libraries(soft_backend_common PRIVATE nnc_core) # This is included because right now common functional is built into nnc_module @@ -25,10 +24,11 @@ function(make_soft_backend NAME) target_include_directories(${NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(${NAME} PRIVATE soft_backend_common) - target_link_libraries(${NAME} PRIVATE nncc_core) target_link_libraries(${NAME} PRIVATE nnc_plugin_core) - target_link_libraries(${NAME} PRIVATE nncc_foundation) target_link_libraries(${NAME} PRIVATE nnc_core) + + # install soft backend c++ library + install_nnc_plugin(${NAME}) endfunction(make_soft_backend) make_soft_backend(soft_backend_cpp ${SOFT_BACKEND_CPP_SOURCES}) diff --git a/contrib/nnc/libs/backend/soft/src/c_backend.cpp b/contrib/nnc/libs/backend/soft/src/c_backend.cpp index e4bb7f5..ef31a6e 100644 --- a/contrib/nnc/libs/backend/soft/src/c_backend.cpp +++ b/contrib/nnc/libs/backend/soft/src/c_backend.cpp @@ -1,8 +1,6 @@ #include "soft_backend.h" #include "c_generator.h" -#include "ConfigException.h" - using namespace nncc::contrib::plugin; using namespace nncc::contrib::backend::soft; @@ -44,7 +42,7 @@ private: } // namespace nncc -extern "C" AbstractPluginInstance *get_instance() +extern "C" Plugin *get_instance() { return &CSoftBackend::getInstance(); } diff --git a/contrib/nnc/libs/backend/soft/src/cpp_backend.cpp b/contrib/nnc/libs/backend/soft/src/cpp_backend.cpp index d4927b1..3b5240f 100644 --- a/contrib/nnc/libs/backend/soft/src/cpp_backend.cpp +++ b/contrib/nnc/libs/backend/soft/src/cpp_backend.cpp @@ -1,8 +1,6 @@ #include "soft_backend.h" #include "cpp_generator.h" -#include "ConfigException.h" - using namespace nncc::contrib::plugin; using namespace nncc::contrib::backend::soft; @@ -44,7 +42,7 @@ private: } // namespace nncc -extern "C" AbstractPluginInstance *get_instance() +extern "C" Plugin *get_instance() { return &CPPSoftBackend::getInstance(); } diff --git a/contrib/nnc/libs/backend/soft/src/soft_backend.cpp b/contrib/nnc/libs/backend/soft/src/soft_backend.cpp index cd4b56f..c8284c1 100644 --- a/contrib/nnc/libs/backend/soft/src/soft_backend.cpp +++ b/contrib/nnc/libs/backend/soft/src/soft_backend.cpp @@ -5,9 +5,7 @@ #include "soft_backend.h" #include "PluginException.h" -#include "ConfigException.h" #include "nnc/core/IR/model/graph/graph.h" -#include "Options.h" #include "debug.h" #define DEBUG_AREA "soft_backend" diff --git a/contrib/nnc/libs/core/CMakeLists.txt b/contrib/nnc/libs/core/CMakeLists.txt index c567135..9de80f3 100644 --- a/contrib/nnc/libs/core/CMakeLists.txt +++ b/contrib/nnc/libs/core/CMakeLists.txt @@ -4,5 +4,6 @@ file(GLOB_RECURSE SOURCES "src/*.cpp") add_nncc_library(nnc_core SHARED ${HEADERS} ${SOURCES}) set_target_properties(nnc_core PROPERTIES LINKER_LANGUAGE CXX) target_include_directories(nnc_core PUBLIC include) -target_link_libraries(nnc_core PRIVATE nncc_core) +# install nnc core library +install_common_library(nnc_core) diff --git a/contrib/nnc/libs/frontend/CMakeLists.txt b/contrib/nnc/libs/frontend/CMakeLists.txt index 9c8c557..6fc7dc4 100644 --- a/contrib/nnc/libs/frontend/CMakeLists.txt +++ b/contrib/nnc/libs/frontend/CMakeLists.txt @@ -12,7 +12,6 @@ target_include_directories(${nn_import_common} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR set_target_properties(${nn_import_common} PROPERTIES POSITION_INDEPENDENT_CODE ON) target_link_libraries(${nn_import_common} PRIVATE nnc_core) -target_link_libraries(${nn_import_common} PRIVATE nncc_core) target_link_libraries(${nn_import_common} PRIVATE nnc_plugin_core) add_subdirectory(tflite) diff --git a/contrib/nnc/libs/frontend/caffe/CMakeLists.txt b/contrib/nnc/libs/frontend/caffe/CMakeLists.txt index 312286c..6b3bae2 100644 --- a/contrib/nnc/libs/frontend/caffe/CMakeLists.txt +++ b/contrib/nnc/libs/frontend/caffe/CMakeLists.txt @@ -23,8 +23,10 @@ target_link_libraries(caffe_importer PUBLIC caffeproto) target_link_libraries(caffe_importer PUBLIC ${nn_import_common}) target_link_libraries(caffe_importer PRIVATE nnc_support) target_link_libraries(caffe_importer PRIVATE nnc_core) -target_link_libraries(caffe_importer PRIVATE nncc_core) target_link_libraries(caffe_importer PRIVATE nnc_plugin_core) add_nncc_example_executable(caffe_model_dumper ${OPTIONS_SRC} examples/model_dump.cpp) nncc_target_link_libraries(caffe_model_dumper nnc_support caffe_importer) + +# install caffe frontend library +install_nnc_plugin(caffe_importer) diff --git a/contrib/nnc/libs/frontend/caffe/src/caffe_plugin.cpp b/contrib/nnc/libs/frontend/caffe/src/caffe_plugin.cpp index 4a20855..9597d68 100644 --- a/contrib/nnc/libs/frontend/caffe/src/caffe_plugin.cpp +++ b/contrib/nnc/libs/frontend/caffe/src/caffe_plugin.cpp @@ -4,7 +4,6 @@ #include "PluginInstance.h" #include "PluginException.h" -#include "ConfigException.h" #include "Options.h" #include "caffe_importer.h" @@ -50,7 +49,7 @@ void *ImporterPlugin::execute(void *) } // anonymous namespace -extern "C" AbstractPluginInstance *get_instance() +extern "C" Plugin *get_instance() { return &ImporterPlugin::getInstance(); } diff --git a/contrib/nnc/libs/frontend/tflite/CMakeLists.txt b/contrib/nnc/libs/frontend/tflite/CMakeLists.txt index 8f0e01d..b40e29a 100644 --- a/contrib/nnc/libs/frontend/tflite/CMakeLists.txt +++ b/contrib/nnc/libs/frontend/tflite/CMakeLists.txt @@ -37,9 +37,8 @@ target_link_libraries(${tflite_import} PUBLIC tflite_schema) target_link_libraries(${tflite_import} PUBLIC flatbuffers) target_link_libraries(${tflite_import} PUBLIC ${nn_import_common}) target_link_libraries(${tflite_import} PUBLIC nnc_support) -target_link_libraries(${tflite_import} PRIVATE nnc_core) -target_link_libraries(${tflite_import} PRIVATE nncc_core) -target_link_libraries(${tflite_import} PRIVATE nnc_plugin_core) +target_link_libraries(${tflite_import} PUBLIC nnc_core) +target_link_libraries(${tflite_import} PUBLIC nnc_plugin_core) ################### # TFLITE examples # @@ -52,3 +51,6 @@ add_executable(${tflite_import_example} ${tflite_example_sources} ${OPTIONS_SRC} target_link_libraries(${tflite_import_example} PUBLIC tflite_schema) target_link_libraries(${tflite_import_example} PRIVATE ${tflite_import}) + +# install tflite frontend library +install_nnc_plugin(tflite_import) diff --git a/contrib/nnc/libs/frontend/tflite/src/tflite_plugin.cpp b/contrib/nnc/libs/frontend/tflite/src/tflite_plugin.cpp index ef8af71..280e971 100644 --- a/contrib/nnc/libs/frontend/tflite/src/tflite_plugin.cpp +++ b/contrib/nnc/libs/frontend/tflite/src/tflite_plugin.cpp @@ -4,7 +4,6 @@ #include "PluginInstance.h" #include "PluginException.h" -#include "ConfigException.h" #include "Options.h" #include "tflite_v3_importer.h" @@ -50,7 +49,7 @@ void *ImporterPlugin::execute(void *) } // anonymous namespace -extern "C" AbstractPluginInstance *get_instance() +extern "C" Plugin *get_instance() { return &ImporterPlugin::getInstance(); } diff --git a/contrib/nnc/libs/plugin/CMakeLists.txt b/contrib/nnc/libs/plugin/CMakeLists.txt index 00007af..af67be2 100644 --- a/contrib/nnc/libs/plugin/CMakeLists.txt +++ b/contrib/nnc/libs/plugin/CMakeLists.txt @@ -3,6 +3,7 @@ file(GLOB_RECURSE SOURCES "src/*.cpp") add_nncc_library(nnc_plugin_core SHARED ${HEADERS} ${SOURCES}) set_target_properties(nnc_plugin_core PROPERTIES LINKER_LANGUAGE CXX) -target_link_libraries(nnc_plugin_core PRIVATE nncc_foundation) +target_link_libraries(nnc_plugin_core PRIVATE dl) target_include_directories(nnc_plugin_core PUBLIC include) +install_common_library(nnc_plugin_core) diff --git a/contrib/nnc/libs/plugin/include/ConfigException.h b/contrib/nnc/libs/plugin/include/ConfigException.h deleted file mode 100644 index 1e986e0..0000000 --- a/contrib/nnc/libs/plugin/include/ConfigException.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Created by snusmumric on 04.05.18. -// -#ifndef __CONFIGEXCEPTION_H__ -#define __CONFIGEXCEPTION_H__ - -#include - -#include - -namespace nncc -{ -namespace contrib -{ - -class ConfigException : public nncc::foundation::Exception -{ -public: - ConfigException() = default; - ~ConfigException() throw() override = default; - - explicit ConfigException(const std::string &info); - explicit ConfigException(Exception &e, const std::string &info); -}; - -} // namespace contrib -} // namespace nncc - -#endif // __CONFIGEXCEPTION_H__ diff --git a/contrib/nnc/libs/plugin/include/PluginException.h b/contrib/nnc/libs/plugin/include/PluginException.h index d3f8d33..ef9c9e9 100644 --- a/contrib/nnc/libs/plugin/include/PluginException.h +++ b/contrib/nnc/libs/plugin/include/PluginException.h @@ -6,23 +6,28 @@ #include -#include - namespace nncc { namespace contrib { -class PluginException : public nncc::foundation::Exception +class PluginException { public: - PluginException() = default; - ~PluginException() throw() override = default; + PluginException(const PluginException &) noexcept {}; + + explicit PluginException(const std::string &info) { _msg = info; } - explicit PluginException(const std::string &info); - explicit PluginException(Exception &e, const std::string &info); + /** + * @brief get message from exception object + */ + std::string what() const { return _msg; } + +private: + std::string _msg; }; + } // namespace contrib } // namespace nncc diff --git a/contrib/nnc/libs/plugin/include/PluginInstance.h b/contrib/nnc/libs/plugin/include/PluginInstance.h index 8c5b9ad..272e2b6 100644 --- a/contrib/nnc/libs/plugin/include/PluginInstance.h +++ b/contrib/nnc/libs/plugin/include/PluginInstance.h @@ -14,43 +14,43 @@ namespace plugin // // This class and its methods are NOT thread safe // -class AbstractPluginInstance +class Plugin { public: - AbstractPluginInstance &operator=(const AbstractPluginInstance &) = delete; - AbstractPluginInstance(const AbstractPluginInstance &) = delete; + Plugin &operator=(const Plugin &) = delete; + Plugin(const Plugin &) = delete; virtual void *execute(void *data) = 0; protected: - AbstractPluginInstance() = default; - virtual ~AbstractPluginInstance() = default; + Plugin() = default; + virtual ~Plugin() = default; }; -class FrontendPlugin : public AbstractPluginInstance +class FrontendPlugin : public Plugin { public: FrontendPlugin &operator=(const FrontendPlugin &) = delete; FrontendPlugin(const FrontendPlugin &) = delete; - virtual void *execute(void *data) = 0; + void *execute(void *data) override = 0; protected: FrontendPlugin() = default; - virtual ~FrontendPlugin() = default; + ~FrontendPlugin() override = default; }; -class BackendPlugin : public AbstractPluginInstance +class BackendPlugin : public Plugin { public: BackendPlugin &operator=(const BackendPlugin &) = delete; BackendPlugin (const BackendPlugin &) = delete; - virtual void *execute(void *data) = 0; + void *execute(void *data) override = 0; protected: BackendPlugin() = default; - virtual ~BackendPlugin() = default; + ~BackendPlugin() override = default; }; } // namespace plugin diff --git a/contrib/nnc/libs/plugin/include/PluginManager.h b/contrib/nnc/libs/plugin/include/PluginManager.h new file mode 100644 index 0000000..0ae66d3 --- /dev/null +++ b/contrib/nnc/libs/plugin/include/PluginManager.h @@ -0,0 +1,62 @@ +#ifndef __PLUGIN_MANAGER_H__ +#define __PLUGIN_MANAGER_H__ + +#include +#include + +#include "PluginProxy.h" + +namespace nncc +{ +namespace contrib +{ +namespace plugin +{ + +/** + * @brief plugin manager class + * this class manages plugin loading, execution and unloading + */ +class PluginManager +{ +public: + /** + * @param plugin_path - absolute plugin path + * @throw PluginException if couldn't load plugin + */ + explicit PluginManager(const std::string &plugin_path); + + /** + * @throw PluginException if couldn't unload plugin + */ + ~PluginManager(); + + /** + * @brief get plugin + */ + Plugin *getPlugin(); + + /** + * @brief print plugin + * @param st - output stream + * @param pm - plugin manager object + */ + friend std::ostream &operator<<(std::ostream &st, const PluginManager &pm); + +private: + /** + * @brief load/unload plugin + */ + void loadPlugin(); + void unloadPlugin(); + + // data + std::string _plugin_path; // path to plugin + std::shared_ptr _plugin_proxy; // access to plugin +}; + +} // namespace plugin +} // namespace contrib +} // namespace nncc + +#endif // __PLUGIN_MANAGER_H__ diff --git a/contrib/nnc/libs/plugin/include/PluginProxy.h b/contrib/nnc/libs/plugin/include/PluginProxy.h new file mode 100644 index 0000000..2f26694 --- /dev/null +++ b/contrib/nnc/libs/plugin/include/PluginProxy.h @@ -0,0 +1,79 @@ +#ifndef __PLUGIN_PROXY_H__ +#define __PLUGIN_PROXY_H__ + +#include +#include +#include + +#include "shared_library.h" +#include "PluginException.h" +#include "PluginInstance.h" + +namespace nncc +{ +namespace contrib +{ +namespace plugin +{ + +/** + * @brief this proxy class provides access to plugins + */ +class PluginProxy +{ +public: + /** + * @brief factory method that load plugin + * @param pluginPath - absolute path to plugin + * @return proxy class instance + * @throw PluginException if couldn't load plugin library or plugin is inappropriate + */ + // TODO it is possible to eliminate factory method and create proxy in constructor + static std::shared_ptr create(const std::string &pluginPath); + + /** + * @brief unload plugin + * @throw PluginException if couldn't unload plugin library + */ + // TODO it is possible to eliminate this method and do unloading library in destructor + void remove(); + + /** + * @brief get plugin absolute path and plugin name + */ + const std::string &getPluginPath() const { return _lib->getPath(); } + const std::string &getPluginName() const { return _pluginName; } + + /** + * @brief get loaded plugin instance + * @return pointer to plugin (don't need to be freed) + */ + Plugin *getPluginInstance(); + + /** + * @brief name of function that provides information + * about plugin. Every plugin must contain this function + */ + static const std::string getInstanceFuncName; + +private: + // only factory method can create class instances + explicit PluginProxy(const std::string &pluginPath); + + friend std::ostream &operator<<(std::ostream &st, const PluginProxy &pl); + + // type of function that returns loaded plugin + using get_instance_t = Plugin* (*)(); + + // data + Plugin *_pluginInstance; // pointer to loaded plugin + std::shared_ptr> _lib; // plugin library + get_instance_t _getInstance; // function from plugin that returns pointer to plugin + std::string _pluginName; // name of plugin +}; + +} // namespace plugin +} // namespace contrib +} // namespace nncc + +#endif /* __PLUGIN_PROXY_H__ */ diff --git a/contrib/nnc/libs/plugin/include/shared_library.h b/contrib/nnc/libs/plugin/include/shared_library.h new file mode 100644 index 0000000..c9d9aae --- /dev/null +++ b/contrib/nnc/libs/plugin/include/shared_library.h @@ -0,0 +1,125 @@ +#ifndef NNCC_SHAREDLIBRARY_H +#define NNCC_SHAREDLIBRARY_H + +#include +#include +#include +#include + +namespace nncc +{ +namespace contrib +{ +namespace plugin +{ + +/** + * @brief class provides access to shared library + * @tparam ExceptionT - thrown exception type if errors occur + */ +template +class SharedLibrary +{ +public: + explicit SharedLibrary(const std::string &fullPath) : _handle(nullptr), _path(fullPath), _isLoaded(false) {} + + /** + * @brief find function from shared library + * @param funcName - function name + * @return pointer to found function + * @throw ExceptionT if errors occurred + */ + void *findFunc(const std::string &funcName); + + /** + * @brief unload shared library + * @throw ExceptionT if couldn't unload library + */ + void unloadLibrary(); + + /** + * @brief get path of shared library + */ + const std::string& getPath() const { return _path; }; + +private: + // load shared library + void *loadLibrary(); + + // data + std::string _path; // path to shared library + void *_handle; // handle returned by dlopen + bool _isLoaded; +}; + + +template +void *SharedLibrary::findFunc(const std::string &funcName) +{ + if ( !_isLoaded ) + { + _handle = loadLibrary(); + _isLoaded = true; + } + + // reset errors + dlerror(); + + // get function address + assert(_handle); + void *func = dlsym(_handle, funcName.c_str()); + + char *dlsym_error = dlerror(); + + if ( dlsym_error ) + { + throw ExceptionT("Cannot load symbol: '" + funcName + "' : " + dlsym_error); + } + + return func; + +} // findFunc + +template +void *SharedLibrary::loadLibrary() +{ +// NNC_DEBUG(dbgs() << "Opening " << _path << std::endl); + + // open the library + void *handle = dlopen(_path.c_str(), RTLD_LAZY); + + if ( !handle ) + { + throw ExceptionT("Cannot open library: '" + _path + "' : " + dlerror()); + } + + return handle; + +} // loadLibrary + +template +void SharedLibrary::unloadLibrary() +{ + // reset errors + dlerror(); + + // close the library + if ( dlclose(_handle) ) + { + throw ExceptionT("Cannot unloaded library: '" + _path + "' : " + dlerror()); + } + +} // unloadLibrary + +template +std::ostream &operator<<(std::ostream &st, const SharedLibrary &lib) +{ + st << lib.getPath(); + return st; +} + +} // namespase plugin +} // namespace contrib +} // namespace nncc + +#endif // NNCC_SHAREDLIBRARY_H diff --git a/contrib/nnc/libs/plugin/src/ConfigException.cpp b/contrib/nnc/libs/plugin/src/ConfigException.cpp deleted file mode 100644 index 884687f..0000000 --- a/contrib/nnc/libs/plugin/src/ConfigException.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// Created by snusmumric on 04.05.18. -// - -#include - -#include "ConfigException.h" - -namespace nncc -{ -namespace contrib -{ - -ConfigException::ConfigException(const std::string &info) : Exception(info) {} - -ConfigException::ConfigException(Exception &e, const std::string &info) : Exception(e, info) -{ -} - -} // namespace contrib -} // namespace nncc diff --git a/contrib/nnc/libs/plugin/src/PluginException.cpp b/contrib/nnc/libs/plugin/src/PluginException.cpp deleted file mode 100644 index 9acc7e1..0000000 --- a/contrib/nnc/libs/plugin/src/PluginException.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// -// Created by v.cherepanov@samsung.com on 04.05.18. -// - -#include - -#include "PluginException.h" - -namespace nncc -{ -namespace contrib -{ - -PluginException::PluginException(const std::string &info) : Exception(info) {} - -PluginException::PluginException(Exception &e, const std::string &info) : Exception(e, info) {} - -} // namespace contrib -} // namespace nncc diff --git a/contrib/nnc/libs/plugin/src/PluginManager.cpp b/contrib/nnc/libs/plugin/src/PluginManager.cpp new file mode 100644 index 0000000..15393d3 --- /dev/null +++ b/contrib/nnc/libs/plugin/src/PluginManager.cpp @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +#include "PluginProxy.h" +#include "PluginManager.h" +#include "PluginInstance.h" +#include "Options.h" + +#include "PluginException.h" + +//#include "debug.h" +//#define DEBUG_AREA "plugin" + +namespace nncc +{ +namespace contrib +{ +namespace plugin +{ + +PluginManager::PluginManager(const std::string &plugin_path) +{ + _plugin_path = plugin_path; + loadPlugin(); + +} // PluginManager + +PluginManager::~PluginManager() +{ + unloadPlugin(); + +} // ~PluginManager + +void PluginManager::loadPlugin() +{ + // TODO: we need to move debug to support directory + //NNC_DEBUG(dbgs() << "Current plugin path is <" << _plugin_path << ">" << std::endl); + _plugin_proxy = PluginProxy::create(_plugin_path); + +} // loadPlugin + +void PluginManager::unloadPlugin() +{ + _plugin_proxy->remove(); + +} // unloadPlugin + +Plugin *PluginManager::getPlugin() +{ + return _plugin_proxy->getPluginInstance(); + +} // getPlugin + +std::ostream &operator<<(std::ostream &st, const PluginManager &pm) +{ + st << pm._plugin_path << std::endl; + return st; +} + +} // namespace plugin +} // namespace contrib +} // namespace nncc diff --git a/contrib/nnc/libs/plugin/src/PluginProxy.cpp b/contrib/nnc/libs/plugin/src/PluginProxy.cpp new file mode 100644 index 0000000..2a356f2 --- /dev/null +++ b/contrib/nnc/libs/plugin/src/PluginProxy.cpp @@ -0,0 +1,66 @@ +#include +#include +#include + +#include "PluginProxy.h" +#include "shared_library.h" + +namespace nncc +{ +namespace contrib +{ +namespace plugin +{ + +const std::string PluginProxy::getInstanceFuncName = "get_instance"; + +PluginProxy::PluginProxy(const std::string &pluginPath) + : _getInstance(nullptr), _lib(nullptr), _pluginInstance(nullptr) +{ + _lib = std::make_shared>(pluginPath); + + // get plugin name by path + auto i = pluginPath.find_last_of('/'); + _pluginName = ( i == std::string::npos ) ? pluginPath : pluginPath.substr(i + 1); + +} // PluginProxy + +std::shared_ptr PluginProxy::create(const std::string &pluginPath) +{ + auto proxy = std::shared_ptr(new PluginProxy(pluginPath)); + + // get plugin function from shared library + proxy->_getInstance = (get_instance_t)proxy->_lib->findFunc(getInstanceFuncName); + + // call plugin function + proxy->_pluginInstance = proxy->_getInstance(); + + if ( !proxy->_pluginInstance ) + throw PluginException("this shared library is not NNC plugin"); + + return proxy; + +} // create + +void PluginProxy::remove() +{ + _lib->unloadLibrary(); + +} // remove + +Plugin *PluginProxy::getPluginInstance() +{ + assert(_pluginInstance); + return _pluginInstance; + +} // getPluginInstance + +std::ostream &operator<<(std::ostream &st, const PluginProxy &pl) +{ + st << *(pl._lib); + return st; +} + +} // namespace plugin +} // namespace contrib +} // namespace nncc diff --git a/contrib/nnc/src/Driver.cpp b/contrib/nnc/src/Driver.cpp new file mode 100644 index 0000000..c17bd20 --- /dev/null +++ b/contrib/nnc/src/Driver.cpp @@ -0,0 +1,101 @@ +#include "PluginManager.h" +#include "CommandLine.h" +#include "Definitions.h" +#include "Options.h" +#include "Driver.h" + +using namespace nncc::contrib; +using namespace nncc::contrib::plugin; + +namespace nncc +{ +namespace contrib +{ + +/** + * @brief run plugin + * @param plugin_path - absolute path to plugin + * @param data - plugin input data + * @return pointer to data that plugin generated + * @throw PluginException, if errors occured + */ +static void *executePlugin(const std::string &plugin_path, void *data) +{ + PluginManager pluginManager(plugin_path); + + Plugin *plugin = pluginManager.getPlugin(); + void *res = plugin->execute(data); + + return res; + +} // executePlugin + +/** + * @return absolute path to frontend plugin + * @throw DriverException if errors occurred + */ +static std::string getFrontendPlugin() +{ + std::string plugin; + + if ( clopt::caffeFrontend ) + { + plugin = NNC_PLUGINS_PATH "/" NNC_FRONTEND_CAFFE_NAME; + } + else if ( clopt::tflFrontend ) + { + plugin = NNC_PLUGINS_PATH "/" NNC_FRONTEND_TFLITE_NAME; + } + else + { + throw DriverException("one of the following options must be defined: '" + + clopt::caffeFrontend.getNames()[0] + "', '" + + clopt::tflFrontend.getNames()[0] + "'"); + } + + return plugin; + +} // getFrontendPlugin + +/** + * @return absolute path to backend plugin + * @throw DriverException if errors occurred + */ +static std::string getBackendPlugin() +{ + std::string plugin; + + assert( clopt::target == NNC_TARGET_X86_CPP || clopt::target == NNC_TARGET_INTERPRETER ); + + plugin = NNC_PLUGINS_PATH "/"; + + if ( clopt::target == NNC_TARGET_X86_CPP ) + { + plugin += NNC_BACKEND_SOFT_CPP_NAME; + } + else if ( clopt::target == NNC_TARGET_INTERPRETER ) + { + plugin += NNC_BACKEND_INTERPRETER_NAME; + } + + return plugin; + +} // getBackendPlugin + +void Driver::runDriver() +{ + std::string plugin; + void *plugin_result; + + // run frontend plugin + plugin = getFrontendPlugin(); + plugin_result = executePlugin(plugin, nullptr); + + // run backend plugin + plugin = getBackendPlugin(); + executePlugin(plugin, plugin_result); + +} // runDriver + +} // contrib +} // nncc diff --git a/contrib/nnc/src/Options.cpp b/contrib/nnc/src/Options.cpp index b0d91a6..325978d 100644 --- a/contrib/nnc/src/Options.cpp +++ b/contrib/nnc/src/Options.cpp @@ -1,6 +1,7 @@ #include #include "CommandLine.h" +#include "Options.h" namespace nncc { @@ -10,14 +11,13 @@ namespace clopt { /** - * @breif Options for compiler driver + * Options for *compiler driver* */ -Option pluginsPath(optname("--plugins-path"), - overview("path where plugins will be searched"), - "", - optional(true), - optvalues(""), - checkPluginsPath); +Option Help(optname("--help, -h"), + overview("print usage and exit"), + false, + optional(true)); + Option pluginVerbose(optname("--plugins-verbose"), overview("verbose printing when plugins will be being searched"), false, @@ -32,47 +32,68 @@ Option debugZones(optname("--debug-area"), overview("if specified, debug code will be executed only in given areas"), "", optional(true)); +Option caffeFrontend(optname("--caffe"), + overview("define that input model in 'caffe' format type"), + false, + optional(true)); +Option tflFrontend(optname("--tflite"), + overview("define that input model in 'caffe' format type"), + false, + optional(true)); +Option target(optname("--target"), + overview("target for which compiler generates artifact." + " valid values are '" NNC_TARGET_X86_CPP "', '" NNC_TARGET_INTERPRETER "'"), + std::string(), + optional(false), + optvalues(NNC_TARGET_X86_CPP "," NNC_TARGET_INTERPRETER), + nullptr, + separators("=")); /** - * @breif Options for frontend + * Options for *frontend* */ -Option inputFile(optname("--input-filename"), - overview("path to AI model file"), - "", - optional(true), +Option inputFile(optname("--nnmodel, -m"), + overview("path to NN model file"), + std::string(), + optional(false), optvalues(""), - checkInFile); + checkInFile, + separators("=")); /** - * @breif Options for backend + * Options for *backend* */ // options for soft backend -Option artifactName(optname("--out-name"), +Option artifactName(optname("--output, -o"), overview("artifact output file name"), "nnmodel", optional(true), optvalues(""), checkOutFile); -Option artifactDir(optname("--out-dir"), +Option artifactDir(optname("--output-dir, -d"), overview("directory contains artifact output files"), ".", // default is current directory optional(true), optvalues(""), - checkOutDir); -// options for interpreter -Option interFileName(optname("--filename"), - overview("input file for interpreter"), - "", - optional(true), - optvalues(""), - checkInFile); -Option interInNode(optname("--input"), + checkOutDir, + separators("=")); + +/** + * Options for *interpreter* + */ +Option interInputData(optname("--input-model-data"), + overview("data input file of model for interpreter"), + std::string(), + optional(true), + optvalues(""), + checkInFile); +Option interInNode(optname("--input-node"), overview("interpreter option: sets input node in Computational Graph"), - "", + std::string(), optional(true)); -Option interOutNode(optname("--output"), +Option interOutNode(optname("--output-node"), overview("interpreter option: sets output node in Computational Graph"), - "", + std::string(), optional(true)); } // namespace clopt diff --git a/contrib/nnc/src/main.cpp b/contrib/nnc/src/main.cpp index 7429893..ba5fadf 100644 --- a/contrib/nnc/src/main.cpp +++ b/contrib/nnc/src/main.cpp @@ -1,49 +1,45 @@ #include #include -#include "ConfigException.h" -#include "module/AbstractModule.h" -#include "module/FrontendModule.h" -#include "module/BackendModule.h" -#include "module/plugin/PluginManager.h" +#include "PluginException.h" #include "CommandLine.h" +#include "Driver.h" + +#define DEBUG_AREA using namespace nncc::contrib; -using namespace nncc::contrib::clopt; -int main(int argc, char *argv[]) +int main(int argc, const char *argv[]) { + int exit_code = EXIT_FAILURE; + try { - module::plugin::PluginManager &pluginManager = module::plugin::PluginManager::getInstance(); - std::vector modules; - - modules.push_back(&module::FrontendModule::getInstance()); - modules.push_back(&module::BackendModule::getInstance()); - // Parse command line - CommandLine::getParser()->parseCommandLine(argc, const_cast(argv)); - - pluginManager.loadPlugins(); - // FIXME: it's necessary to make this printing via debugging system (see issue #893) - //std::cout << "plugins found:" << std::endl << pluginManager << std::endl; - - void *exRes = nullptr; - for (auto m : modules) - exRes = m->execute(exRes); - - // No errors - return 0; + clopt::CommandLine::getParser()->parseCommandLine(argc, argv); + + // + // run compiler pipeline: + // + // for_each(all_plugins): + // load plugin + // execute plugin + // unload plugin + // + Driver::runDriver(); + + // errors didn't happen + exit_code = EXIT_SUCCESS; } - catch (module::plugin::PluginManagerException &e) + catch ( const DriverException &e ) { - std::cout << e.what() << std::endl; + std::cerr << e.reason() << std::endl; + std::cerr << "use --help for more information" << std::endl; } - catch (ConfigException &e) + catch ( const PluginException &e ) { - std::cout << e.what() << std::endl; + std::cerr << e.what() << std::endl; } - // Some exception right there - return 1; + return exit_code; } diff --git a/contrib/nnc/src/module/AbstractModule.cpp b/contrib/nnc/src/module/AbstractModule.cpp deleted file mode 100644 index eba01b9..0000000 --- a/contrib/nnc/src/module/AbstractModule.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include -#include - -#include "module/AbstractModule.h" -#include "PluginInstance.h" - -namespace nncc -{ -namespace contrib -{ -namespace module -{ -AbstractModule::AbstractModule() : _activePlugin(nullptr) {} - -AbstractModule::~AbstractModule() {} - -void AbstractModule::registerPlugin(std::shared_ptr &pl) { _plugins.push_back(pl); } - -void *AbstractModule::execute(void *data) { - if (_activePlugin == nullptr) - throw ConfigException("Module has not been configured!"); - void *result = nullptr; - - try { - // FIXME: it's necessary to make this printing via debugging system (see issue #893) - //std::cout << "Executing plugin <" << _activePlugin->getPluginName() << ">" << std::endl; - result = _activePlugin->getPluginInstance()->execute(data); - } catch (nncc::foundation::Exception &e) { - e.append("Plugin <" + _activePlugin->getPluginName() + "> execution failed!"); - throw; - } - return result; -} - -std::ostream &operator<<(std::ostream &st, const AbstractModule &m) { - st << "plugins {" << std::endl; - for (const auto &p : m._plugins) - st << " " << *p << std::endl; - st << "}" << std::endl; - return st; -} - -} // namespace module -} // namespace contrib -} // namespace nncc diff --git a/contrib/nnc/src/module/BackendModule.cpp b/contrib/nnc/src/module/BackendModule.cpp deleted file mode 100644 index cc455b6..0000000 --- a/contrib/nnc/src/module/BackendModule.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "module/BackendModule.h" - -namespace nncc -{ -namespace contrib -{ -namespace module -{ - -BackendModule &BackendModule::getInstance() { - static BackendModule instance; - return instance; -} - -BackendModule::BackendModule() : AbstractModule() {} -BackendModule::~BackendModule() {} - -} // namespace module -} // namespace contrib -} // namespace nncc diff --git a/contrib/nnc/src/module/FrontendModule.cpp b/contrib/nnc/src/module/FrontendModule.cpp deleted file mode 100644 index 904cee3..0000000 --- a/contrib/nnc/src/module/FrontendModule.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "module/FrontendModule.h" - -namespace nncc -{ -namespace contrib -{ -namespace module -{ - -FrontendModule &FrontendModule::getInstance() { - static FrontendModule instance; - return instance; -} - -FrontendModule::FrontendModule() : AbstractModule() {} -FrontendModule::~FrontendModule() {} - -} // namespace module -} // namespace contrib -} // namespace nncc diff --git a/contrib/nnc/src/module/plugin/PluginManager.cpp b/contrib/nnc/src/module/plugin/PluginManager.cpp deleted file mode 100644 index 251631e..0000000 --- a/contrib/nnc/src/module/plugin/PluginManager.cpp +++ /dev/null @@ -1,139 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "module/plugin/PluginProxy.h" -#include "module/plugin/PluginManager.h" -#include "PluginInstance.h" -#include "Options.h" - -#include "PluginException.h" -#include "ConfigException.h" - -#ifdef __APPLE__ -#define STR_EXTENSION_PLUGIN ".dylib" -#else /* !__APPLE__ */ -#define STR_EXTENSION_PLUGIN ".so" -#endif /* __APPLE__ */ - -#include "debug.h" -#define DEBUG_AREA "plugins" - -namespace nncc -{ -namespace contrib -{ -namespace module -{ -namespace plugin -{ - -std::vector PluginManager::getPluginPathList() { - std::vector pluginPathList; - std::vector dirList; - - // Push first path - dirList.clear(); - dirList.push_back(clopt::pluginsPath); - - while (!dirList.empty()) { - const auto curPluginsPath = dirList.back(); - dirList.pop_back(); - - DIR *dir; - struct dirent *ent; - if ((dir = opendir(curPluginsPath.c_str())) != nullptr) { - while ((ent = readdir(dir)) != nullptr) { - if ((ent->d_type == DT_DIR) && (std::string(ent->d_name) != ".") && - (std::string(ent->d_name) != "..")) { - std::string f = curPluginsPath + std::string("/") + std::string(ent->d_name); - dirList.push_back(f); - } else if (strstr(ent->d_name, STR_EXTENSION_PLUGIN) != nullptr) { - std::string f = curPluginsPath + std::string("/") + std::string(ent->d_name); - pluginPathList.push_back(f); - } - } - closedir(dir); - } else { - // could not open directory - // TODO add some log - } - } - return pluginPathList; -} - -void PluginManager::loadPlugins() -{ - NNC_DEBUG(dbgs() << "Current plugin path is <" << clopt::pluginsPath << ">" << std::endl); - auto plugins = getPluginPathList(); - - for (const auto &pluginPath : plugins) - { - try - { - auto pl = PluginProxy::create(pluginPath); - - if (clopt::pluginVerbose) - std::cout << "plugin <" + pluginPath + ">: {" << std::endl - << "name <" + pl->getPluginName() + "> " << std::endl - << "}" << std::endl; - - _plugins.push_back(pl); - } - catch (PluginException &e) - { - if (clopt::pluginVerbose) - std::cout << "plugin <" + pluginPath << ">: {" << std::endl - << "bad plugin :" << e.what() << std::endl - << "}" << std::endl; - } - } - - if (_plugins.empty()) - throw PluginManagerException("No plugins found"); - - // Fill modules by plugins - for (auto &pl : _plugins) - { - auto ptype = pl->getPluginInstance(); - - if ( dynamic_cast(ptype) ) - { - module::FrontendModule::getInstance().registerPlugin(pl); - } - else if ( dynamic_cast(ptype) ) - { - module::BackendModule::getInstance().registerPlugin(pl); - } - else - { - throw PluginManagerException("Incorrect plugin type"); - } - } -} - -std::ostream &operator<<(std::ostream &st, const PluginManager &mod) { - for (const auto &pl : mod._plugins) - st << *pl << std::endl; - return st; -} - -PluginManager &PluginManager::getInstance() { - static PluginManager instance; - return instance; -} - -PluginManagerException::PluginManagerException(const std::string &info) : Exception(info) {} - -PluginManagerException::PluginManagerException(Exception &e, const std::string &info) - : Exception(e, info) { -} - -} // namespace plugin -} // namespace module -} // namespace contrib -} // namespace nncc diff --git a/contrib/nnc/src/module/plugin/PluginProxy.cpp b/contrib/nnc/src/module/plugin/PluginProxy.cpp deleted file mode 100644 index d65bc3f..0000000 --- a/contrib/nnc/src/module/plugin/PluginProxy.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include -#include "module/plugin/PluginProxy.h" - -namespace nncc -{ -namespace contrib -{ -namespace module -{ -namespace plugin -{ - -const std::string PluginProxy::getInstanceFuncName = "get_instance"; - -void *PluginProxy::getFuncAddr(const std::string &func_name) { - void *fp; - fp = _lib->findFunc(func_name); - - if (fp == nullptr) - throw PluginException(std::string("function not found: <") + func_name + ">"); - return fp; -} - -PluginProxy::PluginProxy(const std::string &pluginPath) : _getInstance(nullptr), _lib(nullptr), _pluginInstance(nullptr) { - _lib = std::make_shared(pluginPath); - - auto i = pluginPath.find_last_of('/'); - if (i != std::string::npos) - _pluginName = pluginPath.substr(i + 1); - else - _pluginName = pluginPath; -} - -void PluginProxy::init() noexcept(false) { - // Fill instance - _getInstance = (PluginProxy::get_instance_t) getFuncAddr(getInstanceFuncName); - _pluginInstance = _getInstance(); - - if (_pluginInstance == nullptr) - throw PluginException("bad plugin instance"); -} - -std::shared_ptr PluginProxy::create(const std::string &pluginPath) { - std::shared_ptr pl = nullptr; - try { - pl = std::shared_ptr(new PluginProxy(pluginPath)); - pl->init(); - return pl; - } - catch (PluginException &e) { - throw PluginException(e, "cannot create plugin"); - } -} - -PluginProxy::~PluginProxy() {} - -std::ostream &operator<<(std::ostream &st, const PluginProxy &pl) { - st << *(pl._lib); - return st; -} - -const std::string &PluginProxy::getPluginPath() const { return _lib->getPath(); } - -const std::string &PluginProxy::getPluginName() const { return _pluginName; } - -contrib::plugin::AbstractPluginInstance *PluginProxy::getPluginInstance() { - if (_pluginInstance == nullptr) - throw PluginException(std::string("bad plugin instance <") + getPluginPath() + ">"); - return _pluginInstance; -} - -} // namespace plugins -} // namespace module -} // namespace contrib -} // namespace nncc diff --git a/contrib/nnc/src/module/plugin/shared_library.cpp b/contrib/nnc/src/module/plugin/shared_library.cpp deleted file mode 100644 index 698529c..0000000 --- a/contrib/nnc/src/module/plugin/shared_library.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#include "module/plugin/shared_library.h" - -#include "debug.h" -#define DEBUG_AREA "plugins" - -namespace nncc -{ -namespace contrib -{ -namespace module -{ -namespace plugin -{ - -SharedLibrary::SharedLibrary(const std::string &fullPath) - : _handle(nullptr), _path(fullPath), _isLoaded(false) -{ -} - -void *SharedLibrary::findFunc(const std::string &funcName) -{ - if (!loadLibrary()) - { - return nullptr; - } - - // reset errors - dlerror(); - - void *func = dlsym(_handle, funcName.c_str()); - char *dlsym_error = dlerror(); - - if (nullptr != dlsym_error) - { - std::cout << "Cannot load symbol '" << funcName << "': " << dlsym_error << std::endl; - return nullptr; - } - return func; -} - -bool SharedLibrary::loadLibrary() -{ - if (nullptr == _handle && !_isLoaded) - { - _isLoaded = true; - - // open the library - NNC_DEBUG(dbgs() << "Opening " << _path << std::endl); - - _handle = dlopen(_path.c_str(), RTLD_LAZY); - - if (!_handle) - { - std::cout << "Cannot open library <" << _path << ">: " << dlerror() << std::endl; - } - } - - return (nullptr != _handle); -} - -const std::string& SharedLibrary::getPath() const { return _path; } - -std::ostream &operator<<(std::ostream &st, const SharedLibrary &lib) -{ - st << lib.getPath(); - return st; -} - -} // namespase plugin -} // namespace module -} // namespace contrib -} // namespace nncc diff --git a/contrib/nnc/support/CMakeLists.txt b/contrib/nnc/support/CMakeLists.txt index ab393f6..d1f94e0 100644 --- a/contrib/nnc/support/CMakeLists.txt +++ b/contrib/nnc/support/CMakeLists.txt @@ -3,4 +3,5 @@ set(SUPPORT_HEADERS include/CommandLine.h) add_library(nnc_support SHARED ${SUPPORT_SOURCES} ${SUPPORT_HEADERS}) -target_include_directories(nnc_support PUBLIC include) \ No newline at end of file +target_include_directories(nnc_support PUBLIC include) +install_common_library(nnc_support) diff --git a/contrib/nnc/support/include/CommandLine.h b/contrib/nnc/support/include/CommandLine.h index d6b3f66..63d7f6d 100644 --- a/contrib/nnc/support/include/CommandLine.h +++ b/contrib/nnc/support/include/CommandLine.h @@ -26,7 +26,7 @@ class BaseOption; class BadOption { public: - BadOption() = default; + BadOption(const BadOption &) noexcept {} explicit BadOption(const std::string &optname, const std::string &value) : _option_name(optname), _option_value(value) {} @@ -73,8 +73,9 @@ public: * @brief parse command line option * @param argc - number of command line arguments * @param argv - command line arguments + * @param check_nonoptional - if true then check that all non optional declared options are presented */ - void parseCommandLine(int argc, const char **argv); + void parseCommandLine(int argc, const char **argv, bool check_nonoptional = true); /** * @brief register option for parser @@ -82,6 +83,7 @@ public: */ void registerOption(BaseOption *opt); +private: /** * @brief print usage and exit * @param msg - additional user message @@ -89,9 +91,8 @@ public: */ [[ noreturn ]] void usage(const std::string &msg = "", int exit_code = EXIT_FAILURE); -private: /** - * @brief check that all registered options are passed from command line + * @brief check that all non optional registered options are passed from command line * @param cmd_args - arguments from command line */ void checkRegisteredOptions(const std::set &cmd_args); @@ -158,12 +159,6 @@ public: */ const T &getRawValue() const { return *this; } T getRawValue() { return *this; } - -protected: - // methods for Option - bool convToBool(const std::string &val) { assert(false && "only for scalar types"); } - char convToChar(const std::string &val) { assert(false && "only for scalar types"); } - template Tnum convToNum(const std::string &val) { assert(false && "only for scalar types"); } }; // for scalar type @@ -182,7 +177,6 @@ public: * @param val - option value */ template void setRawValue(const Tval &val) { _value = val; } - void setRawValue(const std::string &val) { assert(false && "invalid conversion"); } /** * @brief get option value @@ -269,18 +263,18 @@ public: * @param default_val - option value accepted by default * @param is_optional - is option optional? * @param vals - valid values for option. Other values are interpreted as invalid + * @param checker - function verifies option * @param seps - symbols that separates name option from value (by default is spaces) */ explicit Option(const std::vector &optnames, - const std::string &desrc, + const std::string &descr, const T &default_val = T(), bool is_optional = false, const std::vector &vals = std::vector(), option_checker_t checker = nullptr, const std::vector &seps = std::vector()); - // options must not be copyable and default constructable - Option() = delete; + // options must not be copyable and assignment Option(const Option&) = delete; Option& operator=(const Option&) = delete; @@ -288,7 +282,7 @@ public: * @brief overload assignment operator for type */ template T &operator=(const Tval& val) { - this->setRawValue(val); + setRawValue(val); return this->getRawValue(); // If not using `this` it won't work } @@ -423,44 +417,6 @@ Tnum OptionType::convToNum(const std::string &val) } // convToNum -template -void Option::setValue(const std::string &val) -{ - if ( std::is_same::value ) - { - if ( !val.empty() ) - this->setRawValue(val); - - } else if ( std::is_same::value ) - { - this->setRawValue(this->convToBool(val)); - - } else if ( std::is_same::value ) - { - if ( !val.empty() ) - this->setRawValue(this->convToChar(val)); - - } else if ( std::is_same::value || - std::is_same::value || - std::is_same::value ) - { - if ( !val.empty() ) - this->setRawValue(this->template convToNum(val)); - - } else if ( std::is_same::value || - std::is_same::value || - std::is_same::value ) - { - if ( !val.empty() ) - this->setRawValue(this->template convToNum(val)); - - } else - { - std::cerr << "unsupported option value type\n"; - exit(EXIT_FAILURE); - } - -} // setValue template Option::Option(const std::vector &optnames, @@ -476,8 +432,7 @@ Option::Option(const std::vector &optnames, { _names.push_back(n); - // name must start with `-` - assert(n[0] == '-'); + assert(n[0] == '-' && "option name must start with `-`"); } _descr = descr; diff --git a/contrib/nnc/support/src/CommandLine.cpp b/contrib/nnc/support/src/CommandLine.cpp index 3cc1cf8..3f2b61d 100644 --- a/contrib/nnc/support/src/CommandLine.cpp +++ b/contrib/nnc/support/src/CommandLine.cpp @@ -7,6 +7,8 @@ #include #include #include +#include "cstring" + #include "CommandLine.h" using namespace nncc::contrib::clopt; @@ -26,7 +28,7 @@ static std::vector splitByComma(const char *str) if ( std::string(str).empty() ) return ret; - for ( int i = 0, cnt = 0; str[i] != '\0'; i++ ) + for ( size_t i = 0, cnt = 0; str[i] != '\0'; i++ ) { if ( str[i] == ',' ) { @@ -166,7 +168,7 @@ BaseOption *CommandLine::findOption(const char *optname) { // optname can contain separators, try // to strip these separators and repeat a search - int i = 0; + size_t i = 0; for ( ; optname[i] != '\0' && optname[i] != '=' && optname[i] != ':'; i++ ) ; std::string strip_optname(optname, i); @@ -177,6 +179,16 @@ BaseOption *CommandLine::findOption(const char *optname) // couldn't find option throw BadOption(optname, ""); } + else + { + BaseOption *opt = it->second; + + if ( opt->getSeparators().empty() ) + { + // couldn't find option + throw BadOption(optname, ""); + } + } } return it->second; @@ -322,7 +334,7 @@ void CommandLine::checkOptions(const std::set &cmd_args) } // checkOptions -void CommandLine::parseCommandLine(int argc, const char **argv) +void CommandLine::parseCommandLine(int argc, const char **argv, bool check_nonoptional) { std::set cmd_args; BaseOption *opt; @@ -331,6 +343,21 @@ void CommandLine::parseCommandLine(int argc, const char **argv) _prog_name = argv[0]; _args_num = argc; + if ( argc == 1 ) + { + // empty command line + usage(); + } + + // search help option and print help if this option is passed + for ( int i = 1; i < argc; i++ ) + { + if ( !strcmp(argv[i], "-h") || !strcmp(argv[i], "--help") ) + { + usage("", EXIT_SUCCESS); + } + } + for ( int i = 1; i < argc; i += (argv[i+1] == arg_val) ? 2 : 1 ) { if ( argv[i][0] != '-' ) @@ -371,14 +398,92 @@ void CommandLine::parseCommandLine(int argc, const char **argv) cmd_args.insert(opt->getNames()[0]); } - // check that all registered options are present in command line - checkRegisteredOptions(cmd_args); + if ( check_nonoptional ) + { + // check that all registered options are present in command line + checkRegisteredOptions(cmd_args); + } // verify options checkOptions(cmd_args); } // parseCommandLine + +// +// specializations of setValue method for all supported option type +// +// string +template <> +void Option::setValue(const std::string &val) +{ + if ( !val.empty() ) + this->setRawValue(val); +} + +// bool +template <> +void Option::setValue(const std::string &val) +{ + this->setRawValue(this->convToBool(val)); +} + +// char +template <> +void Option::setValue(const std::string &val) +{ + if ( !val.empty() ) + this->setRawValue(this->convToChar(val)); +} + +// int8 +template <> +void Option::setValue(const std::string &val) +{ + if ( !val.empty() ) + this->setRawValue(this->template convToNum(val)); +} + +// int16 +template <> +void Option::setValue(const std::string &val) +{ + if ( !val.empty() ) + this->setRawValue(this->template convToNum(val)); +} + +// int32 +template <> +void Option::setValue(const std::string &val) +{ + if ( !val.empty() ) + this->setRawValue(this->template convToNum(val)); +} + +// uint8 +template <> +void Option::setValue(const std::string &val) +{ + if ( !val.empty() ) + this->setRawValue(this->template convToNum(val)); +} + +// uint16 +template <> +void Option::setValue(const std::string &val) +{ + if ( !val.empty() ) + this->setRawValue(this->template convToNum(val)); +} + +// uint32 +template <> +void Option::setValue(const std::string &val) +{ + if ( !val.empty() ) + this->setRawValue(this->template convToNum(val)); +} + } // namespace clopt } // namespace contrib } // namespace nncc \ No newline at end of file diff --git a/contrib/nnc/unittests/core/CMakeLists.txt b/contrib/nnc/unittests/core/CMakeLists.txt index 296d3a1..ff437a2 100644 --- a/contrib/nnc/unittests/core/CMakeLists.txt +++ b/contrib/nnc/unittests/core/CMakeLists.txt @@ -2,4 +2,4 @@ file(GLOB_RECURSE HEADERS "${NNC_CORE_DIR}/include/*.h") file(GLOB_RECURSE TESTS "*.cpp") add_nncc_test(nnc_core_test ${TESTS}) -nncc_target_link_libraries(nnc_core_test nnc_core nncc_core) +nncc_target_link_libraries(nnc_core_test nnc_core) diff --git a/contrib/nnc/unittests/module/BackendModule.cpp b/contrib/nnc/unittests/module/BackendModule.cpp deleted file mode 100644 index 94199f3..0000000 --- a/contrib/nnc/unittests/module/BackendModule.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "module/BackendModule.h" - -#include "gtest/gtest.h" - -using namespace nncc::contrib::module; -using namespace nncc::contrib::plugin; - -TEST(CONTRIB_NNC, BackendModule) -{ - AbstractModule *backendModule1 = &BackendModule::getInstance(); - AbstractModule *backendModule2 = &BackendModule::getInstance(); - ASSERT_EQ(backendModule1, backendModule2); -} diff --git a/contrib/nnc/unittests/module/CMakeLists.txt b/contrib/nnc/unittests/module/CMakeLists.txt index 7533698..98608ac 100644 --- a/contrib/nnc/unittests/module/CMakeLists.txt +++ b/contrib/nnc/unittests/module/CMakeLists.txt @@ -2,7 +2,7 @@ file(GLOB_RECURSE TEST_SOURCES "*.cpp") # Plugin module tests add_nncc_test(nnc_module_test ${OPTIONS_SRC} ${TEST_SOURCES} ${HEADERS}) -nncc_target_link_libraries(nnc_module_test nnc_support nnc_module nncc_core nncc_foundation nnc_plugin_core) +nncc_target_link_libraries(nnc_module_test nnc_support nnc_module nnc_plugin_core dl) # target_include_directories(nnc_module_test PUBLIC ../include) # Set macro in nnc_module_test with some_parser absolute path diff --git a/contrib/nnc/unittests/module/PluginManager.cpp b/contrib/nnc/unittests/module/PluginManager.cpp index 3290962..7db1cc1 100644 --- a/contrib/nnc/unittests/module/PluginManager.cpp +++ b/contrib/nnc/unittests/module/PluginManager.cpp @@ -1,8 +1,5 @@ #include -#include "module/AbstractModule.h" -#include "module/FrontendModule.h" -#include "module/BackendModule.h" -#include "module/plugin/PluginManager.h" +#include "PluginManager.h" #include "gtest/gtest.h" @@ -10,84 +7,32 @@ #define _STRING(s) #s using namespace nncc::contrib; -using namespace nncc::contrib::module::plugin; +using namespace nncc::contrib::plugin; -// PluginManagerException class -std::string managerErrorMsg1 = "error constructor"; -std::string managerErrorMsg2 = "error second constructor"; - -std::vector managerErrorMsgs = {managerErrorMsg1, managerErrorMsg2}; - -void managerErr1() { throw PluginManagerException(managerErrorMsg1); } - -void managerErr2() +// Test PluginManager loading with unexisting path +TEST(CONTRIB_NNC, PluginManagerMissingDir) { try { - managerErr1(); + PluginManager pluginManager("AAA"); + FAIL(); } - catch (PluginManagerException &e) + catch ( const PluginException &e ) { - throw PluginManagerException(e, managerErrorMsg2); - } -} -TEST(CONTRIB_NNC, PluginManagerException) -{ - try - { - managerErr2(); } - catch (PluginManagerException &e) - { - ASSERT_TRUE(managerErrorMsgs == e.getInfo()); - return; - } - - // should not happen - FAIL(); -} - -// PluginManager class - -// Test 'getInstance()' method -TEST(CONTRIB_NNC, PluginManagerGetInstance) -{ - PluginManager &pluginManager = PluginManager::getInstance(); - ASSERT_NE(&pluginManager, nullptr); - PluginManager &pluginManager2 = PluginManager::getInstance(); - ASSERT_EQ(&pluginManager, &pluginManager2); -} - -// Test PluginManager loading with unexisting path -TEST(CONTRIB_NNC, PluginManagerMissingDir) -{ - PluginManager &pluginManager = PluginManager::getInstance(); - - ASSERT_THROW(pluginManager.loadPlugins(), PluginManagerException); } // Test PluginManager work with correct configuration TEST(CONTRIB_NNC, PluginManager) { - PluginManager &pluginManager = PluginManager::getInstance(); - const char *argv[] = {"PluginManager", - "--plugins-path", STRING(CMAKE_SAMPLE_PLUGIN_DIR_ABS_PATH), - nullptr}; - std::cout << STRING(CMAKE_SAMPLE_PLUGIN_DIR_ABS_PATH); - int argc = (sizeof(argv) / sizeof(argv[0])) - 1; - - clopt::CommandLine::getParser()->parseCommandLine(argc, argv); - - pluginManager.loadPlugins(); + PluginManager pluginManager(STRING(CMAKE_SAMPLE_PLUGIN_ABS_PATH)); // Test operator '<<' std::ostringstream os; os << pluginManager; - std::string pluginsOrder1(STRING(CMAKE_SAMPLE_PLUGIN_2_ABS_PATH) "\n" - STRING(CMAKE_SAMPLE_PLUGIN_ABS_PATH) "\n"); - std::string pluginsOrder2(STRING(CMAKE_SAMPLE_PLUGIN_ABS_PATH) "\n" - STRING(CMAKE_SAMPLE_PLUGIN_2_ABS_PATH) "\n"); - EXPECT_TRUE(os.str() == pluginsOrder1 || os.str() == pluginsOrder2); + + std::string plugin(STRING(CMAKE_SAMPLE_PLUGIN_ABS_PATH) "\n"); + EXPECT_TRUE(os.str() == plugin ); } diff --git a/contrib/nnc/unittests/module/PluginProxy.cpp b/contrib/nnc/unittests/module/PluginProxy.cpp index 13c3d17..9279a10 100644 --- a/contrib/nnc/unittests/module/PluginProxy.cpp +++ b/contrib/nnc/unittests/module/PluginProxy.cpp @@ -1,11 +1,13 @@ -#include "module/plugin/PluginProxy.h" +#include "PluginProxy.h" +#include "PluginException.h" #include "gtest/gtest.h" #define STRING(s) _STRING(s) #define _STRING(s) #s -using namespace nncc::contrib::module::plugin; +using namespace nncc::contrib::plugin; +using namespace nncc::contrib; void tryCreatePluginProxy(std::string path) { @@ -14,7 +16,7 @@ void tryCreatePluginProxy(std::string path) std::shared_ptr pp = PluginProxy::create(path); FAIL(); } - catch (nncc::foundation::Exception &e){} + catch ( PluginException &e ) {} } TEST(CONTRIB_NNC, PluginProxy) diff --git a/contrib/nnc/unittests/module/shared_library.cpp b/contrib/nnc/unittests/module/shared_library.cpp index 17660e8..42557a5 100644 --- a/contrib/nnc/unittests/module/shared_library.cpp +++ b/contrib/nnc/unittests/module/shared_library.cpp @@ -1,21 +1,23 @@ -#include "module/plugin/shared_library.h" +#include "shared_library.h" +#include "PluginException.h" #include "gtest/gtest.h" #define STRING(s) _STRING(s) #define _STRING(s) #s -using namespace nncc::contrib::module::plugin; +using namespace nncc::contrib; +using namespace nncc::contrib::plugin; TEST(CONTRIB_NNC, SharedLibrary) { // missing so - missing function - SharedLibrary slMissing("/"); - ASSERT_EQ(slMissing.findFunc("missing_func_name"), nullptr); + SharedLibrary slMissing("/"); + ASSERT_THROW(slMissing.findFunc("missing_func_name"), PluginException); // existing so - missing function - SharedLibrary sl(STRING(CMAKE_SAMPLE_PLUGIN_ABS_PATH)); - ASSERT_EQ(sl.findFunc("missing_func_name"), nullptr); + SharedLibrary sl(STRING(CMAKE_SAMPLE_PLUGIN_ABS_PATH)); + ASSERT_THROW(sl.findFunc("missing_func_name"), PluginException); // existing so - existing function typedef int (*fp_t)(); diff --git a/contrib/nnc/unittests/plugin_core/CMakeLists.txt b/contrib/nnc/unittests/plugin_core/CMakeLists.txt index 9bc38a1..11824eb 100644 --- a/contrib/nnc/unittests/plugin_core/CMakeLists.txt +++ b/contrib/nnc/unittests/plugin_core/CMakeLists.txt @@ -2,4 +2,4 @@ file(GLOB_RECURSE HEADERS "${NNC_PLUGIN_CORE_DIR}/include/*.h") file(GLOB_RECURSE TESTS "*.cpp") add_nncc_test(nnc_plugin_core_test ${TESTS} ${HEADERS}) -nncc_target_link_libraries(nnc_plugin_core_test nnc_plugin_core nncc_foundation) +nncc_target_link_libraries(nnc_plugin_core_test nnc_plugin_core) diff --git a/contrib/nnc/unittests/plugin_core/ConfigException.cpp b/contrib/nnc/unittests/plugin_core/ConfigException.cpp deleted file mode 100644 index bb44703..0000000 --- a/contrib/nnc/unittests/plugin_core/ConfigException.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "ConfigException.h" - -#include "gtest/gtest.h" - -using namespace nncc::contrib; - -std::string configErrorMsg1 = "error constructor"; -std::string configErrorMsg2 = "error second constructor"; - -std::vector configErrorMsgs = {configErrorMsg1, configErrorMsg2}; - -void configErr1() { throw ConfigException(configErrorMsg1); } - -void configErr2() -{ - try - { - configErr1(); - } - catch (ConfigException &e) - { - throw ConfigException(e, configErrorMsg2); - } -} - -TEST(CONTRIB_PLUGIN, ConfigException) -{ - try - { - configErr2(); - } - catch (ConfigException &e) - { - ASSERT_TRUE(configErrorMsgs == e.getInfo()); - return; - } - - // should not happen - ASSERT_TRUE(false); -} diff --git a/contrib/nnc/unittests/plugin_core/PluginException.cpp b/contrib/nnc/unittests/plugin_core/PluginException.cpp index 8b8c13f..65c2f01 100644 --- a/contrib/nnc/unittests/plugin_core/PluginException.cpp +++ b/contrib/nnc/unittests/plugin_core/PluginException.cpp @@ -4,12 +4,9 @@ using namespace nncc::contrib; -std::string pluginErrorMsg1 = "error constructor"; -std::string pluginErrorMsg2 = "error second constructor"; +std::string pluginErrorMsg = "error constructor"; -std::vector pluginErrorMsgs = {pluginErrorMsg1, pluginErrorMsg2}; - -void pluginErr1() { throw PluginException(pluginErrorMsg1); } +void pluginErr1() { throw PluginException(pluginErrorMsg); } void pluginErr2() { @@ -19,7 +16,7 @@ void pluginErr2() } catch (PluginException &e) { - throw PluginException(e, pluginErrorMsg2); + throw; } } @@ -31,7 +28,7 @@ TEST(CONTRIB_PLUGIN, PluginException) } catch (PluginException &e) { - ASSERT_TRUE(pluginErrorMsgs == e.getInfo()); + ASSERT_TRUE(pluginErrorMsg == e.what()); return; } diff --git a/contrib/nnc/unittests/soft_backend/CMakeLists.txt b/contrib/nnc/unittests/soft_backend/CMakeLists.txt index 52cb63c..590695b 100644 --- a/contrib/nnc/unittests/soft_backend/CMakeLists.txt +++ b/contrib/nnc/unittests/soft_backend/CMakeLists.txt @@ -7,7 +7,7 @@ file(GLOB_RECURSE TESTS "*.cpp") make_generated_sources("${SOFT_DEF_SOURCES}" ${CMAKE_CURRENT_BINARY_DIR} SOFT_GENERATED_SOURCES) add_nncc_test(nnc_soft_backend_test ${TESTS} ${OPTIONS_SRC} ${SOFT_BACKEND_CPP_SOURCES} ${SOFT_GENERATED_SOURCES}) -nncc_target_link_libraries(nnc_soft_backend_test nnc_support nnc_interpreter_core nncc_core nnc_core nnc_plugin_core nncc_foundation soft_backend_common) +nncc_target_link_libraries(nnc_soft_backend_test nnc_support nnc_interpreter_core nnc_core nnc_plugin_core soft_backend_common) target_include_directories(nnc_soft_backend_test PUBLIC ${NNC_SOFT_BACKEND_DIR}/include) target_include_directories(nnc_soft_backend_test PUBLIC ${NNC_INTERPRETER_DIR}/include) target_include_directories(nnc_soft_backend_test PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/contrib/nnc/unittests/soft_backend/generator.cpp b/contrib/nnc/unittests/soft_backend/generator.cpp index 77dd02a..037af10 100644 --- a/contrib/nnc/unittests/soft_backend/generator.cpp +++ b/contrib/nnc/unittests/soft_backend/generator.cpp @@ -62,12 +62,12 @@ TEST(Generator, check_generator_call) #define TEST_NAME "someName" #define BASE_NAME TEST_DIR "/" TEST_NAME const char *argv[] = {"soft_backend_test", - "--out-dir", TEST_DIR, - "--out-name", TEST_NAME, + "-d", TEST_DIR, + "-o", TEST_NAME, nullptr}; int argc = (sizeof(argv) / sizeof(argv[0])) - 1; - clopt::CommandLine::getParser()->parseCommandLine(argc, argv); + clopt::CommandLine::getParser()->parseCommandLine(argc, argv, false); nncc::contrib::core::IR::model::Graph g; g.create("input"); -- 2.7.4