From 49372852da1614236fef11a929b69c3cdf44edd9 Mon Sep 17 00:00:00 2001 From: Gabriel Somlo Date: Thu, 24 Oct 2019 13:56:20 -0400 Subject: [PATCH] build/lattice/trellis: optionally allow failure if p&r timing not met When timing requirements are strict, allow the build process to fail upon failure to meet timing. This facilitates running the build process from a loop, repeatedly, until a "lucky" p&r solution is found, e.g.: while true; do litex/boards/targets/versa_ecp5.py --gateware-toolchain trellis \ --sys-clk-freq=60e06 --cpu-type rocket --cpu-variant linux \ --with-ethernet --yosys-nowidelut \ --nextpnr-timingstrict if [ "$?" == "0" ]; then echo "Success" | mail -s "Build Succeeded" your@email.here break fi done This augments commit #683e0668, which unconditionally forced p&r to succeed, regardless of whether timing was met, via '--timing-allow-fail'. Signed-off-by: Gabriel Somlo --- litex/boards/targets/versa_ecp5.py | 6 +++--- litex/build/lattice/trellis.py | 21 ++++++++++++++------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/litex/boards/targets/versa_ecp5.py b/litex/boards/targets/versa_ecp5.py index bc9eacb11..f2d9275f7 100755 --- a/litex/boards/targets/versa_ecp5.py +++ b/litex/boards/targets/versa_ecp5.py @@ -11,7 +11,7 @@ from migen.genlib.resetsync import AsyncResetSynchronizer from litex.boards.platforms import versa_ecp5 -from litex.build.lattice.trellis import yosys_args, yosys_argdict +from litex.build.lattice.trellis import trellis_args, trellis_argdict from litex.soc.cores.clock import * from litex.soc.integration.soc_sdram import * @@ -135,7 +135,7 @@ def main(): help='gateware toolchain to use, diamond (default) or trellis') builder_args(parser) soc_sdram_args(parser) - yosys_args(parser) + trellis_args(parser) parser.add_argument("--sys-clk-freq", default=75e6, help="system clock frequency (default=75MHz)") parser.add_argument("--with-ethernet", action="store_true", @@ -145,7 +145,7 @@ def main(): cls = EthernetSoC if args.with_ethernet else BaseSoC soc = cls(toolchain=args.toolchain, sys_clk_freq=int(float(args.sys_clk_freq)), **soc_sdram_argdict(args)) builder = Builder(soc, **builder_argdict(args)) - builder.build(**yosys_argdict(args)) + builder.build(**trellis_argdict(args)) if __name__ == "__main__": main() diff --git a/litex/build/lattice/trellis.py b/litex/build/lattice/trellis.py index caf76b170..c194d3f10 100644 --- a/litex/build/lattice/trellis.py +++ b/litex/build/lattice/trellis.py @@ -73,7 +73,7 @@ def _build_lpf(named_sc, named_pc): def _build_script(source, build_template, build_name, architecture, - package, freq_constraint): + package, freq_constraint, timingstrict): if sys.platform in ("win32", "cygwin"): script_ext = ".bat" build_script_contents = "@echo off\nrem Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n\n" @@ -89,6 +89,7 @@ def _build_script(source, build_template, build_name, architecture, architecture=architecture, package=package, freq_constraint=freq_constraint, + timefailarg="--timing-allow-fail" if not timingstrict else "", fail_stmt=fail_stmt) build_script_file = "build_" + build_name + script_ext @@ -143,14 +144,16 @@ class LatticeTrellisToolchain: self.build_template = [ "yosys -q -l {build_name}.rpt {build_name}.ys", - "nextpnr-ecp5 --json {build_name}.json --lpf {build_name}.lpf --textcfg {build_name}.config --{architecture} --package {package} --freq {freq_constraint} --timing-allow-fail", + "nextpnr-ecp5 --json {build_name}.json --lpf {build_name}.lpf --textcfg {build_name}.config --{architecture} --package {package} --freq {freq_constraint} {timefailarg}", "ecppack {build_name}.config --svf {build_name}.svf --bit {build_name}.bit" ] self.freq_constraints = dict() def build(self, platform, fragment, build_dir="build", build_name="top", - toolchain_path=None, run=True, nowidelut=False, **kwargs): + toolchain_path=None, run=True, + nowidelut=False, timingstrict=False, + **kwargs): if toolchain_path is None: toolchain_path = "/usr/share/trellis/" os.makedirs(build_dir, exist_ok=True) @@ -188,7 +191,8 @@ class LatticeTrellisToolchain: default=0.0)) script = _build_script(False, self.build_template, build_name, - architecture, package, freq_constraint) + architecture, package, freq_constraint, + timingstrict) # run scripts if run: @@ -204,11 +208,14 @@ class LatticeTrellisToolchain: def add_period_constraint(self, platform, clk, period): platform.add_platform_command("""FREQUENCY PORT "{clk}" {freq} MHz;""".format(freq=str(float(1/period)*1000), clk="{clk}"), clk=clk) -def yosys_args(parser): +def trellis_args(parser): parser.add_argument("--yosys-nowidelut", action="store_true", help="pass '-nowidelut' to yosys synth_ecp5") + parser.add_argument("--nextpnr-timingstrict", action="store_true", + help="fail if timing not met, i.e., do NOT pass '--timing-allow-fail' to nextpnr") -def yosys_argdict(args): +def trellis_argdict(args): return { - "nowidelut": args.yosys_nowidelut + "nowidelut": args.yosys_nowidelut, + "timingstrict": args.nextpnr_timingstrict, }