add quart plic irqs
[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 slowifdeclmux(self):
10 return ''
11
12 def slowifinstance(self):
13 return ''
14
15 def slowimport(self):
16 return ''
17
18 def num_axi_regs32(self):
19 return 0
20
21 def slowifdecl(self):
22 return ''
23
24 def axibase(self, name, ifacenum):
25 name = name.upper()
26 return "%(name)s%(ifacenum)dBase" % locals()
27
28 def axiend(self, name, ifacenum):
29 name = name.upper()
30 return "%(name)s%(ifacenum)dEnd" % locals()
31
32 def axi_reg_def(self, start, name, ifacenum):
33 name = name.upper()
34 offs = self.num_axi_regs32() * 4 * 16
35 if offs == 0:
36 return ('', 0)
37 end = start + offs - 1
38 bname = self.axibase(name, ifacenum)
39 bend = self.axiend(name, ifacenum)
40 comment = "%d 32-bit regs" % self.num_axi_regs32()
41 return (" `define %(bname)s 'h%(start)08X\n"
42 " `define %(bend)s 'h%(end)08X // %(comment)s" % locals(),
43 offs)
44
45 def axi_slave_name(self, name, ifacenum):
46 name = name.upper()
47 return "{0}{1}_slave_num".format(name, ifacenum)
48
49 def axi_slave_idx(self, idx, name, ifacenum):
50 name = self.axi_slave_name(name, ifacenum)
51 return ("typedef {0} {1};".format(idx, name), 1)
52
53 def axi_addr_map(self, name, ifacenum):
54 bname = self.axibase(name, ifacenum)
55 bend = self.axiend(name, ifacenum)
56 name = self.axi_slave_name(name, ifacenum)
57 return """\
58 if(addr>=`{0} && addr<=`{1})
59 return tuple2(True,fromInteger(valueOf({2})));
60 else""".format(bname, bend, name)
61
62 def mk_pincon(self, name, count):
63 # TODO: really should be using bsv.interface_decl.Interfaces
64 # pin-naming rules.... logic here is hard-coded to duplicate
65 # it (see Interface.__init__ outen)
66 ret = []
67 for p in self.peripheral.pinspecs:
68 typ = p['type']
69 pname = p['name']
70 #n = "{0}{1}".format(self.name, self.mksuffix(name, count))
71 n = name # "{0}{1}".format(self.name, self.mksuffix(name, count))
72 ret.append(" //%s %s" % (n, str(p)))
73 sname = self.peripheral.pname(pname).format(count)
74 ps = "pinmux.peripheral_side.%s" % sname
75 if typ == 'out' or typ == 'inout':
76 ret.append(" rule con_%s%d_%s_out;" % (name, count, pname))
77 fname = self.pinname_out(pname)
78 if not n.startswith('gpio'): # XXX EURGH! horrible hack
79 n_ = "{0}{1}".format(n, count)
80 else:
81 n_ = n
82 if fname:
83 if p.get('outen'):
84 ps_ = ps + '_out'
85 else:
86 ps_ = ps
87 ret.append(" {0}({1}.{2});".format(ps_, n_, fname))
88 fname = None
89 if p.get('outen'):
90 fname = self.pinname_outen(pname)
91 if fname:
92 if isinstance(fname, str):
93 fname = "{0}.{1}".format(n_, fname)
94 fname = self.pinname_tweak(pname, 'outen', fname)
95 ret.append(" {0}_outen({1});".format(ps, fname))
96 ret.append(" endrule")
97 if typ == 'in' or typ == 'inout':
98 fname = self.pinname_in(pname)
99 if fname:
100 if p.get('outen'):
101 ps_ = ps + '_in'
102 else:
103 ps_ = ps
104 ret.append(
105 " rule con_%s%d_%s_in;" %
106 (name, count, pname))
107 n_ = "{0}{1}".format(n, count)
108 n_ = '{0}.{1}'.format(n_, fname)
109 n_ = self.ifname_tweak(pname, 'in', n_)
110 ret.append(" {1}({0});".format(ps_, n_))
111 ret.append(" endrule")
112 return '\n'.join(ret)
113
114 def mk_cellconn(self, *args):
115 return ''
116
117 def mkslow_peripheral(self, size=0):
118 return ''
119
120 def mksuffix(self, name, i):
121 return i
122
123 def __mk_connection(self, con, aname):
124 txt = " mkConnection (slow_fabric.v_to_slaves\n" + \
125 " [fromInteger(valueOf({1}))],\n" + \
126 " {0});"
127
128 print "PBase __mk_connection", self.name, aname
129 if not con:
130 return ''
131 return txt.format(con, aname)
132
133 def mk_connection(self, count, name=None):
134 if name is None:
135 name = self.name
136 print "PBase mk_conn", self.name, count
137 aname = self.axi_slave_name(name, count)
138 #dname = self.mksuffix(name, count)
139 #dname = "{0}{1}".format(name, dname)
140 con = self._mk_connection(name, count).format(count, aname)
141 return self.__mk_connection(con, aname)
142
143 def _mk_connection(self, name=None, count=0):
144 return ''
145
146 def pinname_out(self, pname):
147 return ''
148
149 def pinname_in(self, pname):
150 return ''
151
152 def pinname_outen(self, pname):
153 return ''
154
155 def ifname_tweak(self, pname, typ, txt):
156 return txt
157
158 def pinname_tweak(self, pname, typ, txt):
159 return txt
160
161 def num_irqs(self):
162 return 0
163
164 def mk_plic(self, inum, irq_offs):
165 res = []
166 print "mk_plic", self.name, inum, irq_offs
167 niq = self.num_irqs()
168 if niq == 0:
169 return ('', irq_offs)
170 name = "{0}{1}".format(self.name, self.mksuffix(self.name, inum))
171 res.append(" // PLIC rules for {0}".format(name))
172 for idx in range(niq):
173 plic_obj = self.plic_object(name, idx)
174 print "plic_obj", name, idx, plic_obj
175 plic = mkplic_rule.format(name, plic_obj, irq_offs)
176 res.append(plic)
177 irq_offs += 1 # increment to next irq
178 return ('\n'.join(res), irq_offs)
179
180 mkplic_rule = """\
181 rule rl_connect_{0}_to_plic_{2};
182 if({1} == 1'b1) begin
183 ff_gateway_queue[{2}].enq(1);
184 plic.ifc_external_irq[{2}].irq_frm_gateway(True);
185 end
186 endrule
187 """
188
189 class uart(PBase):
190
191 def slowimport(self):
192 return " import Uart_bs :: *;\n" + \
193 " import RS232_modified::*;"
194
195 def slowifdecl(self):
196 return " interface RS232 uart{0}_coe;\n" + \
197 " method Bit#(1) uart{0}_intr;"
198
199 def num_axi_regs32(self):
200 return 8
201
202 def mkslow_peripheral(self, size=0):
203 return " Ifc_Uart_bs uart{0} <- \n" + \
204 " mkUart_bs(clocked_by sp_clock,\n" + \
205 " reset_by uart_reset, sp_clock, sp_reset);"
206
207 def _mk_connection(self, name=None, count=0):
208 return "uart{0}.slave_axi_uart"
209
210 def pinname_out(self, pname):
211 return {'tx': 'coe_rs232.sout'}.get(pname, '')
212
213 def pinname_in(self, pname):
214 return {'rx': 'coe_rs232.sin'}.get(pname, '')
215
216
217 class quart(PBase):
218
219 def slowimport(self):
220 return " import Uart16550 :: *;"
221
222 def slowifdecl(self):
223 return " interface RS232_PHY_Ifc quart{0}_coe;\n" + \
224 " method Bit#(1) quart{0}_intr;"
225
226 def num_axi_regs32(self):
227 return 8
228
229 def mkslow_peripheral(self, size=0):
230 return " Uart16550_AXI4_Lite_Ifc quart{0} <- \n" + \
231 " mkUart16550(clocked_by sp_clock,\n" + \
232 " reset_by uart_reset, sp_clock, sp_reset);"
233
234 def _mk_connection(self, name=None, count=0):
235 return "quart{0}.slave_axi_uart"
236
237 def pinname_out(self, pname):
238 return {'tx' : 'coe_rs232.modem_output_stx',
239 'rts': 'coe_rs232.modem_output_rts',
240 }.get(pname, '')
241
242 def _pinname_in(self, pname):
243 return {'rx': 'coe_rs232.modem_input.srx',
244 'cts': 'coe_rs232.modem_input.cts'
245 }.get(pname, '')
246
247 def mk_pincon(self, name, count):
248 ret = [PBase.mk_pincon(self, name, count)]
249 ret.append(" rule con_%s%d_io_in;" % (name, count))
250 ret.append(" {0}{1}.coe_rs232.modem_input(".format(name, count))
251 for idx, pname in enumerate(['rx', 'cts']):
252 sname = self.peripheral.pname(pname).format(count)
253 ps = "pinmux.peripheral_side.%s" % sname
254 ret.append(" {0},".format(ps))
255 ret.append(" 1'b1,1'b0,1'b1")
256 ret.append(" );")
257 ret.append(" endrule")
258
259 return '\n'.join(ret)
260
261 def num_irqs(self):
262 return 1
263
264 def plic_object(self, pname, idx):
265 return "{0}_interrupt.read".format(pname)
266
267 def mk_plic(self, inum, irq_offs):
268 name = "{0}{1}".format(self.name, self.mksuffix(self.name, inum))
269 ret = [uart_plic_template.format(name, irq_offs)]
270 (ret2, irq_offs) = PBase.mk_plic(self, inum, irq_offs)
271 ret.append(ret2)
272 return ('\n'.join(ret), irq_offs)
273
274 uart_plic_template = """\
275 // PLIC {0} synchronisation with irq {1}
276 SyncBitIfc#(Bit#(1)) {0}_interrupt <-
277 mkSyncBitToCC(sp_clock, uart_reset);
278 rule plic_synchronize_{0}_interrupt_{1};
279 {0}_interrupt.send({0}.irq);
280 endrule
281 """
282
283 class rs232(PBase):
284
285 def slowimport(self):
286 return " import Uart_bs::*;\n" + \
287 " import RS232_modified::*;"
288
289 def slowifdecl(self):
290 return " interface RS232 uart{0}_coe;"
291
292 def num_axi_regs32(self):
293 return 2
294
295 def mkslow_peripheral(self, size=0):
296 return " //Ifc_Uart_bs uart{0} <-" + \
297 " // mkUart_bs(clocked_by uart_clock,\n" + \
298 " // reset_by uart_reset,sp_clock, sp_reset);" +\
299 " Ifc_Uart_bs uart{0} <-" + \
300 " mkUart_bs(clocked_by sp_clock,\n" + \
301 " reset_by sp_reset, sp_clock, sp_reset);"
302
303 def _mk_connection(self, name=None, count=0):
304 return "uart{0}.slave_axi_uart"
305
306 def pinname_out(self, pname):
307 return {'tx': 'coe_rs232.sout'}.get(pname, '')
308
309 def pinname_in(self, pname):
310 return {'rx': 'coe_rs232.sin'}.get(pname, '')
311
312
313 class twi(PBase):
314
315 def slowimport(self):
316 return " import I2C_top :: *;"
317
318 def slowifdecl(self):
319 return " interface I2C_out twi{0}_out;\n" + \
320 " method Bit#(1) twi{0}_isint;"
321
322 def num_axi_regs32(self):
323 return 8
324
325 def mkslow_peripheral(self, size=0):
326 return " I2C_IFC twi{0} <- mkI2CController();"
327
328 def _mk_connection(self, name=None, count=0):
329 return "twi{0}.slave_i2c_axi"
330
331 def pinname_out(self, pname):
332 return {'sda': 'out.sda_out',
333 'scl': 'out.scl_out'}.get(pname, '')
334
335 def pinname_in(self, pname):
336 return {'sda': 'out.sda_in',
337 'scl': 'out.scl_in'}.get(pname, '')
338
339 def pinname_outen(self, pname):
340 return {'sda': 'out.sda_out_en',
341 'scl': 'out.scl_out_en'}.get(pname, '')
342
343 def pinname_tweak(self, pname, typ, txt):
344 if typ == 'outen':
345 return "pack({0})".format(txt)
346 return txt
347
348 def num_irqs(self):
349 return 3
350
351 def plic_object(self, pname, idx):
352 return ["{0}.isint()",
353 "{0}.timerint()",
354 "{0}.isber()"
355 ][idx].format(pname)
356
357
358 class eint(PBase):
359
360 def slowimport(self):
361 size = len(self.peripheral.pinspecs)
362 return " `define NUM_EINTS %d" % size
363
364 def mkslow_peripheral(self, size=0):
365 size = len(self.peripheral.pinspecs)
366 return " Wire#(Bit#(%d)) wr_interrupt <- mkWire();" % size
367
368 def axi_slave_name(self, name, ifacenum):
369 return ''
370
371 def axi_slave_idx(self, idx, name, ifacenum):
372 return ('', 0)
373
374 def axi_addr_map(self, name, ifacenum):
375 return ''
376
377 def ifname_tweak(self, pname, typ, txt):
378 if typ != 'in':
379 return txt
380 print "ifnameweak", pname, typ, txt
381 return "wr_interrupt[{0}] <= ".format(pname)
382
383 def mk_pincon(self, name, count):
384 ret = [PBase.mk_pincon(self, name, count)]
385 size = len(self.peripheral.pinspecs)
386 ret.append(eint_pincon_template.format(size))
387 ret.append(" rule con_%s%d_io_in;" % (name, count))
388 ret.append(" wr_interrupt <= ({")
389 for idx, p in enumerate(self.peripheral.pinspecs):
390 pname = p['name']
391 sname = self.peripheral.pname(pname).format(count)
392 ps = "pinmux.peripheral_side.%s" % sname
393 comma = '' if idx == size - 1 else ','
394 ret.append(" {0}{1}".format(ps, comma))
395 ret.append(" });")
396 ret.append(" endrule")
397
398 return '\n'.join(ret)
399
400
401 eint_pincon_template = '''\
402 // EINT is offset at end of other peripheral interrupts
403 for(Integer i=0;i<{0};i=i+ 1)begin
404 rule connect_int_to_plic(wr_interrupt[i]==1);
405 ff_gateway_queue[i+`NUM_SLOW_IRQS].enq(1);
406 plic.ifc_external_irq[i+`NUM_SLOW_IRQS].irq_frm_gateway(True);
407 endrule
408 end
409 '''
410
411
412 class jtag(PBase):
413
414 def axi_slave_name(self, name, ifacenum):
415 return ''
416
417 def axi_slave_idx(self, idx, name, ifacenum):
418 return ('', 0)
419
420 def axi_addr_map(self, name, ifacenum):
421 return ''
422
423 def slowifdeclmux(self):
424 return " method Action jtag_ms (Bit#(1) in);\n" + \
425 " method Bit#(1) jtag_di;\n" + \
426 " method Action jtag_do (Bit#(1) in);\n" + \
427 " method Action jtag_ck (Bit#(1) in);"
428
429 def slowifinstance(self):
430 return jtag_method_template # bit of a lazy hack this...
431
432 jtag_method_template = """\
433 method Action jtag_ms (Bit#(1) in);
434 pinmux.peripheral_side.jtag_ms(in);
435 endmethod
436 method Bit#(1) jtag_di=pinmux.peripheral_side.jtag_di;
437 method Action jtag_do (Bit#(1) in);
438 pinmux.peripheral_side.jtag_do(in);
439 endmethod
440 method Action jtag_ck (Bit#(1) in);
441 pinmux.peripheral_side.jtag_ck(in);
442 endmethod
443 """
444
445 class sdmmc(PBase):
446
447 def slowimport(self):
448 return " import sdcard_dummy :: *;"
449
450 def slowifdecl(self):
451 return " interface QSPI_out sd{0}_out;\n" + \
452 " method Bit#(1) sd{0}_isint;"
453
454 def num_axi_regs32(self):
455 return 13
456
457 def mkslow_peripheral(self):
458 return " Ifc_sdcard_dummy sd{0} <- mksdcard_dummy();"
459
460 def _mk_connection(self, name=None, count=0):
461 return "sd{0}.slave"
462
463 def pinname_in(self, pname):
464 return "%s_in" % pname
465
466 def pinname_out(self, pname):
467 if pname.startswith('d'):
468 return "%s_out" % pname
469 return pname
470
471 def pinname_outen(self, pname):
472 if pname.startswith('d'):
473 return "%s_outen" % pname
474
475
476 class spi(PBase):
477
478 def slowimport(self):
479 return " import qspi :: *;"
480
481 def slowifdecl(self):
482 return " interface QSPI_out spi{0}_out;\n" + \
483 " method Bit#(1) spi{0}_isint;"
484
485 def num_axi_regs32(self):
486 return 13
487
488 def mkslow_peripheral(self):
489 return " Ifc_qspi spi{0} <- mkqspi();"
490
491 def _mk_connection(self, name=None, count=0):
492 return "spi{0}.slave"
493
494 def pinname_out(self, pname):
495 return {'clk': 'out.clk_o',
496 'nss': 'out.ncs_o',
497 'mosi': 'out.io_o[0]',
498 'miso': 'out.io_o[1]',
499 }.get(pname, '')
500
501 def pinname_outen(self, pname):
502 return {'clk': 1,
503 'nss': 1,
504 'mosi': 'out.io_enable[0]',
505 'miso': 'out.io_enable[1]',
506 }.get(pname, '')
507
508 def mk_pincon(self, name, count):
509 ret = [PBase.mk_pincon(self, name, count)]
510 # special-case for gpio in, store in a temporary vector
511 plen = len(self.peripheral.pinspecs)
512 ret.append(" // XXX NSS and CLK are hard-coded master")
513 ret.append(" // TODO: must add spi slave-mode")
514 ret.append(" // all ins done in one rule from 4-bitfield")
515 ret.append(" rule con_%s%d_io_in;" % (name, count))
516 ret.append(" {0}{1}.out.io_i({{".format(name, count))
517 for idx, pname in enumerate(['mosi', 'miso']):
518 sname = self.peripheral.pname(pname).format(count)
519 ps = "pinmux.peripheral_side.%s_in" % sname
520 ret.append(" {0},".format(ps))
521 ret.append(" 1'b0,1'b0")
522 ret.append(" });")
523 ret.append(" endrule")
524 return '\n'.join(ret)
525
526
527 class qspi(PBase):
528
529 def slowimport(self):
530 return " import qspi :: *;"
531
532 def slowifdecl(self):
533 return " interface QSPI_out qspi{0}_out;\n" + \
534 " method Bit#(1) qspi{0}_isint;"
535
536 def num_axi_regs32(self):
537 return 13
538
539 def mkslow_peripheral(self, size=0):
540 return " Ifc_qspi qspi{0} <- mkqspi();"
541
542 def _mk_connection(self, name=None, count=0):
543 return "qspi{0}.slave"
544
545 def pinname_out(self, pname):
546 return {'ck': 'out.clk_o',
547 'nss': 'out.ncs_o',
548 'io0': 'out.io_o[0]',
549 'io1': 'out.io_o[1]',
550 'io2': 'out.io_o[2]',
551 'io3': 'out.io_o[3]',
552 }.get(pname, '')
553
554 def pinname_outen(self, pname):
555 return {'ck': 1,
556 'nss': 1,
557 'io0': 'out.io_enable[0]',
558 'io1': 'out.io_enable[1]',
559 'io2': 'out.io_enable[2]',
560 'io3': 'out.io_enable[3]',
561 }.get(pname, '')
562
563 def mk_pincon(self, name, count):
564 ret = [PBase.mk_pincon(self, name, count)]
565 # special-case for gpio in, store in a temporary vector
566 plen = len(self.peripheral.pinspecs)
567 ret.append(" // XXX NSS and CLK are hard-coded master")
568 ret.append(" // TODO: must add qspi slave-mode")
569 ret.append(" // all ins done in one rule from 4-bitfield")
570 ret.append(" rule con_%s%d_io_in;" % (name, count))
571 ret.append(" {0}{1}.out.io_i({{".format(name, count))
572 for i, p in enumerate(self.peripheral.pinspecs):
573 typ = p['type']
574 pname = p['name']
575 if not pname.startswith('io'):
576 continue
577 idx = pname[1:]
578 n = name
579 sname = self.peripheral.pname(pname).format(count)
580 ps = "pinmux.peripheral_side.%s_in" % sname
581 comma = '' if i == 5 else ','
582 ret.append(" {0}{1}".format(ps, comma))
583 ret.append(" });")
584 ret.append(" endrule")
585 return '\n'.join(ret)
586
587 def num_irqs(self):
588 return 6
589
590 def plic_object(self, pname, idx):
591 return "{0}.interrupts()[{1}]".format(pname, idx)
592
593
594 class pwm(PBase):
595
596 def slowimport(self):
597 return " import pwm::*;"
598
599 def slowifdecl(self):
600 return " interface PWMIO pwm{0}_io;"
601
602 def num_axi_regs32(self):
603 return 4
604
605 def mkslow_peripheral(self, size=0):
606 return " Ifc_PWM_bus pwm{0} <- mkPWM_bus(sp_clock);"
607
608 def _mk_connection(self, name=None, count=0):
609 return "pwm{0}.axi4_slave"
610
611 def pinname_out(self, pname):
612 return {'out': 'pwm_io.pwm_o'}.get(pname, '')
613
614
615 class gpio(PBase):
616
617 def slowimport(self):
618 return " import pinmux::*;\n" + \
619 " import mux::*;\n" + \
620 " import gpio::*;\n"
621
622 def slowifdeclmux(self):
623 size = len(self.peripheral.pinspecs)
624 return " interface GPIO_config#(%d) pad_config{0};" % size
625
626 def num_axi_regs32(self):
627 return 2
628
629 def axi_slave_idx(self, idx, name, ifacenum):
630 """ generates AXI slave number definition, except
631 GPIO also has a muxer per bank
632 """
633 name = name.upper()
634 mname = 'mux' + name[4:]
635 mname = mname.upper()
636 print "AXIslavenum", name, mname
637 (ret, x) = PBase.axi_slave_idx(self, idx, name, ifacenum)
638 (ret2, x) = PBase.axi_slave_idx(self, idx + 1, mname, ifacenum)
639 return ("%s\n%s" % (ret, ret2), 2)
640
641 def mkslow_peripheral(self, size=0):
642 print "gpioslow", self.peripheral, dir(self.peripheral)
643 size = len(self.peripheral.pinspecs)
644 return " MUX#(%d) mux{0} <- mkmux();\n" % size + \
645 " GPIO#(%d) gpio{0} <- mkgpio();" % size
646
647 def mk_connection(self, count):
648 print "GPIO mk_conn", self.name, count
649 res = []
650 dname = self.mksuffix(self.name, count)
651 for i, n in enumerate(['gpio' + dname, 'mux' + dname]):
652 res.append(PBase.mk_connection(self, count, n))
653 return '\n'.join(res)
654
655 def _mk_connection(self, name=None, count=0):
656 n = self.mksuffix(name, count)
657 if name.startswith('gpio'):
658 return "gpio{0}.axi_slave".format(n)
659 if name.startswith('mux'):
660 return "mux{0}.axi_slave".format(n)
661
662 def mksuffix(self, name, i):
663 if name.startswith('mux'):
664 return name[3:]
665 return name[4:]
666
667 def mk_cellconn(self, cellnum, name, count):
668 ret = []
669 bank = self.mksuffix(name, count)
670 txt = " pinmux.mux_lines.cell{0}_mux(mux{1}.mux_config.mux[{2}]);"
671 for p in self.peripheral.pinspecs:
672 ret.append(txt.format(cellnum, bank, p['name'][1:]))
673 cellnum += 1
674 return ("\n".join(ret), cellnum)
675
676 def pinname_out(self, pname):
677 return "func.gpio_out[{0}]".format(pname[1:])
678
679 def pinname_outen(self, pname):
680 return "func.gpio_out_en[{0}]".format(pname[1:])
681
682 def mk_pincon(self, name, count):
683 ret = [PBase.mk_pincon(self, name, count)]
684 # special-case for gpio in, store in a temporary vector
685 plen = len(self.peripheral.pinspecs)
686 ret.append(" rule con_%s%d_in;" % (name, count))
687 ret.append(" Vector#({0},Bit#(1)) temp;".format(plen))
688 for p in self.peripheral.pinspecs:
689 typ = p['type']
690 pname = p['name']
691 idx = pname[1:]
692 n = name
693 sname = self.peripheral.pname(pname).format(count)
694 ps = "pinmux.peripheral_side.%s_in" % sname
695 ret.append(" temp[{0}]={1};".format(idx, ps))
696 ret.append(" {0}.func.gpio_in(temp);".format(name))
697 ret.append(" endrule")
698 return '\n'.join(ret)
699
700
701 axi_slave_declarations = """\
702 typedef 0 SlowMaster;
703 {0}
704 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
705 CLINT_slave_num;
706 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
707 Plic_slave_num;
708 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
709 AxiExp1_slave_num;
710 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
711 """
712
713 pinmux_cellrule = """\
714 rule connect_select_lines_pinmux;
715 {0}
716 endrule
717 """
718
719
720 class CallFn(object):
721 def __init__(self, peripheral, name):
722 self.peripheral = peripheral
723 self.name = name
724
725 def __call__(self, *args):
726 #print "__call__", self.name, self.peripheral.slow, args
727 if not self.peripheral.slow:
728 return ''
729 return getattr(self.peripheral.slow, self.name)(*args[1:])
730
731
732 class PeripheralIface(object):
733 def __init__(self, ifacename):
734 self.slow = None
735 slow = slowfactory.getcls(ifacename)
736 print "Iface", ifacename, slow
737 if slow:
738 self.slow = slow(ifacename)
739 self.slow.peripheral = self
740 for fname in ['slowimport',
741 'slowifinstance', 'slowifdecl', 'slowifdeclmux',
742 'mkslow_peripheral', 'mk_plic',
743 'mk_connection', 'mk_cellconn', 'mk_pincon']:
744 fn = CallFn(self, fname)
745 setattr(self, fname, types.MethodType(fn, self))
746
747 #print "PeripheralIface"
748 #print dir(self)
749
750 def mksuffix(self, name, i):
751 if self.slow is None:
752 return i
753 return self.slow.mksuffix(name, i)
754
755 def axi_reg_def(self, start, count):
756 if not self.slow:
757 return ('', 0)
758 return self.slow.axi_reg_def(start, self.ifacename, count)
759
760 def axi_slave_idx(self, start, count):
761 if not self.slow:
762 return ('', 0)
763 return self.slow.axi_slave_idx(start, self.ifacename, count)
764
765 def axi_addr_map(self, count):
766 if not self.slow:
767 return ''
768 return self.slow.axi_addr_map(self.ifacename, count)
769
770
771 class PeripheralInterfaces(object):
772 def __init__(self):
773 pass
774
775 def slowimport(self, *args):
776 ret = []
777 for (name, count) in self.ifacecount:
778 #print "slowimport", name, self.data[name].slowimport
779 ret.append(self.data[name].slowimport())
780 return '\n'.join(list(filter(None, ret)))
781
782 def slowifinstance(self, *args):
783 ret = []
784 for (name, count) in self.ifacecount:
785 #print "slowimport", name, self.data[name].slowimport
786 ret.append(self.data[name].slowifinstance())
787 return '\n'.join(list(filter(None, ret)))
788
789 def slowifdeclmux(self, *args):
790 ret = []
791 for (name, count) in self.ifacecount:
792 for i in range(count):
793 ret.append(self.data[name].slowifdeclmux().format(i, name))
794 return '\n'.join(list(filter(None, ret)))
795
796 def slowifdecl(self, *args):
797 ret = []
798 for (name, count) in self.ifacecount:
799 for i in range(count):
800 ret.append(self.data[name].slowifdecl().format(i, name))
801 return '\n'.join(list(filter(None, ret)))
802
803 def axi_reg_def(self, *args):
804 ret = []
805 start = 0x00011100 # start of AXI peripherals address
806 for (name, count) in self.ifacecount:
807 for i in range(count):
808 x = self.data[name].axi_reg_def(start, i)
809 #print ("ifc", name, x)
810 (rdef, offs) = x
811 ret.append(rdef)
812 start += offs
813 return '\n'.join(list(filter(None, ret)))
814
815 def axi_slave_idx(self, *args):
816 ret = []
817 start = 0
818 for (name, count) in self.ifacecount:
819 for i in range(count):
820 (rdef, offs) = self.data[name].axi_slave_idx(start, i)
821 #print ("ifc", name, rdef, offs)
822 ret.append(rdef)
823 start += offs
824 ret.append("typedef %d LastGen_slave_num;" % (start - 1))
825 decls = '\n'.join(list(filter(None, ret)))
826 return axi_slave_declarations.format(decls)
827
828 def axi_addr_map(self, *args):
829 ret = []
830 for (name, count) in self.ifacecount:
831 for i in range(count):
832 ret.append(self.data[name].axi_addr_map(i))
833 return '\n'.join(list(filter(None, ret)))
834
835 def mkslow_peripheral(self, *args):
836 ret = []
837 for (name, count) in self.ifacecount:
838 for i in range(count):
839 print "mkslow", name, count
840 x = self.data[name].mkslow_peripheral()
841 print name, count, x
842 suffix = self.data[name].mksuffix(name, i)
843 ret.append(x.format(suffix))
844 return '\n'.join(list(filter(None, ret)))
845
846 def mk_connection(self, *args):
847 ret = []
848 for (name, count) in self.ifacecount:
849 for i in range(count):
850 print "mk_conn", name, i
851 txt = self.data[name].mk_connection(i)
852 if name == 'gpioa':
853 print "txt", txt
854 print self.data[name].mk_connection
855 ret.append(txt)
856 return '\n'.join(list(filter(None, ret)))
857
858 def mk_cellconn(self):
859 ret = []
860 cellcount = 0
861 for (name, count) in self.ifacecount:
862 for i in range(count):
863 res = self.data[name].mk_cellconn(cellcount, name, i)
864 if not res:
865 continue
866 (txt, cellcount) = res
867 ret.append(txt)
868 ret = '\n'.join(list(filter(None, ret)))
869 return pinmux_cellrule.format(ret)
870
871 def mk_pincon(self):
872 ret = []
873 for (name, count) in self.ifacecount:
874 for i in range(count):
875 txt = self.data[name].mk_pincon(name, i)
876 ret.append(txt)
877 return '\n'.join(list(filter(None, ret)))
878
879
880 def mk_plic(self):
881 ret = []
882 irq_offs = 8 # XXX: DMA scovers 0-7?
883 for (name, count) in self.ifacecount:
884 for i in range(count):
885 res = self.data[name].mk_plic(i, irq_offs)
886 if not res:
887 continue
888 (txt, irq_offs) = res
889 ret.append(txt)
890 self.num_slow_irqs = irq_offs
891 return '\n'.join(list(filter(None, ret)))
892
893 def mk_sloirqsdef(self):
894 return " `define NUM_SLOW_IRQS {0}".format(self.num_slow_irqs)
895
896
897 class PFactory(object):
898 def getcls(self, name):
899 for k, v in {'uart': uart,
900 'rs232': rs232,
901 'twi': twi,
902 'quart': quart,
903 'qspi': qspi,
904 'spi': spi,
905 'pwm': pwm,
906 'eint': eint,
907 'sd': sdmmc,
908 'jtag': jtag,
909 'gpio': gpio
910 }.items():
911 if name.startswith(k):
912 return v
913 return None
914
915
916 slowfactory = PFactory()
917
918 if __name__ == '__main__':
919 p = uart('uart')
920 print p.slowimport()
921 print p.slowifdecl()
922 i = PeripheralIface('uart')
923 print i, i.slow
924 i = PeripheralIface('gpioa')
925 print i, i.slow