6e9c63cee4865d06f1ccdec722ee84b5f35d7238
[nmigen.git] / nmigen / vendor / quicklogic.py
1 from abc import abstractproperty
2
3 from ..hdl import *
4 from ..lib.cdc import ResetSynchronizer
5 from ..build import *
6
7
8 __all__ = ["QuicklogicPlatform"]
9
10
11 class QuicklogicPlatform(TemplatedPlatform):
12 """
13 Symbiflow toolchain
14 -------------------
15
16 Required tools:
17 * ``symbiflow_synth``
18 * ``symbiflow_pack``
19 * ``symbiflow_place``
20 * ``symbiflow_route``
21 * ``symbiflow_write_fasm``
22 * ``symbiflow_write_bitstream``
23
24 The environment is populated by running the script specified in the environment variable
25 ``NMIGEN_ENV_QLSymbiflow``, if present.
26
27 Available overrides:
28 * ``add_constraints``: inserts commands in XDC file.
29 """
30
31 device = abstractproperty()
32 package = abstractproperty()
33
34 # Since the QuickLogic version of SymbiFlow toolchain is not upstreamed yet
35 # we should distinguish the QuickLogic version from mainline one.
36 # QuickLogic toolchain: https://github.com/QuickLogic-Corp/quicklogic-fpga-toolchain/releases
37 toolchain = "QLSymbiflow"
38
39 required_tools = [
40 "symbiflow_synth",
41 "symbiflow_pack",
42 "symbiflow_place",
43 "symbiflow_route",
44 "symbiflow_write_fasm",
45 "symbiflow_write_bitstream"
46 ]
47 file_templates = {
48 **TemplatedPlatform.build_script_templates,
49 "{{name}}.v": r"""
50 /* {{autogenerated}} */
51 {{emit_verilog()}}
52 """,
53 "{{name}}.debug.v": r"""
54 /* {{autogenerated}} */
55 {{emit_debug_verilog()}}
56 """,
57 "{{name}}.pcf": r"""
58 # {{autogenerated}}
59 {% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%}
60 set_io {{port_name}} {{pin_name}}
61 {% endfor %}
62 """,
63 "{{name}}.xdc": r"""
64 # {{autogenerated}}
65 {% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%}
66 {% for attr_name, attr_value in attrs.items() -%}
67 set_property {{attr_name}} {{attr_value}} [get_ports {{port_name|tcl_escape}} }]
68 {% endfor %}
69 {% endfor %}
70 {{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
71 """,
72 "{{name}}.sdc": r"""
73 # {{autogenerated}}
74 {% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
75 {% if port_signal is not none -%}
76 create_clock -period {{100000000/frequency}} {{port_signal.name|ascii_escape}}
77 {% endif %}
78 {% endfor %}
79 """
80 }
81 command_templates = [
82 r"""
83 {{invoke_tool("symbiflow_synth")}}
84 -t {{name}}
85 -v {% for file in platform.iter_files(".v", ".sv", ".vhd", ".vhdl") -%} {{file}} {% endfor %} {{name}}.v
86 -d {{platform.device}}
87 -p {{name}}.pcf
88 -P {{platform.package}}
89 -x {{name}}.xdc
90 """,
91 r"""
92 {{invoke_tool("symbiflow_pack")}}
93 -e {{name}}.eblif
94 -d {{platform.device}}
95 -s {{name}}.sdc
96 """,
97 r"""
98 {{invoke_tool("symbiflow_place")}}
99 -e {{name}}.eblif
100 -d {{platform.device}}
101 -p {{name}}.pcf
102 -n {{name}}.net
103 -P {{platform.package}}
104 -s {{name}}.sdc
105 """,
106 r"""
107 {{invoke_tool("symbiflow_route")}}
108 -e {{name}}.eblif
109 -d {{platform.device}}
110 -s {{name}}.sdc
111 """,
112 r"""
113 {{invoke_tool("symbiflow_write_fasm")}}
114 -e {{name}}.eblif
115 -d {{platform.device}}
116 -s {{name}}.sdc
117 """,
118 r"""
119 {{invoke_tool("symbiflow_write_bitstream")}}
120 -f {{name}}.fasm
121 -d {{platform.device}}
122 -P {{platform.package}}
123 -b {{name}}.bit
124 """
125 ]
126
127 # Common logic
128
129 def __init__(self):
130 super().__init__()
131
132 def add_clock_constraint(self, clock, frequency):
133 super().add_clock_constraint(clock, frequency)
134 clock.attrs["keep"] = "TRUE"
135
136 def create_missing_domain(self, name):
137 if name == "sync" and self.default_clk is not None:
138 m = Module()
139 if self.default_clk == "sys_clk0":
140 clk_i = Signal()
141 sys_clk0 = Signal()
142 m.submodules += Instance("qlal4s3b_cell_macro",
143 o_Sys_Clk0=sys_clk0)
144 m.submodules += Instance("gclkbuff",
145 o_A=sys_clk0,
146 o_Z=clk_i)
147 else:
148 clk_i = self.request(self.default_clk).i
149
150 if self.default_rst is not None:
151 rst_i = self.request(self.default_rst).i
152 else:
153 rst_i = Const(0)
154
155 m.domains += ClockDomain("sync")
156 m.d.comb += ClockSignal("sync").eq(clk_i)
157 m.submodules.reset_sync = ResetSynchronizer(rst_i, domain="sync")
158 return m