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
.mspi("0", ('W', 24), 0)
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
.gpio("", ('E', 5), 0, 0, 8) # split GPIO 8-8
92 ps
.jtag("", ('E', 13), 0, 0, 4)
93 ps
.gpio("", ('E', 17), 0, 8, 8) # the other 8 GPIO
94 ps
.eint("", ('E', 25), 0, 0, 3)
95 ps
.vss("I", ('E', 28), 0, 5, 1)
96 ps
.vdd("I", ('E', 29), 0, 5, 1)
97 ps
.vss("I", ('E', 30), 0, 5, 1)
98 ps
.vdd("I", ('E', 31), 0, 5, 1)
100 ps
.vss("E", ('N', 6), 0, 6, 1)
101 ps
.vdd("E", ('N', 7), 0, 6, 1)
102 ps
.vdd("I", ('N', 8), 0, 6, 1)
103 ps
.vss("I", ('N', 9), 0, 6, 1)
104 #ps.pwm("", ('N', 2), 0, 0, 2) comment out (litex problem 25mar2021)
105 #ps.mspi("1", ('N', 7), 0) comment out (litex problem 25mar2021)
106 #ps.sdmmc("0", ('N', 11), 0) # comment out (litex problem 25mar2021)
107 ps
.sys("", ('N', 27), 0, 0, 5) # all but analog out in top right
108 ps
.vss("I", ('N', 22), 0, 7, 1)
109 ps
.vdd("I", ('N', 23), 0, 7, 1)
110 ps
.vss("I", ('N', 24), 0, 7, 1)
111 ps
.vdd("I", ('N', 25), 0, 7, 1)
113 #ps.mquadspi("1", ('S', 0), 0)
115 print "ps clocks", ps
.clocks
117 # Scenarios below can be spec'd out as either "find first interface"
118 # by name/number e.g. SPI1, or as "find in bank/mux" which must be
119 # spec'd as "BM:Name" where B is bank (A-F), M is Mux (0-3)
120 # EINT and PWM are grouped together, specially, but may still be spec'd
121 # using "BM:Name". Pins are removed in-order as listed from
122 # lists (interfaces, EINTs, PWMs) from available pins.
125 # 'SD0', litex problem 25mar2021
126 'UART0', 'GPIOS', 'GPIOE', 'JTAG', 'PWM', 'EINT',
129 # 'MSPI1', litex problem 25mar2021
132 ls180_pwm
= []#['B0:PWM_0']
134 'SD0': 'user-facing: internal (on Card), multiplexed with JTAG\n'
135 'and UART2, for debug purposes',
144 'B1:LCD/22': '18-bit RGB/TTL LCD',
145 'ULPI0/8': 'user-facing: internal (on Card), USB-OTG ULPI PHY',
146 'ULPI1': 'dual USB2 Host ULPI PHY'
149 ps
.add_scenario("Libre-SOC 180nm", ls180
, ls180_eint
, ls180_pwm
,
155 # map pins to litex name conventions, primarily for use in coriolis2
156 # yes this is a mess. it'll do the job though. improvements later
157 def pinparse(psp
, pinspec
):
158 p
= Parse(pinspec
, verify
=False)
163 print p
.muxed_cells_bank
169 pads
= {'N': pn
, 'S': ps
, 'E': pe
, 'W': pw
}
177 for (padnum
, name
, x
), bank
in zip(p
.muxed_cells
, p
.muxed_cells_bank
):
180 domain
= None # TODO, get this from the PinSpec. sigh
182 start
= p
.bankstart
[bank
]
183 banknum
= padnum
- start
184 print "bank", bank
, banknum
, "padname", name
, padnum
, x
188 if name
.startswith('vss'):
189 name
= 'p_%s_' % name
[:-2] + name
[-1]
191 name
= 'ground_' + name
[-1]
194 name
= 'ioground_' + name
[-1]
198 elif name
.startswith('vdd'):
201 name
= 'power_' + name
[-1]
205 name
= 'iopower_' + name
[-1]
209 elif name
.startswith('sys'):
211 if name
== 'sys_pllclk':
212 pad
= ["p_"+name
, name
, name
]
213 elif name
== 'sys_rst':
214 #name = 'p_sys_rst_1'
215 pad
= [name
, name
, name
]
216 padbank
[banknum
] = name
217 print "sys_rst add", bank
, banknum
, name
219 elif name
== 'sys_pllclk':
221 elif name
== 'sys_pllvcout':
222 name
= 'sys_pll_vco_o'
223 pad
= ['p_' + name
, name
, name
, "A"] # A for Analog
224 elif name
== 'sys_plltestout':
225 name
= 'sys_pll_testout_o'
226 pad
= ['p_' + name
, name
, name
]
227 elif name
.startswith('sys_pllsel'):
229 name2
= 'sys_clksel_i(%s)' % i
230 name
= 'p_sys_clksel_' + i
231 pad
= [name
, name2
, name2
]
233 # iopads.append([pname, name, name])
234 print "sys pad", name
236 elif name
.startswith('mspi0') or name
.startswith('mspi1'):
241 elif suffix
== 'nss':
243 if name
.startswith('mspi0'):
244 prefix
= 'spimaster_'
246 prefix
= 'spisdcard_'
247 litex_name
= name
[:6] + suffix
248 name
= prefix
+ suffix
249 pad
= ['p_' + name
, name
, name
]
251 elif name
.startswith('sd0'):
253 if name
.startswith('sd0_d'):
255 name
= 'sdcard_data' + i
256 name2
= 'sdcard_data_%%s(%s)' % i
257 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
258 elif name
.startswith('sd0_cmd'):
260 name2
= 'sdcard_cmd_%s'
261 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
263 name
= 'sdcard_' + name
[4:]
264 pad
= ['p_' + name
, name
, name
]
265 litex_name
= orig_name
[:4] + "_".join(name
.split("_")[1:])
267 elif name
.startswith('sdr'):
269 if name
== 'sdr_clk':
271 pad
= ['p_' + name
, name
, name
]
272 elif name
.startswith('sdr_ad'):
274 name
= 'sdram_a_' + i
275 name2
= 'sdram_a(%s)' % i
276 pad
= ['p_' + name
, name2
, name2
]
277 elif name
.startswith('sdr_ba'):
279 name
= 'sdram_ba_' + i
280 name2
= 'sdram_ba(%s)' % i
281 pad
= ['p_' + name
, name2
, name2
]
282 elif name
.startswith('sdr_dqm'):
284 name
= 'sdram_dm_' + i
285 name2
= 'sdram_dm(%s)' % i
286 pad
= ['p_' + name
, name2
, name2
]
287 elif name
.startswith('sdr_d'):
289 name
= 'sdram_dq_' + i
290 name2
= 'sdram_dq_%%s(%s)' % i
291 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
292 elif name
== 'sdr_csn0':
294 pad
= ['p_' + name
, name
, name
]
295 elif name
[-1] == 'n':
296 name
= 'sdram_' + name
[4:-1] + '_n'
297 pad
= ['p_' + name
, name
, name
]
299 name
= 'sdram_' + name
[4:]
300 pad
= ['p_' + name
, name
, name
]
301 litex_name
= orig_name
[:4] + "_".join(name
.split("_")[1:])
303 elif name
.startswith('uart'):
305 name
= 'uart_' + name
[6:]
306 pad
= ['p_' + name
, name
, name
]
308 elif name
.startswith('gpio'):
313 name2
= 'gpio_%%s(%s)' % i
314 pad
= ['p_' + name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
315 print ("GPIO pad", name
, pad
)
316 litex_name
= "gpio_%s" % gbank
+ "_".join(name
.split("_")[1:])
318 elif name
.startswith('mtwi'):
321 litex_name
= 'mtwi' + suffix
322 name
= 'i2c' + suffix
323 if name
.startswith('i2c_sda'):
325 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
326 print ("I2C pad", name
, pad
)
328 pad
= ['p_' + name
, name
, name
]
330 elif name
.startswith('twi'):
332 name
= 'i2c' + name
[3:]
334 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
335 print ("I2C pad", name
, pad
)
337 elif name
.startswith('eint'):
341 name2
= 'eint_%s' % i
342 pad
= ['p_' + name
, name2
, name2
]
344 elif name
.startswith('pwm'):
348 name2
= 'pwm(%s)' % i
349 pad
= ['p_' + name
, name2
, name2
]
351 pad
= ['p_' + name
, name
, name
]
352 print ("GPIO pad", name
, pad
)
354 if litex_name
is None:
358 if name
and name
.startswith('jtag'):
361 if name
and not name
.startswith('p_'):
362 if 'power' not in name
and 'ground' not in name
:
365 padbank
[banknum
] = name
367 if domain
is not None:
368 if domain
not in domains
:
370 domains
[domain
].append(name
)
372 if domain
in psp
.clocks
and orig_name
.startswith(dl
):
373 clk
= psp
.clocks
[domain
]
374 if clk
.lower() in orig_name
: # TODO, might over-match
375 clocks
[domain
] = name
377 pinmap
[orig_name
] = name
378 litexmap
[litex_name
] = name
381 if domain
and pad
is not None:
382 # append direction from spec/domain. damn awkward processing
384 fn
, name
= orig_name
.split("_")
389 for k
in psp
.byspec
.keys():
390 if k
.startswith(domain
):
392 print "spec found", domain
, spec
393 assert spec
is not None
396 if pname
.lower().startswith(name
):
398 print "found spec", found
399 assert found
is not None
400 # whewwww. add the direction onto the pad spec list
407 elif pad
is not None:
412 for pl
in [pe
, pw
, pn
, ps
]:
413 for i
in range(len(pl
)):
415 name
= 'nc_%d' % nc_idx
416 name2
= 'nc(%d)' % nc_idx
419 iopads
.append([name
, name2
, name2
, "-"])
435 print "chip domains (excluding sys-default)"
437 print "chip clocks (excluding sys-default)"
447 'pads.instances' : iopads
,
448 'pins.specs' : psp
.byspec
,
450 'litex.map' : litexmap
,
451 'chip.domains' : domains
,
452 'chip.clocks' : clocks
,
453 'chip.n_intpower': n_intpower
,
454 'chip.n_extpower': n_extpower
,