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 name = 'i2c' + name[4:]
303 if name.startswith('i2c_sda'):
304 name2 = 'i2c_sda_%s'
305 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
306 print ("I2C pad", name, pad)
307 else:
308 pad = ['p_' + name, name, name]
309 # I2C bi-directional
310 elif name.startswith('twi'):
311 domain = 'TWI'
312 name = 'i2c' + name[3:]
313 name2 = name + '_%s'
314 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
315 print ("I2C pad", name, pad)
316 # EINT
317 elif name.startswith('eint'):
318 domain = 'EINT'
319 i = name[-1]
320 name = 'eint_%s' % i
321 name2 = 'eint_%s' % i
322 pad = ['p_' + name, name2, name2]
323 # PWM
324 elif name.startswith('pwm'):
325 domain = 'PWM'
326 name = name[:-4]
327 i = name[3:]
328 name2 = 'pwm(%s)' % i
329 pad = ['p_' + name, name2, name2]
330 else:
331 pad = ['p_' + name, name, name]
332 print ("GPIO pad", name, pad)
333
334 if litex_name is None:
335 litex_name = name
336
337 # JTAG domain
338 if name and name.startswith('jtag'):
339 domain = 'JTAG'
340
341 if name and not name.startswith('p_'):
342 if 'power' not in name and 'ground' not in name:
343 name = 'p_' + name
344 if name is not None:
345 padbank[banknum] = name
346 # create domains
347 if domain is not None:
348 if domain not in domains:
349 domains[domain] = []
350 domains[domain].append(name)
351 dl = domain.lower()
352 if domain in psp.clocks and orig_name.startswith(dl):
353 clk = psp.clocks[domain]
354 if clk.lower() in orig_name: # TODO, might over-match
355 clocks[domain] = name
356 # record remap
357 pinmap[orig_name] = name
358 litexmap[litex_name] = name
359
360 # add pad to iopads
361 if domain and pad is not None:
362 # append direction from spec/domain. damn awkward processing
363 # to find it.
364 fn, name = orig_name.split("_")
365 if domain == 'PWM':
366 name = fn[3:]
367 print psp.byspec
368 spec = None
369 for k in psp.byspec.keys():
370 if k.startswith(domain):
371 spec = psp.byspec[k]
372 print "spec found", domain, spec
373 assert spec is not None
374 found = None
375 for pname in spec:
376 if pname.lower().startswith(name):
377 found = pname
378 print "found spec", found
379 assert found is not None
380 # whewwww. add the direction onto the pad spec list
381 pad.append(found[-1])
382 iopads.append(pad)
383 elif pad is not None:
384 iopads.append(pad)
385
386 # not connected
387 nc_idx = 0
388 for pl in [pe, pw, pn, ps]:
389 for i in range(len(pl)):
390 if pl[i] == '':
391 name = 'nc_%d' % nc_idx
392 name2 = 'nc(%d)' % nc_idx
393 pl[i] = name
394 pinmap[name] = name
395 iopads.append([name, name2, name2, "-"])
396 nc_idx += 1
397
398 print p.bankstart
399 pprint(psp.clocks)
400
401 print
402 print "N pads", pn
403 print "S pads", ps
404 print "E pads", pe
405 print "W pads", pw
406
407 # do not want these
408 del clocks['SYS']
409 del domains['SYS']
410
411 print "chip domains (excluding sys-default)"
412 pprint(domains)
413 print "chip clocks (excluding sys-default)"
414 pprint(clocks)
415 print "pin spec"
416 pprint(psp.byspec)
417
418 chip = {
419 'pads.south' : ps,
420 'pads.east' : pe,
421 'pads.north' : pn,
422 'pads.west' : pw,
423 'pads.instances' : iopads,
424 'pins.specs' : psp.byspec,
425 'pins.map' : pinmap,
426 'litex.map' : litexmap,
427 'chip.domains' : domains,
428 'chip.clocks' : clocks,
429 'chip.n_intpower': n_intpower,
430 'chip.n_extpower': n_extpower,
431 }
432
433 return pinmap, chip