Merge pull request #674 from daveshah1/radiant-yosys-synth
build/radiant: Allow synthesis with Yosys
This commit is contained in:
commit
72140f6df9
|
@ -22,6 +22,50 @@ from litex.build.generic_platform import *
|
||||||
from litex.build import tools
|
from litex.build import tools
|
||||||
from litex.build.lattice import common
|
from litex.build.lattice import common
|
||||||
|
|
||||||
|
# Mixed Radiant+Yosys support
|
||||||
|
|
||||||
|
def _run_yosys(device, sources, vincpaths, build_name):
|
||||||
|
ys_contents = ""
|
||||||
|
incflags = ""
|
||||||
|
for path in vincpaths:
|
||||||
|
incflags += " -I" + path
|
||||||
|
for filename, language, library in sources:
|
||||||
|
assert language != "vhdl"
|
||||||
|
ys_contents += "read_{}{} {}\n".format(language, incflags, filename)
|
||||||
|
|
||||||
|
ys_contents += """\
|
||||||
|
hierarchy -top {build_name}
|
||||||
|
|
||||||
|
# Map keep to keep=1 for yosys
|
||||||
|
log
|
||||||
|
log XX. Converting (* keep = "xxxx" *) attribute for Yosys
|
||||||
|
log
|
||||||
|
attrmap -tocase keep -imap keep="true" keep=1 -imap keep="false" keep=0 -remove keep=0
|
||||||
|
select -list a:keep=1
|
||||||
|
|
||||||
|
# Add keep=1 for yosys to objects which have dont_touch="true" attribute.
|
||||||
|
log
|
||||||
|
log XX. Converting (* dont_touch = "true" *) attribute for Yosys
|
||||||
|
log
|
||||||
|
select -list a:dont_touch=true
|
||||||
|
setattr -set keep 1 a:dont_touch=true
|
||||||
|
|
||||||
|
# Convert (* async_reg = "true" *) to async registers for Yosys.
|
||||||
|
# (* async_reg = "true", dont_touch = "true" *) reg xilinxmultiregimpl0_regs1 = 1'd0;
|
||||||
|
log
|
||||||
|
log XX. Converting (* async_reg = "true" *) attribute to async registers for Yosys
|
||||||
|
log
|
||||||
|
select -list a:async_reg=true
|
||||||
|
setattr -set keep 1 a:async_reg=true
|
||||||
|
|
||||||
|
synth_nexus -top {build_name} -vm {build_name}_yosys.vm
|
||||||
|
""".format(build_name=build_name)
|
||||||
|
|
||||||
|
ys_name = build_name + ".ys"
|
||||||
|
tools.write_to_file(ys_name, ys_contents)
|
||||||
|
r = subprocess.call(["yosys", ys_name])
|
||||||
|
if r != 0:
|
||||||
|
raise OSError("Subprocess failed")
|
||||||
|
|
||||||
# Constraints (.ldc) -------------------------------------------------------------------------------
|
# Constraints (.ldc) -------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -68,7 +112,7 @@ def _build_pdc(named_sc, named_pc, clocks, vns, build_name):
|
||||||
|
|
||||||
# Project (.tcl) -----------------------------------------------------------------------------------
|
# Project (.tcl) -----------------------------------------------------------------------------------
|
||||||
|
|
||||||
def _build_tcl(device, sources, vincpaths, build_name, pdc_file):
|
def _build_tcl(device, sources, vincpaths, build_name, pdc_file, synth_mode):
|
||||||
tcl = []
|
tcl = []
|
||||||
# Create project
|
# Create project
|
||||||
tcl.append(" ".join([
|
tcl.append(" ".join([
|
||||||
|
@ -86,8 +130,17 @@ def _build_tcl(device, sources, vincpaths, build_name, pdc_file):
|
||||||
tcl.append("prj_set_impl_opt {include path} {\"" + vincpath + "\"}")
|
tcl.append("prj_set_impl_opt {include path} {\"" + vincpath + "\"}")
|
||||||
|
|
||||||
# Add sources
|
# Add sources
|
||||||
for filename, language, library in sources:
|
if synth_mode == "yosys":
|
||||||
tcl.append("prj_add_source \"{}\" -work {}".format(tcl_path(filename), library))
|
# NOTE: it is seemingly impossible to skip synthesis using the Tcl flow
|
||||||
|
# so we give Synplify the structural netlist from Yosys which it won't actually touch
|
||||||
|
# The other option is to call the low level Radiant commands starting from 'map'
|
||||||
|
# with the structural netlist from Yosys, but this would be harder to do in a cross
|
||||||
|
# platform way.
|
||||||
|
tcl.append("prj_add_source \"{}_yosys.vm\" -work work".format(build_name))
|
||||||
|
library = "work"
|
||||||
|
else:
|
||||||
|
for filename, language, library in sources:
|
||||||
|
tcl.append("prj_add_source \"{}\" -work {}".format(tcl_path(filename), library))
|
||||||
|
|
||||||
tcl.append("prj_add_source \"{}\" -work {}".format(tcl_path(pdc_file), library))
|
tcl.append("prj_add_source \"{}\" -work {}".format(tcl_path(pdc_file), library))
|
||||||
|
|
||||||
|
@ -203,6 +256,7 @@ class LatticeRadiantToolchain:
|
||||||
build_name = "top",
|
build_name = "top",
|
||||||
run = True,
|
run = True,
|
||||||
timingstrict = True,
|
timingstrict = True,
|
||||||
|
synth_mode = "radiant",
|
||||||
**kwargs):
|
**kwargs):
|
||||||
|
|
||||||
# Create build directory
|
# Create build directory
|
||||||
|
@ -227,13 +281,15 @@ class LatticeRadiantToolchain:
|
||||||
pdc_file = build_dir + "\\" + build_name + ".pdc"
|
pdc_file = build_dir + "\\" + build_name + ".pdc"
|
||||||
|
|
||||||
# Generate design script file (.tcl)
|
# Generate design script file (.tcl)
|
||||||
_build_tcl(platform.device, platform.sources, platform.verilog_include_paths, build_name, pdc_file)
|
_build_tcl(platform.device, platform.sources, platform.verilog_include_paths, build_name, pdc_file, synth_mode)
|
||||||
|
|
||||||
# Generate build script
|
# Generate build script
|
||||||
script = _build_script(build_name, platform.device)
|
script = _build_script(build_name, platform.device)
|
||||||
|
|
||||||
# Run
|
# Run
|
||||||
if run:
|
if run:
|
||||||
|
if synth_mode == "yosys":
|
||||||
|
_run_yosys(platform.device, platform.sources, platform.verilog_include_paths, build_name)
|
||||||
_run_script(script)
|
_run_script(script)
|
||||||
if timingstrict:
|
if timingstrict:
|
||||||
_check_timing(build_name)
|
_check_timing(build_name)
|
||||||
|
@ -256,3 +312,10 @@ class LatticeRadiantToolchain:
|
||||||
to.attr.add("keep")
|
to.attr.add("keep")
|
||||||
if (to, from_) not in self.false_paths:
|
if (to, from_) not in self.false_paths:
|
||||||
self.false_paths.add((from_, to))
|
self.false_paths.add((from_, to))
|
||||||
|
|
||||||
|
def radiant_build_args(parser):
|
||||||
|
parser.add_argument("--synth-mode", default="vivado", help="synthesis mode (synplify or yosys, default=synplify)")
|
||||||
|
|
||||||
|
|
||||||
|
def radiant_build_argdict(args):
|
||||||
|
return {"synth_mode": args.synth_mode}
|
||||||
|
|
Loading…
Reference in New Issue