add pin rules
[pinmux.git] / src / bsv / peripheral_gen.py
1 import types
2 from copy import deepcopy
3
4
5 class PBase(object):
6 def __init__(self, name):
7 self.name = name
8
9 def axibase(self, name, ifacenum):
10 name = name.upper()
11 return "%(name)s%(ifacenum)dBase" % locals()
12
13 def axiend(self, name, ifacenum):
14 name = name.upper()
15 return "%(name)s%(ifacenum)dEnd" % locals()
16
17 def axi_reg_def(self, start, name, ifacenum):
18 name = name.upper()
19 offs = self.num_axi_regs32() * 4 * 16
20 end = start + offs - 1
21 bname = self.axibase(name, ifacenum)
22 bend = self.axiend(name, ifacenum)
23 comment = "%d 32-bit regs" % self.num_axi_regs32()
24 return (" `define%(bname)s 'h%(start)08X\n"
25 " `define%(bend)s 'h%(end)08X // %(comment)s" % locals(),
26 offs)
27
28 def axi_slave_name(self, name, ifacenum):
29 name = name.upper()
30 return "{0}{1}_slave_num".format(name, ifacenum)
31
32 def axi_slave_idx(self, idx, name, ifacenum):
33 name = self.axi_slave_name(name, ifacenum)
34 return ("typedef {0} {1};".format(idx, name), 1)
35
36 def axi_addr_map(self, name, ifacenum):
37 bname = self.axibase(name, ifacenum)
38 bend = self.axiend(name, ifacenum)
39 name = self.axi_slave_name(name, ifacenum)
40 return """\
41 if(addr>=`{0} && addr<=`{1})
42 return tuple2(True,fromInteger(valueOf({2})));
43 else""".format(bname, bend, name)
44
45 def mk_pincon(self, name, count):
46 ret = []
47 for p in self.peripheral.pinspecs:
48 typ = p['type']
49 pname = p['name']
50 ret.append(" rule con_%s%d_%s_%s" % (name, count, pname, typ))
51 sname = self.peripheral.pname(pname).format(count)
52 ps = "pinmux.peripheral_side.%s" % sname
53 if typ == 'out':
54 fname = self.pinname_out(pname)
55 n = "{0}{1}".format(name, self.mksuffix(name, count))
56 ret.append(" {0}_out({1}.{2});".format(ps, n, fname))
57 ret.append(" //%s" % str(p))
58 ret.append(" endrule")
59 return '\n'.join(ret)
60
61 def mk_cellconn(self, *args):
62 return ''
63
64 def mkslow_peripheral(self):
65 return ''
66
67 def mksuffix(self, name, i):
68 return i
69
70 def __mk_connection(self, con, aname):
71 txt = " mkConnection (slow_fabric.v_to_slaves\n" + \
72 " [fromInteger(valueOf({1}))],\n" + \
73 " {0});"
74
75 print "PBase __mk_connection", self.name, aname
76 if not con:
77 return ''
78 return txt.format(con, aname)
79
80 def mk_connection(self, count, name=None):
81 if name is None:
82 name = self.name
83 print "PBase mk_conn", self.name, count
84 aname = self.axi_slave_name(name, count)
85 #dname = self.mksuffix(name, count)
86 #dname = "{0}{1}".format(name, dname)
87 con = self._mk_connection(name, count).format(count, aname)
88 return self.__mk_connection(con, aname)
89
90 def _mk_connection(self, name=None, count=0):
91 return ''
92
93 def pinname_out(self, pname):
94 return ''
95
96 def pinname_in(self, pname):
97 return ''
98
99 def pinname_outen(self, pname):
100 return ''
101
102
103 class uart(PBase):
104
105 def slowimport(self):
106 return " import Uart16550 :: *;"
107
108 def slowifdecl(self):
109 return " interface RS232_PHY_Ifc uart{0}_coe;\n" + \
110 " method Bit#(1) uart{0}_intr;"
111
112 def num_axi_regs32(self):
113 return 8
114
115 def mkslow_peripheral(self):
116 return " Uart16550_AXI4_Lite_Ifc uart{0} <- \n" + \
117 " mkUart16550(clocked_by uart_clock,\n" + \
118 " reset_by uart_reset, sp_clock, sp_reset);"
119
120 def _mk_connection(self, name=None, count=0):
121 return "uart{0}.slave_axi_uart"
122
123 def pinname_out(self, pname):
124 return {'tx': 'coe_rs232.sout'}.get(pname, '')
125
126 def pinname_in(self, pname):
127 return {'rx': 'coe_rs232.sin'}.get(pname, '')
128
129
130 class rs232(PBase):
131
132 def slowimport(self):
133 return " import Uart_bs::*;\n" + \
134 " import RS232_modified::*;"
135
136 def slowifdecl(self):
137 return " interface RS232 uart{0}_coe;"
138
139 def num_axi_regs32(self):
140 return 2
141
142 def mkslow_peripheral(self):
143 return " //Ifc_Uart_bs uart{0} <-" + \
144 " // mkUart_bs(clocked_by uart_clock,\n" + \
145 " // reset_by uart_reset,sp_clock, sp_reset);" +\
146 " Ifc_Uart_bs uart{0} <-" + \
147 " mkUart_bs(clocked_by sp_clock,\n" + \
148 " reset_by sp_reset, sp_clock, sp_reset);"
149
150 def _mk_connection(self, name=None, count=0):
151 return "uart{0}.slave_axi_uart"
152
153
154 class twi(PBase):
155
156 def slowimport(self):
157 return " import I2C_top :: *;"
158
159 def slowifdecl(self):
160 return " interface I2C_out i2c{0}_out;\n" + \
161 " method Bit#(1) i2c{0}_isint;"
162
163 def num_axi_regs32(self):
164 return 8
165
166 def mkslow_peripheral(self):
167 return " I2C_IFC i2c{0} <- mkI2CController();"
168
169 def _mk_connection(self, name=None, count=0):
170 return "i2c{0}.slave_i2c_axi"
171
172
173 class qspi(PBase):
174
175 def slowimport(self):
176 return " import qspi :: *;"
177
178 def slowifdecl(self):
179 return " interface QSPI_out qspi{0}_out;\n" + \
180 " method Bit#(1) qspi{0}_isint;"
181
182 def num_axi_regs32(self):
183 return 13
184
185 def mkslow_peripheral(self):
186 return " Ifc_qspi qspi{0} <- mkqspi();"
187
188 def _mk_connection(self, name=None, count=0):
189 return "qspi{0}.slave"
190
191
192 class pwm(PBase):
193
194 def slowimport(self):
195 return " import pwm::*;"
196
197 def slowifdecl(self):
198 return " interface PWMIO pwm{0}_o;"
199
200 def num_axi_regs32(self):
201 return 4
202
203 def mkslow_peripheral(self):
204 return " Ifc_PWM_bus pwm{0}_bus <- mkPWM_bus(sp_clock);"
205
206 def _mk_connection(self, name=None, count=0):
207 return "pwm{0}_bus.axi4_slave"
208
209
210 class gpio(PBase):
211
212 def slowimport(self):
213 return " import pinmux::*;\n" + \
214 " import mux::*;\n" + \
215 " import gpio::*;\n"
216
217 def slowifdecl(self):
218 return " interface GPIO_config#({1}) pad_config{0};"
219
220 def num_axi_regs32(self):
221 return 2
222
223 def axi_slave_idx(self, idx, name, ifacenum):
224 """ generates AXI slave number definition, except
225 GPIO also has a muxer per bank
226 """
227 name = name.upper()
228 (ret, x) = PBase.axi_slave_idx(self, idx, name, ifacenum)
229 (ret2, x) = PBase.axi_slave_idx(self, idx, "mux", ifacenum)
230 return ("%s\n%s" % (ret, ret2), 2)
231
232 def mkslow_peripheral(self):
233 return " MUX#(%(name)s) mux{0} <- mkmux();\n" + \
234 " GPIO#(%(name)s) gpio{0} <- mkgpio();" % \
235 {'name': self.name}
236
237 def mk_connection(self, count):
238 print "GPIO mk_conn", self.name, count
239 res = []
240 dname = self.mksuffix(self.name, count)
241 for i, n in enumerate(['gpio' + dname, 'mux' + dname]):
242 res.append(PBase.mk_connection(self, count, n))
243 return '\n'.join(res)
244
245 def _mk_connection(self, name=None, count=0):
246 n = self.mksuffix(name, count)
247 if name.startswith('gpio'):
248 return "gpio{0}.axi_slave".format(n)
249 if name.startswith('mux'):
250 return "mux{0}.axi_slave".format(n)
251
252 def mksuffix(self, name, i):
253 if name.startswith('mux'):
254 return name[3:]
255 return name[4:]
256
257 def mk_cellconn(self, cellnum, name, count):
258 ret = []
259 bank = self.mksuffix(name, count)
260 txt = " pinmux.mux_lines.cell{0}_mux(mux{1}.mux_config.mux[{2}]);"
261 for p in self.peripheral.pinspecs:
262 ret.append(txt.format(cellnum, bank, p['name'][1:]))
263 cellnum += 1
264 return ("\n".join(ret), cellnum)
265
266
267 axi_slave_declarations = """\
268 typedef 0 SlowMaster;
269 {0}
270 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
271 CLINT_slave_num;
272 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
273 Plic_slave_num;
274 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
275 AxiExp1_slave_num;
276 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
277 """
278
279 pinmux_cellrule = """\
280 rule connect_select_lines_pinmux;
281 {0}
282 endrule
283 """
284
285
286 class CallFn(object):
287 def __init__(self, peripheral, name):
288 self.peripheral = peripheral
289 self.name = name
290
291 def __call__(self, *args):
292 #print "__call__", self.name, self.peripheral.slow, args
293 if not self.peripheral.slow:
294 return ''
295 return getattr(self.peripheral.slow, self.name)(*args[1:])
296
297
298 class PeripheralIface(object):
299 def __init__(self, ifacename):
300 self.slow = None
301 slow = slowfactory.getcls(ifacename)
302 print "Iface", ifacename, slow
303 if slow:
304 self.slow = slow(ifacename)
305 self.slow.peripheral = self
306 for fname in ['slowimport', 'slowifdecl', 'mkslow_peripheral',
307 'mk_connection', 'mk_cellconn', 'mk_pincon']:
308 fn = CallFn(self, fname)
309 setattr(self, fname, types.MethodType(fn, self))
310
311 #print "PeripheralIface"
312 #print dir(self)
313
314 def mksuffix(self, name, i):
315 if self.slow is None:
316 return i
317 return self.slow.mksuffix(name, i)
318
319 def axi_reg_def(self, start, count):
320 if not self.slow:
321 return ('', 0)
322 return self.slow.axi_reg_def(start, self.ifacename, count)
323
324 def axi_slave_idx(self, start, count):
325 if not self.slow:
326 return ('', 0)
327 return self.slow.axi_slave_idx(start, self.ifacename, count)
328
329 def axi_addr_map(self, count):
330 if not self.slow:
331 return ''
332 return self.slow.axi_addr_map(self.ifacename, count)
333
334
335 class PeripheralInterfaces(object):
336 def __init__(self):
337 pass
338
339 def slowimport(self, *args):
340 ret = []
341 for (name, count) in self.ifacecount:
342 #print "slowimport", name, self.data[name].slowimport
343 ret.append(self.data[name].slowimport())
344 return '\n'.join(list(filter(None, ret)))
345
346 def slowifdecl(self, *args):
347 ret = []
348 for (name, count) in self.ifacecount:
349 for i in range(count):
350 ret.append(self.data[name].slowifdecl().format(i, name))
351 return '\n'.join(list(filter(None, ret)))
352
353 def axi_reg_def(self, *args):
354 ret = []
355 start = 0x00011100 # start of AXI peripherals address
356 for (name, count) in self.ifacecount:
357 for i in range(count):
358 x = self.data[name].axi_reg_def(start, i)
359 #print ("ifc", name, x)
360 (rdef, offs) = x
361 ret.append(rdef)
362 start += offs
363 return '\n'.join(list(filter(None, ret)))
364
365 def axi_slave_idx(self, *args):
366 ret = []
367 start = 0
368 for (name, count) in self.ifacecount:
369 for i in range(count):
370 (rdef, offs) = self.data[name].axi_slave_idx(start, i)
371 #print ("ifc", name, rdef, offs)
372 ret.append(rdef)
373 start += offs
374 ret.append("typedef %d LastGen_slave_num" % (start - 1))
375 decls = '\n'.join(list(filter(None, ret)))
376 return axi_slave_declarations.format(decls)
377
378 def axi_addr_map(self, *args):
379 ret = []
380 for (name, count) in self.ifacecount:
381 for i in range(count):
382 ret.append(self.data[name].axi_addr_map(i))
383 return '\n'.join(list(filter(None, ret)))
384
385 def mkslow_peripheral(self, *args):
386 ret = []
387 for (name, count) in self.ifacecount:
388 for i in range(count):
389 print "mkslow", name, count
390 x = self.data[name].mkslow_peripheral()
391 print name, count, x
392 suffix = self.data[name].mksuffix(name, i)
393 ret.append(x.format(suffix))
394 return '\n'.join(list(filter(None, ret)))
395
396 def mk_connection(self, *args):
397 ret = []
398 for (name, count) in self.ifacecount:
399 for i in range(count):
400 print "mk_conn", name, i
401 txt = self.data[name].mk_connection(i)
402 if name == 'gpioa':
403 print "txt", txt
404 print self.data[name].mk_connection
405 ret.append(txt)
406 return '\n'.join(list(filter(None, ret)))
407
408 def mk_cellconn(self):
409 ret = []
410 cellcount = 0
411 for (name, count) in self.ifacecount:
412 for i in range(count):
413 res = self.data[name].mk_cellconn(cellcount, name, i)
414 if not res:
415 continue
416 (txt, cellcount) = res
417 ret.append(txt)
418 ret = '\n'.join(list(filter(None, ret)))
419 return pinmux_cellrule.format(ret)
420
421 def mk_pincon(self):
422 ret = []
423 for (name, count) in self.ifacecount:
424 for i in range(count):
425 txt = self.data[name].mk_pincon(name, i)
426 ret.append(txt)
427 return '\n'.join(list(filter(None, ret)))
428
429 class PFactory(object):
430 def getcls(self, name):
431 for k, v in {'uart': uart,
432 'rs232': rs232,
433 'twi': twi,
434 'qspi': qspi,
435 'pwm': pwm,
436 'gpio': gpio
437 }.items():
438 if name.startswith(k):
439 return v
440 return None
441
442
443 slowfactory = PFactory()
444
445 if __name__ == '__main__':
446 p = uart('uart')
447 print p.slowimport()
448 print p.slowifdecl()
449 i = PeripheralIface('uart')
450 print i, i.slow
451 i = PeripheralIface('gpioa')
452 print i, i.slow