_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:
whitequark 2020-06-11 16:12:52 +00:00
parent a7b8ced92c
commit bddec3741e
2 changed files with 24 additions and 11 deletions

View file

@ -2,6 +2,7 @@ import os
import sys
import re
import subprocess
import warnings
try:
from importlib import metadata as importlib_metadata # py3.8+ stdlib
except ImportError:
@ -20,6 +21,10 @@ class YosysError(Exception):
pass
class YosysWarning(Warning):
pass
class YosysBinary:
@classmethod
def available(cls):
@ -72,6 +77,16 @@ class YosysBinary:
"""
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"
@ -93,15 +108,12 @@ class _BuiltinYosys(YosysBinary):
return (int(match[1]), int(match[2]), int(match[3] or 0))
@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],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
encoding="utf-8")
stdout, stderr = popen.communicate(stdin)
if popen.returncode:
raise YosysError(stderr.strip())
else:
return stdout
return cls._process_result(popen.returncode, stdout, stderr, ignore_warnings, src_loc_at)
class _SystemYosys(YosysBinary):
@ -118,7 +130,7 @@ class _SystemYosys(YosysBinary):
return (int(match[1]), int(match[2]), int(match[3] or 0))
@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],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
encoding="utf-8")
@ -129,10 +141,7 @@ class _SystemYosys(YosysBinary):
#
# This is not ideal, but Verific license conditions rule out any other solution.
stdout = re.sub(r"\A(-- .+\n|\n)*", "", stdout)
if popen.returncode:
raise YosysError(stderr.strip())
else:
return stdout
return cls._process_result(popen.returncode, stdout, stderr, ignore_warnings, src_loc_at)
def find_yosys(requirement):

View file

@ -38,7 +38,11 @@ write_verilog -norename {write_verilog_opts}
prune="# " if yosys_version < (0, 9, 231) else "",
attr_map=" ".join(attr_map),
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):