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
.vdd("E", ('S', 0), 0, 0, 1)
63 ps
.vss("E", ('S', 1), 0, 0, 1)
64 ps
.vdd("I", ('S', 2), 0, 0, 1)
65 ps
.vss("I", ('S', 3), 0, 0, 1)
66 ps
.sdram1("", ('S', 4), 0, 0, 21)
67 ps
.mi2c("", ('S', 26), 0, 0, 2)
68 ps
.vss("I", ('S', 28), 0, 1, 1)
69 ps
.vdd("I", ('S', 29), 0, 1, 1)
70 ps
.vss("E", ('S', 30), 0, 1, 1)
71 ps
.vdd("E", ('S', 31), 0, 1, 1)
73 ps
.vdd("E", ('W', 0), 0, 2, 1)
74 ps
.vss("E", ('W', 1), 0, 2, 1)
75 ps
.vdd("I", ('W', 2), 0, 2, 1)
76 ps
.vss("I", ('W', 3), 0, 2, 1)
77 ps
.sdram2("", ('W', 4), 0, 0, 12)
78 ps
.sdram1("", ('W', 16), 0, 21, 9)
79 ps
.uart("0", ('W', 22), 0)
80 ps
.jtag("", ('W', 24), 0, 0, 4)
81 ps
.vss("I", ('W', 28), 0, 3, 1)
82 ps
.vdd("I", ('W', 29), 0, 3, 1)
83 ps
.vss("E", ('W', 30), 0, 3, 1)
84 ps
.vdd("E", ('W', 31), 0, 3, 1)
86 ps
.vss("I", ('E', 0), 0, 4, 1)
87 ps
.vdd("I", ('E', 1), 0, 4, 1)
88 ps
.vdd("I", ('E', 2), 0, 4, 1)
89 ps
.vss("I", ('E', 3), 0, 4, 1)
90 ps
.sys("", ('E', 4), 0, 5, 1) # analog VCO out in right top
91 ps
.mspi("0", ('E', 5), 0)
92 ps
.gpio("", ('E', 9), 0, 0, 16)
93 ps
.eint("", ('E', 25), 0, 0, 3)
94 ps
.vss("I", ('E', 28), 0, 5, 1)
95 ps
.vdd("I", ('E', 29), 0, 5, 1)
96 ps
.vss("I", ('E', 30), 0, 5, 1)
97 ps
.vdd("I", ('E', 31), 0, 5, 1)
99 ps
.vss("E", ('N', 0), 0, 6, 1)
100 ps
.vdd("E", ('N', 1), 0, 6, 1)
101 ps
.vdd("I", ('N', 2), 0, 6, 1)
102 ps
.vss("I", ('N', 3), 0, 6, 1)
103 #ps.pwm("", ('N', 2), 0, 0, 2) comment out (litex problem 25mar2021)
104 #ps.mspi("1", ('N', 7), 0) comment out (litex problem 25mar2021)
105 #ps.sdmmc("0", ('N', 11), 0) # comment out (litex problem 25mar2021)
106 ps
.sys("", ('N', 23), 0, 0, 5) # all but analog out in top right
107 ps
.vss("I", ('N', 28), 0, 7, 1)
108 ps
.vdd("I", ('N', 29), 0, 7, 1)
109 ps
.vss("I", ('N', 30), 0, 7, 1)
110 ps
.vdd("I", ('N', 31), 0, 7, 1)
112 #ps.mquadspi("1", ('S', 0), 0)
114 print "ps clocks", ps
.clocks
116 # Scenarios below can be spec'd out as either "find first interface"
117 # by name/number e.g. SPI1, or as "find in bank/mux" which must be
118 # spec'd as "BM:Name" where B is bank (A-F), M is Mux (0-3)
119 # EINT and PWM are grouped together, specially, but may still be spec'd
120 # using "BM:Name". Pins are removed in-order as listed from
121 # lists (interfaces, EINTs, PWMs) from available pins.
124 # 'SD0', litex problem 25mar2021
125 'UART0', 'GPIOS', 'GPIOE', 'JTAG', 'PWM', 'EINT',
128 # 'MSPI1', litex problem 25mar2021
131 ls180_pwm
= []#['B0:PWM_0']
133 'SD0': 'user-facing: internal (on Card), multiplexed with JTAG\n'
134 'and UART2, for debug purposes',
143 'B1:LCD/22': '18-bit RGB/TTL LCD',
144 'ULPI0/8': 'user-facing: internal (on Card), USB-OTG ULPI PHY',
145 'ULPI1': 'dual USB2 Host ULPI PHY'
148 ps
.add_scenario("Libre-SOC 180nm", ls180
, ls180_eint
, ls180_pwm
,
154 # map pins to litex name conventions, primarily for use in coriolis2
155 # yes this is a mess. it'll do the job though. improvements later
156 def pinparse(psp
, pinspec
):
157 p
= Parse(pinspec
, verify
=False)
162 print p
.muxed_cells_bank
168 pads
= {'N': pn
, 'S': ps
, 'E': pe
, 'W': pw
}
176 for (padnum
, name
, x
), bank
in zip(p
.muxed_cells
, p
.muxed_cells_bank
):
179 domain
= None # TODO, get this from the PinSpec. sigh
181 start
= p
.bankstart
[bank
]
182 banknum
= padnum
- start
183 print "bank", bank
, banknum
, "padname", name
, padnum
, x
187 if name
.startswith('vss'):
188 name
= 'p_%s_' % name
[:-2] + name
[-1]
190 name
= 'ground_' + name
[-1]
193 name
= 'ioground_' + name
[-1]
197 elif name
.startswith('vdd'):
200 name
= 'power_' + name
[-1]
204 name
= 'iopower_' + name
[-1]
208 elif name
.startswith('sys'):
210 if name
== 'sys_pllclk':
211 pad
= ["p_"+name
, name
, name
]
212 elif name
== 'sys_rst':
213 #name = 'p_sys_rst_1'
214 pad
= [name
, name
, name
]
215 padbank
[banknum
] = name
216 print "sys_rst add", bank
, banknum
, name
218 elif name
== 'sys_pllclk':
220 elif name
== 'sys_pllvcout':
221 name
= 'sys_pll_vco_o'
222 pad
= ['p_' + name
, name
, name
, "A"] # A for Analog
223 elif name
== 'sys_plltestout':
224 name
= 'sys_pll_testout_o'
225 pad
= ['p_' + name
, name
, name
]
226 elif name
.startswith('sys_pllsel'):
228 name2
= 'sys_clksel_i(%s)' % i
229 name
= 'p_sys_clksel_' + i
230 pad
= [name
, name2
, name2
]
232 # iopads.append([pname, name, name])
233 print "sys pad", name
235 elif name
.startswith('mspi0') or name
.startswith('mspi1'):
240 elif suffix
== 'nss':
242 if name
.startswith('mspi0'):
243 prefix
= 'spimaster_'
245 prefix
= 'spisdcard_'
246 litex_name
= name
[:6] + suffix
247 name
= prefix
+ suffix
248 pad
= ['p_' + name
, name
, name
]
250 elif name
.startswith('sd0'):
252 if name
.startswith('sd0_d'):
254 name
= 'sdcard_data' + i
255 name2
= 'sdcard_data_%%s(%s)' % i
256 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
257 elif name
.startswith('sd0_cmd'):
259 name2
= 'sdcard_cmd_%s'
260 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
262 name
= 'sdcard_' + name
[4:]
263 pad
= ['p_' + name
, name
, name
]
264 litex_name
= orig_name
[:4] + "_".join(name
.split("_")[1:])
266 elif name
.startswith('sdr'):
268 if name
== 'sdr_clk':
270 pad
= ['p_' + name
, name
, name
]
271 elif name
.startswith('sdr_ad'):
273 name
= 'sdram_a_' + i
274 name2
= 'sdram_a(%s)' % i
275 pad
= ['p_' + name
, name2
, name2
]
276 elif name
.startswith('sdr_ba'):
278 name
= 'sdram_ba_' + i
279 name2
= 'sdram_ba(%s)' % i
280 pad
= ['p_' + name
, name2
, name2
]
281 elif name
.startswith('sdr_dqm'):
283 name
= 'sdram_dm_' + i
284 name2
= 'sdram_dm(%s)' % i
285 pad
= ['p_' + name
, name2
, name2
]
286 elif name
.startswith('sdr_d'):
288 name
= 'sdram_dq_' + i
289 name2
= 'sdram_dq_%%s(%s)' % i
290 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
291 elif name
== 'sdr_csn0':
293 pad
= ['p_' + name
, name
, name
]
294 elif name
[-1] == 'n':
295 name
= 'sdram_' + name
[4:-1] + '_n'
296 pad
= ['p_' + name
, name
, name
]
298 name
= 'sdram_' + name
[4:]
299 pad
= ['p_' + name
, name
, name
]
300 litex_name
= orig_name
[:4] + "_".join(name
.split("_")[1:])
302 elif name
.startswith('uart'):
304 name
= 'uart_' + name
[6:]
305 pad
= ['p_' + name
, name
, name
]
307 elif name
.startswith('gpio'):
312 name2
= 'gpio_%%s(%s)' % i
313 pad
= ['p_' + name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
314 print ("GPIO pad", name
, pad
)
315 litex_name
= "gpio_%s" % gbank
+ "_".join(name
.split("_")[1:])
317 elif name
.startswith('mtwi'):
320 litex_name
= 'mtwi' + suffix
321 name
= 'i2c' + suffix
322 if name
.startswith('i2c_sda'):
324 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
325 print ("I2C pad", name
, pad
)
327 pad
= ['p_' + name
, name
, name
]
329 elif name
.startswith('twi'):
331 name
= 'i2c' + name
[3:]
333 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
334 print ("I2C pad", name
, pad
)
336 elif name
.startswith('eint'):
340 name2
= 'eint_%s' % i
341 pad
= ['p_' + name
, name2
, name2
]
343 elif name
.startswith('pwm'):
347 name2
= 'pwm(%s)' % i
348 pad
= ['p_' + name
, name2
, name2
]
350 pad
= ['p_' + name
, name
, name
]
351 print ("GPIO pad", name
, pad
)
353 if litex_name
is None:
357 if name
and name
.startswith('jtag'):
360 if name
and not name
.startswith('p_'):
361 if 'power' not in name
and 'ground' not in name
:
364 padbank
[banknum
] = name
366 if domain
is not None:
367 if domain
not in domains
:
369 domains
[domain
].append(name
)
371 if domain
in psp
.clocks
and orig_name
.startswith(dl
):
372 clk
= psp
.clocks
[domain
]
373 if clk
.lower() in orig_name
: # TODO, might over-match
374 clocks
[domain
] = name
376 pinmap
[orig_name
] = name
377 litexmap
[litex_name
] = name
380 if domain
and pad
is not None:
381 # append direction from spec/domain. damn awkward processing
383 fn
, name
= orig_name
.split("_")
388 for k
in psp
.byspec
.keys():
389 if k
.startswith(domain
):
391 print "spec found", domain
, spec
392 assert spec
is not None
395 if pname
.lower().startswith(name
):
397 print "found spec", found
398 assert found
is not None
399 # whewwww. add the direction onto the pad spec list
406 elif pad
is not None:
411 for pl
in [pe
, pw
, pn
, ps
]:
412 for i
in range(len(pl
)):
414 name
= 'nc_%d' % nc_idx
415 name2
= 'nc(%d)' % nc_idx
418 iopads
.append([name
, name2
, name2
, "-"])
434 print "chip domains (excluding sys-default)"
436 print "chip clocks (excluding sys-default)"
446 'pads.instances' : iopads
,
447 'pins.specs' : psp
.byspec
,
449 'litex.map' : litexmap
,
450 'chip.domains' : domains
,
451 'chip.clocks' : clocks
,
452 'chip.n_intpower': n_intpower
,
453 'chip.n_extpower': n_extpower
,