From d79a2808cf2446fa21d91a6141f6fbe2318c03ec Mon Sep 17 00:00:00 2001 From: Benedikt Tutzer Date: Thu, 16 Aug 2018 16:00:11 +0200 Subject: [PATCH] Python Passes can now be added with the -m option or with the plugin command. There are still issues when run in shell mode, but they can be used just fine in a python script --- Makefile | 2 +- kernel/python_wrappers.cc | 66 ++++++++++++++++++++++++++++++++++++++- kernel/yosys.cc | 26 +++++++++++++++ kernel/yosys.h | 5 +++ passes/cmds/plugin.cc | 63 +++++++++++++++++++++++++++++++++++++ 5 files changed, 160 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 691f43798..6466bddf2 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ PYTHON_VERSION := 3.5 # other configuration flags ENABLE_GPROF := 0 -ENABLE_DEBUG := 0 +ENABLE_DEBUG := 1 ENABLE_NDEBUG := 0 LINK_CURSES := 0 LINK_TERMCAP := 0 diff --git a/kernel/python_wrappers.cc b/kernel/python_wrappers.cc index 18b0010ae..197be0853 100644 --- a/kernel/python_wrappers.cc +++ b/kernel/python_wrappers.cc @@ -34,6 +34,11 @@ namespace YOSYS_PYTHON { Yosys::run_pass(command); } + void log(std::string text) + { + Yosys::log(text.c_str()); + } + struct IdString { Yosys::RTLIL::IdString* ref_obj; @@ -1388,7 +1393,7 @@ namespace YOSYS_PYTHON { virtual void py_notify_connect_tuple(Module *module, boost::python::tuple sigsig){}; virtual void py_notify_connect_list(Module* module, boost::python::list sigsig_list){}; virtual void py_notify_blackout(Module*){}; - }; + }; struct MonitorWrap : Monitor, boost::python::wrapper { @@ -1471,6 +1476,59 @@ namespace YOSYS_PYTHON { } }; + struct PyPass : public Yosys::Pass + { + PyPass(std::string name, std::string short_help) : Yosys::Pass(name, short_help) { } + + virtual void execute(vector args, Yosys::RTLIL::Design* d) YS_OVERRIDE + { + boost::python::list py_args; + for(auto arg : args) + py_args.append(arg); + py_execute(py_args, new Design(d)); + } + + virtual void help() YS_OVERRIDE + { + py_help(); + } + + virtual void py_execute(boost::python::list args, Design* d){} + virtual void py_help(){} + }; + + struct PassWrap : PyPass, boost::python::wrapper + { + + PassWrap(std::string name, std::string short_help) : PyPass(name, short_help) { } + + void py_execute(boost::python::list args, Design* d) + { + if(boost::python::override py_execute = this->get_override("py_execute")) + py_execute(args, d); + else + PyPass::py_execute(args, d); + } + + void default_py_execute(boost::python::list args, Design* d) + { + this->PyPass::py_execute(args, d); + } + + void py_help() + { + if(boost::python::override py_help = this->get_override("py_help")) + py_help(); + else + PyPass::py_help(); + } + + void default_py_help() + { + this->PyPass::py_help(); + } + }; + void Module::register_monitor(Monitor* const m) { Yosys::RTLIL::Module* cpp_module = this->get_cpp_obj(); @@ -2778,6 +2836,11 @@ namespace YOSYS_PYTHON { .def("py_notify_blackout", &Monitor::py_notify_blackout, &MonitorWrap::default_py_notify_blackout) ; + class_("Pass", init()) + .def("py_execute", &PyPass::py_execute, &PassWrap::default_py_execute) + .def("py_help", &PyPass::py_help, &PassWrap::default_py_help) + ; + class_("Initializer"); scope().attr("_hidden") = new Initializer(); @@ -3099,6 +3162,7 @@ namespace YOSYS_PYTHON { def("const_neg", const_neg); def("run",run); + def("log",log); } diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 750a154e6..8e16ba01d 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -469,21 +469,40 @@ int GetSize(RTLIL::Wire *wire) return wire->width; } +bool already_setup = false; + void yosys_setup() { + if(already_setup) + return; + already_setup = true; // if there are already IdString objects then we have a global initialization order bug IdString empty_id; log_assert(empty_id.index_ == 0); IdString::get_reference(empty_id.index_); + #ifdef WITH_PYTHON + Py_Initialize(); + PyRun_SimpleString("import sys"); + PyRun_SimpleString("sys.path.append(\"./\")"); + //PyRun_SimpleString("import libyosys"); + //PyRun_SimpleString("sys.path.append(\"./plugins\")"); + //PyRun_SimpleString(("sys.path.append(\""+proc_share_dirname()+"plugins\")").c_str()); + #endif + Pass::init_register(); yosys_design = new RTLIL::Design; yosys_celltypes.setup(); log_push(); } +bool already_shutdown = false; + void yosys_shutdown() { + if(already_shutdown) + return; + already_shutdown = true; log_pop(); delete yosys_design; @@ -511,9 +530,16 @@ void yosys_shutdown() dlclose(it.second); loaded_plugins.clear(); +#ifdef WITH_PYTHON + loaded_python_plugins.clear(); +#endif loaded_plugin_aliases.clear(); #endif +#ifdef WITH_PYTHON + Py_Finalize(); +#endif + IdString empty_id; IdString::put_reference(empty_id.index_); } diff --git a/kernel/yosys.h b/kernel/yosys.h index 14cbcd610..4380a5b69 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -66,6 +66,8 @@ #include #include +#include + #ifndef _YOSYS_ # error It looks like you are trying to build Yosys without the config defines set. \ When building Yosys with a custom make system, make sure you set all the \ @@ -317,6 +319,9 @@ extern std::vector pushed_designs; // from passes/cmds/pluginc.cc extern std::map loaded_plugins; +#ifdef WITH_PYTHON +extern std::map loaded_python_plugins; +#endif extern std::map loaded_plugin_aliases; void load_plugin(std::string filename, std::vector aliases); diff --git a/passes/cmds/plugin.cc b/passes/cmds/plugin.cc index 828c671de..b5d22a84a 100644 --- a/passes/cmds/plugin.cc +++ b/passes/cmds/plugin.cc @@ -23,9 +23,17 @@ # include #endif +#ifdef WITH_PYTHON +# include +# include +#endif + YOSYS_NAMESPACE_BEGIN std::map loaded_plugins; +#ifdef WITH_PYTHON +std::map loaded_python_plugins; +#endif std::map loaded_plugin_aliases; #ifdef YOSYS_ENABLE_PLUGINS @@ -37,6 +45,48 @@ void load_plugin(std::string filename, std::vector aliases) filename = "./" + filename; if (!loaded_plugins.count(filename)) { + + #ifdef WITH_PYTHON + if(boost::algorithm::ends_with(filename, ".py")) + { + int last_slash = filename.find('/'); + filename = filename.substr(last_slash+1, filename.size()); + filename = filename.substr(0,filename.size()-3); + PyObject *filename_p = PyUnicode_FromString(filename.c_str());//filename.c_str()); + if(filename_p == NULL) + { + log_cmd_error("Issues converting `%s' to Python\n", filename.c_str()); + return; + } + PyObject *module_p = PyImport_Import(filename_p); + if(module_p == NULL) + { + log_cmd_error("Can't load python module `%s'\n", filename.c_str()); + return; + }/* + PyObject *dict_p = PyModule_GetDict(module_p); + if(dict_p == NULL) + { + log_cmd_error("Can't load dictionary from module `%s'\n", filename.c_str()); + return; + } + PyObject *func_p = PyDict_GetItemString(dict_p, "test"); + if(module_p == NULL) + { + log_cmd_error("Module `%s' does not contain test function\n", filename.c_str()); + return; + } + PyObject *args_p = PyTuple_New(0); + PyObject *result_p = PyObject_CallObject(func_p, args_p); + if(result_p == NULL) + printf("Calling test failed\n"); + printf("Loaded Python module\n"); + */ + loaded_python_plugins[orig_filename] = module_p; + Pass::init_register(); + } else { + #endif + void *hdl = dlopen(filename.c_str(), RTLD_LAZY|RTLD_LOCAL); if (hdl == NULL && orig_filename.find('/') == std::string::npos) hdl = dlopen((proc_share_dirname() + "plugins/" + orig_filename + ".so").c_str(), RTLD_LAZY|RTLD_LOCAL); @@ -44,6 +94,10 @@ void load_plugin(std::string filename, std::vector aliases) log_cmd_error("Can't load module `%s': %s\n", filename.c_str(), dlerror()); loaded_plugins[orig_filename] = hdl; Pass::init_register(); + + #ifdef WITH_PYTHON + } + #endif } for (auto &alias : aliases) @@ -107,7 +161,11 @@ struct PluginPass : public Pass { if (list_mode) { log("\n"); +#ifdef WITH_PYTHON + if (loaded_plugins.empty() and loaded_python_plugins.empty()) +#else if (loaded_plugins.empty()) +#endif log("No plugins loaded.\n"); else log("Loaded plugins:\n"); @@ -115,6 +173,11 @@ struct PluginPass : public Pass { for (auto &it : loaded_plugins) log(" %s\n", it.first.c_str()); +#ifdef WITH_PYTHON + for (auto &it : loaded_python_plugins) + log(" %s\n", it.first.c_str()); +#endif + if (!loaded_plugin_aliases.empty()) { log("\n"); int max_alias_len = 1; -- 2.30.2