mirror of https://github.com/YosysHQ/yosys.git
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
This commit is contained in:
parent
bf7b73acfc
commit
d79a2808cf
2
Makefile
2
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
|
||||
|
|
|
@ -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;
|
||||
|
@ -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<string> 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<PyPass>
|
||||
{
|
||||
|
||||
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_<PassWrap, boost::noncopyable>("Pass", init<std::string, std::string>())
|
||||
.def("py_execute", &PyPass::py_execute, &PassWrap::default_py_execute)
|
||||
.def("py_help", &PyPass::py_help, &PassWrap::default_py_help)
|
||||
;
|
||||
|
||||
class_<Initializer>("Initializer");
|
||||
scope().attr("_hidden") = new Initializer();
|
||||
|
||||
|
@ -3099,6 +3162,7 @@ namespace YOSYS_PYTHON {
|
|||
def("const_neg", const_neg);
|
||||
|
||||
def("run",run);
|
||||
def("log",log);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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_);
|
||||
}
|
||||
|
|
|
@ -66,6 +66,8 @@
|
|||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#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<RTLIL::Design*> pushed_designs;
|
|||
|
||||
// from passes/cmds/pluginc.cc
|
||||
extern std::map<std::string, void*> loaded_plugins;
|
||||
#ifdef WITH_PYTHON
|
||||
extern std::map<std::string, void*> loaded_python_plugins;
|
||||
#endif
|
||||
extern std::map<std::string, std::string> loaded_plugin_aliases;
|
||||
void load_plugin(std::string filename, std::vector<std::string> aliases);
|
||||
|
||||
|
|
|
@ -23,9 +23,17 @@
|
|||
# include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
# include <boost/algorithm/string/predicate.hpp>
|
||||
# include <Python.h>
|
||||
#endif
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
std::map<std::string, void*> loaded_plugins;
|
||||
#ifdef WITH_PYTHON
|
||||
std::map<std::string, void*> loaded_python_plugins;
|
||||
#endif
|
||||
std::map<std::string, std::string> loaded_plugin_aliases;
|
||||
|
||||
#ifdef YOSYS_ENABLE_PLUGINS
|
||||
|
@ -37,6 +45,48 @@ void load_plugin(std::string filename, std::vector<std::string> 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<std::string> 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;
|
||||
|
|
Loading…
Reference in New Issue