From c0fa4fd1f442d14d8dbad2854157bb36f17d86e1 Mon Sep 17 00:00:00 2001 From: Pepijn de Vos Date: Mon, 28 Sep 2020 13:12:07 +0200 Subject: [PATCH 1/5] initial build support for Gowin --- litex/build/gowin/__init__.py | 0 litex/build/gowin/common.py | 8 +++ litex/build/gowin/gowin.py | 113 ++++++++++++++++++++++++++++++++++ litex/build/gowin/platform.py | 34 ++++++++++ 4 files changed, 155 insertions(+) create mode 100644 litex/build/gowin/__init__.py create mode 100644 litex/build/gowin/common.py create mode 100644 litex/build/gowin/gowin.py create mode 100644 litex/build/gowin/platform.py diff --git a/litex/build/gowin/__init__.py b/litex/build/gowin/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/litex/build/gowin/common.py b/litex/build/gowin/common.py new file mode 100644 index 000000000..3d428dea3 --- /dev/null +++ b/litex/build/gowin/common.py @@ -0,0 +1,8 @@ +# +# This file is part of LiteX. +# +# Copyright (c) 2020 Pepijn de Vos +# Copyright (c) 2015-2018 Florent Kermarrec +# SPDX-License-Identifier: BSD-2-Clause + +gowin_special_overrides = {} diff --git a/litex/build/gowin/gowin.py b/litex/build/gowin/gowin.py new file mode 100644 index 000000000..26234a15c --- /dev/null +++ b/litex/build/gowin/gowin.py @@ -0,0 +1,113 @@ +# +# This file is part of LiteX. +# +# Copyright (c) 2020 Pepijn de Vos +# Copyright (c) 2015-2018 Florent Kermarrec +# SPDX-License-Identifier: BSD-2-Clause + +import os +import subprocess + +from migen.fhdl.structure import _Fragment + +from litex.build.generic_platform import Pins, IOStandard, Misc +from litex.build import tools + +def _build_cst(named_sc, named_pc): + lines = [] + + flat_sc = [] + for name, pins, other, resource in named_sc: + if len(pins) > 1: + for i, p in enumerate(pins): + flat_sc.append((f"{name}[{i}]", p, other)) + else: + flat_sc.append((name, pins[0], other)) + + for name, pin, other in flat_sc: + lines.append(f"IO_LOC \"{name}\" {pin};") + + for c in other: + if isinstance(c, IOStandard): + lines.append(f"IO_PORT \"{name}\" IO_TYPE={c.name};") + elif isinstance(c, Misc): + lines.append(f"IO_PORT \"{name}\" {c.misc};") + + if named_pc: + lines.extend(named_pc) + + cst = "\n".join(lines) + with open("top.cst", "w") as f: + f.write(cst) + +def _build_script(name, partnumber, files, options): + lines = [ + f"set_device -name {name} {partnumber}", + "add_file top.cst", + ] + + for f, typ, lib in files: + lines.append(f"add_file {f}") + + for opt, val in options.items(): + lines.append(f"set_option -{opt} {val}") + + lines.append("run all") + + tcl = "\n".join(lines) + with open("run.tcl", "w") as f: + f.write(tcl) + +class GowinToolchain(): + def __init__(self): + self.options = {} + + def attr_translate(*args): + print(args) + pass + + def build(self, platform, fragment, + build_dir = "build", + build_name = "top", + run = True, + **kwargs): + + # Create build directory + cwd = os.getcwd() + os.makedirs(build_dir, exist_ok=True) + os.chdir(build_dir) + + # Finalize design + if not isinstance(fragment, _Fragment): + fragment = fragment.get_fragment() + platform.finalize(fragment) + + # Generate verilog + v_output = platform.get_verilog(fragment, name=build_name, **kwargs) + named_sc, named_pc = platform.resolve_signals(v_output.ns) + v_file = build_name + ".v" + v_output.write(v_file) + platform.add_source(v_file) + + if platform.verilog_include_paths: + self.options['includ_path'] = '{' + ';'.join(platform.verilog_include_paths) + '}' + + # Generate constraints file (.cst) + _build_cst( + named_sc = named_sc, + named_pc = named_pc) + + # Generate TCL build script + script = _build_script( + name = platform.name, + partnumber = platform.device, + files = platform.sources, + options = self.options) + + # Run + if run: + subprocess.run(["gw_sh", "run.tcl"]) + + os.chdir(cwd) + + return v_output.ns diff --git a/litex/build/gowin/platform.py b/litex/build/gowin/platform.py new file mode 100644 index 000000000..82aabc5de --- /dev/null +++ b/litex/build/gowin/platform.py @@ -0,0 +1,34 @@ +# +# This file is part of LiteX. +# +# Copyright (c) 2020 Pepijn de Vos +# Copyright (c) 2015-2018 Florent Kermarrec +# SPDX-License-Identifier: BSD-2-Clause + +import os + +from litex.build.generic_platform import GenericPlatform +from litex.build.gowin import common, gowin + +# GowinPlatform ----------------------------------------------------------------------------------- + +class GowinPlatform(GenericPlatform): + bitstream_ext = ".fs" + + def __init__(self, *args, toolchain="gowin", **kwargs): + GenericPlatform.__init__(self, *args, **kwargs) + if toolchain == "gowin": + self.toolchain = gowin.GowinToolchain() + elif toolchain == "apicula": + raise ValueError("Apicula toolchain needs more work") + else: + raise ValueError("Unknown toolchain") + + def get_verilog(self, *args, special_overrides=dict(), **kwargs): + so = dict(common.gowin_special_overrides) + so.update(special_overrides) + return GenericPlatform.get_verilog(self, *args, special_overrides=so, + attr_translate=self.toolchain.attr_translate, **kwargs) + + def build(self, *args, **kwargs): + return self.toolchain.build(self, *args, **kwargs) From 95564b7475c514bcda5386cdba33368374e719ff Mon Sep 17 00:00:00 2001 From: Pepijn de Vos Date: Mon, 28 Sep 2020 17:49:41 +0200 Subject: [PATCH 2/5] change name->devicename, working bios --- litex/build/gowin/gowin.py | 2 +- litex/build/gowin/platform.py | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/litex/build/gowin/gowin.py b/litex/build/gowin/gowin.py index 26234a15c..987b272a3 100644 --- a/litex/build/gowin/gowin.py +++ b/litex/build/gowin/gowin.py @@ -99,7 +99,7 @@ class GowinToolchain(): # Generate TCL build script script = _build_script( - name = platform.name, + name = platform.devicename, partnumber = platform.device, files = platform.sources, options = self.options) diff --git a/litex/build/gowin/platform.py b/litex/build/gowin/platform.py index 82aabc5de..dbe36e938 100644 --- a/litex/build/gowin/platform.py +++ b/litex/build/gowin/platform.py @@ -15,8 +15,13 @@ from litex.build.gowin import common, gowin class GowinPlatform(GenericPlatform): bitstream_ext = ".fs" - def __init__(self, *args, toolchain="gowin", **kwargs): - GenericPlatform.__init__(self, *args, **kwargs) + def __init__(self, device, *args, toolchain="gowin", devicename=None, **kwargs): + GenericPlatform.__init__(self, device, *args, **kwargs) + if not devicename: + idx = device.find('-') + likely_name = f"{device[:idx]}-{device[idx+3]}" + raise ValueError(f"devicename not provided, maybe {likely_name}?") + self.devicename = devicename if toolchain == "gowin": self.toolchain = gowin.GowinToolchain() elif toolchain == "apicula": @@ -27,8 +32,7 @@ class GowinPlatform(GenericPlatform): def get_verilog(self, *args, special_overrides=dict(), **kwargs): so = dict(common.gowin_special_overrides) so.update(special_overrides) - return GenericPlatform.get_verilog(self, *args, special_overrides=so, - attr_translate=self.toolchain.attr_translate, **kwargs) + return GenericPlatform.get_verilog(self, *args, special_overrides=so, **kwargs) def build(self, *args, **kwargs): return self.toolchain.build(self, *args, **kwargs) From dd2b1f21f08a23cd581248c0dde0d8c6af6941f2 Mon Sep 17 00:00:00 2001 From: Pepijn de Vos Date: Tue, 29 Sep 2020 15:24:36 +0200 Subject: [PATCH 3/5] typo and dead code --- litex/build/gowin/gowin.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/litex/build/gowin/gowin.py b/litex/build/gowin/gowin.py index 987b272a3..130e8b06f 100644 --- a/litex/build/gowin/gowin.py +++ b/litex/build/gowin/gowin.py @@ -62,10 +62,6 @@ class GowinToolchain(): def __init__(self): self.options = {} - def attr_translate(*args): - print(args) - pass - def build(self, platform, fragment, build_dir = "build", build_name = "top", @@ -90,7 +86,7 @@ class GowinToolchain(): platform.add_source(v_file) if platform.verilog_include_paths: - self.options['includ_path'] = '{' + ';'.join(platform.verilog_include_paths) + '}' + self.options['include_path'] = '{' + ';'.join(platform.verilog_include_paths) + '}' # Generate constraints file (.cst) _build_cst( From eca5a25e270cf82c5ac6ddde838672011bee9dfc Mon Sep 17 00:00:00 2001 From: Pepijn de Vos Date: Tue, 29 Sep 2020 15:55:07 +0200 Subject: [PATCH 4/5] add dummy attr_translate --- litex/build/gowin/gowin.py | 13 +++++++++++++ litex/build/gowin/platform.py | 4 +++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/litex/build/gowin/gowin.py b/litex/build/gowin/gowin.py index 130e8b06f..ea486a187 100644 --- a/litex/build/gowin/gowin.py +++ b/litex/build/gowin/gowin.py @@ -59,6 +59,19 @@ def _build_script(name, partnumber, files, options): f.write(tcl) class GowinToolchain(): + + attr_translate = { + "keep": None, + "no_retiming": None, + "async_reg": None, + "mr_ff": None, + "mr_false_path": None, + "ars_ff1": None, + "ars_ff2": None, + "ars_false_path": None, + "no_shreg_extract": None + } + def __init__(self): self.options = {} diff --git a/litex/build/gowin/platform.py b/litex/build/gowin/platform.py index dbe36e938..8ac93ebdb 100644 --- a/litex/build/gowin/platform.py +++ b/litex/build/gowin/platform.py @@ -32,7 +32,9 @@ class GowinPlatform(GenericPlatform): def get_verilog(self, *args, special_overrides=dict(), **kwargs): so = dict(common.gowin_special_overrides) so.update(special_overrides) - return GenericPlatform.get_verilog(self, *args, special_overrides=so, **kwargs) + return GenericPlatform.get_verilog(self, *args, special_overrides=so, + attr_translate=self.toolchain.attr_translate, + **kwargs) def build(self, *args, **kwargs): return self.toolchain.build(self, *args, **kwargs) From 890ccaf4bd506055f5fab1fe7f0ecf320ae4749f Mon Sep 17 00:00:00 2001 From: Pepijn de Vos Date: Thu, 1 Oct 2020 08:39:32 +0200 Subject: [PATCH 5/5] support writing bitstream to flash --- litex/build/openfpgaloader.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/litex/build/openfpgaloader.py b/litex/build/openfpgaloader.py index 8189be13f..1d845505c 100644 --- a/litex/build/openfpgaloader.py +++ b/litex/build/openfpgaloader.py @@ -17,5 +17,8 @@ class OpenFPGALoader(GenericProgrammer): def __init__(self, board): self.board = board - def load_bitstream(self, bitstream_file): - subprocess.call(["openFPGALoader", "--board", self.board, bitstream_file]) + def load_bitstream(self, bitstream_file, flash=False): + cmd = ["openFPGALoader", "--board", self.board, "--bitstream", bitstream_file] + if flash: + cmd.append("--write-flash") + subprocess.call(cmd)