2018-12-11 13:50:56 -07:00
|
|
|
import os
|
2019-08-19 17:28:33 -06:00
|
|
|
import re
|
2018-12-11 13:50:56 -07:00
|
|
|
import subprocess
|
2020-04-23 15:46:10 -06:00
|
|
|
import itertools
|
2018-12-11 13:50:56 -07:00
|
|
|
|
2019-08-28 05:32:18 -06:00
|
|
|
from .._toolchain import *
|
2018-12-11 13:50:56 -07:00
|
|
|
from . import rtlil
|
|
|
|
|
|
|
|
|
2019-08-19 13:27:02 -06:00
|
|
|
__all__ = ["YosysError", "convert", "convert_fragment"]
|
2018-12-11 13:50:56 -07:00
|
|
|
|
|
|
|
|
|
|
|
class YosysError(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2019-08-19 17:28:33 -06:00
|
|
|
def _yosys_version():
|
2019-08-30 17:27:22 -06:00
|
|
|
yosys_path = require_tool("yosys")
|
|
|
|
version = subprocess.check_output([yosys_path, "-V"], encoding="utf-8")
|
2020-04-22 06:23:14 -06:00
|
|
|
# If Yosys is built with Verific, then Verific license information is printed first.
|
2020-04-23 15:46:10 -06:00
|
|
|
# See below for details.
|
2020-04-22 06:23:14 -06:00
|
|
|
m = re.search(r"^Yosys ([\d.]+)(?:\+(\d+))?", version, flags=re.M)
|
2019-08-26 03:35:37 -06:00
|
|
|
tag, offset = m[1], m[2] or 0
|
2019-08-19 17:28:33 -06:00
|
|
|
return tuple(map(int, tag.split("."))), offset
|
|
|
|
|
|
|
|
|
2019-08-21 16:14:33 -06:00
|
|
|
def _convert_rtlil_text(rtlil_text, *, strip_internal_attrs=False, write_verilog_opts=()):
|
2019-08-19 17:28:33 -06:00
|
|
|
version, offset = _yosys_version()
|
2019-08-26 03:35:37 -06:00
|
|
|
if version < (0, 9):
|
2019-10-15 23:10:19 -06:00
|
|
|
raise YosysError("Yosys {}.{} is not supported".format(*version))
|
2019-08-19 17:28:33 -06:00
|
|
|
|
2019-04-22 08:08:01 -06:00
|
|
|
attr_map = []
|
2019-09-24 08:54:22 -06:00
|
|
|
if strip_internal_attrs:
|
|
|
|
attr_map.append("-remove generator")
|
|
|
|
attr_map.append("-remove top")
|
2019-04-22 08:08:01 -06:00
|
|
|
attr_map.append("-remove src")
|
2019-09-24 08:54:22 -06:00
|
|
|
attr_map.append("-remove nmigen.hierarchy")
|
|
|
|
attr_map.append("-remove nmigen.decoding")
|
2019-04-22 08:08:01 -06:00
|
|
|
|
2019-08-19 17:28:33 -06:00
|
|
|
script = """
|
2018-12-12 21:51:15 -07:00
|
|
|
# Convert nMigen's RTLIL to readable Verilog.
|
2018-12-11 13:50:56 -07:00
|
|
|
read_ilang <<rtlil
|
|
|
|
{}
|
|
|
|
rtlil
|
2019-10-28 04:11:41 -06:00
|
|
|
{prune}delete w:$verilog_initial_trigger
|
2019-08-26 03:35:37 -06:00
|
|
|
{prune}proc_prune
|
2018-12-11 13:50:56 -07:00
|
|
|
proc_init
|
|
|
|
proc_arst
|
|
|
|
proc_dff
|
|
|
|
proc_clean
|
2018-12-20 18:55:59 -07:00
|
|
|
memory_collect
|
2019-09-24 08:54:22 -06:00
|
|
|
attrmap {attr_map}
|
|
|
|
attrmap -modattr {attr_map}
|
2019-08-21 16:14:33 -06:00
|
|
|
write_verilog -norename {write_verilog_opts}
|
2019-09-24 08:54:22 -06:00
|
|
|
""".format(rtlil_text,
|
|
|
|
prune="# " if version == (0, 9) and offset == 0 else "",
|
|
|
|
attr_map=" ".join(attr_map),
|
2019-08-21 16:14:33 -06:00
|
|
|
write_verilog_opts=" ".join(write_verilog_opts),
|
2019-09-24 08:54:22 -06:00
|
|
|
)
|
2019-08-19 17:28:33 -06:00
|
|
|
|
2019-08-30 17:27:22 -06:00
|
|
|
popen = subprocess.Popen([require_tool("yosys"), "-q", "-"],
|
2019-08-19 17:28:33 -06:00
|
|
|
stdin=subprocess.PIPE,
|
|
|
|
stdout=subprocess.PIPE,
|
|
|
|
stderr=subprocess.PIPE,
|
|
|
|
encoding="utf-8")
|
|
|
|
verilog_text, error = popen.communicate(script)
|
2018-12-11 13:50:56 -07:00
|
|
|
if popen.returncode:
|
|
|
|
raise YosysError(error.strip())
|
|
|
|
else:
|
2020-04-23 15:46:10 -06:00
|
|
|
# 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
|
|
|
|
# valid at the start of a Verilog file, and thus may be reliably removed.
|
|
|
|
verilog_text = "\n".join(itertools.dropwhile(
|
|
|
|
lambda x: x == "" or x.startswith("--"),
|
|
|
|
verilog_text.splitlines()
|
|
|
|
))
|
2018-12-11 13:50:56 -07:00
|
|
|
return verilog_text
|
2019-08-19 13:27:02 -06:00
|
|
|
|
|
|
|
|
2019-09-24 08:54:22 -06:00
|
|
|
def convert_fragment(*args, strip_internal_attrs=False, **kwargs):
|
|
|
|
rtlil_text, name_map = rtlil.convert_fragment(*args, **kwargs)
|
|
|
|
return _convert_rtlil_text(rtlil_text, strip_internal_attrs=strip_internal_attrs), name_map
|
2019-08-19 13:27:02 -06:00
|
|
|
|
|
|
|
|
2019-09-24 08:54:22 -06:00
|
|
|
def convert(*args, strip_internal_attrs=False, **kwargs):
|
|
|
|
rtlil_text = rtlil.convert(*args, **kwargs)
|
|
|
|
return _convert_rtlil_text(rtlil_text, strip_internal_attrs=strip_internal_attrs)
|