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