really laborious way of getting the direction of the pin into the json file
[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.sys("", ('S', 0), 0, 0, 7)
77 ps.vss("I", ('S', 7), 0, 2, 1)
78 ps.vdd("I", ('S', 8), 0, 2, 1)
79 ps.mi2c("", ('S', 9), 0, 0, 2)
80 ps.mspi("0", ('S', 15), 0)
81 ps.uart("0", ('S', 20), 0)
82 ps.gpio("", ('S', 22), 0, 0, 8)
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)
89 ps.eint("", ('W', 4), 0, 0, 3)
90 ps.mspi("1", ('W', 7), 0)
91 ps.sdmmc("0", ('W', 11), 0)
92 ps.vss("I", ('W', 30), 0, 4, 1)
93 ps.vdd("I", ('W', 31), 0, 4, 1)
94 #ps.mspi("0", ('W', 8), 0)
95 #ps.mspi("1", ('W', 8), 0)
96
97 #ps.mquadspi("1", ('S', 0), 0)
98
99 print "ps clocks", ps.clocks
100
101 # Scenarios below can be spec'd out as either "find first interface"
102 # by name/number e.g. SPI1, or as "find in bank/mux" which must be
103 # spec'd as "BM:Name" where B is bank (A-F), M is Mux (0-3)
104 # EINT and PWM are grouped together, specially, but may still be spec'd
105 # using "BM:Name". Pins are removed in-order as listed from
106 # lists (interfaces, EINTs, PWMs) from available pins.
107
108 ls180 = ['SD0', 'UART0', 'GPIOS', 'GPIOE', 'JTAG', 'PWM', 'EINT',
109 'VDD', 'VSS', 'SYS',
110 'MTWI', 'MSPI0', 'MSPI1', 'SDR']
111 ls180_eint = []
112 ls180_pwm = []#['B0:PWM_0']
113 descriptions = {
114 'SD0': 'user-facing: internal (on Card), multiplexed with JTAG\n'
115 'and UART2, for debug purposes',
116 'MTWI': 'I2C.\n',
117 'E2:SD1': '',
118 'MSPI1': '',
119 'UART0': '',
120 'LPC1': '',
121 'SYS': '',
122 'LPC2': '',
123 'SDR': '',
124 'B1:LCD/22': '18-bit RGB/TTL LCD',
125 'ULPI0/8': 'user-facing: internal (on Card), USB-OTG ULPI PHY',
126 'ULPI1': 'dual USB2 Host ULPI PHY'
127 }
128
129 ps.add_scenario("Libre-SOC 180nm", ls180, ls180_eint, ls180_pwm,
130 descriptions)
131
132 return ps
133
134
135 # map pins to litex name conventions, primarily for use in coriolis2
136 # yes this is a mess. it'll do the job though. improvements later
137 def pinparse(psp, pinspec):
138 p = Parse(pinspec, verify=False)
139 pinmap = {}
140
141 print p.muxed_cells
142 print p.muxed_cells_bank
143
144 ps = [''] * 32
145 pn = [''] * 32
146 pe = [''] * 32
147 pw = [''] * 32
148 pads = {'N': pn, 'S': ps, 'E': pe, 'W': pw}
149
150 iopads = []
151 domains = {}
152 clocks = {}
153
154 n_intpower = 0
155 n_extpower = 0
156 for (padnum, name, x), bank in zip(p.muxed_cells, p.muxed_cells_bank):
157 orig_name = name
158 domain = None # TODO, get this from the PinSpec. sigh
159 padnum = int(padnum)
160 start = p.bankstart[bank]
161 banknum = padnum - start
162 print "bank", bank, banknum, "padname", name, padnum, x
163 padbank = pads[bank]
164 pad = None
165 # VSS
166 if name.startswith('vss'):
167 name = 'p_%sck_' % name[:-2] + name[-1]
168 # VDD
169 elif name.startswith('vdd'):
170 if 'i' in name:
171 n_intpower += 1
172 else:
173 n_extpower += 1
174 name = 'p_%sck_' % name[:-2] + name[-1]
175 # SYS
176 elif name.startswith('sys'):
177 domain = 'SYS'
178 if name == 'sys_clk':
179 name = 'p_sys_clk_0'
180 elif name == 'sys_rst':
181 #name = 'p_sys_rst_1'
182 pad = [name, name, name]
183 padbank[banknum] = name
184 print "sys_rst add", bank, banknum, name
185 name = None
186 elif name == 'sys_pllclk':
187 name = None # ignore
188 elif name == 'sys_pllout':
189 name = 'sys_pll_48_o'
190 pad = ['p_' + name, name, name]
191 elif name.startswith('sys_csel'):
192 i = name[-1]
193 name2 = 'sys_clksel_i(%s)' % i
194 name = 'p_sys_clksel_' + i
195 pad = [name, name2, name2]
196 #if name:
197 # iopads.append([pname, name, name])
198 print "sys pad", name
199 # SPI Card
200 elif name.startswith('mspi0') or name.startswith('mspi1'):
201 domain = 'MSPI'
202 suffix = name[6:]
203 if suffix == 'ck':
204 suffix = 'clk'
205 elif suffix == 'nss':
206 suffix = 'cs_n'
207 if name.startswith('mspi1'):
208 prefix = 'spimaster_'
209 else:
210 prefix = 'spisdcard_'
211 name = prefix + suffix
212 pad = ['p_' + name, name, name]
213 # SD/MMC
214 elif name.startswith('sd0'):
215 domain = 'SD'
216 if name.startswith('sd0_d'):
217 i = name[5:]
218 name = 'sdcard_data' + i
219 name2 = 'sdcard_data_%%s(%s)' % i
220 pad = ['p_' + name, name, name2 % 'o', name2 % 'i',
221 'sdcard_data_oe']
222 elif name.startswith('sd0_cmd'):
223 name = 'sdcard_cmd'
224 name2 = 'sdcard_cmd_%s'
225 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
226 else:
227 name = 'sdcard_' + name[4:]
228 pad = ['p_' + name, name, name]
229 # SDRAM
230 elif name.startswith('sdr'):
231 domain = 'SDR'
232 if name == 'sdr_clk':
233 name = 'sdram_clock'
234 pad = ['p_' + name, name, name]
235 elif name.startswith('sdr_ad'):
236 i = name[6:]
237 name = 'sdram_a_' + i
238 name2 = 'sdram_a(%s)' % i
239 pad = ['p_' + name, name2, name2]
240 elif name.startswith('sdr_ba'):
241 i = name[-1]
242 name = 'sdram_ba_' + i
243 name2 = 'sdram_ba(%s)' % i
244 pad = ['p_' + name, name2, name2]
245 elif name.startswith('sdr_dqm'):
246 i = name[-1]
247 name = 'sdram_dm_' + i
248 name2 = 'sdram_dm(%s)' % i
249 pad = ['p_' + name, name2, name2]
250 elif name.startswith('sdr_d'):
251 i = name[5:]
252 name = 'sdram_dq_' + i
253 name2 = 'sdram_dq_%%s(%s)' % i
254 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', 'sdram_dq_oe']
255 elif name == 'sdr_csn0':
256 name = 'sdram_cs_n'
257 pad = ['p_' + name, name, name]
258 elif name[-1] == 'n':
259 name = 'sdram_' + name[4:-1] + '_n'
260 pad = ['p_' + name, name, name]
261 else:
262 name = 'sdram_' + name[4:]
263 pad = ['p_' + name, name, name]
264 # UART
265 elif name.startswith('uart'):
266 domain = 'UART'
267 name = 'uart_' + name[6:]
268 pad = ['p_' + name, name, name]
269 # GPIO
270 elif name.startswith('gpio'):
271 domain = 'GPIO'
272 i = name[7:]
273 name = 'gpio_' + i
274 name2 = 'gpio_%%s(%s)' % i
275 pad = ['p_' + name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
276 print ("GPIO pad", name, pad)
277 # I2C master-only
278 elif name.startswith('mtwi'):
279 domain = 'MTWI'
280 name = 'i2c' + name[4:]
281 if name.startswith('i2c_sda'):
282 name2 = 'i2c_sda_%s'
283 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
284 print ("I2C pad", name, pad)
285 else:
286 pad = ['p_' + name, name, name]
287 # I2C bi-directional
288 elif name.startswith('twi'):
289 domain = 'TWI'
290 name = 'i2c' + name[3:]
291 name2 = name + '_%s'
292 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
293 print ("I2C pad", name, pad)
294 # EINT
295 elif name.startswith('eint'):
296 i = name[-1]
297 name = 'eint_%s' % i
298 name2 = 'eint(%s)' % i
299 pad = ['p_' + name, name2, name2]
300 # PWM
301 elif name.startswith('pwm'):
302 name = name[:-4]
303 i = name[3:]
304 name2 = 'pwm(%s)' % i
305 pad = ['p_' + name, name2, name2]
306 else:
307 pad = ['p_' + name, name, name]
308 print ("GPIO pad", name, pad)
309
310 # JTAG domain
311 if name and name.startswith('jtag'):
312 domain = 'JTAG'
313
314 if name and not name.startswith('p_'):
315 name = 'p_' + name
316 if name is not None:
317 padbank[banknum] = name
318 # create domains
319 if domain is not None:
320 if domain not in domains:
321 domains[domain] = []
322 domains[domain].append(name)
323 dl = domain.lower()
324 if domain in psp.clocks and orig_name.startswith(dl):
325 clk = psp.clocks[domain]
326 if clk.lower() in orig_name: # TODO, might over-match
327 clocks[domain] = name
328 # record remap
329 pinmap[orig_name] = name
330
331 # add pad to iopads
332 if domain and pad is not None:
333 # append direction from spec/domain. damn awkward processing
334 # to find it.
335 fn, name = orig_name.split("_")
336 if domain == 'PWM':
337 name = fn[3:]
338 print dir(psp)
339 print dir(p)
340 print psp.byspec
341 spec = None
342 for k in psp.byspec.keys():
343 if k.startswith(domain):
344 spec = psp.byspec[k]
345 print "spec found", domain, spec
346 assert spec is not None
347 found = None
348 for pname in spec:
349 if pname.lower().startswith(name):
350 found = pname
351 print "found spec", found
352 assert found is not None
353 # whewwww. add the direction onto the pad spec list
354 pad.append(found[-1])
355 iopads.append(pad)
356
357 # not connected
358 nc_idx = 0
359 for pl in [pe, pw, pn, ps]:
360 for i in range(len(pl)):
361 if pl[i] == '':
362 pl[i] = 'nc_%d' % nc_idx
363 nc_idx += 1
364
365 print p.bankstart
366 pprint(psp.clocks)
367
368 print
369 print "N pads", pn
370 print "S pads", ps
371 print "E pads", pe
372 print "W pads", pw
373
374 # do not want these
375 del clocks['SYS']
376 del domains['SYS']
377
378 print "chip domains (excluding sys-default)"
379 pprint(domains)
380 print "chip clocks (excluding sys-default)"
381 pprint(clocks)
382 print "pin spec"
383 pprint(psp.byspec)
384
385 chip = {
386 'pads.south' : ps,
387 'pads.east' : pe,
388 'pads.north' : pn,
389 'pads.west' : pw,
390 'pads.instances' : iopads,
391 'pins.specs' : psp.byspec,
392 'pins.map' : pinmap,
393 'chip.domains' : domains,
394 'chip.clocks' : clocks,
395 'chip.n_intpower': n_intpower,
396 'chip.n_extpower': n_extpower,
397 }
398
399 chip = json.dumps(chip)
400 with open("ls180/litex_pinpads.json", "w") as f:
401 f.write(chip)
402
403 return pinmap