diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index d59f8e1ec..d66239a16 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -110,7 +110,7 @@ jobs: MACOSX_DEPLOYMENT_TARGET=11 makeFlags='BOOST_PYTHON_LIB=./boost/pfx/lib/libboost_python*.a CONFIG=clang' CIBW_BEFORE_BUILD: bash ./.github/workflows/wheels/cibw_before_build.sh - CIBW_TEST_COMMAND: python3 -c "from pyosys import libyosys as ys;d=ys.Design();ys.run_pass('help', d)" + CIBW_TEST_COMMAND: python3 {project}/tests/arch/ecp5/add_sub.py - uses: actions/upload-artifact@v4 with: name: python-wheels-${{ matrix.os.runner }} diff --git a/Makefile b/Makefile index f81e1fea2..0be664b9a 100644 --- a/Makefile +++ b/Makefile @@ -737,6 +737,12 @@ compile-only: $(OBJS) $(GENFILES) $(EXTRA_TARGETS) @echo " Compile successful." @echo "" +.PHONY: share +share: $(EXTRA_TARGETS) + @echo "" + @echo " Share directory created." + @echo "" + $(PROGRAM_PREFIX)yosys$(EXE): $(OBJS) $(P) $(CXX) -o $(PROGRAM_PREFIX)yosys$(EXE) $(EXE_LINKFLAGS) $(LINKFLAGS) $(OBJS) $(LIBS) $(LIBS_VERIFIC) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 510151479..374b07d06 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -554,17 +554,17 @@ void yosys_setup() #include "kernel/constids.inc" #undef X - #ifdef WITH_PYTHON - // With Python 3.12, calling PyImport_AppendInittab on an already - // initialized platform fails (such as when libyosys is imported - // from a Python interpreter) - if (!Py_IsInitialized()) { - PyImport_AppendInittab((char*)"libyosys", INIT_MODULE); - Py_Initialize(); - PyRun_SimpleString("import sys"); - signal(SIGINT, SIG_DFL); - } - #endif +#ifdef WITH_PYTHON + // With Python 3.12, calling PyImport_AppendInittab on an already + // initialized platform fails (such as when libyosys is imported + // from a Python interpreter) + if (!Py_IsInitialized()) { + PyImport_AppendInittab((char*)"libyosys", INIT_MODULE); + Py_Initialize(); + PyRun_SimpleString("import sys"); + signal(SIGINT, SIG_DFL); + } +#endif Pass::init_register(); yosys_design = new RTLIL::Design; @@ -1013,6 +1013,16 @@ void init_share_dirname() #else void init_share_dirname() { +# ifdef WITH_PYTHON + PyObject *sys_obj = PyImport_ImportModule("sys"); + + if (PyObject_HasAttrString(sys_obj, "_pyosys_share_dirname")) { + PyObject *share_path_obj = PyObject_GetAttrString(sys_obj, "_pyosys_share_dirname"); + const char *share_path = PyUnicode_AsUTF8(share_path_obj); + yosys_share_dirname = std::string(share_path); + return; + } +# endif std::string proc_self_path = proc_self_dirname(); # if defined(_WIN32) && !defined(YOSYS_WIN32_UNIX_DIR) std::string proc_share_path = proc_self_path + "share\\"; @@ -1058,12 +1068,20 @@ void init_abc_executable_name() } #else yosys_abc_executable = proc_self_dirname() + proc_program_prefix()+ "yosys-abc"; -#endif -#ifdef _WIN32 -#ifndef ABCEXTERNAL +# ifdef _WIN32 if (!check_file_exists(yosys_abc_executable + ".exe") && check_file_exists(proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc.exe")) yosys_abc_executable = proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc"; -#endif +# endif + +# ifdef WITH_PYTHON + PyObject *sys_obj = PyImport_ImportModule("sys"); + + if (PyObject_HasAttrString(sys_obj, "_pyosys_abc")) { + PyObject *abc_path_obj = PyObject_GetAttrString(sys_obj, "_pyosys_abc"); + const char *abc_path = PyUnicode_AsUTF8(abc_path_obj); + yosys_abc_executable = std::string(abc_path); + } +# endif #endif } @@ -1132,7 +1150,7 @@ bool run_frontend(std::string filename, std::string command, RTLIL::Design *desi if (command == "auto") { std::string filename_trim = filename; - + auto has_extension = [](const std::string& filename, const std::string& extension) { if (filename.size() >= extension.size()) { return filename.compare(filename.size() - extension.size(), extension.size(), extension) == 0; @@ -1143,7 +1161,7 @@ bool run_frontend(std::string filename, std::string command, RTLIL::Design *desi if (has_extension(filename_trim, ".gz")) { filename_trim.erase(filename_trim.size() - 3); } - + if (has_extension(filename_trim, ".v")) { command = " -vlog2k"; } else if (has_extension(filename_trim, ".sv")) { diff --git a/misc/__init__.py b/misc/__init__.py index 330fd6d86..d74e3f5bd 100644 --- a/misc/__init__.py +++ b/misc/__init__.py @@ -1,5 +1,19 @@ import os import sys + sys.setdlopenflags(os.RTLD_NOW | os.RTLD_GLOBAL) +__dir__ = os.path.abspath(os.path.dirname(__file__)) +sys._pyosys_dir = os.path.abspath(__dir__) + +bin_ext = ".exe" if os.name == "nt" else "" + +_share_candidate = os.path.join(__dir__, "share") +if os.path.isdir(_share_candidate): + sys._pyosys_share_dirname = _share_candidate + os.path.sep + +_abc_candidate = os.path.join(__dir__, f"yosys-abc{bin_ext}") +if os.path.isfile(_abc_candidate): + sys._pyosys_abc = _abc_candidate + __all__ = ["libyosys"] diff --git a/setup.py b/setup.py index 221965971..b3a6a9280 100644 --- a/setup.py +++ b/setup.py @@ -44,26 +44,50 @@ class libyosys_so_ext(Extension): "ENABLE_PYTHON_CONFIG_EMBED=0", # Would need to be installed separately by the user "ENABLE_TCL=0", - # Would need to be installed separately by the user "ENABLE_READLINE=0", + "ENABLE_EDITLINE=0", + # Always compile and include ABC in wheel + "ABCEXTERNAL=", # Show compile commands "PRETTY=0", ] def custom_build(self, bext: build_ext): bext.spawn( - ["make", f"-j{os.cpu_count() or 1}", self.name] + [ + "make", + f"-j{os.cpu_count() or 1}", + self.name, + "yosys-abc", + "share", + ] + shlex.split(os.getenv("makeFlags", "")) + self.args ) build_path = os.path.dirname(os.path.dirname(bext.get_ext_fullpath(self.name))) pyosys_path = os.path.join(build_path, "pyosys") - target = os.path.join(pyosys_path, os.path.basename(self.name)) os.makedirs(pyosys_path, exist_ok=True) - shutil.copyfile(self.name, target) + + # libyosys.so + target = os.path.join(pyosys_path, os.path.basename(self.name)) + shutil.copy(self.name, target) + bext.spawn(["strip", "-S", target]) + + # yosys-abc + yosys_abc_target = os.path.join(pyosys_path, "yosys-abc") + shutil.copy("yosys-abc", yosys_abc_target) + bext.spawn(["strip", "-S", "yosys-abc"]) + + # share directory + share_target = os.path.join(pyosys_path, "share") + try: + shutil.rmtree(share_target) + except FileNotFoundError: + pass + + shutil.copytree("share", share_target) # I don't know how debug info is getting here. - bext.spawn(["strip", "-S", target]) class custom_build_ext(build_ext): diff --git a/tests/arch/ecp5/add_sub.py b/tests/arch/ecp5/add_sub.py new file mode 100644 index 000000000..0232ac1db --- /dev/null +++ b/tests/arch/ecp5/add_sub.py @@ -0,0 +1,20 @@ +import os +from pyosys import libyosys as ys + +__dir__ = os.path.dirname(os.path.abspath(__file__)) +add_sub = os.path.join(__dir__, "..", "common", "add_sub.v") + +base = ys.Design() +ys.run_pass(f"read_verilog {add_sub}", base) +ys.run_pass("hierarchy -top top", base) +ys.run_pass("proc", base) +ys.run_pass("equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5", base) + +postopt = ys.Design() +ys.run_pass("design -load postopt", postopt) +ys.run_pass("cd top", postopt) +ys.run_pass("select -assert-min 25 t:LUT4", postopt) +ys.run_pass("select -assert-max 26 t:LUT4", postopt) +ys.run_pass("select -assert-count 10 t:PFUMX", postopt) +ys.run_pass("select -assert-count 6 t:L6MUX21", postopt) +ys.run_pass("select -assert-none t:LUT4 t:PFUMX t:L6MUX21 %% t:* %D", postopt)