1 # This file is Copyright (c) 2015 Florent Kermarrec <florent@enjoy-digital.fr>
9 from litex
.gen
.fhdl
.structure
import _Fragment
10 from litex
.gen
.fhdl
.verilog
import DummyAttrTranslate
12 from litex
.build
.generic_platform
import *
13 from litex
.build
import tools
14 from litex
.build
.lattice
import common
17 def _format_constraint(c
):
18 if isinstance(c
, Pins
):
19 return ("LOCATE COMP ", " SITE " + "\"" + c
.identifiers
[0] + "\"")
20 elif isinstance(c
, IOStandard
):
21 return ("IOBUF PORT ", " IO_TYPE=" + c
.name
)
22 elif isinstance(c
, Misc
):
26 def _format_lpf(signame
, pin
, others
, resname
):
27 fmt_c
= [_format_constraint(c
) for c
in ([Pins(pin
)] + others
)]
29 for pre
, suf
in fmt_c
:
30 r
+= pre
+ "\"" + signame
+ "\"" + suf
+ ";\n"
34 def _build_lpf(named_sc
, named_pc
):
35 r
= "BLOCK RESETPATHS;\n"
36 r
+= "BLOCK ASYNCPATHS;\n"
37 for sig
, pins
, others
, resname
in named_sc
:
39 for i
, p
in enumerate(pins
):
40 r
+= _format_lpf(sig
+ "[" + str(i
) + "]", p
, others
, resname
)
42 r
+= _format_lpf(sig
, pins
[0], others
, resname
)
44 r
+= "\n" + "\n\n".join(named_pc
)
48 def _build_files(device
, sources
, vincpaths
, build_name
):
50 tcl
.append("prj_project new -name \"{}\" -impl \"implementation\" -dev {} -synthesis \"synplify\"".format(build_name
, device
))
51 for path
in vincpaths
:
52 tcl
.append("prj_impl option {include path} {\"" + path
+ "\"}")
53 for filename
, language
, library
in sources
:
54 tcl
.append("prj_src add \"" + filename
+ "\" -work " + library
)
55 tcl
.append("prj_run Synthesis -impl implementation -forceOne")
56 tcl
.append("prj_run Translate -impl implementation")
57 tcl
.append("prj_run Map -impl implementation")
58 tcl
.append("prj_run PAR -impl implementation")
59 tcl
.append("prj_run Export -impl implementation -task Bitgen")
60 tools
.write_to_file(build_name
+ ".tcl", "\n".join(tcl
))
63 def _run_diamond(build_name
, toolchain_path
, 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")
72 elif sys
.platform
== "linux":
73 bindir
= os
.path
.join(toolchain_path
, 'bin/lin64')
74 envfile
= os
.path
.join(bindir
, 'diamond_env')
75 build_script_contents
= "# Autogenerated by LiteX\n"
76 build_script_contents
+= "set -e\n"
77 build_script_contents
+= "bindir='{}/'\n".format(bindir
)
78 build_script_contents
+= "source {}\n".format(envfile
)
79 build_script_contents
+= "diamondc {}.tcl | tee build.log\n".format(build_name
)
80 build_script_file
= "build_{}.sh".format(build_name
)
82 tools
.write_to_file(build_script_file
, build_script_contents
)
83 r
= subprocess
.call(['/bin/sh', build_script_file
])
84 shutil
.copy(os
.path
.join("implementation", build_name
+ "_implementation.bit"), build_name
+ ".bit")
86 raise NotImplementedError
89 raise OSError("Subprocess failed")
92 class LatticeDiamondToolchain
:
93 attr_translate
= DummyAttrTranslate()
95 special_overrides
= common
.diamond_special_overrides
97 def build(self
, platform
, fragment
, build_dir
="build", build_name
="top",
98 toolchain_path
="/opt/Diamond", run
=True, **kwargs
):
99 os
.makedirs(build_dir
, exist_ok
=True)
103 if not isinstance(fragment
, _Fragment
):
104 fragment
= fragment
.get_fragment()
105 platform
.finalize(fragment
)
107 v_output
= platform
.get_verilog(fragment
, name
=build_name
, **kwargs
)
108 named_sc
, named_pc
= platform
.resolve_signals(v_output
.ns
)
109 v_file
= build_name
+ ".v"
110 v_output
.write(v_file
)
111 sources
= platform
.sources |
{(v_file
, "verilog", "work")}
112 _build_files(platform
.device
, sources
, platform
.verilog_include_paths
, build_name
)
114 tools
.write_to_file(build_name
+ ".lpf", _build_lpf(named_sc
, named_pc
))
117 _run_diamond(build_name
, toolchain_path
)
123 def add_period_constraint(self
, platform
, clk
, period
):
124 # TODO: handle differential clk
125 platform
.add_platform_command("""FREQUENCY PORT "{clk}" {freq} MHz;""".format(freq
=str(float(1/period
)*1000), clk
="{clk}"), clk
=clk
)