1 # This file is Copyright (c) 2015 Florent Kermarrec <florent@enjoy-digital.fr>
9 from litex
.gen
.fhdl
.structure
import _Fragment
11 from litex
.build
.generic_platform
import *
12 from litex
.build
import tools
13 from litex
.build
.lattice
import common
16 def _format_constraint(c
):
17 if isinstance(c
, Pins
):
18 return ("LOCATE COMP ", " SITE " + "\"" + c
.identifiers
[0] + "\"")
19 elif isinstance(c
, IOStandard
):
20 return ("IOBUF PORT ", " IO_TYPE=" + c
.name
)
21 elif isinstance(c
, Misc
):
25 def _format_lpf(signame
, pin
, others
, resname
):
26 fmt_c
= [_format_constraint(c
) for c
in ([Pins(pin
)] + others
)]
28 for pre
, suf
in fmt_c
:
29 r
+= pre
+ "\"" + signame
+ "\"" + suf
+ ";\n"
33 def _build_lpf(named_sc
, named_pc
):
34 r
= "BLOCK RESETPATHS;\n"
35 r
+= "BLOCK ASYNCPATHS;\n"
36 for sig
, pins
, others
, resname
in named_sc
:
38 for i
, p
in enumerate(pins
):
39 r
+= _format_lpf(sig
+ "[" + str(i
) + "]", p
, others
, resname
)
41 r
+= _format_lpf(sig
, pins
[0], others
, resname
)
43 r
+= "\n" + "\n\n".join(named_pc
)
47 def _build_files(device
, sources
, vincpaths
, build_name
):
49 tcl
.append("prj_project new -name \"{}\" -impl \"implementation\" -dev {} -synthesis \"synplify\"".format(build_name
, device
))
50 for path
in vincpaths
:
51 tcl
.append("prj_impl option {include path} {\"" + path
+ "\"}")
52 for filename
, language
, library
in sources
:
53 tcl
.append("prj_src add \"" + filename
+ "\" -work " + library
)
54 tcl
.append("prj_run Synthesis -impl implementation -forceOne")
55 tcl
.append("prj_run Translate -impl implementation")
56 tcl
.append("prj_run Map -impl implementation")
57 tcl
.append("prj_run PAR -impl implementation")
58 tcl
.append("prj_run Export -impl implementation -task Bitgen")
59 tcl
.append("prj_run Export -impl implementation -task Jedecgen")
60 tools
.write_to_file(build_name
+ ".tcl", "\n".join(tcl
))
63 def _run_diamond(build_name
, source
, ver
=None):
64 if sys
.platform
== "win32" or sys
.platform
== "cygwin":
65 build_script_contents
= "REM Autogenerated by LiteX\n"
66 build_script_contents
= "pnmainc " + build_name
+ ".tcl\n"
67 build_script_file
= "build_" + build_name
+ ".bat"
68 tools
.write_to_file(build_script_file
, build_script_contents
)
69 r
= subprocess
.call([build_script_file
])
70 shutil
.copy(os
.path
.join("implementation", build_name
+ "_implementation.bit"), build_name
+ ".bit")
71 shutil
.copy(os
.path
.join("implementation", build_name
+ "_implementation.jed"), build_name
+ ".jed")
73 raise NotImplementedError
76 raise OSError("Subprocess failed")
79 class LatticeDiamondToolchain
:
80 def build(self
, platform
, fragment
, build_dir
="build", build_name
="top",
81 toolchain_path
="/opt/Diamond", run
=True, **kwargs
):
82 os
.makedirs(build_dir
, exist_ok
=True)
86 if not isinstance(fragment
, _Fragment
):
87 fragment
= fragment
.get_fragment()
88 platform
.finalize(fragment
)
90 v_output
= platform
.get_verilog(fragment
, name
=build_name
, **kwargs
)
91 named_sc
, named_pc
= platform
.resolve_signals(v_output
.ns
)
92 v_file
= build_name
+ ".v"
93 v_output
.write(v_file
)
94 sources
= platform
.sources |
{(v_file
, "verilog", "work")}
95 _build_files(platform
.device
, sources
, platform
.verilog_include_paths
, build_name
)
97 tools
.write_to_file(build_name
+ ".lpf", _build_lpf(named_sc
, named_pc
))
100 _run_diamond(build_name
, toolchain_path
)
106 def add_period_constraint(self
, platform
, clk
, period
):
107 # TODO: handle differential clk
108 platform
.add_platform_command("""FREQUENCY PORT "{clk}" {freq} MHz;""".format(freq
=str(float(1/period
)*1000), clk
="{clk}"), clk
=clk
)