```
./nnc --plugins-path . \
--input-filename inceptionv3.tflite \
---emit-source c++ \
+--emit-c++ \
--out-code nn.cpp \
--out-header nn.h \
--out-model param.file</p>
```
-``--emit-source c++`` is a _soft backend_ option that selects target language to emit
+``--emit-c++`` is a _soft backend_ option that selects target language to emit(for now supported ``--emit-c++`` and ``--emit-c``)
``--out-code nn.cpp`` is a _soft backend_ option, it sets path to source code file
-file(GLOB_RECURSE SOFT_BACKEND_SOURCES src/*.cpp)
-file(GLOB_RECURSE HEADERS "include/*.h")
+set(SOFT_BACKEND_COMMON_SOURCES src/soft_backend.cpp src/generator.cpp src/model_analyzer.cpp)
+set(SOFT_BACKEND_CPP_SOURCES src/cpp_backend.cpp)
+set(SOFT_BACKEND_C_SOURCES src/c_backend.cpp)
set(DEF_CONV src/def2src.cpp)
file(GLOB_RECURSE TESTS "src/*.test.cpp")
file(GLOB_RECURSE SOFT_DEF_SOURCES include/*.def)
-list(REMOVE_ITEM SOFT_BACKEND_SOURCES ${TESTS} ${DEF_CONV})
set(SOFT_GENERATED_SOURCES "")
foreach(file IN LISTS SOFT_DEF_SOURCES)
)
endforeach()
-add_library(soft_backend SHARED ${SOFT_BACKEND_SOURCES} ${SOFT_GENERATED_SOURCES})
+add_executable(def2src ${DEF_CONV})
-add_nncc_test(nnc_soft_backend_test ${TESTS})
-nncc_target_link_libraries(nnc_soft_backend_test nncc_core nnc_core nnc_plugin_core nncc_foundation soft_backend)
+add_library(soft_backend_common STATIC ${SOFT_BACKEND_COMMON_SOURCES} ${SOFT_GENERATED_SOURCES})
+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)
+
+function(make_soft_backend NAME SOURCES)
+ message(${NAME} ${SOURCES})
+ add_library(${NAME} SHARED ${SOURCES} ${SOFT_GENERATED_SOURCES})
+ target_include_directories(${NAME} PUBLIC include)
+ 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)
+endfunction(make_soft_backend)
+
+make_soft_backend(soft_backend_cpp ${SOFT_BACKEND_CPP_SOURCES})
+make_soft_backend(soft_backend_c ${SOFT_BACKEND_C_SOURCES})
+
+add_nncc_test(nnc_soft_backend_test ${TESTS} ${SOFT_BACKEND_COMMON_SOURCES})
+nncc_target_link_libraries(nnc_soft_backend_test nncc_core nnc_core nnc_plugin_core nncc_foundation soft_backend_common)
target_include_directories(nnc_soft_backend_test PUBLIC include)
target_include_directories(nnc_soft_backend_test PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
-
-add_executable(def2src ${DEF_CONV})
-
-target_link_libraries(soft_backend PRIVATE nncc_core)
-
-target_include_directories(soft_backend PUBLIC include)
-target_include_directories(soft_backend PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
-
-target_link_libraries(soft_backend PRIVATE nnc_plugin_core)
-target_link_libraries(soft_backend PRIVATE nncc_foundation)
-target_link_libraries(soft_backend PRIVATE nnc_core)
--- /dev/null
+#ifndef _NNC_SOFT_BACKEND_PLUGIN_H_
+#define _NNC_SOFT_BACKEND_PLUGIN_H_
+
+#include "PluginInstance.h"
+#include "nnc/core/IR/model/graph/graph.h"
+
+#include <string>
+#include <map>
+
+namespace nncc
+{
+namespace contrib
+{
+namespace backend
+{
+namespace soft
+{
+
+enum class OPT_ID;
+
+class BaseSoftBackend : public nncc::contrib::plugin::AbstractPluginInstance
+{
+public:
+ BaseSoftBackend &operator=(const BaseSoftBackend &) = delete;
+
+ BaseSoftBackend(const BaseSoftBackend &) = delete;
+
+ void fillSession() override;
+
+ void checkConfig() override;
+
+ void *execute(void *data) override;
+
+ void setParam(const std::string &name) override;
+
+ void setParam(const std::string &name, const std::string &value) override;
+
+protected:
+ std::string _outHeaderFile;
+ std::string _outCodeFile;
+ std::string _outModelFile;
+
+ const std::string _pluginName;
+
+ // general options with some expected value
+ std::map<std::string, OPT_ID> _opts;
+
+ // flag options
+ std::map<std::string, OPT_ID> _flags;
+
+ BaseSoftBackend(const std::string &name, const std::string &target_opt);
+
+ ~BaseSoftBackend() override = default;
+
+ virtual void generate(nncc::contrib::core::IR::model::Graph *g) = 0;
+};
+
+} // namespace soft
+} // namespace backend
+} // namespace contrib
+} // namespace nncc
+
+#endif //_NNC_SOFT_BACKEND_PLUGIN_H_
--- /dev/null
+#include "soft_backend.h"
+#include "generator.h"
+
+#include "ConfigException.h"
+
+using namespace nncc::contrib::config;
+using namespace nncc::contrib::plugin;
+using namespace nncc::contrib::backend::soft;
+
+namespace nncc
+{
+namespace contrib
+{
+namespace backend
+{
+namespace soft
+{
+
+namespace
+{
+const char *target_opt = "emit-c";
+const char *backend_name = "C soft backend";
+} // unnamed namespace
+
+class CSoftBackend final: public BaseSoftBackend
+{
+public:
+ CSoftBackend &operator=(const CSoftBackend &) = delete;
+
+ CSoftBackend(const CSoftBackend &) = delete;
+
+ void fillSession() override
+ {
+ BaseSoftBackend::fillSession();
+ getSession()->registerParam(PluginParam(target_opt, "option enables C backend", false));
+ }
+
+ void generate(nncc::contrib::core::IR::model::Graph *g) override
+ {
+ CCodeGenerator::create(_outHeaderFile, _outCodeFile, _outModelFile).generate(g);
+ }
+
+ static CSoftBackend &getInstance()
+ {
+ static CSoftBackend instance;
+ return instance;
+ }
+
+private:
+ CSoftBackend(): BaseSoftBackend(backend_name, target_opt) {}
+};
+
+} // namespace soft
+} // namespace backend
+} // namespace contrib
+} // namespace nncc
+
+
+extern "C" AbstractPluginInstance *get_instance()
+{
+ return &CSoftBackend::getInstance();
+}
--- /dev/null
+#include "soft_backend.h"
+#include "generator.h"
+
+#include "ConfigException.h"
+
+using namespace nncc::contrib::config;
+using namespace nncc::contrib::plugin;
+using namespace nncc::contrib::backend::soft;
+
+namespace nncc
+{
+namespace contrib
+{
+namespace backend
+{
+namespace soft
+{
+
+namespace
+{
+const char *target_opt = "emit-c++";
+const char *backend_name = "C++ soft backend";
+} // unnamed namespace
+
+class CPPSoftBackend final: public BaseSoftBackend
+{
+public:
+ CPPSoftBackend &operator=(const CPPSoftBackend &) = delete;
+
+ CPPSoftBackend(const CPPSoftBackend &) = delete;
+
+ void fillSession() override
+ {
+ BaseSoftBackend::fillSession();
+ getSession()->registerParam(PluginParam(target_opt, "option enables C++ backend", false));
+ }
+
+ void generate(nncc::contrib::core::IR::model::Graph *g) override
+ {
+ CPPCodeGenerator::create(_outHeaderFile, _outCodeFile, _outModelFile).generate(g);
+ }
+
+ static CPPSoftBackend &getInstance()
+ {
+ static CPPSoftBackend instance;
+ return instance;
+ }
+
+private:
+ CPPSoftBackend(): BaseSoftBackend(backend_name, target_opt) {}
+};
+
+} // namespace soft
+} // namespace backend
+} // namespace contrib
+} // namespace nncc
+
+
+extern "C" AbstractPluginInstance *get_instance()
+{
+ return &CPPSoftBackend::getInstance();
+}
#include <iostream>
#include <cassert>
-#include "PluginInstance.h"
+#include "soft_backend.h"
#include "PluginException.h"
#include "ConfigException.h"
#include "PluginType.h"
using namespace nncc::contrib::core::IR::model;
using namespace nncc::contrib::backend::soft;
+namespace nncc
+{
+namespace contrib
+{
+namespace backend
+{
+namespace soft
+{
+
namespace
{
-const string pluginName = "soft backend";
const string pluginVersion = "0.01";
const string pluginDesc = "Generates source code for selected programming language from IR";
const PluginType pluginType = typeBackEnd;
+const char *outCodeOpt = "out-code";
+const char *outHeaderOpt = "out-header";
+const char *outModelOpt = "out-model";
+} // unnamed namespace
+
// Helpers
enum class OPT_ID
{
INVALID,
- TARGET_LANG,
+ TARGET,
OUT_HEADER,
OUT_CODE,
OUT_MODEL
};
-const char *targetLangOpt = "emit-source";
-const char *outCodeOpt = "out-code";
-const char *outHeaderOpt = "out-header";
-const char *outModelOpt = "out-model";
-
-// general options with some expected value
-const map<string, OPT_ID> opts = {{targetLangOpt, OPT_ID::TARGET_LANG},
- {outCodeOpt, OPT_ID::OUT_CODE},
- {outHeaderOpt, OPT_ID::OUT_HEADER},
- {outModelOpt, OPT_ID::OUT_MODEL}};
-
-// flag options
-const map<string, OPT_ID> flags;
-
-enum class LANG_ID
-{
- INVALID,
- C,
- CPP
-};
-
-const map<string, LANG_ID> langs = {{"c", LANG_ID::C},
- {"c++", LANG_ID::CPP}};
-
-// Plugin implementation
-class SoftBackendInstance : public AbstractPluginInstance
-{
-public:
- SoftBackendInstance &operator=(const SoftBackendInstance &) = delete;
- SoftBackendInstance(const SoftBackendInstance &) = delete;
-
- static AbstractPluginInstance &getInstance();
- void fillSession() override;
- void checkConfig() override;
- void *execute(void *data) override;
-
- void setParam(const string &name) override;
- void setParam(const string &name, const string &value) override;
-
-private:
- LANG_ID _target;
- string _outHeaderFile;
- string _outCodeFile;
- string _outModelFile;
-
- SoftBackendInstance();
- ~SoftBackendInstance() override = default;
-};
-
-SoftBackendInstance::SoftBackendInstance(): _target(LANG_ID::INVALID)
-{
- // EMPTY
-}
-
-AbstractPluginInstance &SoftBackendInstance::getInstance()
-{
- static SoftBackendInstance instance;
- return instance;
-}
-
-void SoftBackendInstance::fillSession()
+void BaseSoftBackend::fillSession()
{
const static map<string, string> info = {{"module description", pluginDesc}};
- const static vector<PluginParam> moduleParams = {{targetLangOpt, "language to emit: c,c++", false},
- {outCodeOpt, "output file for code", true},
+ const static vector<PluginParam> moduleParams = {{outCodeOpt, "output file for code", true},
{outHeaderOpt, "output file for header", true},
{outModelOpt, "output file for model parameters", true}};
- AbstractPluginInstance::fillSessionBase(pluginType, pluginVersion, pluginName);
+ AbstractPluginInstance::fillSessionBase(pluginType, pluginVersion, _pluginName);
for (auto &i : info)
getSession()->addInfo(i.first, i.second);
getSession()->registerParam(p);
}
-void SoftBackendInstance::checkConfig()
+void BaseSoftBackend::checkConfig()
{
- assert(_target != LANG_ID::INVALID && "No target language selected");
// Nothing to check for now
}
-void *SoftBackendInstance::execute(void *data)
+void *BaseSoftBackend::execute(void *data)
{
- assert(_target != LANG_ID::INVALID);
assert(data);
Graph *graph = static_cast<Graph*>(data);
- switch (_target)
- {
- case LANG_ID::C:
- CCodeGenerator::create(_outHeaderFile, _outCodeFile, _outModelFile).generate(graph);
- break;
- case LANG_ID::CPP:
- CPPCodeGenerator::create(_outHeaderFile, _outCodeFile, _outModelFile).generate(graph);
- break;
- default:
- assert(false && "Unsupported language");
- break;
- };
- clog << "[" << pluginName << "] Plugin executed" << endl;
+ generate(graph);
+ clog << "[" << _pluginName << "] Plugin executed" << endl;
return data;
}
-void SoftBackendInstance::setParam(const string &name)
-{
- auto optionIt = flags.find(name);
- (void) optionIt;
- // plugin do not have flag arguments for now - throw exception
- throw ConfigException("[" + pluginName + "] Unsupported flag parameter <" + name + ">");
-}
-
-void SoftBackendInstance::setParam(const string &name, const string &value)
+void BaseSoftBackend::setParam(const string &name)
{
- auto optionIt = opts.find(name);
- assert(optionIt != opts.end());
+ auto optionIt = _flags.find(name);
switch (optionIt->second)
{
- case OPT_ID::TARGET_LANG:
+ case OPT_ID::TARGET:
{
- auto langId = langs.find(value);
- if (langId == langs.end())
- {
- string info = "[" + pluginName + "] Unsupported target language <" + value + ">";
- throw ConfigException(info);
- }
- _target = langId->second;
break;
}
+ default:
+ throw ConfigException("[" + _pluginName + "] Unsupported flag parameter <" + name + ">");
+ }
+}
+
+void BaseSoftBackend::setParam(const string &name, const string &value)
+{
+ auto optionIt = _opts.find(name);
+ switch (optionIt->second)
+ {
case OPT_ID::OUT_HEADER:
{
_outHeaderFile = value;
break;
}
default:
- throw ConfigException("[" + pluginName + "] Unsupported parameter <" + name + ">");
+ throw ConfigException("[" + _pluginName + "] Unsupported parameter with value <" + name + ">");
}
}
-} // unnamed namespace
-
-extern "C" AbstractPluginInstance *get_instance()
+BaseSoftBackend::BaseSoftBackend(const std::string &name, const std::string &target_opt):
+ _pluginName(name)
{
- return &SoftBackendInstance::getInstance();
+ _flags[target_opt] = OPT_ID::TARGET;
+ _opts[outCodeOpt] = OPT_ID::OUT_CODE;
+ _opts[outHeaderOpt] = OPT_ID::OUT_HEADER;
+ _opts[outModelOpt] = OPT_ID::OUT_MODEL;
}
+
+} // namespace soft
+} // namespace backend
+} // namespace contrib
+} // namespace nncc