build: add microsemi template for polarfire fpgas support
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 15 Nov 2018 17:21:41 +0000 (18:21 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 15 Nov 2018 17:21:41 +0000 (18:21 +0100)
litex/boards/platforms/avalanche.py
litex/build/microsemi/__init__.py [new file with mode: 0644]
litex/build/microsemi/common.py [new file with mode: 0644]
litex/build/microsemi/libero_soc.py [new file with mode: 0644]
litex/build/microsemi/platform.py [new file with mode: 0644]

index 4da58a2470daa6a4b278247496d0e5ca965c1d03..e7f955a6572f89995e8409c96d1372ec3d6ad852 100644 (file)
@@ -1,4 +1,8 @@
+# This file is Copyright (c) 2018 Florent Kermarrec <florent@enjoy-digital.fr>
+# License: BSD
+
 from litex.build.generic_platform import *
+from litex.build.microsemi import MicrosemiPlatform
 
 _io = [
     ("clk50", 0, Pins("R1"), IOStandard("LVCMOS25")),
@@ -76,3 +80,10 @@ _io = [
         IOStandard("LVCMOS25")
     ),
 ]
+
+class Platform(MicrosemiPlatform):
+    default_clk_name = "clk50"
+    default_clk_period = 20.0
+
+    def __init__(self):
+        MicrosemiPlatform.__init__(self, "MPF300TS_ES", _io)
diff --git a/litex/build/microsemi/__init__.py b/litex/build/microsemi/__init__.py
new file mode 100644 (file)
index 0000000..1b054bb
--- /dev/null
@@ -0,0 +1 @@
+from litex.build.microsemi.platform import MicrosemiPlatform
diff --git a/litex/build/microsemi/common.py b/litex/build/microsemi/common.py
new file mode 100644 (file)
index 0000000..2b82aed
--- /dev/null
@@ -0,0 +1,2 @@
+microsemi_polarfire_special_overrides = {
+}
diff --git a/litex/build/microsemi/libero_soc.py b/litex/build/microsemi/libero_soc.py
new file mode 100644 (file)
index 0000000..ff0043c
--- /dev/null
@@ -0,0 +1,84 @@
+# This file is Copyright (c) 2018 Florent Kermarrec <florent@enjoy-digital.fr>
+# License: BSD
+
+import os
+import sys
+import subprocess
+import shutil
+
+from migen.fhdl.structure import _Fragment
+
+from litex.build.generic_platform import *
+from litex.build import tools
+from litex.build.microsemi import common
+
+def _build_files(device, sources, vincpaths, build_name):
+    print("TODO: _build_files")
+
+def _build_script(build_name, device, toolchain_path, ver=None):
+    if sys.platform in ("win32", "cygwin"):
+        script_ext = ".bat"
+        build_script_contents = "@echo off\nrem Autogenerated by Migen\n\n"
+        copy_stmt = "copy"
+        fail_stmt = " || exit /b"
+    else:
+        raise NotImplementedError
+
+    build_script_file = "build_" + build_name + script_ext
+    tools.write_to_file(build_script_file, build_script_contents,
+                        force_unix=False)
+    return build_script_file
+
+def _run_script(script):
+    if sys.platform in ("win32", "cygwin"):
+        shell = ["cmd", "/c"]
+    else:
+        shell = ["bash"]
+
+    if subprocess.call(shell + [script]) != 0:
+        raise OSError("Subprocess failed")
+
+
+class MicrosemiLiberoSoCPolarfireToolchain:
+    attr_translate = {
+        # FIXME: document
+        "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
+    }
+
+    special_overrides = common.microsemi_polarfire_special_overrides
+
+    def build(self, platform, fragment, build_dir="build", build_name="top",
+              toolchain_path=None, run=True, **kwargs):
+        os.makedirs(build_dir, exist_ok=True)
+        cwd = os.getcwd()
+        os.chdir(build_dir)
+
+        if not isinstance(fragment, _Fragment):
+            fragment = fragment.get_fragment()
+        platform.finalize(fragment)
+
+        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)
+        sources = platform.sources | {(v_file, "verilog", "work")}
+        _build_files(platform.device, sources, platform.verilog_include_paths, build_name)
+
+        script = _build_script(build_name, platform.device, toolchain_path)
+        if run:
+            _run_script(script)
+
+        os.chdir(cwd)
+
+        return v_output.ns
+
+    def add_period_constraint(self, platform, clk, period):
+        print("TODO: add_period_constraint")
\ No newline at end of file
diff --git a/litex/build/microsemi/platform.py b/litex/build/microsemi/platform.py
new file mode 100644 (file)
index 0000000..6ecb8e9
--- /dev/null
@@ -0,0 +1,29 @@
+from litex.build.generic_platform import GenericPlatform
+from litex.build.microsemi import common, libero_soc
+
+
+class MicrosemiPlatform(GenericPlatform):
+    bitstream_ext = ".bit"
+
+    def __init__(self, *args, toolchain="libero_soc_polarfire", **kwargs):
+        GenericPlatform.__init__(self, *args, **kwargs)
+        if toolchain == "libero_soc_polarfire":
+            self.toolchain = libero_soc.MicrosemiLiberoSoCPolarfireToolchain()
+        else:
+            raise ValueError("Unknown toolchain")
+
+    def get_verilog(self, *args, special_overrides=dict(), **kwargs):
+        so = dict()  # No common overrides between ECP and ice40.
+        so.update(self.toolchain.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)
+
+    def add_period_constraint(self, clk, period):
+        if hasattr(clk, "p"):
+            clk = clk.p
+        self.toolchain.add_period_constraint(self, clk, period)