build/yosys_wrapper: a Yosys wrapper
This commit is contained in:
parent
74467e3b38
commit
b2adabbece
|
@ -0,0 +1,136 @@
|
|||
#
|
||||
# This file is part of LiteX.
|
||||
#
|
||||
# Copyright (c) 2022 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
|
||||
from litex.build import tools
|
||||
|
||||
|
||||
class YosysWrapper():
|
||||
"""
|
||||
YosysWrapper synthesis wrapper
|
||||
"""
|
||||
|
||||
def __init__(self, platform, build_name, target="", output_name="",
|
||||
template=[], yosys_opts="",
|
||||
yosys_cmds=[],
|
||||
synth_format="json",
|
||||
**kwargs):
|
||||
"""
|
||||
Parameters
|
||||
==========
|
||||
platform : GenericPlatform subclass
|
||||
current platform.
|
||||
build_name : str
|
||||
gateware name.
|
||||
target: str
|
||||
target model (ice40, ecp5, nexus, ...).
|
||||
output_name: str
|
||||
output name if different to build_name [optional]
|
||||
template: str
|
||||
yosys template to use instead of default.
|
||||
yosys_opts : str
|
||||
Yosys options to use for synth_xxx
|
||||
yosys_cmds : list
|
||||
optionals commands called before synth_xxx
|
||||
synth_format : str
|
||||
Yosys ouptput format
|
||||
kwargs: dict
|
||||
list of key/value for yosys_opts [optional]
|
||||
"""
|
||||
|
||||
assert platform != ""
|
||||
assert build_name != ""
|
||||
assert target != ""
|
||||
assert synth_format != ""
|
||||
|
||||
self._template = self._default_template if template == [] else template
|
||||
self._output_name = build_name if output_name == "" else output_name
|
||||
|
||||
self._platform = platform
|
||||
self._build_name = build_name
|
||||
self._synth_format = synth_format
|
||||
self._yosys_opts = yosys_opts
|
||||
self._yosys_cmds = yosys_cmds
|
||||
|
||||
self._target=target
|
||||
|
||||
for key,value in kwargs.items():
|
||||
key = key.replace("_","-")
|
||||
if isinstance(value, bool):
|
||||
self._yosys_opts += f"-{key} " if value else ""
|
||||
else:
|
||||
self._yosys_opts += f"-{key} {value} "
|
||||
|
||||
def _import_sources(self):
|
||||
"""built a list of sources to read
|
||||
Return
|
||||
======
|
||||
a string containing all read_xxx lines
|
||||
"""
|
||||
includes = ""
|
||||
reads = []
|
||||
for path in self._platform.verilog_include_paths:
|
||||
includes += " -I" + path
|
||||
for filename, language, library, *copy in self._platform.sources:
|
||||
# yosys has no such function read_systemverilog
|
||||
if language == "systemverilog":
|
||||
language = "verilog -sv"
|
||||
reads.append(f"read_{language}{includes} {filename}")
|
||||
return "\n".join(reads)
|
||||
|
||||
_default_template = [
|
||||
"verilog_defaults -push",
|
||||
"verilog_defaults -add -defer",
|
||||
"{read_files}",
|
||||
"verilog_defaults -pop",
|
||||
"attrmap -tocase keep -imap keep=\"true\" keep=1 -imap keep=\"false\" keep=0 -remove keep=0",
|
||||
"{yosys_cmds}",
|
||||
"synth_{target} {synth_opts} -top {build_name}",
|
||||
"write_{write_fmt} {write_opts} {output_name}.{synth_fmt}",
|
||||
]
|
||||
|
||||
def build_script(self):
|
||||
"""fill and write ys script.
|
||||
"""
|
||||
read_files = self._import_sources()
|
||||
|
||||
format_dict = {
|
||||
"build_name" : self._build_name,
|
||||
"read_files" : read_files,
|
||||
"synth_opts" : self._yosys_opts,
|
||||
"target" : self._target,
|
||||
"synth_fmt" : self._synth_format,
|
||||
"write_fmt" : "verilog" if self._synth_format[0] == "v" else self._synth_format,
|
||||
"write_opts" : "-pvector bra -attrprop" if self._synth_format == "edif" else "",
|
||||
"output_name" : self._output_name,
|
||||
}
|
||||
|
||||
yosys_cmds = [l.format(**format_dict) for l in self._yosys_cmds]
|
||||
format_dict["yosys_cmds"] = "\n".join(yosys_cmds)
|
||||
|
||||
ys = [l.format(**format_dict) for l in self._template]
|
||||
|
||||
tools.write_to_file(self._build_name + ".ys", "\n".join(ys))
|
||||
|
||||
def get_yosys_call(self, target="script"):
|
||||
"""built the script command or Makefile rule + command
|
||||
|
||||
Parameters
|
||||
==========
|
||||
target : str
|
||||
selects if it's a script command or a Makefile rule to be returned
|
||||
|
||||
Returns
|
||||
=======
|
||||
str containing instruction and/or rule
|
||||
"""
|
||||
base_cmd = f"yosys -l {self._build_name}.rpt {self._build_name}.ys\n"
|
||||
if target == "makefile":
|
||||
return f"{self._build_name}.{self._synth_format}:\n\t" + base_cmd
|
||||
elif target == "script":
|
||||
return base_cmd
|
||||
else:
|
||||
raise ValueError("Invalid script type")
|
Loading…
Reference in New Issue