diff --git a/tasks.py b/tasks.py index bc23654..b6170c4 100644 --- a/tasks.py +++ b/tasks.py @@ -74,49 +74,86 @@ def expand_test_target(target): else: raise ValueError(f"Unknown target type {t}") +def phase(name): + print("") + print("*"*(len(name)+6)) + print(f"** {name} **") + print("*"*(len(name)+6)) + print("") + @task def build(c, target="."): + phase("Compile Bluespec") + + verilog_files = [] for target in expand_build_target(target): out_info, out_verilog, out_bsc = ensure_build_dirs(target, "info", "verilog", "bsc") print(f"Building {target}") c.run(f"bsc -aggressive-conditions -check-assert -u -verilog -info-dir {out_info} -vdir {out_verilog} -bdir {out_bsc} -p {target.parent}:lib:%/Libraries -show-module-use -show-compiles {target}") + module_name = Path(f"mk{target.stem}") + verilog_files.append(out_verilog / module_name.with_suffix(".v")) + with open(out_verilog / module_name.with_suffix(".use")) as f: + verilog_files.extend(find_verilog_modules(c, f.read().splitlines())) + + print("\nVerilog files for synthesis:") + for v in verilog_files: + print(" "+str(v)) + + return verilog_files + @task def synth(c, target): target = resolve_synth_target(target) - pin_map = target.parent / "pin_map.lpf" - if not pin_map.is_file(): - raise ArgumentError(f"Pin mapping {pin_map} not found") - - module_name = Path(f"mk{target.stem}") out_info, out_verilog, out_bsc, out_yosys, out_nextpnr = ensure_build_dirs(target, "info", "verilog", "bsc", "yosys", "nextpnr") - build(c, target) - - verilog_files = [out_verilog / module_name.with_suffix(".v")] - with open(out_verilog / module_name.with_suffix(".use")) as f: - verilog_files.extend(find_verilog_modules(c, f.read().splitlines())) + module_name = Path(f"mk{target.stem}") + verilog_files = build(c, target) + phase("Logic synthesis") yosys_script = out_yosys / "script.ys" yosys_json = out_yosys / module_name.with_suffix(".json") yosys_report = out_yosys / module_name.with_suffix(".stats") yosys_log = out_yosys / module_name.with_suffix(".log") + yosys_preprocessed = out_yosys / module_name.with_suffix(".v") + yosys_compiled = out_yosys / f"{module_name.stem}_compiled.v" with open(yosys_script, "w", encoding="UTF-8") as f: f.write(dedent(f"""\ read_verilog -sv -defer {' '.join(str(f) for f in verilog_files)} hierarchy -top {module_name} - synth_ecp5 -top {module_name} -json {yosys_json} + synth_ecp5 -top {module_name} -run :map_ram + write_verilog -sv {yosys_preprocessed} + synth_ecp5 -run map_ram: -json {yosys_json} + write_verilog -sv {yosys_compiled} tee -o {yosys_report} stat """)) c.run(f"yosys -q -L {yosys_log} -T {yosys_script}") with open(yosys_report) as f: - print(f.read()) + ls = f.readlines()[3:] + print("".join(ls)) + print(f" JSON : {yosys_json}") + print(f" Log : {yosys_log}") + print(f" Flat : {yosys_preprocessed}") + print(f"Compiled : {yosys_compiled}") + pin_map = target.parent / "pin_map.lpf" + if not pin_map.is_file(): + print(f"WARNING: no pin map at {pin_map}, skipping place&route and bitstream generation") + return + + phase("Place and route") nextpnr_out = out_nextpnr / module_name.with_suffix(".pnr") - out = c.run(f"nextpnr-ecp5 --85k --detailed-timing-report --report {out_nextpnr / "timing.json"} --json {yosys_json} --lpf {pin_map} --package=CABGA381 --textcfg {nextpnr_out}", hide='stderr') - print_filtered_paragraphs(out.stderr, "Device utilization", "Critical path", common_prefix="Info: ") + nextpnr_log = out_nextpnr / module_name.with_suffix(".log") + nextpnr_timing = out_nextpnr / module_name.with_suffix(".log") + out = c.run(f"nextpnr-ecp5 --85k --detailed-timing-report -l {nextpnr_log} --report {nextpnr_timing} --json {yosys_json} --lpf {pin_map} --package=CABGA381 --textcfg {nextpnr_out}") #, hide='stderr') + print_filtered_paragraphs(out.stderr, "Device utilisation", "Critical path", "Max frequency", "Max delay", common_prefix="Info: ") + print(f" PNR : {nextpnr_out}") + print(f" Log : {nextpnr_log}") + print(f"Timing : {nextpnr_timing}") + + phase("Bitstream generation") bitstream = nextpnr_out.with_suffix(".bit") c.run(f"ecppack {nextpnr_out} {bitstream}") print(f"Wrote bitstream to {bitstream}") @@ -139,4 +176,5 @@ def test(c, target="."): @task def clean(c): - shutil.rmtree("out") + if Path("out").is_dir(): + shutil.rmtree("out")