2 # see https://bugs.libre-soc.org/show_bug.cgi?id=304
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 pinbanks
= OrderedDict((
42 'PWM': 'PWM (pulse-width modulation)',
43 'MSPI0': 'SPI Master 1 (general)',
44 'MSPI1': 'SPI Master 2 (SDCard)',
45 'UART0': 'UART (TX/RX) 1',
46 'SYS': 'System Control',
48 'EINT': 'External Interrupt',
51 'MTWI': 'I2C Master 1',
56 #'LPC1': 'Low Pincount Interface 1',
57 #'LPC2': 'Low Pincount Interface 2',
60 ps
= PinSpec(pinbanks
, fixedpins
, function_names
)
62 ps
.vss("E", ('N', 0), 0, 0, 1)
63 ps
.vdd("E", ('N', 1), 0, 0, 1)
64 ps
.sdram1("", ('N', 2), 0, 0, 30)
65 ps
.vss("I", ('N', 30), 0, 0, 1)
66 ps
.vdd("I", ('N', 31), 0, 0, 1)
68 ps
.vss("E", ('E', 0), 0, 1, 1)
69 ps
.vdd("E", ('E', 1), 0, 1, 1)
70 ps
.sdram2("", ('E', 2), 0, 0, 12)
71 ps
.vss("I", ('E', 14), 0, 1, 1)
72 ps
.vdd("I", ('E', 15), 0, 1, 1)
73 ps
.gpio("", ('E', 16), 0, 8, 8)
74 ps
.jtag("", ('E', 25), 0, 0, 4)
76 ps
.vss("I", ('S', 0), 0, 2, 1)
77 ps
.vdd("I", ('S', 1), 0, 2, 1)
78 ps
.mi2c("", ('S', 2), 0, 0, 2)
79 ps
.mspi("0", ('S', 8), 0)
80 ps
.uart("0", ('S', 13), 0)
81 ps
.gpio("", ('S', 15), 0, 0, 8)
82 ps
.sys("", ('S', 23), 0, 0, 7)
83 ps
.vss("I", ('S', 30), 0, 3, 1)
84 ps
.vdd("I", ('S', 31), 0, 3, 1)
86 ps
.vss("E", ('W', 0), 0, 2, 1)
87 ps
.vdd("E", ('W', 1), 0, 2, 1)
88 #ps.pwm("", ('W', 2), 0, 0, 2) comment out (litex problem 25mar2021)
89 ps
.eint("", ('W', 4), 0, 0, 3)
90 #ps.mspi("1", ('W', 7), 0) comment out (litex problem 25mar2021)
91 #ps.sdmmc("0", ('W', 11), 0) # comment out (litex problem 25mar2021)
92 ps
.vss("I", ('W', 30), 0, 4, 1)
93 ps
.vdd("I", ('W', 31), 0, 4, 1)
95 #ps.mquadspi("1", ('S', 0), 0)
97 print "ps clocks", ps
.clocks
99 # Scenarios below can be spec'd out as either "find first interface"
100 # by name/number e.g. SPI1, or as "find in bank/mux" which must be
101 # spec'd as "BM:Name" where B is bank (A-F), M is Mux (0-3)
102 # EINT and PWM are grouped together, specially, but may still be spec'd
103 # using "BM:Name". Pins are removed in-order as listed from
104 # lists (interfaces, EINTs, PWMs) from available pins.
107 # 'SD0', litex problem 25mar2021
108 'UART0', 'GPIOS', 'GPIOE', 'JTAG', 'PWM', 'EINT',
111 # 'MSPI1', litex problem 25mar2021
114 ls180_pwm
= []#['B0:PWM_0']
116 'SD0': 'user-facing: internal (on Card), multiplexed with JTAG\n'
117 'and UART2, for debug purposes',
126 'B1:LCD/22': '18-bit RGB/TTL LCD',
127 'ULPI0/8': 'user-facing: internal (on Card), USB-OTG ULPI PHY',
128 'ULPI1': 'dual USB2 Host ULPI PHY'
131 ps
.add_scenario("Libre-SOC 180nm", ls180
, ls180_eint
, ls180_pwm
,
137 # map pins to litex name conventions, primarily for use in coriolis2
138 # yes this is a mess. it'll do the job though. improvements later
139 def pinparse(psp
, pinspec
):
140 p
= Parse(pinspec
, verify
=False)
144 print p
.muxed_cells_bank
150 pads
= {'N': pn
, 'S': ps
, 'E': pe
, 'W': pw
}
158 for (padnum
, name
, x
), bank
in zip(p
.muxed_cells
, p
.muxed_cells_bank
):
160 domain
= None # TODO, get this from the PinSpec. sigh
162 start
= p
.bankstart
[bank
]
163 banknum
= padnum
- start
164 print "bank", bank
, banknum
, "padname", name
, padnum
, x
168 if name
.startswith('vss'):
169 name
= 'p_%s_' % name
[:-2] + name
[-1]
171 name
= 'ground_' + name
[-1]
174 name
= 'ioground_' + name
[-1]
178 elif name
.startswith('vdd'):
181 name
= 'power_' + name
[-1]
185 name
= 'iopower_' + name
[-1]
189 elif name
.startswith('sys'):
191 if name
== 'sys_clk':
192 pad
= ["p_"+name
, name
, name
]
193 elif name
== 'sys_rst':
194 #name = 'p_sys_rst_1'
195 pad
= [name
, name
, name
]
196 padbank
[banknum
] = name
197 print "sys_rst add", bank
, banknum
, name
199 elif name
== 'sys_pllclk':
201 elif name
== 'sys_pllock':
202 name
= 'sys_pll_lck_o'
203 pad
= ['p_' + name
, name
, name
]
204 elif name
== 'sys_pllout':
205 name
= 'sys_pll_18_o'
206 pad
= ['p_' + name
, name
, name
]
207 elif name
.startswith('sys_csel'):
209 name2
= 'sys_clksel_i(%s)' % i
210 name
= 'p_sys_clksel_' + i
211 pad
= [name
, name2
, name2
]
213 # iopads.append([pname, name, name])
214 print "sys pad", name
216 elif name
.startswith('mspi0') or name
.startswith('mspi1'):
221 elif suffix
== 'nss':
223 if name
.startswith('mspi0'):
224 prefix
= 'spimaster_'
226 prefix
= 'spisdcard_'
227 name
= prefix
+ suffix
228 pad
= ['p_' + name
, name
, name
]
230 elif name
.startswith('sd0'):
232 if name
.startswith('sd0_d'):
234 name
= 'sdcard_data' + i
235 name2
= 'sdcard_data_%%s(%s)' % i
236 pad
= ['p_' + name
, name
, name2
% 'o', name2
% 'i',
238 elif name
.startswith('sd0_cmd'):
240 name2
= 'sdcard_cmd_%s'
241 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
243 name
= 'sdcard_' + name
[4:]
244 pad
= ['p_' + name
, name
, name
]
246 elif name
.startswith('sdr'):
248 if name
== 'sdr_clk':
250 pad
= ['p_' + name
, name
, name
]
251 elif name
.startswith('sdr_ad'):
253 name
= 'sdram_a_' + i
254 name2
= 'sdram_a(%s)' % i
255 pad
= ['p_' + name
, name2
, name2
]
256 elif name
.startswith('sdr_ba'):
258 name
= 'sdram_ba_' + i
259 name2
= 'sdram_ba(%s)' % i
260 pad
= ['p_' + name
, name2
, name2
]
261 elif name
.startswith('sdr_dqm'):
263 name
= 'sdram_dm_' + i
264 name2
= 'sdram_dm(%s)' % i
265 pad
= ['p_' + name
, name2
, name2
]
266 elif name
.startswith('sdr_d'):
268 name
= 'sdram_dq_' + i
269 name2
= 'sdram_dq_%%s(%s)' % i
270 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', 'sdram_dq_oe']
271 elif name
== 'sdr_csn0':
273 pad
= ['p_' + name
, name
, name
]
274 elif name
[-1] == 'n':
275 name
= 'sdram_' + name
[4:-1] + '_n'
276 pad
= ['p_' + name
, name
, name
]
278 name
= 'sdram_' + name
[4:]
279 pad
= ['p_' + name
, name
, name
]
281 elif name
.startswith('uart'):
283 name
= 'uart_' + name
[6:]
284 pad
= ['p_' + name
, name
, name
]
286 elif name
.startswith('gpio'):
290 name2
= 'gpio_%%s(%s)' % i
291 pad
= ['p_' + name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
292 print ("GPIO pad", name
, pad
)
294 elif name
.startswith('mtwi'):
296 name
= 'i2c' + name
[4:]
297 if name
.startswith('i2c_sda'):
299 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
300 print ("I2C pad", name
, pad
)
302 pad
= ['p_' + name
, name
, name
]
304 elif name
.startswith('twi'):
306 name
= 'i2c' + name
[3:]
308 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
309 print ("I2C pad", name
, pad
)
311 elif name
.startswith('eint'):
315 name2
= 'eint_%s' % i
316 pad
= ['p_' + name
, name2
, name2
]
318 elif name
.startswith('pwm'):
322 name2
= 'pwm(%s)' % i
323 pad
= ['p_' + name
, name2
, name2
]
325 pad
= ['p_' + name
, name
, name
]
326 print ("GPIO pad", name
, pad
)
329 if name
and name
.startswith('jtag'):
332 if name
and not name
.startswith('p_'):
333 if 'power' not in name
and 'ground' not in name
:
336 padbank
[banknum
] = name
338 if domain
is not None:
339 if domain
not in domains
:
341 domains
[domain
].append(name
)
343 if domain
in psp
.clocks
and orig_name
.startswith(dl
):
344 clk
= psp
.clocks
[domain
]
345 if clk
.lower() in orig_name
: # TODO, might over-match
346 clocks
[domain
] = name
348 pinmap
[orig_name
] = name
351 if domain
and pad
is not None:
352 # append direction from spec/domain. damn awkward processing
354 fn
, name
= orig_name
.split("_")
359 for k
in psp
.byspec
.keys():
360 if k
.startswith(domain
):
362 print "spec found", domain
, spec
363 assert spec
is not None
366 if pname
.lower().startswith(name
):
368 print "found spec", found
369 assert found
is not None
370 # whewwww. add the direction onto the pad spec list
371 pad
.append(found
[-1])
373 elif pad
is not None:
378 for pl
in [pe
, pw
, pn
, ps
]:
379 for i
in range(len(pl
)):
381 name
= 'nc_%d' % nc_idx
382 name2
= 'nc(%d)' % nc_idx
385 iopads
.append([name
, name2
, name2
, "-"])
401 print "chip domains (excluding sys-default)"
403 print "chip clocks (excluding sys-default)"
413 'pads.instances' : iopads
,
414 'pins.specs' : psp
.byspec
,
416 'chip.domains' : domains
,
417 'chip.clocks' : clocks
,
418 'chip.n_intpower': n_intpower
,
419 'chip.n_extpower': n_extpower
,
422 chip
= json
.dumps(chip
)
423 with
open("ls180/litex_pinpads.json", "w") as f
: