2 # see https://bugs.libre-soc.org/show_bug.cgi?id=739
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 # TODO - Turn the number of pins per side into a variable?
15 pinbanks
= OrderedDict((
43 'PWM': 'PWM (pulse-width modulation)',
44 'MSPI0': 'SPI Master 1 (general)',
45 'MSPI1': 'SPI Master 2 (SDCard)',
46 'UART0': 'UART (TX/RX) 1',
47 'SYS': 'System Control',
49 'EINT': 'External Interrupt',
51 'RG0': 'Gigabit Ethernet 0',
52 'RG1': 'Gigabit Ethernet 1',
54 'MTWI': 'I2C Master 1',
59 #'LPC1': 'Low Pincount Interface 1',
60 #'LPC2': 'Low Pincount Interface 2',
63 ps
= PinSpec(pinbanks
, fixedpins
, function_names
)
65 ps
.sdram1("", ('W', 0), 0, 15, 6, rev
=True) # AD4-9, turned round
66 ps
.vdd("E", ('W', 6), 0, 0, 1)
67 ps
.vss("E", ('W', 7), 0, 0, 1)
68 ps
.vdd("I", ('W', 8), 0, 0, 1)
69 ps
.vss("I", ('W', 9), 0, 0, 1)
70 ps
.sdram1("", ('W', 10), 0, 0, 15, rev
=True) # SDRAM DAM0, D0-7, AD0-3
71 ps
.mi2c("", ('W', 26), 0, 0, 2)
72 ps
.vss("I", ('W', 28), 0, 1, 1)
73 ps
.vdd("I", ('W', 29), 0, 1, 1)
74 ps
.vss("E", ('W', 30), 0, 1, 1)
75 ps
.vdd("E", ('W', 31), 0, 1, 1)
77 ps
.sdram2("", ('S', 0), 0, 0, 4) # 1st 4, AD10-12,DQM1
78 ps
.vdd("E", ('S', 4), 0, 2, 1)
79 ps
.vss("E", ('S', 5), 0, 2, 1)
80 ps
.vdd("I", ('S', 6), 0, 2, 1)
81 ps
.vss("I", ('S', 7), 0, 2, 1)
82 ps
.sdram2("", ('S', 8), 0, 4, 8) # D8-15
83 ps
.sdram1("", ('S', 16), 0, 21, 9) # clk etc.
84 ps
.vss("I", ('S', 22), 0, 3, 1)
85 ps
.vdd("I", ('S', 23), 0, 3, 1)
86 ps
.vss("E", ('S', 24), 0, 3, 1)
87 ps
.vdd("E", ('S', 25), 0, 3, 1)
88 ps
.uart("0", ('S', 26), 0)
89 ps
.mspi("0", ('S', 28), 0)
91 ps
.gpio("", ('E', 0), 0, 0, 6) # GPIO 0-5
92 ps
.vss("E", ('E', 6), 0, 4, 1)
93 ps
.vdd("E", ('E', 7), 0, 4, 1)
94 ps
.vdd("I", ('E', 8), 0, 4, 1)
95 ps
.vss("I", ('E', 9), 0, 4, 1)
96 ps
.gpio("", ('E', 10), 0, 6, 3) # GPIO 6-8
97 ps
.jtag("", ('E', 13), 0, 0, 4)
98 ps
.gpio("", ('E', 17), 0, 9, 5) # GPIO 9-13
99 ps
.vss("I", ('E', 22), 0, 5, 1)
100 ps
.vdd("I", ('E', 23), 0, 5, 1)
101 ps
.vss("E", ('E', 24), 0, 5, 1)
102 ps
.vdd("E", ('E', 25), 0, 5, 1)
103 ps
.gpio("", ('E', 26), 0, 14, 2) # GPIO 14-15
104 ps
.eint("", ('E', 28), 0, 0, 3)
105 ps
.rgmii("0", ('E', 31), 0, 0, 18)
106 ps
.sys("", ('E', 63), 0, 5, 1) # analog VCO out in right top
108 ps
.vss("E", ('N', 6), 0, 6, 1)
109 ps
.vdd("E", ('N', 7), 0, 6, 1)
110 ps
.vdd("I", ('N', 8), 0, 6, 1)
111 ps
.vss("I", ('N', 9), 0, 6, 1)
112 ps
.rgmii("1", ('N', 10), 0, 0, 18)
113 #ps.pwm("", ('N', 2), 0, 0, 2) comment out (litex problem 25mar2021)
114 #ps.mspi("1", ('N', 7), 0) comment out (litex problem 25mar2021)
115 #ps.sdmmc("0", ('N', 11), 0) # comment out (litex problem 25mar2021)
116 ps
.sys("", ('N', 59), 0, 0, 5) # all but analog out in top right
117 ps
.vss("I", ('N', 54), 0, 7, 1)
118 ps
.vdd("I", ('N', 55), 0, 7, 1)
119 ps
.vss("E", ('N', 56), 0, 7, 1)
120 ps
.vdd("E", ('N', 57), 0, 7, 1)
122 #ps.mquadspi("1", ('S', 0), 0)
124 print ("ps clocks", ps
.clocks
)
126 # Scenarios below can be spec'd out as either "find first interface"
127 # by name/number e.g. SPI1, or as "find in bank/mux" which must be
128 # spec'd as "BM:Name" where B is bank (A-F), M is Mux (0-3)
129 # EINT and PWM are grouped together, specially, but may still be spec'd
130 # using "BM:Name". Pins are removed in-order as listed from
131 # lists (interfaces, EINTs, PWMs) from available pins.
134 # 'SD0', litex problem 25mar2021
135 'UART0', 'GPIOS', 'GPIOE', 'JTAG', 'PWM', 'EINT',
139 # 'MSPI1', litex problem 25mar2021
142 ngi_router_pwm
= []#['B0:PWM_0']
144 'SD0': 'user-facing: internal (on Card), multiplexed with JTAG\n'
145 'and UART2, for debug purposes',
154 'B1:LCD/22': '18-bit RGB/TTL LCD',
155 'ULPI0/8': 'user-facing: internal (on Card), USB-OTG ULPI PHY',
156 'ULPI1': 'dual USB2 Host ULPI PHY'
159 ps
.add_scenario("NGI ROUTER Libre-SOC 180nm", ngi_router
, ngi_router_eint
, ngi_router_pwm
,
165 # map pins to litex name conventions, primarily for use in coriolis2
166 # yes this is a mess. it'll do the job though. improvements later
167 def pinparse(psp
, pinspec
):
168 p
= Parse(pinspec
, verify
=False)
172 print (p
.muxed_cells
)
173 print (p
.muxed_cells_bank
)
175 # TODO - Turn the number of pins per side into a variable?
180 pads
= {'N': pn
, 'S': ps
, 'E': pe
, 'W': pw
}
188 for (padnum
, name
, x
), bank
in zip(p
.muxed_cells
, p
.muxed_cells_bank
):
191 domain
= None # TODO, get this from the PinSpec. sigh
193 start
= p
.bankstart
[bank
]
194 banknum
= padnum
- start
195 print ("bank", bank
, banknum
, "padname", name
, padnum
, x
)
199 if name
.startswith('vss'):
200 name
= 'p_%s_' % name
[:-2] + name
[-1]
202 name
= 'ground_' + name
[-1]
205 name
= 'ioground_' + name
[-1]
209 elif name
.startswith('vdd'):
212 name
= 'power_' + name
[-1]
216 name
= 'iopower_' + name
[-1]
220 elif name
.startswith('sys'):
222 if name
== 'sys_pllclk':
223 pad
= ["p_"+name
, name
, name
]
224 elif name
== 'sys_rst':
225 #name = 'p_sys_rst_1'
226 pad
= [name
, name
, name
]
227 padbank
[banknum
] = name
228 print ("sys_rst add", bank
, banknum
, name
)
230 elif name
== 'sys_pllclk':
232 elif name
== 'sys_pllvcout':
233 name
= 'sys_pll_vco_o'
234 pad
= ['p_' + name
, name
, name
, "A"] # A for Analog
235 elif name
== 'sys_plltestout':
236 name
= 'sys_pll_testout_o'
237 pad
= ['p_' + name
, name
, name
]
238 elif name
.startswith('sys_pllsel'):
240 name2
= 'sys_clksel_i(%s)' % i
241 name
= 'p_sys_clksel_' + i
242 pad
= [name
, name2
, name2
]
244 # iopads.append([pname, name, name])
245 print ("sys pad", name
)
247 elif name
.startswith('mspi0') or name
.startswith('mspi1'):
252 elif suffix
== 'nss':
254 if name
.startswith('mspi0'):
255 prefix
= 'spimaster_'
257 prefix
= 'spisdcard_'
258 litex_name
= name
[:6] + suffix
259 name
= prefix
+ suffix
260 pad
= ['p_' + name
, name
, name
]
262 elif name
.startswith('sd0'):
264 if name
.startswith('sd0_d'):
266 name
= 'sdcard_data' + i
267 name2
= 'sdcard_data_%%s(%s)' % i
268 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
269 elif name
.startswith('sd0_cmd'):
271 name2
= 'sdcard_cmd_%s'
272 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
274 name
= 'sdcard_' + name
[4:]
275 pad
= ['p_' + name
, name
, name
]
276 litex_name
= orig_name
[:4] + "_".join(name
.split("_")[1:])
278 elif name
.startswith('sdr'):
280 if name
== 'sdr_clk':
282 pad
= ['p_' + name
, name
, name
]
283 elif name
.startswith('sdr_ad'):
285 name
= 'sdram_a_' + i
286 name2
= 'sdram_a(%s)' % i
287 pad
= ['p_' + name
, name2
, name2
]
288 elif name
.startswith('sdr_ba'):
290 name
= 'sdram_ba_' + i
291 name2
= 'sdram_ba(%s)' % i
292 pad
= ['p_' + name
, name2
, name2
]
293 elif name
.startswith('sdr_dqm'):
295 name
= 'sdram_dm_' + i
296 name2
= 'sdram_dm(%s)' % i
297 pad
= ['p_' + name
, name2
, name2
]
298 elif name
.startswith('sdr_d'):
300 name
= 'sdram_dq_' + i
301 name2
= 'sdram_dq_%%s(%s)' % i
302 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
303 elif name
== 'sdr_csn0':
305 pad
= ['p_' + name
, name
, name
]
306 elif name
[-1] == 'n':
307 name
= 'sdram_' + name
[4:-1] + '_n'
308 pad
= ['p_' + name
, name
, name
]
310 name
= 'sdram_' + name
[4:]
311 pad
= ['p_' + name
, name
, name
]
312 litex_name
= orig_name
[:4] + "_".join(name
.split("_")[1:])
314 elif name
.startswith('uart'):
316 name
= 'uart_' + name
[6:]
317 pad
= ['p_' + name
, name
, name
]
319 elif name
.startswith('gpio'):
324 name2
= 'gpio_%%s(%s)' % i
325 pad
= ['p_' + name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
326 print ("GPIO pad", name
, pad
)
327 litex_name
= "gpio_%s" % gbank
+ "_".join(name
.split("_")[1:])
329 elif name
.startswith('mtwi'):
332 litex_name
= 'mtwi' + suffix
333 name
= 'i2c' + suffix
334 if name
.startswith('i2c_sda'):
336 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
337 print ("I2C pad", name
, pad
)
339 pad
= ['p_' + name
, name
, name
]
341 elif name
.startswith('twi'):
343 name
= 'i2c' + name
[3:]
345 pad
= ['p_'+name
, name
, name2
% 'o', name2
% 'i', name2
% 'oe']
346 print ("I2C pad", name
, pad
)
348 elif name
.startswith('eint'):
352 name2
= 'eint_%s' % i
353 pad
= ['p_' + name
, name2
, name2
]
355 elif name
.startswith('pwm'):
359 name2
= 'pwm(%s)' % i
360 pad
= ['p_' + name
, name2
, name2
]
362 pad
= ['p_' + name
, name
, name
]
363 print ("GPIO pad", name
, pad
)
365 if litex_name
is None:
369 if name
and name
.startswith('jtag'):
372 if name
and not name
.startswith('p_'):
373 if 'power' not in name
and 'ground' not in name
:
376 padbank
[banknum
] = name
378 if domain
is not None:
379 if domain
not in domains
:
381 domains
[domain
].append(name
)
383 if domain
in psp
.clocks
and orig_name
.startswith(dl
):
384 clk
= psp
.clocks
[domain
]
385 if clk
.lower() in orig_name
: # TODO, might over-match
386 clocks
[domain
] = name
388 pinmap
[orig_name
] = name
389 litexmap
[litex_name
] = name
392 if domain
and pad
is not None:
393 # append direction from spec/domain. damn awkward processing
395 fn
, name
= orig_name
.split("_")
400 for k
in psp
.byspec
.keys():
401 if k
.startswith(domain
):
403 print ("spec found", domain
, spec
)
404 assert spec
is not None
407 if pname
.lower().startswith(name
):
409 print ("found spec", found
)
410 assert found
is not None
411 # whewwww. add the direction onto the pad spec list
418 elif pad
is not None:
423 for pl
in [pe
, pw
, pn
, ps
]:
424 for i
in range(len(pl
)):
426 name
= 'nc_%d' % nc_idx
427 name2
= 'nc(%d)' % nc_idx
430 iopads
.append([name
, name2
, name2
, "-"])
446 print ("chip domains (excluding sys-default)")
448 print ("chip clocks (excluding sys-default)")
458 'pads.instances' : iopads
,
459 'pins.specs' : psp
.byspec
,
461 'litex.map' : litexmap
,
462 'chip.domains' : domains
,
463 'chip.clocks' : clocks
,
464 'chip.n_intpower': n_intpower
,
465 'chip.n_extpower': n_extpower
,