Merge pull request #2025 from YosysHQ/eddie/frontend_cleanup
[yosys.git] / techlibs / xilinx / cells_xtra.py
1 #!/usr/bin/env python3
2
3 from argparse import ArgumentParser
4 from io import StringIO
5 from enum import Enum, auto
6 import os.path
7 import sys
8 import re
9
10
11 class Cell:
12 def __init__(self, name, keep=False, port_attrs={}):
13 self.name = name
14 self.keep = keep
15 self.port_attrs = port_attrs
16
17
18 CELLS = [
19 # Design element types listed in:
20 # - UG607 (Spartan 3)
21 # - UG613 (Spartan 3A)
22 # - UG617 (Spartan 3E)
23 # - UG615 (Spartan 6)
24 # - UG619 (Virtex 4)
25 # - UG621 (Virtex 5)
26 # - UG623 (Virtex 6)
27 # - UG953 (Series 7)
28 # - UG974 (Ultrascale)
29
30 # CLB -- RAM/ROM.
31 # Cell('RAM16X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
32 # Cell('RAM16X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
33 # Cell('RAM32X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
34 # Cell('RAM32X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
35 # Cell('RAM64X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
36 # Cell('RAM64X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
37 # Cell('RAM128X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
38 # Cell('RAM128X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
39 # Cell('RAM256X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
40 # Cell('RAM512X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
41 # Cell('RAM16X2S', port_attrs={'WCLK': ['clkbuf_sink']}),
42 # Cell('RAM32X2S', port_attrs={'WCLK': ['clkbuf_sink']}),
43 # Cell('RAM64X2S', port_attrs={'WCLK': ['clkbuf_sink']}),
44 # Cell('RAM16X4S', port_attrs={'WCLK': ['clkbuf_sink']}),
45 # Cell('RAM32X4S', port_attrs={'WCLK': ['clkbuf_sink']}),
46 # Cell('RAM16X8S', port_attrs={'WCLK': ['clkbuf_sink']}),
47 # Cell('RAM32X8S', port_attrs={'WCLK': ['clkbuf_sink']}),
48 # Cell('RAM16X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
49 # Cell('RAM16X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}),
50 # Cell('RAM32X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
51 # Cell('RAM32X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}),
52 # Cell('RAM64X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
53 # Cell('RAM64X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}),
54 # Cell('RAM128X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
55 # Cell('RAM256X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
56 # Cell('RAM32M', port_attrs={'WCLK': ['clkbuf_sink']}),
57 # Cell('RAM32M16', port_attrs={'WCLK': ['clkbuf_sink']}),
58 # Cell('RAM64M', port_attrs={'WCLK': ['clkbuf_sink']}),
59 # Cell('RAM64M8', port_attrs={'WCLK': ['clkbuf_sink']}),
60 # Cell('ROM16X1'),
61 # Cell('ROM32X1'),
62 # Cell('ROM64X1'),
63 # Cell('ROM128X1'),
64 # Cell('ROM256X1'),
65
66 # CLB -- registers/latches.
67 # Virtex 1/2/4/5, Spartan 3.
68 # Cell('FDCPE', port_attrs={'C': ['clkbuf_sink']}),
69 # Cell('FDRSE', port_attrs={'C': ['clkbuf_sink']}),
70 # Cell('LDCPE', port_attrs={'C': ['clkbuf_sink']}),
71 # Virtex 6, Spartan 6, Series 7, Ultrascale.
72 # Cell('FDCE'),
73 # Cell('FDPE'),
74 # Cell('FDRE'),
75 # Cell('FDSE'),
76 # Cell('LDCE'),
77 # Cell('LDPE'),
78 # Cell('AND2B1L'),
79 # Cell('OR2L'),
80
81 # CLB -- other.
82 # Cell('LUT1'),
83 # Cell('LUT2'),
84 # Cell('LUT3'),
85 # Cell('LUT4'),
86 # Cell('LUT5'),
87 # Cell('LUT6'),
88 # Cell('LUT6_2'),
89 # Cell('MUXF5'),
90 # Cell('MUXF6'),
91 # Cell('MUXF7'),
92 # Cell('MUXF8'),
93 # Cell('MUXF9'),
94 # Cell('CARRY4'),
95 # Cell('CARRY8'),
96 # Cell('MUXCY'),
97 # Cell('XORCY'),
98 # Cell('ORCY'),
99 # Cell('MULT_AND'),
100 # Cell('SRL16', port_attrs={'CLK': ['clkbuf_sink']}),
101 # Cell('SRL16E', port_attrs={'CLK': ['clkbuf_sink']}),
102 # Cell('SRLC16', port_attrs={'CLK': ['clkbuf_sink']}),
103 # Cell('SRLC16E', port_attrs={'CLK': ['clkbuf_sink']}),
104 # Cell('SRLC32E', port_attrs={'CLK': ['clkbuf_sink']}),
105 # Cell('CFGLUT5', port_attrs={'CLK': ['clkbuf_sink']}),
106
107 # Block RAM.
108 # Virtex.
109 # TODO: RAMB4_*
110 # Virtex 2, Spartan 3.
111 Cell('RAMB16_S1', port_attrs={'CLK': ['clkbuf_sink']}),
112 Cell('RAMB16_S2', port_attrs={'CLK': ['clkbuf_sink']}),
113 Cell('RAMB16_S4', port_attrs={'CLK': ['clkbuf_sink']}),
114 Cell('RAMB16_S9', port_attrs={'CLK': ['clkbuf_sink']}),
115 Cell('RAMB16_S18', port_attrs={'CLK': ['clkbuf_sink']}),
116 Cell('RAMB16_S36', port_attrs={'CLK': ['clkbuf_sink']}),
117 Cell('RAMB16_S1_S1', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
118 Cell('RAMB16_S1_S2', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
119 Cell('RAMB16_S1_S4', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
120 Cell('RAMB16_S1_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
121 Cell('RAMB16_S1_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
122 Cell('RAMB16_S1_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
123 Cell('RAMB16_S2_S2', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
124 Cell('RAMB16_S2_S4', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
125 Cell('RAMB16_S2_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
126 Cell('RAMB16_S2_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
127 Cell('RAMB16_S2_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
128 Cell('RAMB16_S4_S4', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
129 Cell('RAMB16_S4_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
130 Cell('RAMB16_S4_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
131 Cell('RAMB16_S4_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
132 Cell('RAMB16_S9_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
133 Cell('RAMB16_S9_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
134 Cell('RAMB16_S9_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
135 Cell('RAMB16_S18_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
136 Cell('RAMB16_S18_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
137 Cell('RAMB16_S36_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
138 # Spartan 3A (in addition to above).
139 Cell('RAMB16BWE_S18', port_attrs={'CLK': ['clkbuf_sink']}),
140 Cell('RAMB16BWE_S36', port_attrs={'CLK': ['clkbuf_sink']}),
141 Cell('RAMB16BWE_S18_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
142 Cell('RAMB16BWE_S18_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
143 Cell('RAMB16BWE_S36_S9', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
144 Cell('RAMB16BWE_S36_S18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
145 Cell('RAMB16BWE_S36_S36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
146 # Spartan 3A DSP.
147 Cell('RAMB16BWER', port_attrs={ 'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
148 # Spartan 6 (in addition to above).
149 Cell('RAMB8BWER', port_attrs={ 'CLKAWRCLK': ['clkbuf_sink'], 'CLKBRDCLK': ['clkbuf_sink']}),
150 # Virtex 4.
151 Cell('FIFO16', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
152 Cell('RAMB16', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
153 Cell('RAMB32_S64_ECC', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
154 # Virtex 5.
155 Cell('FIFO18', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
156 Cell('FIFO18_36', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
157 Cell('FIFO36', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
158 Cell('FIFO36_72', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
159 Cell('RAMB18', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
160 Cell('RAMB36', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
161 Cell('RAMB18SDP', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
162 Cell('RAMB36SDP', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
163 # Virtex 6 / Series 7.
164 Cell('FIFO18E1', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
165 Cell('FIFO36E1', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
166 #Cell('RAMB18E1', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']]}),
167 #Cell('RAMB36E1', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']]}),
168 # Ultrascale.
169 Cell('FIFO18E2', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
170 Cell('FIFO36E2', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
171 Cell('RAMB18E2', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']}),
172 Cell('RAMB36E2', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']}),
173
174 # Ultra RAM.
175 Cell('URAM288', port_attrs={'CLK': ['clkbuf_sink']}),
176 Cell('URAM288_BASE', port_attrs={'CLK': ['clkbuf_sink']}),
177
178 # Multipliers and DSP.
179 # Cell('MULT18X18'), # Virtex 2, Spartan 3
180 # Cell('MULT18X18S', port_attrs={'C': ['clkbuf_sink']}), # Spartan 3
181 # Cell('MULT18X18SIO', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3E
182 # Cell('DSP48A', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3A DSP
183 # Cell('DSP48A1', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 6
184 # Cell('DSP48', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 4
185 Cell('DSP48E', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 5
186 #Cell('DSP48E1', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 6 / Series 7
187 Cell('DSP48E2', port_attrs={'CLK': ['clkbuf_sink']}), # Ultrascale
188
189 # I/O logic.
190 # Virtex 2, Spartan 3.
191 Cell('IFDDRCPE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'D': ['iopad_external_pin']}),
192 Cell('IFDDRRSE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'D': ['iopad_external_pin']}),
193 Cell('OFDDRCPE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'Q': ['iopad_external_pin']}),
194 Cell('OFDDRRSE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'Q': ['iopad_external_pin']}),
195 Cell('OFDDRTCPE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'O': ['iopad_external_pin']}),
196 Cell('OFDDRTRSE', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink'], 'O': ['iopad_external_pin']}),
197 # Spartan 3E.
198 Cell('IDDR2', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink']}),
199 Cell('ODDR2', port_attrs={'C0': ['clkbuf_sink'], 'C1': ['clkbuf_sink']}),
200 # Virtex 4.
201 Cell('IDDR', port_attrs={'C': ['clkbuf_sink']}),
202 Cell('IDDR_2CLK', port_attrs={'C': ['clkbuf_sink'], 'CB': ['clkbuf_sink']}),
203 Cell('ODDR', port_attrs={'C': ['clkbuf_sink']}),
204 Cell('IDELAYCTRL', keep=True, port_attrs={'REFCLK': ['clkbuf_sink']}),
205 Cell('IDELAY', port_attrs={'C': ['clkbuf_sink']}),
206 Cell('ISERDES', port_attrs={
207 'CLK': ['clkbuf_sink'],
208 'OCLK': ['clkbuf_sink'],
209 'CLKDIV': ['clkbuf_sink'],
210 }),
211 Cell('OSERDES', port_attrs={'CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink']}),
212 # Virtex 5.
213 Cell('IODELAY', port_attrs={'C': ['clkbuf_sink']}),
214 Cell('ISERDES_NODELAY', port_attrs={
215 'CLK': ['clkbuf_sink'],
216 'CLKB': ['clkbuf_sink'],
217 'OCLK': ['clkbuf_sink'],
218 'CLKDIV': ['clkbuf_sink'],
219 }),
220 # Virtex 6.
221 Cell('IODELAYE1', port_attrs={'C': ['clkbuf_sink']}),
222 Cell('ISERDESE1', port_attrs={
223 'CLK': ['clkbuf_sink'],
224 'CLKB': ['clkbuf_sink'],
225 'OCLK': ['clkbuf_sink'],
226 'CLKDIV': ['clkbuf_sink'],
227 }),
228 Cell('OSERDESE1', port_attrs={'CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink']}),
229 # Series 7.
230 Cell('IDELAYE2', port_attrs={'C': ['clkbuf_sink']}),
231 Cell('ODELAYE2', port_attrs={'C': ['clkbuf_sink']}),
232 Cell('ISERDESE2', port_attrs={
233 'CLK': ['clkbuf_sink'],
234 'CLKB': ['clkbuf_sink'],
235 'OCLK': ['clkbuf_sink'],
236 'OCLKB': ['clkbuf_sink'],
237 'CLKDIV': ['clkbuf_sink'],
238 'CLKDIVP': ['clkbuf_sink'],
239 }),
240 Cell('OSERDESE2', port_attrs={'CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink']}),
241 Cell('PHASER_IN'),
242 Cell('PHASER_IN_PHY'),
243 Cell('PHASER_OUT'),
244 Cell('PHASER_OUT_PHY'),
245 Cell('PHASER_REF'),
246 Cell('PHY_CONTROL'),
247 # Ultrascale.
248 Cell('IDDRE1', port_attrs={'C': ['clkbuf_sink'], 'CB': ['clkbuf_sink']}),
249 Cell('ODDRE1', port_attrs={'C': ['clkbuf_sink']}),
250 Cell('IDELAYE3', port_attrs={'CLK': ['clkbuf_sink']}),
251 Cell('ODELAYE3', port_attrs={'CLK': ['clkbuf_sink']}),
252 Cell('ISERDESE3', port_attrs={
253 'CLK': ['clkbuf_sink'],
254 'CLK_B': ['clkbuf_sink'],
255 'FIFO_RD_CLK': ['clkbuf_sink'],
256 'CLKDIV': ['clkbuf_sink'],
257 }),
258 Cell('OSERDESE3', port_attrs={'CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink']}),
259 Cell('BITSLICE_CONTROL', keep=True),
260 Cell('RIU_OR'),
261 Cell('RX_BITSLICE'),
262 Cell('RXTX_BITSLICE'),
263 Cell('TX_BITSLICE'),
264 Cell('TX_BITSLICE_TRI'),
265 # Spartan 6.
266 Cell('IODELAY2', port_attrs={'IOCLK0': ['clkbuf_sink'], 'IOCLK1': ['clkbuf_sink'], 'CLK': ['clkbuf_sink']}),
267 Cell('IODRP2', port_attrs={'IOCLK0': ['clkbuf_sink'], 'IOCLK1': ['clkbuf_sink'], 'CLK': ['clkbuf_sink']}),
268 Cell('IODRP2_MCB', port_attrs={'IOCLK0': ['clkbuf_sink'], 'IOCLK1': ['clkbuf_sink'], 'CLK': ['clkbuf_sink']}),
269 Cell('ISERDES2', port_attrs={
270 'CLK0': ['clkbuf_sink'],
271 'CLK1': ['clkbuf_sink'],
272 'CLKDIV': ['clkbuf_sink'],
273 }),
274 Cell('OSERDES2', port_attrs={
275 'CLK0': ['clkbuf_sink'],
276 'CLK1': ['clkbuf_sink'],
277 'CLKDIV': ['clkbuf_sink'],
278 }),
279
280 # I/O buffers.
281 # Input.
282 # Cell('IBUF', port_attrs={'I': ['iopad_external_pin']}),
283 Cell('IBUF_DLY_ADJ', port_attrs={'I': ['iopad_external_pin']}),
284 Cell('IBUF_IBUFDISABLE', port_attrs={'I': ['iopad_external_pin']}),
285 Cell('IBUF_INTERMDISABLE', port_attrs={'I': ['iopad_external_pin']}),
286 Cell('IBUF_ANALOG', port_attrs={'I': ['iopad_external_pin']}),
287 Cell('IBUFE3', port_attrs={'I': ['iopad_external_pin']}),
288 Cell('IBUFDS', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
289 Cell('IBUFDS_DLY_ADJ', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
290 Cell('IBUFDS_IBUFDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
291 Cell('IBUFDS_INTERMDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
292 Cell('IBUFDS_DIFF_OUT', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
293 Cell('IBUFDS_DIFF_OUT_IBUFDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
294 Cell('IBUFDS_DIFF_OUT_INTERMDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
295 Cell('IBUFDSE3', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
296 Cell('IBUFDS_DPHY', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
297 # Cell('IBUFG', port_attrs={'I': ['iopad_external_pin']}),
298 Cell('IBUFGDS', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
299 Cell('IBUFGDS_DIFF_OUT', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
300 # I/O.
301 # Cell('IOBUF', port_attrs={'IO': ['iopad_external_pin']}),
302 Cell('IOBUF_DCIEN', port_attrs={'IO': ['iopad_external_pin']}),
303 Cell('IOBUF_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin']}),
304 Cell('IOBUFE3', port_attrs={'IO': ['iopad_external_pin']}),
305 Cell('IOBUFDS', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
306 Cell('IOBUFDS_DCIEN', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
307 Cell('IOBUFDS_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
308 Cell('IOBUFDS_DIFF_OUT', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
309 Cell('IOBUFDS_DIFF_OUT_DCIEN', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
310 Cell('IOBUFDS_DIFF_OUT_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
311 Cell('IOBUFDSE3', port_attrs={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
312 # Output.
313 # Cell('OBUF', port_attrs={'O': ['iopad_external_pin']}),
314 Cell('OBUFDS', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
315 Cell('OBUFDS_DPHY', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
316 # Output + tristate.
317 # Cell('OBUFT', port_attrs={'O': ['iopad_external_pin']}),
318 Cell('OBUFTDS', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
319 # Pulls.
320 Cell('KEEPER'),
321 Cell('PULLDOWN'),
322 Cell('PULLUP'),
323 # Misc.
324 Cell('DCIRESET', keep=True),
325 Cell('HPIO_VREF'), # Ultrascale
326
327 # Clock buffers (global).
328 # Cell('BUFG', port_attrs={'O': ['clkbuf_driver']}),
329 Cell('BUFGCE', port_attrs={'O': ['clkbuf_driver']}),
330 Cell('BUFGCE_1', port_attrs={'O': ['clkbuf_driver']}),
331 Cell('BUFGMUX', port_attrs={'O': ['clkbuf_driver']}),
332 Cell('BUFGMUX_1', port_attrs={'O': ['clkbuf_driver']}),
333 #Cell('BUFGCTRL', port_attrs={'O': ['clkbuf_driver']}),
334 Cell('BUFGMUX_CTRL', port_attrs={'O': ['clkbuf_driver']}),
335 Cell('BUFGMUX_VIRTEX4', port_attrs={'O': ['clkbuf_driver']}),
336 Cell('BUFG_GT', port_attrs={'O': ['clkbuf_driver']}),
337 Cell('BUFG_GT_SYNC'),
338 Cell('BUFG_PS', port_attrs={'O': ['clkbuf_driver']}),
339 Cell('BUFGCE_DIV', port_attrs={'O': ['clkbuf_driver']}),
340 Cell('BUFH', port_attrs={'O': ['clkbuf_driver']}),
341 #Cell('BUFHCE', port_attrs={'O': ['clkbuf_driver']}),
342
343 # Clock buffers (IO) -- Spartan 6.
344 Cell('BUFIO2', port_attrs={'IOCLK': ['clkbuf_driver'], 'DIVCLK': ['clkbuf_driver']}),
345 Cell('BUFIO2_2CLK', port_attrs={'IOCLK': ['clkbuf_driver'], 'DIVCLK': ['clkbuf_driver']}),
346 Cell('BUFIO2FB', port_attrs={'O': ['clkbuf_driver']}),
347 Cell('BUFPLL', port_attrs={'IOCLK': ['clkbuf_driver']}),
348 Cell('BUFPLL_MCB', port_attrs={'IOCLK0': ['clkbuf_driver'], 'IOCLK1': ['clkbuf_driver']}),
349
350 # Clock buffers (IO and regional) -- Virtex.
351 Cell('BUFIO', port_attrs={'O': ['clkbuf_driver']}),
352 Cell('BUFIODQS', port_attrs={'O': ['clkbuf_driver']}),
353 Cell('BUFR', port_attrs={'O': ['clkbuf_driver']}),
354 Cell('BUFMR', port_attrs={'O': ['clkbuf_driver']}),
355 Cell('BUFMRCE', port_attrs={'O': ['clkbuf_driver']}),
356
357 # Clock components.
358 # VIrtex.
359 # TODO: CLKDLL
360 # TODO: CLKDLLE
361 # TODO: CLKDLLHF
362 # Virtex 2, Spartan 3.
363 Cell('DCM'),
364 # Spartan 3E.
365 Cell('DCM_SP'),
366 # Spartan 6 (also uses DCM_SP and PLL_BASE).
367 Cell('DCM_CLKGEN'),
368 # Virtex 4/5.
369 Cell('DCM_ADV'),
370 Cell('DCM_BASE'),
371 Cell('DCM_PS'),
372 # Virtex 4.
373 Cell('PMCD'),
374 # Virtex 5.
375 Cell('PLL_ADV'),
376 Cell('PLL_BASE'),
377 # Virtex 6.
378 Cell('MMCM_ADV'),
379 Cell('MMCM_BASE'),
380 # Series 7.
381 Cell('MMCME2_ADV'),
382 Cell('MMCME2_BASE'),
383 Cell('PLLE2_ADV'),
384 Cell('PLLE2_BASE'),
385 # Ultrascale.
386 Cell('MMCME3_ADV'),
387 Cell('MMCME3_BASE'),
388 Cell('PLLE3_ADV'),
389 Cell('PLLE3_BASE'),
390 # Ultrascale+.
391 Cell('MMCME4_ADV'),
392 Cell('MMCME4_BASE'),
393 Cell('PLLE4_ADV'),
394 Cell('PLLE4_BASE'),
395
396 # Misc stuff.
397 Cell('BUFT'),
398 # Series 7 I/O FIFOs.
399 Cell('IN_FIFO', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
400 Cell('OUT_FIFO', port_attrs={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
401 # Ultrascale special synchronizer register.
402 Cell('HARD_SYNC', port_attrs={'CLK': ['clkbuf_sink']}),
403
404 # Singletons.
405 # Startup.
406 # TODO: STARTUP_VIRTEX
407 # TODO: STARTUP_VIRTEX2
408 Cell('STARTUP_SPARTAN3', keep=True),
409 Cell('STARTUP_SPARTAN3E', keep=True),
410 Cell('STARTUP_SPARTAN3A', keep=True),
411 Cell('STARTUP_SPARTAN6', keep=True),
412 Cell('STARTUP_VIRTEX4', keep=True),
413 Cell('STARTUP_VIRTEX5', keep=True),
414 Cell('STARTUP_VIRTEX6', keep=True),
415 Cell('STARTUPE2', keep=True), # Series 7
416 Cell('STARTUPE3', keep=True), # Ultrascale
417 # Capture trigger.
418 # TODO: CAPTURE_VIRTEX
419 # TODO: CAPTURE_VIRTEX2
420 Cell('CAPTURE_SPARTAN3', keep=True),
421 Cell('CAPTURE_SPARTAN3A', keep=True),
422 Cell('CAPTURE_VIRTEX4', keep=True),
423 Cell('CAPTURE_VIRTEX5', keep=True),
424 Cell('CAPTURE_VIRTEX6', keep=True),
425 Cell('CAPTUREE2', keep=True), # Series 7
426 # Internal Configuration Access Port.
427 # TODO: ICAP_VIRTEX2
428 Cell('ICAP_SPARTAN3A', keep=True),
429 Cell('ICAP_SPARTAN6', keep=True),
430 Cell('ICAP_VIRTEX4', keep=True),
431 Cell('ICAP_VIRTEX5', keep=True),
432 Cell('ICAP_VIRTEX6', keep=True),
433 Cell('ICAPE2', keep=True), # Series 7
434 Cell('ICAPE3', keep=True), # Ultrascale
435 # JTAG.
436 # TODO: BSCAN_VIRTEX
437 # TODO: BSCAN_VIRTEX2
438 Cell('BSCAN_SPARTAN3', keep=True),
439 Cell('BSCAN_SPARTAN3A', keep=True),
440 Cell('BSCAN_SPARTAN6', keep=True),
441 Cell('BSCAN_VIRTEX4', keep=True),
442 Cell('BSCAN_VIRTEX5', keep=True),
443 Cell('BSCAN_VIRTEX6', keep=True),
444 Cell('BSCANE2', keep=True), # Series 7, Ultrascale
445 # DNA port.
446 Cell('DNA_PORT'), # Virtex 5/6, Series 7, Spartan 3A/6
447 Cell('DNA_PORTE2'), # Ultrascale
448 # Frame ECC.
449 Cell('FRAME_ECC_VIRTEX4'),
450 Cell('FRAME_ECC_VIRTEX5'),
451 Cell('FRAME_ECC_VIRTEX6'),
452 Cell('FRAME_ECCE2'), # Series 7
453 Cell('FRAME_ECCE3'), # Ultrascale
454 # AXSS command access.
455 Cell('USR_ACCESS_VIRTEX4'),
456 Cell('USR_ACCESS_VIRTEX5'),
457 Cell('USR_ACCESS_VIRTEX6'),
458 Cell('USR_ACCESSE2'), # Series 7, Ultrascale
459 # Misc.
460 Cell('POST_CRC_INTERNAL'), # Spartan 6
461 Cell('SUSPEND_SYNC', keep=True), # Spartan 6
462 Cell('KEY_CLEAR', keep=True), # Virtex 5
463 Cell('MASTER_JTAG', keep=True), # Ultrascale
464 Cell('SPI_ACCESS', keep=True), # Spartan 3AN
465 Cell('EFUSE_USR'),
466
467 # ADC.
468 Cell('SYSMON'), # Virtex 5/6
469 Cell('XADC'), # Series 7
470 Cell('SYSMONE1'), # Ultrascale
471 Cell('SYSMONE4'), # Ultrascale+
472
473 # Gigabit transceivers.
474 # Spartan 6.
475 Cell('GTPA1_DUAL'),
476 # Virtex 2 Pro.
477 # TODO: GT_*
478 # TODO: GT10_*
479 # Virtex 4.
480 Cell('GT11_CUSTOM'),
481 Cell('GT11_DUAL'),
482 Cell('GT11CLK'),
483 Cell('GT11CLK_MGT'),
484 # Virtex 5.
485 Cell('GTP_DUAL'),
486 Cell('GTX_DUAL'),
487 Cell('CRC32', port_attrs={'CRCCLK': ['clkbuf_sink']}),
488 Cell('CRC64', port_attrs={'CRCCLK': ['clkbuf_sink']}),
489 # Virtex 6.
490 Cell('GTHE1_QUAD'),
491 Cell('GTXE1'),
492 Cell('IBUFDS_GTXE1', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
493 Cell('IBUFDS_GTHE1', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
494 # Series 7.
495 Cell('GTHE2_CHANNEL'),
496 Cell('GTHE2_COMMON'),
497 Cell('GTPE2_CHANNEL'),
498 Cell('GTPE2_COMMON'),
499 Cell('GTXE2_CHANNEL'),
500 Cell('GTXE2_COMMON'),
501 Cell('IBUFDS_GTE2', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
502 # Ultrascale.
503 Cell('GTHE3_CHANNEL'),
504 Cell('GTHE3_COMMON'),
505 Cell('GTHE4_CHANNEL'),
506 Cell('GTHE4_COMMON'),
507 Cell('GTYE3_CHANNEL'),
508 Cell('GTYE3_COMMON'),
509 Cell('GTYE4_CHANNEL'),
510 Cell('GTYE4_COMMON'),
511 Cell('IBUFDS_GTE3', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
512 Cell('IBUFDS_GTE4', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
513 Cell('OBUFDS_GTE3', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
514 Cell('OBUFDS_GTE3_ADV', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
515 Cell('OBUFDS_GTE4', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
516 Cell('OBUFDS_GTE4_ADV', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
517
518 # PCIE IP.
519 Cell('PCIE_A1'), # Spartan 6
520 Cell('PCIE_EP'), # Virtex 5
521 Cell('PCIE_2_0'), # Virtex 6
522 Cell('PCIE_2_1'), # Series 7
523 Cell('PCIE_3_0'), # Series 7
524 Cell('PCIE_3_1'), # Ultrascale
525 Cell('PCIE40E4'), # Ultrascale+
526
527 # Ethernet IP.
528 Cell('EMAC'), # Virtex 4
529 Cell('TEMAC'), # Virtex 5
530 Cell('TEMAC_SINGLE'), # Virtex 6
531 Cell('CMAC'), # Ultrascale
532 Cell('CMACE4'), # Ultrsacale+
533
534 # PowerPC.
535 # TODO PPC405 (Virtex 2)
536 Cell('PPC405_ADV'), # Virtex 4
537 Cell('PPC440'), # Virtex 5
538
539 # Misc hard IP.
540 Cell('MCB'), # Spartan 6 Memory Controller Block
541 Cell('PS7', keep=True), # The Zynq 7000 ARM Processor System.
542 Cell('PS8', keep=True), # The Zynq Ultrascale+ ARM Processor System.
543 Cell('ILKN'), # Ultrascale Interlaken
544 Cell('ILKNE4'), # Ultrascale+ Interlaken
545 ]
546
547
548 class State(Enum):
549 OUTSIDE = auto()
550 IN_MODULE = auto()
551 IN_OTHER_MODULE = auto()
552 IN_FUNCTION = auto()
553 IN_TASK = auto()
554
555 def xtract_cell_decl(cell, dirs, outf):
556 for dir in dirs:
557 fname = os.path.join(dir, cell.name + '.v')
558 try:
559 with open(fname) as f:
560 state = State.OUTSIDE
561 found = False
562 # Probably the most horrible Verilog "parser" ever written.
563 module_ports = []
564 invertible_ports = set()
565 for l in f:
566 l = l.partition('//')[0]
567 l = l.strip()
568 if l == 'module {}'.format(cell.name) or l.startswith('module {} '.format(cell.name)):
569 if found:
570 print('Multiple modules in {}.'.format(fname))
571 sys.exit(1)
572 elif state != State.OUTSIDE:
573 print('Nested modules in {}.'.format(fname))
574 sys.exit(1)
575 found = True
576 state = State.IN_MODULE
577 if cell.keep:
578 outf.write('(* keep *)\n')
579 outf.write('module {} (...);\n'.format(cell.name))
580 elif l.startswith('module '):
581 if state != State.OUTSIDE:
582 print('Nested modules in {}.'.format(fname))
583 sys.exit(1)
584 state = State.IN_OTHER_MODULE
585 elif l.startswith('task '):
586 if state == State.IN_MODULE:
587 state = State.IN_TASK
588 elif l.startswith('function '):
589 if state == State.IN_MODULE:
590 state = State.IN_FUNCTION
591 elif l == 'endtask':
592 if state == State.IN_TASK:
593 state = State.IN_MODULE
594 elif l == 'endfunction':
595 if state == State.IN_FUNCTION:
596 state = State.IN_MODULE
597 elif l == 'endmodule':
598 if state == State.IN_MODULE:
599 for kind, rng, port in module_ports:
600 for attr in cell.port_attrs.get(port, []):
601 outf.write(' (* {} *)\n'.format(attr))
602 if port in invertible_ports:
603 outf.write(' (* invertible_pin = "IS_{}_INVERTED" *)\n'.format(port))
604 if rng is None:
605 outf.write(' {} {};\n'.format(kind, port))
606 else:
607 outf.write(' {} {} {};\n'.format(kind, rng, port))
608 outf.write(l + '\n')
609 outf.write('\n')
610 elif state != State.IN_OTHER_MODULE:
611 print('endmodule in weird place in {}.'.format(cell.name, fname))
612 sys.exit(1)
613 state = State.OUTSIDE
614 elif l.startswith(('input ', 'output ', 'inout ')) and state == State.IN_MODULE:
615 if l.endswith((';', ',')):
616 l = l[:-1]
617 if ';' in l:
618 print('Weird port line in {} [{}].'.format(fname, l))
619 sys.exit(1)
620 kind, _, ports = l.partition(' ')
621 for port in ports.split(','):
622 port = port.strip()
623 if port.startswith('['):
624 rng, port = port.split()
625 else:
626 rng = None
627 module_ports.append((kind, rng, port))
628 elif l.startswith('parameter ') and state == State.IN_MODULE:
629 if 'UNPLACED' in l:
630 continue
631 if l.endswith((';', ',')):
632 l = l[:-1]
633 while ' ' in l:
634 l = l.replace(' ', ' ')
635 if ';' in l:
636 print('Weird parameter line in {} [{}].'.format(fname, l))
637 sys.exit(1)
638 outf.write(' {};\n'.format(l))
639 match = re.search('IS_([a-zA-Z0-9_]+)_INVERTED', l)
640 if match:
641 invertible_ports.add(match[1])
642 if state != State.OUTSIDE:
643 print('endmodule not found in {}.'.format(fname))
644 sys.exit(1)
645 if not found:
646 print('Cannot find module {} in {}.'.format(cell.name, fname))
647 sys.exit(1)
648 return
649 except FileNotFoundError:
650 continue
651 print('Cannot find {}.'.format(cell.name))
652 sys.exit(1)
653
654 if __name__ == '__main__':
655 parser = ArgumentParser(description='Extract Xilinx blackbox cell definitions from ISE and Vivado.')
656 parser.add_argument('vivado_dir', nargs='?', default='/opt/Xilinx/Vivado/2018.1')
657 parser.add_argument('ise_dir', nargs='?', default='/opt/Xilinx/ISE/14.7')
658 args = parser.parse_args()
659
660 dirs = [
661 os.path.join(args.vivado_dir, 'data/verilog/src/xeclib'),
662 os.path.join(args.vivado_dir, 'data/verilog/src/retarget'),
663 os.path.join(args.ise_dir, 'ISE_DS/ISE/verilog/xeclib/unisims'),
664 ]
665 for dir in dirs:
666 if not os.path.isdir(dir):
667 print('{} is not a directory'.format(dir))
668
669 out = StringIO()
670 for cell in CELLS:
671 xtract_cell_decl(cell, dirs, out)
672
673 with open('cells_xtra.v', 'w') as f:
674 f.write('// Created by cells_xtra.py from Xilinx models\n')
675 f.write('\n')
676 f.write(out.getvalue())