+++ /dev/null
-import os
-import shutil
-
-
-__all__ = ["ToolNotFound", "tool_env_var", "has_tool", "require_tool"]
-
-
-class ToolNotFound(Exception):
- pass
-
-
-def tool_env_var(name):
- return name.upper().replace("-", "_")
-
-
-def _get_tool(name):
- return os.environ.get(tool_env_var(name), name)
-
-
-def has_tool(name):
- return shutil.which(_get_tool(name)) is not None
-
-
-def require_tool(name):
- env_var = tool_env_var(name)
- path = _get_tool(name)
- if shutil.which(path) is None:
- if env_var in os.environ:
- raise ToolNotFound("Could not find required tool {} in {} as "
- "specified via the {} environment variable".
- format(name, path, env_var))
- else:
- raise ToolNotFound("Could not find required tool {} in PATH. Place "
- "it directly in PATH or specify path explicitly "
- "via the {} environment variable".
- format(name, env_var))
- return path
--- /dev/null
+import os
+import shutil
+
+
+__all__ = ["ToolNotFound", "tool_env_var", "has_tool", "require_tool"]
+
+
+class ToolNotFound(Exception):
+ pass
+
+
+def tool_env_var(name):
+ return name.upper().replace("-", "_")
+
+
+def _get_tool(name):
+ return os.environ.get(tool_env_var(name), name)
+
+
+def has_tool(name):
+ return shutil.which(_get_tool(name)) is not None
+
+
+def require_tool(name):
+ env_var = tool_env_var(name)
+ path = _get_tool(name)
+ if shutil.which(path) is None:
+ if env_var in os.environ:
+ raise ToolNotFound("Could not find required tool {} in {} as "
+ "specified via the {} environment variable".
+ format(name, path, env_var))
+ else:
+ raise ToolNotFound("Could not find required tool {} in PATH. Place "
+ "it directly in PATH or specify path explicitly "
+ "via the {} environment variable".
+ format(name, env_var))
+ return path
--- /dev/null
+import os
+import sys
+import re
+import subprocess
+import warnings
+import pathlib
+try:
+ from importlib import metadata as importlib_metadata # py3.8+ stdlib
+except ImportError:
+ try:
+ import importlib_metadata # py3.7- shim
+ except ImportError:
+ importlib_metadata = None # not installed
+try:
+ try:
+ from importlib import resources as importlib_resources
+ try:
+ importlib_resources.files # py3.9+ stdlib
+ except AttributeError:
+ import importlib_resources # py3.8- shim
+ except ImportError:
+ import importlib_resources # py3.6- shim
+except ImportError:
+ importlib_resources = None
+
+from . import has_tool, require_tool
+
+
+__all__ = ["YosysError", "YosysBinary", "find_yosys"]
+
+
+class YosysError(Exception):
+ pass
+
+
+class YosysWarning(Warning):
+ pass
+
+
+class YosysBinary:
+ @classmethod
+ def available(cls):
+ """Check for Yosys availability.
+
+ Returns
+ -------
+ available : bool
+ ``True`` if Yosys is installed, ``False`` otherwise. Installed binary may still not
+ be runnable, or might be too old to be useful.
+ """
+ raise NotImplementedError
+
+ @classmethod
+ def version(cls):
+ """Get Yosys version.
+
+ Returns
+ -------
+ ``None`` if version number could not be determined, or a 3-tuple ``(major, minor, distance)`` if it could.
+
+ major : int
+ Major version.
+ minor : int
+ Minor version.
+ distance : int
+ Distance to last tag per ``git describe``. May not be exact for system Yosys.
+ """
+ raise NotImplementedError
+
+ @classmethod
+ def data_dir(cls):
+ """Get Yosys data directory.
+
+ Returns
+ -------
+ data_dir : pathlib.Path
+ Yosys data directory (also known as "datdir").
+ """
+ raise NotImplementedError
+
+ @classmethod
+ def run(cls, args, stdin=""):
+ """Run Yosys process.
+
+ Parameters
+ ----------
+ args : list of str
+ Arguments, not including the program name.
+ stdin : str
+ Standard input.
+
+ Returns
+ -------
+ stdout : str
+ Standard output.
+
+ Exceptions
+ ----------
+ YosysError
+ Raised if Yosys returns a non-zero code. The exception message is the standard error
+ output.
+ """
+ raise NotImplementedError
+
+ @classmethod
+ def _process_result(cls, returncode, stdout, stderr, ignore_warnings, src_loc_at):
+ if returncode:
+ raise YosysError(stderr.strip())
+ if not ignore_warnings:
+ for match in re.finditer(r"(?ms:^Warning: (.+)\n$)", stderr):
+ message = match.group(1).replace("\n", " ")
+ warnings.warn(message, YosysWarning, stacklevel=3 + src_loc_at)
+ return stdout
+
+
+class _BuiltinYosys(YosysBinary):
+ YOSYS_PACKAGE = "nmigen_yosys"
+
+ @classmethod
+ def available(cls):
+ if importlib_metadata is None or importlib_resources is None:
+ return False
+ try:
+ importlib_metadata.version(cls.YOSYS_PACKAGE)
+ return True
+ except importlib_metadata.PackageNotFoundError:
+ return False
+
+ @classmethod
+ def version(cls):
+ version = importlib_metadata.version(cls.YOSYS_PACKAGE)
+ match = re.match(r"^(\d+)\.(\d+)(?:\.post(\d+))?", version)
+ return (int(match[1]), int(match[2]), int(match[3] or 0))
+
+ @classmethod
+ def data_dir(cls):
+ return importlib_resources.files(cls.YOSYS_PACKAGE) / "share"
+
+ @classmethod
+ def run(cls, args, stdin="", *, ignore_warnings=False, src_loc_at=0):
+ popen = subprocess.Popen([sys.executable, "-m", cls.YOSYS_PACKAGE, *args],
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ encoding="utf-8")
+ stdout, stderr = popen.communicate(stdin)
+ return cls._process_result(popen.returncode, stdout, stderr, ignore_warnings, src_loc_at)
+
+
+class _SystemYosys(YosysBinary):
+ YOSYS_BINARY = "yosys"
+
+ @classmethod
+ def available(cls):
+ return has_tool(cls.YOSYS_BINARY)
+
+ @classmethod
+ def version(cls):
+ version = cls.run(["-V"])
+ match = re.match(r"^Yosys (\d+)\.(\d+)(?:\+(\d+))?", version)
+ if match:
+ return (int(match[1]), int(match[2]), int(match[3] or 0))
+ else:
+ return None
+
+ @classmethod
+ def data_dir(cls):
+ popen = subprocess.Popen([require_tool(cls.YOSYS_BINARY) + "-config", "--datdir"],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ encoding="utf-8")
+ stdout, stderr = popen.communicate()
+ if popen.returncode:
+ raise YosysError(stderr.strip())
+ return pathlib.Path(stdout.strip())
+
+ @classmethod
+ def run(cls, args, stdin="", *, ignore_warnings=False, src_loc_at=0):
+ popen = subprocess.Popen([require_tool(cls.YOSYS_BINARY), *args],
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ encoding="utf-8")
+ stdout, stderr = popen.communicate(stdin)
+ # If Yosys is built with an evaluation version of Verific, then Verific license
+ # information is printed first. It consists of empty lines and lines starting with `--`,
+ # which are not normally a part of Yosys output, and can be fairly safely removed.
+ #
+ # This is not ideal, but Verific license conditions rule out any other solution.
+ stdout = re.sub(r"\A(-- .+\n|\n)*", "", stdout)
+ return cls._process_result(popen.returncode, stdout, stderr, ignore_warnings, src_loc_at)
+
+
+def find_yosys(requirement):
+ """Find an available Yosys executable of required version.
+
+ Parameters
+ ----------
+ requirement : function
+ Version check. Should return ``True`` if the version is acceptable, ``False`` otherwise.
+
+ Returns
+ -------
+ yosys_binary : subclass of YosysBinary
+ Proxy for running the requested version of Yosys.
+
+ Exceptions
+ ----------
+ YosysError
+ Raised if required Yosys version is not found.
+ """
+ proxies = []
+ clauses = os.environ.get("NMIGEN_USE_YOSYS", "system,builtin").split(",")
+ for clause in clauses:
+ if clause == "builtin":
+ proxies.append(_BuiltinYosys)
+ elif clause == "system":
+ proxies.append(_SystemYosys)
+ else:
+ raise YosysError("The NMIGEN_USE_YOSYS environment variable contains "
+ "an unrecognized clause {!r}"
+ .format(clause))
+ for proxy in proxies:
+ if proxy.available():
+ version = proxy.version()
+ if version is not None and requirement(version):
+ return proxy
+ else:
+ if "NMIGEN_USE_YOSYS" in os.environ:
+ raise YosysError("Could not find an acceptable Yosys binary. Searched: {}"
+ .format(", ".join(clauses)))
+ else:
+ raise YosysError("Could not find an acceptable Yosys binary. The `nmigen-yosys` PyPI "
+ "package, if available for this platform, can be used as fallback")
+++ /dev/null
-import os
-import sys
-import re
-import subprocess
-import warnings
-import pathlib
-try:
- from importlib import metadata as importlib_metadata # py3.8+ stdlib
-except ImportError:
- try:
- import importlib_metadata # py3.7- shim
- except ImportError:
- importlib_metadata = None # not installed
-try:
- try:
- from importlib import resources as importlib_resources
- try:
- importlib_resources.files # py3.9+ stdlib
- except AttributeError:
- import importlib_resources # py3.8- shim
- except ImportError:
- import importlib_resources # py3.6- shim
-except ImportError:
- importlib_resources = None
-
-from ._toolchain import has_tool, require_tool
-
-
-__all__ = ["YosysError", "YosysBinary", "find_yosys"]
-
-
-class YosysError(Exception):
- pass
-
-
-class YosysWarning(Warning):
- pass
-
-
-class YosysBinary:
- @classmethod
- def available(cls):
- """Check for Yosys availability.
-
- Returns
- -------
- available : bool
- ``True`` if Yosys is installed, ``False`` otherwise. Installed binary may still not
- be runnable, or might be too old to be useful.
- """
- raise NotImplementedError
-
- @classmethod
- def version(cls):
- """Get Yosys version.
-
- Returns
- -------
- ``None`` if version number could not be determined, or a 3-tuple ``(major, minor, distance)`` if it could.
-
- major : int
- Major version.
- minor : int
- Minor version.
- distance : int
- Distance to last tag per ``git describe``. May not be exact for system Yosys.
- """
- raise NotImplementedError
-
- @classmethod
- def data_dir(cls):
- """Get Yosys data directory.
-
- Returns
- -------
- data_dir : pathlib.Path
- Yosys data directory (also known as "datdir").
- """
- raise NotImplementedError
-
- @classmethod
- def run(cls, args, stdin=""):
- """Run Yosys process.
-
- Parameters
- ----------
- args : list of str
- Arguments, not including the program name.
- stdin : str
- Standard input.
-
- Returns
- -------
- stdout : str
- Standard output.
-
- Exceptions
- ----------
- YosysError
- Raised if Yosys returns a non-zero code. The exception message is the standard error
- output.
- """
- raise NotImplementedError
-
- @classmethod
- def _process_result(cls, returncode, stdout, stderr, ignore_warnings, src_loc_at):
- if returncode:
- raise YosysError(stderr.strip())
- if not ignore_warnings:
- for match in re.finditer(r"(?ms:^Warning: (.+)\n$)", stderr):
- message = match.group(1).replace("\n", " ")
- warnings.warn(message, YosysWarning, stacklevel=3 + src_loc_at)
- return stdout
-
-
-class _BuiltinYosys(YosysBinary):
- YOSYS_PACKAGE = "nmigen_yosys"
-
- @classmethod
- def available(cls):
- if importlib_metadata is None or importlib_resources is None:
- return False
- try:
- importlib_metadata.version(cls.YOSYS_PACKAGE)
- return True
- except importlib_metadata.PackageNotFoundError:
- return False
-
- @classmethod
- def version(cls):
- version = importlib_metadata.version(cls.YOSYS_PACKAGE)
- match = re.match(r"^(\d+)\.(\d+)(?:\.post(\d+))?", version)
- return (int(match[1]), int(match[2]), int(match[3] or 0))
-
- @classmethod
- def data_dir(cls):
- return importlib_resources.files(cls.YOSYS_PACKAGE) / "share"
-
- @classmethod
- def run(cls, args, stdin="", *, ignore_warnings=False, src_loc_at=0):
- popen = subprocess.Popen([sys.executable, "-m", cls.YOSYS_PACKAGE, *args],
- stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- encoding="utf-8")
- stdout, stderr = popen.communicate(stdin)
- return cls._process_result(popen.returncode, stdout, stderr, ignore_warnings, src_loc_at)
-
-
-class _SystemYosys(YosysBinary):
- YOSYS_BINARY = "yosys"
-
- @classmethod
- def available(cls):
- return has_tool(cls.YOSYS_BINARY)
-
- @classmethod
- def version(cls):
- version = cls.run(["-V"])
- match = re.match(r"^Yosys (\d+)\.(\d+)(?:\+(\d+))?", version)
- if match:
- return (int(match[1]), int(match[2]), int(match[3] or 0))
- else:
- return None
-
- @classmethod
- def data_dir(cls):
- popen = subprocess.Popen([require_tool(cls.YOSYS_BINARY) + "-config", "--datdir"],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- encoding="utf-8")
- stdout, stderr = popen.communicate()
- if popen.returncode:
- raise YosysError(stderr.strip())
- return pathlib.Path(stdout.strip())
-
- @classmethod
- def run(cls, args, stdin="", *, ignore_warnings=False, src_loc_at=0):
- popen = subprocess.Popen([require_tool(cls.YOSYS_BINARY), *args],
- stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- encoding="utf-8")
- stdout, stderr = popen.communicate(stdin)
- # If Yosys is built with an evaluation version of Verific, then Verific license
- # information is printed first. It consists of empty lines and lines starting with `--`,
- # which are not normally a part of Yosys output, and can be fairly safely removed.
- #
- # This is not ideal, but Verific license conditions rule out any other solution.
- stdout = re.sub(r"\A(-- .+\n|\n)*", "", stdout)
- return cls._process_result(popen.returncode, stdout, stderr, ignore_warnings, src_loc_at)
-
-
-def find_yosys(requirement):
- """Find an available Yosys executable of required version.
-
- Parameters
- ----------
- requirement : function
- Version check. Should return ``True`` if the version is acceptable, ``False`` otherwise.
-
- Returns
- -------
- yosys_binary : subclass of YosysBinary
- Proxy for running the requested version of Yosys.
-
- Exceptions
- ----------
- YosysError
- Raised if required Yosys version is not found.
- """
- proxies = []
- clauses = os.environ.get("NMIGEN_USE_YOSYS", "system,builtin").split(",")
- for clause in clauses:
- if clause == "builtin":
- proxies.append(_BuiltinYosys)
- elif clause == "system":
- proxies.append(_SystemYosys)
- else:
- raise YosysError("The NMIGEN_USE_YOSYS environment variable contains "
- "an unrecognized clause {!r}"
- .format(clause))
- for proxy in proxies:
- if proxy.available():
- version = proxy.version()
- if version is not None and requirement(version):
- return proxy
- else:
- if "NMIGEN_USE_YOSYS" in os.environ:
- raise YosysError("Could not find an acceptable Yosys binary. Searched: {}"
- .format(", ".join(clauses)))
- else:
- raise YosysError("Could not find an acceptable Yosys binary. The `nmigen-yosys` PyPI "
- "package, if available for this platform, can be used as fallback")
-from .._yosys import *
+from .._toolchain.yosys import *
from . import rtlil
-from .._yosys import *
+from .._toolchain.yosys import *
from . import rtlil