fix litex name map
[pinmux.git] / src / spec / ls180.py
1 #!/usr/bin/env python
2 # see https://bugs.libre-soc.org/show_bug.cgi?id=304
3
4 from spec.base import PinSpec
5 from parse import Parse
6 import json
7
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
12
13 def pinspec():
14 pinbanks = OrderedDict((
15 ('N', (32, 2)),
16 ('E', (32, 2)),
17 ('S', (32, 2)),
18 ('W', (32, 2)),
19 ))
20 fixedpins = {
21 'CTRL_SYS': [
22 'TEST',
23 'JTAG_SEL',
24 'UBOOT_SEL',
25 'NMI#',
26 'RESET#',
27 'CLK24M_IN',
28 'CLK24M_OUT',
29 'PLLTEST',
30 'PLLREGIO',
31 'PLLVP25',
32 'PLLDV',
33 'PLLVREG',
34 'PLLGND',
35 ],
36 'POWER_GPIO': [
37 'VDD_GPIOB',
38 'GND_GPIOB',
39 ]}
40 fixedpins = {}
41 function_names = {
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',
47 'GPIO': 'GPIO',
48 'EINT': 'External Interrupt',
49 'PWM': 'PWM',
50 'JTAG': 'JTAG',
51 'MTWI': 'I2C Master 1',
52 'SD0': 'SD/MMC 1',
53 'SDR': 'SDRAM',
54 'VDD': 'Power',
55 'VSS': 'GND',
56 #'LPC1': 'Low Pincount Interface 1',
57 #'LPC2': 'Low Pincount Interface 2',
58 }
59
60 ps = PinSpec(pinbanks, fixedpins, function_names)
61
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)
67
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)
75
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, 2) # should be 7, to do all PLL pins
83 ps.vss("I", ('S', 30), 0, 3, 1)
84 ps.vdd("I", ('S', 31), 0, 3, 1)
85
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)
94
95 #ps.mquadspi("1", ('S', 0), 0)
96
97 print "ps clocks", ps.clocks
98
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.
105
106 ls180 = [
107 # 'SD0', litex problem 25mar2021
108 'UART0', 'GPIOS', 'GPIOE', 'JTAG', 'PWM', 'EINT',
109 'VDD', 'VSS', 'SYS',
110 'MTWI', 'MSPI0',
111 # 'MSPI1', litex problem 25mar2021
112 'SDR']
113 ls180_eint = []
114 ls180_pwm = []#['B0:PWM_0']
115 descriptions = {
116 'SD0': 'user-facing: internal (on Card), multiplexed with JTAG\n'
117 'and UART2, for debug purposes',
118 'MTWI': 'I2C.\n',
119 'E2:SD1': '',
120 'MSPI1': '',
121 'UART0': '',
122 'LPC1': '',
123 'SYS': '',
124 'LPC2': '',
125 'SDR': '',
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'
129 }
130
131 ps.add_scenario("Libre-SOC 180nm", ls180, ls180_eint, ls180_pwm,
132 descriptions)
133
134 return ps
135
136
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)
141 pinmap = {}
142 litexmap = {}
143
144 print p.muxed_cells
145 print p.muxed_cells_bank
146
147 ps = [''] * 32
148 pn = [''] * 32
149 pe = [''] * 32
150 pw = [''] * 32
151 pads = {'N': pn, 'S': ps, 'E': pe, 'W': pw}
152
153 iopads = []
154 domains = {}
155 clocks = {}
156
157 n_intpower = 0
158 n_extpower = 0
159 for (padnum, name, x), bank in zip(p.muxed_cells, p.muxed_cells_bank):
160 orig_name = name
161 litex_name = None
162 domain = None # TODO, get this from the PinSpec. sigh
163 padnum = int(padnum)
164 start = p.bankstart[bank]
165 banknum = padnum - start
166 print "bank", bank, banknum, "padname", name, padnum, x
167 padbank = pads[bank]
168 pad = None
169 # VSS
170 if name.startswith('vss'):
171 name = 'p_%s_' % name[:-2] + name[-1]
172 if 'i' in name:
173 name = 'ground_' + name[-1]
174 name2 = 'vss'
175 else:
176 name = 'ioground_' + name[-1]
177 name2 = 'iovss'
178 pad = [name, name2]
179 # VDD
180 elif name.startswith('vdd'):
181 if 'i' in name:
182 n_intpower += 1
183 name = 'power_' + name[-1]
184 name2 = 'vdd'
185 else:
186 n_extpower += 1
187 name = 'iopower_' + name[-1]
188 name2 = 'iovdd'
189 pad = [name, name2]
190 # SYS
191 elif name.startswith('sys'):
192 domain = 'SYS'
193 if name == 'sys_clk':
194 pad = ["p_"+name, name, name]
195 elif name == 'sys_rst':
196 #name = 'p_sys_rst_1'
197 pad = [name, name, name]
198 padbank[banknum] = name
199 print "sys_rst add", bank, banknum, name
200 name = None
201 elif name == 'sys_pllclk':
202 name = None # ignore
203 elif name == 'sys_pllvcout':
204 name = 'sys_pll_vco_o'
205 pad = ['p_' + name, name, name]
206 elif name == 'sys_plltestout':
207 name = 'sys_pll_testout_o'
208 pad = ['p_' + name, name, name]
209 elif name.startswith('sys_pllsel'):
210 i = name[-1]
211 name2 = 'sys_clksel_i(%s)' % i
212 name = 'p_sys_clksel_' + i
213 pad = [name, name2, name2]
214 #if name:
215 # iopads.append([pname, name, name])
216 print "sys pad", name
217 # SPI Card
218 elif name.startswith('mspi0') or name.startswith('mspi1'):
219 domain = 'MSPI'
220 suffix = name[6:]
221 if suffix == 'ck':
222 suffix = 'clk'
223 elif suffix == 'nss':
224 suffix = 'cs_n'
225 if name.startswith('mspi0'):
226 prefix = 'spimaster_'
227 else:
228 prefix = 'spisdcard_'
229 litex_name = name[:6] + suffix
230 name = prefix + suffix
231 pad = ['p_' + name, name, name]
232 # SD/MMC
233 elif name.startswith('sd0'):
234 domain = 'SD'
235 if name.startswith('sd0_d'):
236 i = name[5:]
237 name = 'sdcard_data' + i
238 name2 = 'sdcard_data_%%s(%s)' % i
239 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
240 elif name.startswith('sd0_cmd'):
241 name = 'sdcard_cmd'
242 name2 = 'sdcard_cmd_%s'
243 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
244 else:
245 name = 'sdcard_' + name[4:]
246 pad = ['p_' + name, name, name]
247 litex_name = orig_name[:4] + "_".join(name.split("_")[1:])
248 # SDRAM
249 elif name.startswith('sdr'):
250 domain = 'SDR'
251 if name == 'sdr_clk':
252 name = 'sdram_clock'
253 pad = ['p_' + name, name, name]
254 elif name.startswith('sdr_ad'):
255 i = name[6:]
256 name = 'sdram_a_' + i
257 name2 = 'sdram_a(%s)' % i
258 pad = ['p_' + name, name2, name2]
259 elif name.startswith('sdr_ba'):
260 i = name[-1]
261 name = 'sdram_ba_' + i
262 name2 = 'sdram_ba(%s)' % i
263 pad = ['p_' + name, name2, name2]
264 elif name.startswith('sdr_dqm'):
265 i = name[-1]
266 name = 'sdram_dm_' + i
267 name2 = 'sdram_dm(%s)' % i
268 pad = ['p_' + name, name2, name2]
269 elif name.startswith('sdr_d'):
270 i = name[5:]
271 name = 'sdram_dq_' + i
272 name2 = 'sdram_dq_%%s(%s)' % i
273 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
274 elif name == 'sdr_csn0':
275 name = 'sdram_cs_n'
276 pad = ['p_' + name, name, name]
277 elif name[-1] == 'n':
278 name = 'sdram_' + name[4:-1] + '_n'
279 pad = ['p_' + name, name, name]
280 else:
281 name = 'sdram_' + name[4:]
282 pad = ['p_' + name, name, name]
283 litex_name = orig_name[:4] + "_".join(name.split("_")[1:])
284 # UART
285 elif name.startswith('uart'):
286 domain = 'UART'
287 name = 'uart_' + name[6:]
288 pad = ['p_' + name, name, name]
289 # GPIO
290 elif name.startswith('gpio'):
291 gbank = name[4]
292 domain = 'GPIO'
293 i = name[7:]
294 name = 'gpio_' + i
295 name2 = 'gpio_%%s(%s)' % i
296 pad = ['p_' + name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
297 print ("GPIO pad", name, pad)
298 litex_name = "gpio_%s" % gbank + "_".join(name.split("_")[1:])
299 # I2C master-only
300 elif name.startswith('mtwi'):
301 domain = 'MTWI'
302 suffix = name[4:]
303 litex_name = 'mtwi' + suffix
304 name = 'i2c' + suffix
305 if name.startswith('i2c_sda'):
306 name2 = 'i2c_sda_%s'
307 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
308 print ("I2C pad", name, pad)
309 else:
310 pad = ['p_' + name, name, name]
311 # I2C bi-directional
312 elif name.startswith('twi'):
313 domain = 'TWI'
314 name = 'i2c' + name[3:]
315 name2 = name + '_%s'
316 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
317 print ("I2C pad", name, pad)
318 # EINT
319 elif name.startswith('eint'):
320 domain = 'EINT'
321 i = name[-1]
322 name = 'eint_%s' % i
323 name2 = 'eint_%s' % i
324 pad = ['p_' + name, name2, name2]
325 # PWM
326 elif name.startswith('pwm'):
327 domain = 'PWM'
328 name = name[:-4]
329 i = name[3:]
330 name2 = 'pwm(%s)' % i
331 pad = ['p_' + name, name2, name2]
332 else:
333 pad = ['p_' + name, name, name]
334 print ("GPIO pad", name, pad)
335
336 if litex_name is None:
337 litex_name = name
338
339 # JTAG domain
340 if name and name.startswith('jtag'):
341 domain = 'JTAG'
342
343 if name and not name.startswith('p_'):
344 if 'power' not in name and 'ground' not in name:
345 name = 'p_' + name
346 if name is not None:
347 padbank[banknum] = name
348 # create domains
349 if domain is not None:
350 if domain not in domains:
351 domains[domain] = []
352 domains[domain].append(name)
353 dl = domain.lower()
354 if domain in psp.clocks and orig_name.startswith(dl):
355 clk = psp.clocks[domain]
356 if clk.lower() in orig_name: # TODO, might over-match
357 clocks[domain] = name
358 # record remap
359 pinmap[orig_name] = name
360 litexmap[litex_name] = name
361
362 # add pad to iopads
363 if domain and pad is not None:
364 # append direction from spec/domain. damn awkward processing
365 # to find it.
366 fn, name = orig_name.split("_")
367 if domain == 'PWM':
368 name = fn[3:]
369 print psp.byspec
370 spec = None
371 for k in psp.byspec.keys():
372 if k.startswith(domain):
373 spec = psp.byspec[k]
374 print "spec found", domain, spec
375 assert spec is not None
376 found = None
377 for pname in spec:
378 if pname.lower().startswith(name):
379 found = pname
380 print "found spec", found
381 assert found is not None
382 # whewwww. add the direction onto the pad spec list
383 pad.append(found[-1])
384 iopads.append(pad)
385 elif pad is not None:
386 iopads.append(pad)
387
388 # not connected
389 nc_idx = 0
390 for pl in [pe, pw, pn, ps]:
391 for i in range(len(pl)):
392 if pl[i] == '':
393 name = 'nc_%d' % nc_idx
394 name2 = 'nc(%d)' % nc_idx
395 pl[i] = name
396 pinmap[name] = name
397 iopads.append([name, name2, name2, "-"])
398 nc_idx += 1
399
400 print p.bankstart
401 pprint(psp.clocks)
402
403 print
404 print "N pads", pn
405 print "S pads", ps
406 print "E pads", pe
407 print "W pads", pw
408
409 # do not want these
410 del clocks['SYS']
411 del domains['SYS']
412
413 print "chip domains (excluding sys-default)"
414 pprint(domains)
415 print "chip clocks (excluding sys-default)"
416 pprint(clocks)
417 print "pin spec"
418 pprint(psp.byspec)
419
420 chip = {
421 'pads.south' : ps,
422 'pads.east' : pe,
423 'pads.north' : pn,
424 'pads.west' : pw,
425 'pads.instances' : iopads,
426 'pins.specs' : psp.byspec,
427 'pins.map' : pinmap,
428 'litex.map' : litexmap,
429 'chip.domains' : domains,
430 'chip.clocks' : clocks,
431 'chip.n_intpower': n_intpower,
432 'chip.n_extpower': n_extpower,
433 }
434
435 return pinmap, chip