3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-10-09 17:31:59 +00:00

pyosys: rewrite using pybind11

- Rewrite all Python features to use the pybind11 library instead of boost::python.
  Unlike boost::python, pybind11 is a header-only library that is just included by Pyosys code, saving a lot of compile time on wheels.
- Factor out as much "translation" code from the generator into proper C++ files
- Fix running the embedded interpreter not supporting "from pyosys import libyosys as ys" like wheels
- Move Python-related elements to `pyosys` directory at the root of the repo
- Slight shift in bridging semantics:
  - Containers are declared as "opaque types" and are passed by reference to Python - many methods have been implemented to make them feel right at home without the overhead/ambiguity of copying to Python and then copying back after mutation
  - Monitor/Pass use "trampoline" pattern to support virual methods overridable in Python: virtual methods no longer require `py_` prefix
- Create really short test set for pyosys that just exercises basic functionality
This commit is contained in:
Mohamed Gaber 2025-09-21 22:36:27 +03:00
parent f7120e9c2a
commit 88be728353
No known key found for this signature in database
27 changed files with 2879 additions and 2674 deletions

View file

@ -24,12 +24,6 @@
# include <dlfcn.h>
#endif
#ifdef WITH_PYTHON
# include <boost/algorithm/string/predicate.hpp>
# include <Python.h>
# include <boost/filesystem.hpp>
#endif
YOSYS_NAMESPACE_BEGIN
std::map<std::string, void*> loaded_plugins;
@ -57,23 +51,23 @@ void load_plugin(std::string filename, std::vector<std::string> aliases)
if (!is_loaded) {
// Check if we're loading a python script
if(filename.find(".py") != std::string::npos)
{
if (filename.rfind(".py") != std::string::npos) {
#ifdef WITH_PYTHON
boost::filesystem::path full_path(filename);
std::string path(full_path.parent_path().c_str());
filename = full_path.filename().c_str();
filename = filename.substr(0,filename.size()-3);
PyRun_SimpleString(("sys.path.insert(0,\""+path+"\")").c_str());
PyErr_Print();
PyObject *module_p = PyImport_ImportModule(filename.c_str());
if(module_p == NULL)
{
PyErr_Print();
log_cmd_error("Can't load python module `%s'\n", full_path.filename());
py::object Path = py::module_::import("pathlib").attr("Path");
py::object full_path = Path(py::cast(filename));
py::object plugin_python_path = full_path.attr("parent");
auto basename = py::cast<std::string>(full_path.attr("stem"));
py::object sys = py::module_::import("sys");
sys.attr("path").attr("insert")(0, py::str(plugin_python_path));
try {
auto module_container = py::module_::import(basename.c_str());
loaded_python_plugins[orig_filename] = module_container.ptr();
} catch (py::error_already_set &e) {
log_cmd_error("Can't load python module `%s': %s\n", basename, e.what());
return;
}
loaded_python_plugins[orig_filename] = module_p;
Pass::init_register();
#else
log_error(