2 # see https://bugs.libre-soc.org/show_bug.cgi?id=739
4 from spec
.base
import PinSpec
5 from parse
import Parse
8 from pprint
import pprint
9 from spec
.ifaceprint
import display
, display_fns
, check_functions
10 from spec
.ifaceprint
import display_fixed
11 from collections
import OrderedDict
14 # TODO - Turn the number of pins per side into a variable?
15 pinbanks
= OrderedDict((
43 'PWM': 'PWM (pulse-width modulation)',
44 'MSPI0': 'SPI Master 1 (general)',
45 'MSPI1': 'SPI Master 2 (SDCard)',
46 'UART0': 'UART (TX/RX) 1',
47 'SYS': 'System Control',
49 'EINT': 'External Interrupt',
52 'MTWI': 'I2C Master 1',
57 #'LPC1': 'Low Pincount Interface 1',
58 #'LPC2': 'Low Pincount Interface 2',
61 ps
= PinSpec(pinbanks
, fixedpins
, function_names
)
63 ps
.sdram1("", ('W', 0), 0, 15, 6, rev
=True) # AD4-9, turned round
64 ps
.vdd("E", ('W', 6), 0, 0, 1)
65 ps
.vss("E", ('W', 7), 0, 0, 1)
66 ps
.vdd("I", ('W', 8), 0, 0, 1)
67 ps
.vss("I", ('W', 9), 0, 0, 1)
68 ps
.sdram1("", ('W', 10), 0, 0, 15, rev
=True) # SDRAM DAM0, D0-7, AD0-3
69 ps
.mi2c("", ('W', 26), 0, 0, 2)
70 ps
.vss("I", ('W', 28), 0, 1, 1)
71 ps
.vdd("I", ('W', 29), 0, 1, 1)
72 ps
.vss("E", ('W', 30), 0, 1, 1)
73 ps
.vdd("E", ('W', 31), 0, 1, 1)
75 ps
.sdram2("", ('S', 0), 0, 0, 4) # 1st 4, AD10-12,DQM1
76 ps
.vdd("E", ('S', 4), 0, 2, 1)
77 ps
.vss("E", ('S', 5), 0, 2, 1)
78 ps
.vdd("I", ('S', 6), 0, 2, 1)
79 ps
.vss("I", ('S', 7), 0, 2, 1)
80 ps
.sdram2("", ('S', 8), 0, 4, 8) # D8-15
81 ps
.sdram1("", ('S', 16), 0, 21, 9) # clk etc.
82 ps
.vss("I", ('S', 22), 0, 3, 1)
83 ps
.vdd("I", ('S', 23), 0, 3, 1)
84 ps
.vss("E", ('S', 24), 0, 3, 1)
85 ps
.vdd("E", ('S', 25), 0, 3, 1)
86 ps
.uart("0", ('S', 26), 0)
87 ps
.mspi("0", ('S', 28), 0)
89 ps
.gpio("", ('E', 0), 0, 0, 6) # GPIO 0-5
90 ps
.vss("E", ('E', 6), 0, 4, 1)
91 ps
.vdd("E", ('E', 7), 0, 4, 1)
92 ps
.vdd("I", ('E', 8), 0, 4, 1)
93 ps
.vss("I", ('E', 9), 0, 4, 1)
94 ps
.gpio("", ('E', 10), 0, 6, 3) # GPIO 6-8
95 ps
.jtag("", ('E', 13), 0, 0, 4)
96 ps
.gpio("", ('E', 17), 0, 9, 5) # GPIO 9-13
97 ps
.vss("I", ('E', 22), 0, 5, 1)
98 ps
.vdd("I", ('E', 23), 0, 5, 1)
99 ps
.vss("E", ('E', 24), 0, 5, 1)
100 ps
.vdd("E", ('E', 25), 0, 5, 1)
101 ps
.gpio("", ('E', 26), 0, 14, 2) # GPIO 14-15
102 ps
.eint("", ('E', 28), 0, 0, 3)
103 ps
.sys("", ('E', 31), 0, 5, 1) # analog VCO out in right top
105 ps
.vss("E", ('N', 6), 0, 6, 1)
106 ps
.vdd("E", ('N', 7), 0, 6, 1)
107 ps
.vdd("I", ('N', 8), 0, 6, 1)
108 ps
.vss("I", ('N', 9), 0, 6, 1)
109 #ps.pwm("", ('N', 2), 0, 0, 2) comment out (litex problem 25mar2021)
110 #ps.mspi("1", ('N', 7), 0) comment out (litex problem 25mar2021)
111 #ps.sdmmc("0", ('N', 11), 0) # comment out (litex problem 25mar2021)
112 ps
.sys("", ('N', 27), 0, 0, 5) # all but analog out in top right
113 ps
.vss("I", ('N', 22), 0, 7, 1)
114 ps
.vdd("I", ('N', 23), 0, 7, 1)
115 ps
.vss("E", ('N', 24), 0, 7, 1)
116 ps
.vdd("E", ('N', 25), 0, 7, 1)
118 #ps.mquadspi("1", ('S', 0), 0)
120 print "ps clocks", ps
.clocks
122 # Scenarios below can be spec'd out as either "find first interface"
123 # by name/number e.g. SPI1, or as "find in bank/mux" which must be
124 # spec'd as "BM:Name" where B is bank (A-F), M is Mux (0-3)
125 # EINT and PWM are grouped together, specially, but may still be spec'd
126 # using "BM:Name". Pins are removed in-order as listed from
127 # lists (interfaces, EINTs, PWMs) from available pins.
130 # 'SD0', litex problem 25mar2021
131 'UART0', 'GPIOS', 'GPIOE', 'JTAG', 'PWM', 'EINT',
134 # 'MSPI1', litex problem 25mar2021
137 ngi_router_pwm
= []#['B0:PWM_0']
139 'SD0': 'user-facing: internal (on Card), multiplexed with JTAG\n'
140 'and UART2, for debug purposes',
149 'B1:LCD/22': '18-bit RGB/TTL LCD',
150 'ULPI0/8': 'user-facing: internal (on Card), USB-OTG ULPI PHY',
151 'ULPI1': 'dual USB2 Host ULPI PHY'
154 ps
.add_scenario("NGI ROUTER Libre-SOC 180nm", ngi_router
, ngi_router_eint
, ngi_router_pwm
,
160 # map pins to litex name conventions, primarily for use in coriolis2
161 # yes this is a mess. it'll do the job though. improvements later
162 def pinparse(psp
, pinspec
):
163 p
= Parse(pinspec
, verify
=False)
168 print p
.muxed_cells_bank
170 # TODO - Turn the number of pins per side into a variable?
175 pads
= {'N': pn
, 'S': ps
, 'E': pe
, 'W': pw
}
183 for (padnum
, name
, x
), bank
in zip(p
.muxed_cells
, p
.muxed_cells_bank
):
186 domain
= None # TODO, get this from the PinSpec. sigh
188 start
= p
.bankstart
[bank
]
189 banknum
= padnum
- start
190 print "bank", bank
, banknum
, "padname", name
, padnum
, x
194 if name
.startswith('vss'):
195 name
= 'p_%s_' % name
[:-2] + name
[-1]
197 name
= 'ground_' + name
[-1]
200 name
= 'ioground_' + name
[-1]
204 elif name
.startswith('vdd'):
207 name
= 'power_' + name
[-1]
211 name
= 'iopower_' + name
[-1]
215 elif name
.startswith('sys'):
217 if name
== 'sys_pllclk':
218 pad
= ["p_"+name
, name
, name
]
219 elif name
== 'sys_rst':
220 #name = 'p_sys_rst_1'
221 pad
= [name
, name
, name
]
222 padbank
[banknum
] = name
223 print "sys_rst add", bank
, banknum
, name
225 elif name
== 'sys_pllclk':
227 elif name
== 'sys_pllvcout':
228 name
= 'sys_pll_vco_o'
229 pad
= ['p_' + name
, name
, name
, "A"] # A for Analog
230 elif name
== 'sys_plltestout':
231 name
= 'sys_pll_testout_o'
232 pad
= ['p_' + name
, name
, name
]
233 elif name
.startswith('sys_pllsel'):
235 name2
= 'sys_clksel_i(%s)' % i
236 name
= 'p_sys_clksel_' + i
237 pad
= [name
, name2
, name2
]
239 # iopads.append([pname, name, name])
240 print "sys pad", name
242 elif name
.startswith('mspi0') or name
.startswith('mspi1'):
247 elif suffix
== 'nss':
249 if name
.startswith('mspi0'):
250 prefix
= 'spimaster_'
252 prefix
= 'spisdcard_'
253 litex_name
= name
[:6] + suffix
254 name
= prefix
+ suffix
255 pad
= ['p_' + name
, name
, name
]
257 elif name
.startswith('sd0'):
259 if name
.startswith('sd0_d'):
261 name
= 'sdcard_data' + i
262 name2
= 'sdcard_data_%%s(%s)' % i
263 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
264 elif name
.startswith('sd0_cmd'):
266 name2
= 'sdcard_cmd_%s'
267 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
269 name
= 'sdcard_' + name
[4:]
270 pad
= ['p_' + name
, name
, name
]
271 litex_name
= orig_name
[:4] + "_".join(name
.split("_")[1:])
273 elif name
.startswith('sdr'):
275 if name
== 'sdr_clk':
277 pad
= ['p_' + name
, name
, name
]
278 elif name
.startswith('sdr_ad'):
280 name
= 'sdram_a_' + i
281 name2
= 'sdram_a(%s)' % i
282 pad
= ['p_' + name
, name2
, name2
]
283 elif name
.startswith('sdr_ba'):
285 name
= 'sdram_ba_' + i
286 name2
= 'sdram_ba(%s)' % i
287 pad
= ['p_' + name
, name2
, name2
]
288 elif name
.startswith('sdr_dqm'):
290 name
= 'sdram_dm_' + i
291 name2
= 'sdram_dm(%s)' % i
292 pad
= ['p_' + name
, name2
, name2
]
293 elif name
.startswith('sdr_d'):
295 name
= 'sdram_dq_' + i
296 name2
= 'sdram_dq_%%s(%s)' % i
297 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
298 elif name
== 'sdr_csn0':
300 pad
= ['p_' + name
, name
, name
]
301 elif name
[-1] == 'n':
302 name
= 'sdram_' + name
[4:-1] + '_n'
303 pad
= ['p_' + name
, name
, name
]
305 name
= 'sdram_' + name
[4:]
306 pad
= ['p_' + name
, name
, name
]
307 litex_name
= orig_name
[:4] + "_".join(name
.split("_")[1:])
309 elif name
.startswith('uart'):
311 name
= 'uart_' + name
[6:]
312 pad
= ['p_' + name
, name
, name
]
314 elif name
.startswith('gpio'):
319 name2
= 'gpio_%%s(%s)' % i
320 pad
= ['p_' + name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
321 print ("GPIO pad", name
, pad
)
322 litex_name
= "gpio_%s" % gbank
+ "_".join(name
.split("_")[1:])
324 elif name
.startswith('mtwi'):
327 litex_name
= 'mtwi' + suffix
328 name
= 'i2c' + suffix
329 if name
.startswith('i2c_sda'):
331 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
332 print ("I2C pad", name
, pad
)
334 pad
= ['p_' + name
, name
, name
]
336 elif name
.startswith('twi'):
338 name
= 'i2c' + name
[3:]
340 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
341 print ("I2C pad", name
, pad
)
343 elif name
.startswith('eint'):
347 name2
= 'eint_%s' % i
348 pad
= ['p_' + name
, name2
, name2
]
350 elif name
.startswith('pwm'):
354 name2
= 'pwm(%s)' % i
355 pad
= ['p_' + name
, name2
, name2
]
357 pad
= ['p_' + name
, name
, name
]
358 print ("GPIO pad", name
, pad
)
360 if litex_name
is None:
364 if name
and name
.startswith('jtag'):
367 if name
and not name
.startswith('p_'):
368 if 'power' not in name
and 'ground' not in name
:
371 padbank
[banknum
] = name
373 if domain
is not None:
374 if domain
not in domains
:
376 domains
[domain
].append(name
)
378 if domain
in psp
.clocks
and orig_name
.startswith(dl
):
379 clk
= psp
.clocks
[domain
]
380 if clk
.lower() in orig_name
: # TODO, might over-match
381 clocks
[domain
] = name
383 pinmap
[orig_name
] = name
384 litexmap
[litex_name
] = name
387 if domain
and pad
is not None:
388 # append direction from spec/domain. damn awkward processing
390 fn
, name
= orig_name
.split("_")
395 for k
in psp
.byspec
.keys():
396 if k
.startswith(domain
):
398 print "spec found", domain
, spec
399 assert spec
is not None
402 if pname
.lower().startswith(name
):
404 print "found spec", found
405 assert found
is not None
406 # whewwww. add the direction onto the pad spec list
413 elif pad
is not None:
418 for pl
in [pe
, pw
, pn
, ps
]:
419 for i
in range(len(pl
)):
421 name
= 'nc_%d' % nc_idx
422 name2
= 'nc(%d)' % nc_idx
425 iopads
.append([name
, name2
, name2
, "-"])
441 print "chip domains (excluding sys-default)"
443 print "chip clocks (excluding sys-default)"
453 'pads.instances' : iopads
,
454 'pins.specs' : psp
.byspec
,
456 'litex.map' : litexmap
,
457 'chip.domains' : domains
,
458 'chip.clocks' : clocks
,
459 'chip.n_intpower': n_intpower
,
460 'chip.n_extpower': n_extpower
,