mirror of
https://github.com/YosysHQ/yosys
synced 2025-10-08 17:01:57 +00:00
- 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
137 lines
4.3 KiB
Python
137 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
|
# Copyright (C) 2024 Efabless Corporation
|
|
#
|
|
# Permission to use, copy, modify, and/or distribute this software for any
|
|
# purpose with or without fee is hereby granted, provided that the above
|
|
# copyright notice and this permission notice appear in all copies.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
import os
|
|
import re
|
|
import shlex
|
|
import shutil
|
|
from pathlib import Path
|
|
from setuptools import setup, Extension
|
|
|
|
import pybind11
|
|
from pybind11.setup_helpers import build_ext
|
|
|
|
__yosys_root__ = Path(__file__).parent
|
|
|
|
yosys_version_rx = re.compile(r"YOSYS_VER\s*:=\s*([\w\-\+\.]+)")
|
|
|
|
with open(__yosys_root__ / "Makefile", encoding="utf8") as f:
|
|
# Extract and convert + to patch version
|
|
version = yosys_version_rx.search(f.read())[1].replace("+", ".")
|
|
|
|
|
|
class libyosys_so_ext(Extension):
|
|
def __init__(
|
|
self,
|
|
) -> None:
|
|
super().__init__(
|
|
"libyosys.so",
|
|
[],
|
|
)
|
|
|
|
# when iterating locally, you probably want to set this variable
|
|
# to avoid mass rebuilds bec of pybind11's include path changing
|
|
pybind_include = os.getenv("_FORCE_PYBIND_INCLUDE", pybind11.get_include())
|
|
|
|
self.args = [
|
|
f"PYBIND11_INCLUDE={pybind_include}",
|
|
"ENABLE_PYOSYS=1",
|
|
# Would need to be installed separately by the user
|
|
"ENABLE_TCL=0",
|
|
"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):
|
|
make_flags_split = shlex.split(os.getenv("makeFlags", ""))
|
|
# abc linking takes a lot of memory, best get it out of the way first
|
|
bext.spawn(
|
|
[
|
|
"make",
|
|
f"-j{os.cpu_count() or 1}",
|
|
"yosys-abc",
|
|
*make_flags_split,
|
|
*self.args,
|
|
]
|
|
)
|
|
# build libyosys and share with abc out of the way
|
|
bext.spawn(
|
|
[
|
|
"make",
|
|
f"-j{os.cpu_count() or 1}",
|
|
self.name,
|
|
"share",
|
|
*make_flags_split,
|
|
*self.args,
|
|
]
|
|
)
|
|
ext_fullpath = Path(bext.get_ext_fullpath(self.name))
|
|
build_path = ext_fullpath.parents[1]
|
|
pyosys_path = build_path / "pyosys"
|
|
os.makedirs(pyosys_path, exist_ok=True)
|
|
|
|
# libyosys.so
|
|
target = pyosys_path / self.name
|
|
shutil.copy(self.name, target)
|
|
bext.spawn(["strip", "-S", str(target)])
|
|
|
|
# yosys-abc
|
|
yosys_abc_target = pyosys_path / "yosys-abc"
|
|
shutil.copy("yosys-abc", yosys_abc_target)
|
|
bext.spawn(["strip", "-S", str(yosys_abc_target)])
|
|
|
|
# share directory
|
|
share_target = pyosys_path / "share"
|
|
try:
|
|
shutil.rmtree(share_target)
|
|
except FileNotFoundError:
|
|
pass
|
|
|
|
shutil.copytree("share", share_target)
|
|
|
|
|
|
class custom_build_ext(build_ext):
|
|
def build_extension(self, ext) -> None:
|
|
if not hasattr(ext, "custom_build"):
|
|
return super().build_extension(ext)
|
|
return ext.custom_build(self)
|
|
|
|
|
|
with open(__yosys_root__ / "README.md", encoding="utf8") as f:
|
|
long_description = f.read()
|
|
|
|
setup(
|
|
name="pyosys",
|
|
packages=["pyosys"],
|
|
version=version,
|
|
description="Python access to libyosys",
|
|
long_description=long_description,
|
|
long_description_content_type="text/markdown",
|
|
license="MIT",
|
|
classifiers=[
|
|
"Programming Language :: Python :: 3",
|
|
"Intended Audience :: Developers",
|
|
"Operating System :: POSIX :: Linux",
|
|
"Operating System :: MacOS :: MacOS X",
|
|
],
|
|
python_requires=">=3.8",
|
|
ext_modules=[libyosys_so_ext()],
|
|
cmdclass={
|
|
"build_ext": custom_build_ext,
|
|
},
|
|
)
|