dd4e300ae0c98ebfcf6905a97fff5eb24bda0f99
3 from argparse
import ArgumentParser
4 from io
import StringIO
5 from enum
import Enum
, auto
11 def __init__(self
, name
, keep
=False, port_attrs
={}):
14 self
.port_attrs
= port_attrs
18 # Design elements types listed in Xilinx UG953
19 Cell('BSCANE2', keep
=True),
20 # Cell('BUFG', port_attrs={'O': ['clkbuf_driver']}),
21 Cell('BUFGCE', port_attrs
={'O': ['clkbuf_driver']}),
22 Cell('BUFGCE_1', port_attrs
={'O': ['clkbuf_driver']}),
23 #Cell('BUFGCTRL', port_attrs={'O': ['clkbuf_driver']}),
24 Cell('BUFGMUX', port_attrs
={'O': ['clkbuf_driver']}),
25 Cell('BUFGMUX_1', port_attrs
={'O': ['clkbuf_driver']}),
26 Cell('BUFGMUX_CTRL', port_attrs
={'O': ['clkbuf_driver']}),
27 Cell('BUFH', port_attrs
={'O': ['clkbuf_driver']}),
28 #Cell('BUFHCE', port_attrs={'O': ['clkbuf_driver']}),
29 Cell('BUFIO', port_attrs
={'O': ['clkbuf_driver']}),
30 Cell('BUFMR', port_attrs
={'O': ['clkbuf_driver']}),
31 Cell('BUFMRCE', port_attrs
={'O': ['clkbuf_driver']}),
32 Cell('BUFR', port_attrs
={'O': ['clkbuf_driver']}),
33 Cell('CAPTUREE2', keep
=True),
35 Cell('CFGLUT5', port_attrs
={'CLK': ['clkbuf_sink']}),
36 Cell('DCIRESET', keep
=True),
38 Cell('DSP48E1', port_attrs
={'CLK': ['clkbuf_sink']}),
44 Cell('FIFO18E1', port_attrs
={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
45 Cell('FIFO36E1', port_attrs
={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
47 Cell('GTHE2_CHANNEL'),
49 Cell('GTPE2_CHANNEL'),
51 Cell('GTXE2_CHANNEL'),
53 # Cell('IBUF', port_attrs={'I': ['iopad_external_pin']}),
54 Cell('IBUF_IBUFDISABLE', port_attrs
={'I': ['iopad_external_pin']}),
55 Cell('IBUF_INTERMDISABLE', port_attrs
={'I': ['iopad_external_pin']}),
56 Cell('IBUFDS', port_attrs
={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
57 Cell('IBUFDS_DIFF_OUT', port_attrs
={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
58 Cell('IBUFDS_DIFF_OUT_IBUFDISABLE', port_attrs
={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
59 Cell('IBUFDS_DIFF_OUT_INTERMDISABLE', port_attrs
={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
60 Cell('IBUFDS_GTE2', port_attrs
={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
61 Cell('IBUFDS_IBUFDISABLE', port_attrs
={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
62 Cell('IBUFDS_INTERMDISABLE', port_attrs
={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
63 Cell('IBUFG', port_attrs
={'I': ['iopad_external_pin']}),
64 Cell('IBUFGDS', port_attrs
={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
65 Cell('IBUFGDS_DIFF_OUT', port_attrs
={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
66 Cell('ICAPE2', keep
=True),
67 Cell('IDDR', port_attrs
={'C': ['clkbuf_sink']}),
68 Cell('IDDR_2CLK', port_attrs
={'C': ['clkbuf_sink'], 'CB': ['clkbuf_sink']}),
69 Cell('IDELAYCTRL', keep
=True, port_attrs
={'REFCLK': ['clkbuf_sink']}),
70 Cell('IDELAYE2', port_attrs
={'C': ['clkbuf_sink']}),
71 Cell('IN_FIFO', port_attrs
={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
72 Cell('IOBUF', port_attrs
={'IO': ['iopad_external_pin']}),
73 Cell('IOBUF_DCIEN', port_attrs
={'IO': ['iopad_external_pin']}),
74 Cell('IOBUF_INTERMDISABLE', port_attrs
={'IO': ['iopad_external_pin']}),
75 Cell('IOBUFDS', port_attrs
={'IO': ['iopad_external_pin']}),
76 Cell('IOBUFDS_DCIEN', port_attrs
={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
77 Cell('IOBUFDS_DIFF_OUT', port_attrs
={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
78 Cell('IOBUFDS_DIFF_OUT_DCIEN', port_attrs
={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
79 Cell('IOBUFDS_DIFF_OUT_INTERMDISABLE', port_attrs
={'IO': ['iopad_external_pin'], 'IOB': ['iopad_external_pin']}),
80 Cell('ISERDESE2', port_attrs
={
81 'CLK': ['clkbuf_sink'],
82 'CLKB': ['clkbuf_sink'],
83 'OCLK': ['clkbuf_sink'],
84 'OCLKB': ['clkbuf_sink'],
85 'CLKDIV': ['clkbuf_sink'],
86 'CLKDIVP': ['clkbuf_sink'],
102 # Cell('OBUF', port_attrs={'O': ['iopad_external_pin']}),
103 Cell('OBUFDS', port_attrs
={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
104 Cell('OBUFT', port_attrs
={'O': ['iopad_external_pin']}),
105 Cell('OBUFTDS', port_attrs
={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
106 Cell('ODDR', port_attrs
={'C': ['clkbuf_sink']}),
107 Cell('ODELAYE2', port_attrs
={'C': ['clkbuf_sink']}),
108 Cell('OSERDESE2', port_attrs
={'CLK': ['clkbuf_sink'], 'CLKDIV': ['clkbuf_sink']}),
109 Cell('OUT_FIFO', port_attrs
={'RDCLK': ['clkbuf_sink'], 'WRCLK': ['clkbuf_sink']}),
111 Cell('PHASER_IN_PHY'),
113 Cell('PHASER_OUT_PHY'),
118 Cell('PS7', keep
=True),
121 #Cell('RAM128X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
122 Cell('RAM128X1S', port_attrs
={'WCLK': ['clkbuf_sink']}),
123 Cell('RAM256X1S', port_attrs
={'WCLK': ['clkbuf_sink']}),
124 Cell('RAM32M', port_attrs
={'WCLK': ['clkbuf_sink']}),
125 #Cell('RAM32X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
126 Cell('RAM32X1S', port_attrs
={'WCLK': ['clkbuf_sink']}),
127 Cell('RAM32X1S_1', port_attrs
={'WCLK': ['clkbuf_sink']}),
128 Cell('RAM32X2S', port_attrs
={'WCLK': ['clkbuf_sink']}),
129 Cell('RAM64M', port_attrs
={'WCLK': ['clkbuf_sink']}),
130 #Cell('RAM64X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
131 Cell('RAM64X1S', port_attrs
={'WCLK': ['clkbuf_sink']}),
132 Cell('RAM64X1S_1', port_attrs
={'WCLK': ['clkbuf_sink']}),
133 Cell('RAM64X2S', port_attrs
={'WCLK': ['clkbuf_sink']}),
134 # Cell('RAMB18E1', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']}),
135 # Cell('RAMB36E1', port_attrs={'CLKARDCLK': ['clkbuf_sink'], 'CLKBWRCLK': ['clkbuf_sink']}),
140 #Cell('SRL16E', port_attrs={'CLK': ['clkbuf_sink']}),
141 #Cell('SRLC32E', port_attrs={'CLK': ['clkbuf_sink']}),
142 Cell('STARTUPE2', keep
=True),
143 Cell('USR_ACCESSE2'),
150 IN_OTHER_MODULE
= auto()
154 def xtract_cell_decl(cell
, dirs
, outf
):
156 fname
= os
.path
.join(dir, cell
.name
+ '.v')
158 with
open(fname
) as f
:
159 state
= State
.OUTSIDE
161 # Probably the most horrible Verilog "parser" ever written.
163 l
= l
.partition('//')[0]
165 if l
== 'module {}'.format(cell
.name
) or l
.startswith('module {} '.format(cell
.name
)):
167 print('Multiple modules in {}.'.format(fname
))
169 elif state
!= State
.OUTSIDE
:
170 print('Nested modules in {}.'.format(fname
))
173 state
= State
.IN_MODULE
175 outf
.write('(* keep *)\n')
176 outf
.write('module {} (...);\n'.format(cell
.name
))
177 elif l
.startswith('module '):
178 if state
!= State
.OUTSIDE
:
179 print('Nested modules in {}.'.format(fname
))
181 state
= State
.IN_OTHER_MODULE
182 elif l
.startswith('task '):
183 if state
== State
.IN_MODULE
:
184 state
= State
.IN_TASK
185 elif l
.startswith('function '):
186 if state
== State
.IN_MODULE
:
187 state
= State
.IN_FUNCTION
189 if state
== State
.IN_TASK
:
190 state
= State
.IN_MODULE
191 elif l
== 'endfunction':
192 if state
== State
.IN_FUNCTION
:
193 state
= State
.IN_MODULE
194 elif l
== 'endmodule':
195 if state
== State
.IN_MODULE
:
198 elif state
!= State
.IN_OTHER_MODULE
:
199 print('endmodule in weird place in {}.'.format(cell
.name
, fname
))
201 state
= State
.OUTSIDE
202 elif l
.startswith(('input ', 'output ', 'inout ')) and state
== State
.IN_MODULE
:
203 if l
.endswith((';', ',')):
206 print('Weird port line in {} [{}].'.format(fname
, l
))
208 kind
, _
, ports
= l
.partition(' ')
209 for port
in ports
.split(','):
211 for attr
in cell
.port_attrs
.get(port
, []):
212 outf
.write(' (* {} *)\n'.format(attr
))
213 outf
.write(' {} {};\n'.format(kind
, port
))
214 elif l
.startswith('parameter ') and state
== State
.IN_MODULE
:
217 if l
.endswith((';', ',')):
220 l
= l
.replace(' ', ' ')
222 print('Weird parameter line in {} [{}].'.format(fname
, l
))
224 outf
.write(' {};\n'.format(l
))
225 if state
!= State
.OUTSIDE
:
226 print('endmodule not found in {}.'.format(fname
))
229 print('Cannot find module {} in {}.'.format(cell
.name
, fname
))
232 except FileNotFoundError
:
234 print('Cannot find {}.'.format(cell
.name
))
237 if __name__
== '__main__':
238 parser
= ArgumentParser(description
='Extract Xilinx blackbox cell definitions from Vivado.')
239 parser
.add_argument('vivado_dir', nargs
='?', default
='/opt/Xilinx/Vivado/2018.1')
240 args
= parser
.parse_args()
243 os
.path
.join(args
.vivado_dir
, 'data/verilog/src/xeclib'),
244 os
.path
.join(args
.vivado_dir
, 'data/verilog/src/retarget'),
247 if not os
.path
.isdir(dir):
248 print('{} is not a directory'.format(dir))
252 xtract_cell_decl(cell
, dirs
, out
)
254 with
open('cells_xtra.v', 'w') as f
:
255 f
.write('// Created by cells_xtra.py from Xilinx models\n')
257 f
.write(out
.getvalue())