_yosys: translate Yosys warnings to Python warnings.
This isn't used yet (the only Yosys warning we can get is useless), but will be handy for CXXRTL.
This commit is contained in:
parent
a7b8ced92c
commit
bddec3741e
|
@ -2,6 +2,7 @@ import os
|
||||||
import sys
|
import sys
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import warnings
|
||||||
try:
|
try:
|
||||||
from importlib import metadata as importlib_metadata # py3.8+ stdlib
|
from importlib import metadata as importlib_metadata # py3.8+ stdlib
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -20,6 +21,10 @@ class YosysError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class YosysWarning(Warning):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class YosysBinary:
|
class YosysBinary:
|
||||||
@classmethod
|
@classmethod
|
||||||
def available(cls):
|
def available(cls):
|
||||||
|
@ -72,6 +77,16 @@ class YosysBinary:
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
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):
|
class _BuiltinYosys(YosysBinary):
|
||||||
YOSYS_PACKAGE = "nmigen_yosys"
|
YOSYS_PACKAGE = "nmigen_yosys"
|
||||||
|
@ -93,15 +108,12 @@ class _BuiltinYosys(YosysBinary):
|
||||||
return (int(match[1]), int(match[2]), int(match[3] or 0))
|
return (int(match[1]), int(match[2]), int(match[3] or 0))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args, stdin=""):
|
def run(cls, args, stdin="", *, ignore_warnings=False, src_loc_at=0):
|
||||||
popen = subprocess.Popen([sys.executable, "-m", cls.YOSYS_PACKAGE, *args],
|
popen = subprocess.Popen([sys.executable, "-m", cls.YOSYS_PACKAGE, *args],
|
||||||
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||||
encoding="utf-8")
|
encoding="utf-8")
|
||||||
stdout, stderr = popen.communicate(stdin)
|
stdout, stderr = popen.communicate(stdin)
|
||||||
if popen.returncode:
|
return cls._process_result(popen.returncode, stdout, stderr, ignore_warnings, src_loc_at)
|
||||||
raise YosysError(stderr.strip())
|
|
||||||
else:
|
|
||||||
return stdout
|
|
||||||
|
|
||||||
|
|
||||||
class _SystemYosys(YosysBinary):
|
class _SystemYosys(YosysBinary):
|
||||||
|
@ -118,7 +130,7 @@ class _SystemYosys(YosysBinary):
|
||||||
return (int(match[1]), int(match[2]), int(match[3] or 0))
|
return (int(match[1]), int(match[2]), int(match[3] or 0))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args, stdin=""):
|
def run(cls, args, stdin="", *, ignore_warnings=False, src_loc_at=0):
|
||||||
popen = subprocess.Popen([require_tool(cls.YOSYS_BINARY), *args],
|
popen = subprocess.Popen([require_tool(cls.YOSYS_BINARY), *args],
|
||||||
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||||
encoding="utf-8")
|
encoding="utf-8")
|
||||||
|
@ -129,10 +141,7 @@ class _SystemYosys(YosysBinary):
|
||||||
#
|
#
|
||||||
# This is not ideal, but Verific license conditions rule out any other solution.
|
# This is not ideal, but Verific license conditions rule out any other solution.
|
||||||
stdout = re.sub(r"\A(-- .+\n|\n)*", "", stdout)
|
stdout = re.sub(r"\A(-- .+\n|\n)*", "", stdout)
|
||||||
if popen.returncode:
|
return cls._process_result(popen.returncode, stdout, stderr, ignore_warnings, src_loc_at)
|
||||||
raise YosysError(stderr.strip())
|
|
||||||
else:
|
|
||||||
return stdout
|
|
||||||
|
|
||||||
|
|
||||||
def find_yosys(requirement):
|
def find_yosys(requirement):
|
||||||
|
|
|
@ -38,7 +38,11 @@ write_verilog -norename {write_verilog_opts}
|
||||||
prune="# " if yosys_version < (0, 9, 231) else "",
|
prune="# " if yosys_version < (0, 9, 231) else "",
|
||||||
attr_map=" ".join(attr_map),
|
attr_map=" ".join(attr_map),
|
||||||
write_verilog_opts=" ".join(write_verilog_opts),
|
write_verilog_opts=" ".join(write_verilog_opts),
|
||||||
))
|
),
|
||||||
|
# At the moment, Yosys always shows a warning indicating that not all processes can be
|
||||||
|
# translated to Verilog. We carefully emit only the processes that *can* be translated, and
|
||||||
|
# squash this warning. Once Yosys' write_verilog pass is fixed, we should remove this.
|
||||||
|
ignore_warnings=True)
|
||||||
|
|
||||||
|
|
||||||
def convert_fragment(*args, strip_internal_attrs=False, **kwargs):
|
def convert_fragment(*args, strip_internal_attrs=False, **kwargs):
|
||||||
|
|
Loading…
Reference in a new issue