2 from copy
import deepcopy
6 def __init__(self
, name
):
9 def slowifdeclmux(self
):
15 def num_axi_regs32(self
):
21 def axibase(self
, name
, ifacenum
):
23 return "%(name)s%(ifacenum)dBase" % locals()
25 def axiend(self
, name
, ifacenum
):
27 return "%(name)s%(ifacenum)dEnd" % locals()
29 def axi_reg_def(self
, start
, name
, ifacenum
):
31 offs
= self
.num_axi_regs32() * 4 * 16
34 end
= start
+ offs
- 1
35 bname
= self
.axibase(name
, ifacenum
)
36 bend
= self
.axiend(name
, ifacenum
)
37 comment
= "%d 32-bit regs" % self
.num_axi_regs32()
38 return (" `define %(bname)s 'h%(start)08X\n"
39 " `define %(bend)s 'h%(end)08X // %(comment)s" % locals(),
42 def axi_slave_name(self
, name
, ifacenum
):
44 return "{0}{1}_slave_num".format(name
, ifacenum
)
46 def axi_slave_idx(self
, idx
, name
, ifacenum
):
47 name
= self
.axi_slave_name(name
, ifacenum
)
48 return ("typedef {0} {1};".format(idx
, name
), 1)
50 def axi_addr_map(self
, name
, ifacenum
):
51 bname
= self
.axibase(name
, ifacenum
)
52 bend
= self
.axiend(name
, ifacenum
)
53 name
= self
.axi_slave_name(name
, ifacenum
)
55 if(addr>=`{0} && addr<=`{1})
56 return tuple2(True,fromInteger(valueOf({2})));
57 else""".format(bname
, bend
, name
)
59 def mk_pincon(self
, name
, count
):
60 # TODO: really should be using bsv.interface_decl.Interfaces
61 # pin-naming rules.... logic here is hard-coded to duplicate
62 # it (see Interface.__init__ outen)
64 for p
in self
.peripheral
.pinspecs
:
67 #n = "{0}{1}".format(self.name, self.mksuffix(name, count))
68 n
= name
# "{0}{1}".format(self.name, self.mksuffix(name, count))
69 ret
.append(" //%s %s" % (n
, str(p
)))
70 sname
= self
.peripheral
.pname(pname
).format(count
)
71 ps
= "pinmux.peripheral_side.%s" % sname
72 if typ
== 'out' or typ
== 'inout':
73 ret
.append(" rule con_%s%d_%s_out;" % (name
, count
, pname
))
74 fname
= self
.pinname_out(pname
)
75 if not n
.startswith('gpio'): # XXX EURGH! horrible hack
76 n_
= "{0}{1}".format(n
, count
)
84 ret
.append(" {0}({1}.{2});".format(ps_
, n_
, fname
))
87 fname
= self
.pinname_outen(pname
)
89 if isinstance(fname
, str):
90 fname
= "{0}.{1}".format(n_
, fname
)
91 fname
= self
.pinname_tweak(pname
, 'outen', fname
)
92 ret
.append(" {0}_outen({1});".format(ps
, fname
))
93 ret
.append(" endrule")
94 if typ
== 'in' or typ
== 'inout':
95 fname
= self
.pinname_in(pname
)
102 " rule con_%s%d_%s_in;" %
103 (name
, count
, pname
))
104 n_
= "{0}{1}".format(n
, count
)
105 n_
= '{0}.{1}'.format(n_
, fname
)
106 n_
= self
.ifname_tweak(pname
, 'in', n_
)
107 ret
.append(" {1}({0});".format(ps_
, n_
))
108 ret
.append(" endrule")
109 return '\n'.join(ret
)
111 def mk_cellconn(self
, *args
):
114 def mkslow_peripheral(self
, size
=0):
117 def mksuffix(self
, name
, i
):
120 def __mk_connection(self
, con
, aname
):
121 txt
= " mkConnection (slow_fabric.v_to_slaves\n" + \
122 " [fromInteger(valueOf({1}))],\n" + \
125 print "PBase __mk_connection", self
.name
, aname
128 return txt
.format(con
, aname
)
130 def mk_connection(self
, count
, name
=None):
133 print "PBase mk_conn", self
.name
, count
134 aname
= self
.axi_slave_name(name
, count
)
135 #dname = self.mksuffix(name, count)
136 #dname = "{0}{1}".format(name, dname)
137 con
= self
._mk
_connection
(name
, count
).format(count
, aname
)
138 return self
.__mk
_connection
(con
, aname
)
140 def _mk_connection(self
, name
=None, count
=0):
143 def pinname_out(self
, pname
):
146 def pinname_in(self
, pname
):
149 def pinname_outen(self
, pname
):
152 def ifname_tweak(self
, pname
, typ
, txt
):
155 def pinname_tweak(self
, pname
, typ
, txt
):
161 def slowimport(self
):
162 return " import Uart_bs :: *;\n" + \
163 " import RS232_modified::*;"
165 def slowifdecl(self
):
166 return " interface RS232 uart{0}_coe;\n" + \
167 " method Bit#(1) uart{0}_intr;"
169 def num_axi_regs32(self
):
172 def mkslow_peripheral(self
, size
=0):
173 return " Ifc_Uart_bs uart{0} <- \n" + \
174 " mkUart_bs(clocked_by sp_clock,\n" + \
175 " reset_by uart_reset, sp_clock, sp_reset);"
177 def _mk_connection(self
, name
=None, count
=0):
178 return "uart{0}.slave_axi_uart"
180 def pinname_out(self
, pname
):
181 return {'tx': 'coe_rs232.sout'}.get(pname
, '')
183 def pinname_in(self
, pname
):
184 return {'rx': 'coe_rs232.sin'}.get(pname
, '')
189 def slowimport(self
):
190 return " import Uart16550 :: *;"
192 def slowifdecl(self
):
193 return " interface RS232_PHY_Ifc uart{0}_coe;\n" + \
194 " method Bit#(1) uart{0}_intr;"
196 def num_axi_regs32(self
):
199 def mkslow_peripheral(self
, size
=0):
200 return " Uart16550_AXI4_Lite_Ifc uart{0} <- \n" + \
201 " mkUart16550(clocked_by sp_clock,\n" + \
202 " reset_by uart_reset, sp_clock, sp_reset);"
204 def _mk_connection(self
, name
=None, count
=0):
205 return "uart{0}.slave_axi_uart"
207 def pinname_out(self
, pname
):
208 return {'tx': 'coe_rs232.sout'}.get(pname
, '')
210 def pinname_in(self
, pname
):
211 return {'rx': 'coe_rs232.sin'}.get(pname
, '')
216 def slowimport(self
):
217 return " import Uart_bs::*;\n" + \
218 " import RS232_modified::*;"
220 def slowifdecl(self
):
221 return " interface RS232 uart{0}_coe;"
223 def num_axi_regs32(self
):
226 def mkslow_peripheral(self
, size
=0):
227 return " //Ifc_Uart_bs uart{0} <-" + \
228 " // mkUart_bs(clocked_by uart_clock,\n" + \
229 " // reset_by uart_reset,sp_clock, sp_reset);" +\
230 " Ifc_Uart_bs uart{0} <-" + \
231 " mkUart_bs(clocked_by sp_clock,\n" + \
232 " reset_by sp_reset, sp_clock, sp_reset);"
234 def _mk_connection(self
, name
=None, count
=0):
235 return "uart{0}.slave_axi_uart"
237 def pinname_out(self
, pname
):
238 return {'tx': 'coe_rs232.sout'}.get(pname
, '')
240 def pinname_in(self
, pname
):
241 return {'rx': 'coe_rs232.sin'}.get(pname
, '')
246 def slowimport(self
):
247 return " import I2C_top :: *;"
249 def slowifdecl(self
):
250 return " interface I2C_out twi{0}_out;\n" + \
251 " method Bit#(1) twi{0}_isint;"
253 def num_axi_regs32(self
):
256 def mkslow_peripheral(self
, size
=0):
257 return " I2C_IFC twi{0} <- mkI2CController();"
259 def _mk_connection(self
, name
=None, count
=0):
260 return "twi{0}.slave_i2c_axi"
262 def pinname_out(self
, pname
):
263 return {'sda': 'out.sda_out',
264 'scl': 'out.scl_out'}.get(pname
, '')
266 def pinname_in(self
, pname
):
267 return {'sda': 'out.sda_in',
268 'scl': 'out.scl_in'}.get(pname
, '')
270 def pinname_outen(self
, pname
):
271 return {'sda': 'out.sda_out_en',
272 'scl': 'out.scl_out_en'}.get(pname
, '')
274 def pinname_tweak(self
, pname
, typ
, txt
):
276 return "pack({0})".format(txt
)
282 def slowimport(self
):
283 size
= len(self
.peripheral
.pinspecs
)
284 return " `define NUM_EINTS %d" % size
286 def mkslow_peripheral(self
, size
=0):
287 size
= len(self
.peripheral
.pinspecs
)
288 return " Wire#(Bit#(%d)) wr_interrupt <- mkWire();" % size
291 def axi_slave_name(self
, name
, ifacenum
):
294 def axi_slave_idx(self
, idx
, name
, ifacenum
):
297 def axi_addr_map(self
, name
, ifacenum
):
300 def ifname_tweak(self
, pname
, typ
, txt
):
303 print "ifnameweak", pname
, typ
, txt
304 return "wr_interrupt[{0}] <= ".format(pname
)
306 def mk_pincon(self
, name
, count
):
307 ret
= [PBase
.mk_pincon(self
, name
, count
)]
308 size
= len(self
.peripheral
.pinspecs
)
309 ret
.append(eint_pincon_template
.format(size
))
310 ret
.append(" rule con_%s%d_io_in;" % (name
, count
))
311 ret
.append(" wr_interrupt <= ({")
312 for idx
, p
in enumerate(self
.peripheral
.pinspecs
):
314 sname
= self
.peripheral
.pname(pname
).format(count
)
315 ps
= "pinmux.peripheral_side.%s" % sname
316 comma
= '' if idx
== size
-1 else ','
317 ret
.append(" {0}{1}".format(ps
, comma
))
319 ret
.append(" endrule")
321 return '\n'.join(ret
)
324 eint_pincon_template
= '''\
325 // TODO: offset i by the number of eints already used
326 for(Integer i=0;i<{0};i=i+ 1)begin
327 rule connect_int_to_plic(wr_interrupt[i]==1);
328 ff_gateway_queue[i].enq(1);
329 plic.ifc_external_irq[i].irq_frm_gateway(True);
337 def slowimport(self
):
338 return " import sdcard_dummy :: *;"
340 def slowifdecl(self
):
341 return " interface QSPI_out sd{0}_out;\n" + \
342 " method Bit#(1) sd{0}_isint;"
344 def num_axi_regs32(self
):
347 def mkslow_peripheral(self
):
348 return " Ifc_sdcard_dummy sd{0} <- mksdcard_dummy();"
350 def _mk_connection(self
, name
=None, count
=0):
353 def pinname_in(self
, pname
):
354 return "out.%s_in" % pname
356 def pinname_out(self
, pname
):
357 return "out.%s_out" % pname
359 def pinname_outen(self
, pname
):
360 if pname
.startswith('d'):
361 return "out.%s_outen" % pname
366 def slowimport(self
):
367 return " import qspi :: *;"
369 def slowifdecl(self
):
370 return " interface QSPI_out spi{0}_out;\n" + \
371 " method Bit#(1) spi{0}_isint;"
373 def num_axi_regs32(self
):
376 def mkslow_peripheral(self
):
377 return " Ifc_qspi spi{0} <- mkqspi();"
379 def _mk_connection(self
, name
=None, count
=0):
380 return "spi{0}.slave"
382 def pinname_out(self
, pname
):
383 return {'clk': 'out.clk_o',
385 'mosi': 'out.io_o[0]',
386 'miso': 'out.io_o[1]',
389 def pinname_outen(self
, pname
):
392 'mosi': 'out.io_enable[0]',
393 'miso': 'out.io_enable[1]',
396 def mk_pincon(self
, name
, count
):
397 ret
= [PBase
.mk_pincon(self
, name
, count
)]
398 # special-case for gpio in, store in a temporary vector
399 plen
= len(self
.peripheral
.pinspecs
)
400 ret
.append(" // XXX NSS and CLK are hard-coded master")
401 ret
.append(" // TODO: must add spi slave-mode")
402 ret
.append(" // all ins done in one rule from 4-bitfield")
403 ret
.append(" rule con_%s%d_io_in;" % (name
, count
))
404 ret
.append(" {0}{1}.out.io_i({{".format(name
, count
))
405 for idx
, pname
in enumerate(['mosi', 'miso']):
406 sname
= self
.peripheral
.pname(pname
).format(count
)
407 ps
= "pinmux.peripheral_side.%s_in" % sname
408 ret
.append(" {0},".format(ps
))
409 ret
.append(" 1'b0,1'b0")
411 ret
.append(" endrule")
412 return '\n'.join(ret
)
417 def slowimport(self
):
418 return " import qspi :: *;"
420 def slowifdecl(self
):
421 return " interface QSPI_out qspi{0}_out;\n" + \
422 " method Bit#(1) qspi{0}_isint;"
424 def num_axi_regs32(self
):
427 def mkslow_peripheral(self
, size
=0):
428 return " Ifc_qspi qspi{0} <- mkqspi();"
430 def _mk_connection(self
, name
=None, count
=0):
431 return "qspi{0}.slave"
433 def pinname_out(self
, pname
):
434 return {'ck': 'out.clk_o',
436 'io0': 'out.io_o[0]',
437 'io1': 'out.io_o[1]',
438 'io2': 'out.io_o[2]',
439 'io3': 'out.io_o[3]',
442 def pinname_outen(self
, pname
):
445 'io0': 'out.io_enable[0]',
446 'io1': 'out.io_enable[1]',
447 'io2': 'out.io_enable[2]',
448 'io3': 'out.io_enable[3]',
451 def mk_pincon(self
, name
, count
):
452 ret
= [PBase
.mk_pincon(self
, name
, count
)]
453 # special-case for gpio in, store in a temporary vector
454 plen
= len(self
.peripheral
.pinspecs
)
455 ret
.append(" // XXX NSS and CLK are hard-coded master")
456 ret
.append(" // TODO: must add qspi slave-mode")
457 ret
.append(" // all ins done in one rule from 4-bitfield")
458 ret
.append(" rule con_%s%d_io_in;" % (name
, count
))
459 ret
.append(" {0}{1}.out.io_i({{".format(name
, count
))
460 for i
, p
in enumerate(self
.peripheral
.pinspecs
):
463 if not pname
.startswith('io'):
467 sname
= self
.peripheral
.pname(pname
).format(count
)
468 ps
= "pinmux.peripheral_side.%s_in" % sname
469 comma
= '' if i
== 5 else ','
470 ret
.append(" {0}{1}".format(ps
, comma
))
472 ret
.append(" endrule")
473 return '\n'.join(ret
)
478 def slowimport(self
):
479 return " import pwm::*;"
481 def slowifdecl(self
):
482 return " interface PWMIO pwm{0}_io;"
484 def num_axi_regs32(self
):
487 def mkslow_peripheral(self
, size
=0):
488 return " Ifc_PWM_bus pwm{0} <- mkPWM_bus(sp_clock);"
490 def _mk_connection(self
, name
=None, count
=0):
491 return "pwm{0}.axi4_slave"
493 def pinname_out(self
, pname
):
494 return {'out': 'pwm_io.pwm_o'}.get(pname
, '')
499 def slowimport(self
):
500 return " import pinmux::*;\n" + \
501 " import mux::*;\n" + \
504 def slowifdeclmux(self
):
505 size
= len(self
.peripheral
.pinspecs
)
506 return " interface GPIO_config#(%d) pad_config{0};" % size
508 def num_axi_regs32(self
):
511 def axi_slave_idx(self
, idx
, name
, ifacenum
):
512 """ generates AXI slave number definition, except
513 GPIO also has a muxer per bank
516 mname
= 'mux' + name
[4:]
517 mname
= mname
.upper()
518 print "AXIslavenum", name
, mname
519 (ret
, x
) = PBase
.axi_slave_idx(self
, idx
, name
, ifacenum
)
520 (ret2
, x
) = PBase
.axi_slave_idx(self
, idx
+1, mname
, ifacenum
)
521 return ("%s\n%s" % (ret
, ret2
), 2)
523 def mkslow_peripheral(self
, size
=0):
524 print "gpioslow", self
.peripheral
, dir(self
.peripheral
)
525 size
= len(self
.peripheral
.pinspecs
)
526 return " MUX#(%d) mux{0} <- mkmux();\n" % size
+ \
527 " GPIO#(%d) gpio{0} <- mkgpio();" % size
529 def mk_connection(self
, count
):
530 print "GPIO mk_conn", self
.name
, count
532 dname
= self
.mksuffix(self
.name
, count
)
533 for i
, n
in enumerate(['gpio' + dname
, 'mux' + dname
]):
534 res
.append(PBase
.mk_connection(self
, count
, n
))
535 return '\n'.join(res
)
537 def _mk_connection(self
, name
=None, count
=0):
538 n
= self
.mksuffix(name
, count
)
539 if name
.startswith('gpio'):
540 return "gpio{0}.axi_slave".format(n
)
541 if name
.startswith('mux'):
542 return "mux{0}.axi_slave".format(n
)
544 def mksuffix(self
, name
, i
):
545 if name
.startswith('mux'):
549 def mk_cellconn(self
, cellnum
, name
, count
):
551 bank
= self
.mksuffix(name
, count
)
552 txt
= " pinmux.mux_lines.cell{0}_mux(mux{1}.mux_config.mux[{2}]);"
553 for p
in self
.peripheral
.pinspecs
:
554 ret
.append(txt
.format(cellnum
, bank
, p
['name'][1:]))
556 return ("\n".join(ret
), cellnum
)
558 def pinname_out(self
, pname
):
559 return "func.gpio_out[{0}]".format(pname
[1:])
561 def pinname_outen(self
, pname
):
562 return "func.gpio_out_en[{0}]".format(pname
[1:])
564 def mk_pincon(self
, name
, count
):
565 ret
= [PBase
.mk_pincon(self
, name
, count
)]
566 # special-case for gpio in, store in a temporary vector
567 plen
= len(self
.peripheral
.pinspecs
)
568 ret
.append(" rule con_%s%d_in;" % (name
, count
))
569 ret
.append(" Vector#({0},Bit#(1)) temp;".format(plen
))
570 for p
in self
.peripheral
.pinspecs
:
575 sname
= self
.peripheral
.pname(pname
).format(count
)
576 ps
= "pinmux.peripheral_side.%s_in" % sname
577 ret
.append(" temp[{0}]={1};".format(idx
, ps
))
578 ret
.append(" {0}.func.gpio_in(temp);".format(name
))
579 ret
.append(" endrule")
580 return '\n'.join(ret
)
583 axi_slave_declarations
= """\
584 typedef 0 SlowMaster;
586 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
588 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
590 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
592 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
595 pinmux_cellrule
= """\
596 rule connect_select_lines_pinmux;
602 class CallFn(object):
603 def __init__(self
, peripheral
, name
):
604 self
.peripheral
= peripheral
607 def __call__(self
, *args
):
608 #print "__call__", self.name, self.peripheral.slow, args
609 if not self
.peripheral
.slow
:
611 return getattr(self
.peripheral
.slow
, self
.name
)(*args
[1:])
614 class PeripheralIface(object):
615 def __init__(self
, ifacename
):
617 slow
= slowfactory
.getcls(ifacename
)
618 print "Iface", ifacename
, slow
620 self
.slow
= slow(ifacename
)
621 self
.slow
.peripheral
= self
622 for fname
in ['slowimport', 'slowifdecl', 'slowifdeclmux',
624 'mk_connection', 'mk_cellconn', 'mk_pincon']:
625 fn
= CallFn(self
, fname
)
626 setattr(self
, fname
, types
.MethodType(fn
, self
))
628 #print "PeripheralIface"
631 def mksuffix(self
, name
, i
):
632 if self
.slow
is None:
634 return self
.slow
.mksuffix(name
, i
)
636 def axi_reg_def(self
, start
, count
):
639 return self
.slow
.axi_reg_def(start
, self
.ifacename
, count
)
641 def axi_slave_idx(self
, start
, count
):
644 return self
.slow
.axi_slave_idx(start
, self
.ifacename
, count
)
646 def axi_addr_map(self
, count
):
649 return self
.slow
.axi_addr_map(self
.ifacename
, count
)
652 class PeripheralInterfaces(object):
656 def slowimport(self
, *args
):
658 for (name
, count
) in self
.ifacecount
:
659 #print "slowimport", name, self.data[name].slowimport
660 ret
.append(self
.data
[name
].slowimport())
661 return '\n'.join(list(filter(None, ret
)))
663 def slowifdeclmux(self
, *args
):
665 for (name
, count
) in self
.ifacecount
:
666 for i
in range(count
):
667 ret
.append(self
.data
[name
].slowifdeclmux().format(i
, name
))
668 return '\n'.join(list(filter(None, ret
)))
670 def slowifdecl(self
, *args
):
672 for (name
, count
) in self
.ifacecount
:
673 for i
in range(count
):
674 ret
.append(self
.data
[name
].slowifdecl().format(i
, name
))
675 return '\n'.join(list(filter(None, ret
)))
677 def axi_reg_def(self
, *args
):
679 start
= 0x00011100 # start of AXI peripherals address
680 for (name
, count
) in self
.ifacecount
:
681 for i
in range(count
):
682 x
= self
.data
[name
].axi_reg_def(start
, i
)
683 #print ("ifc", name, x)
687 return '\n'.join(list(filter(None, ret
)))
689 def axi_slave_idx(self
, *args
):
692 for (name
, count
) in self
.ifacecount
:
693 for i
in range(count
):
694 (rdef
, offs
) = self
.data
[name
].axi_slave_idx(start
, i
)
695 #print ("ifc", name, rdef, offs)
698 ret
.append("typedef %d LastGen_slave_num;" % (start
- 1))
699 decls
= '\n'.join(list(filter(None, ret
)))
700 return axi_slave_declarations
.format(decls
)
702 def axi_addr_map(self
, *args
):
704 for (name
, count
) in self
.ifacecount
:
705 for i
in range(count
):
706 ret
.append(self
.data
[name
].axi_addr_map(i
))
707 return '\n'.join(list(filter(None, ret
)))
709 def mkslow_peripheral(self
, *args
):
711 for (name
, count
) in self
.ifacecount
:
712 for i
in range(count
):
713 print "mkslow", name
, count
714 x
= self
.data
[name
].mkslow_peripheral()
716 suffix
= self
.data
[name
].mksuffix(name
, i
)
717 ret
.append(x
.format(suffix
))
718 return '\n'.join(list(filter(None, ret
)))
720 def mk_connection(self
, *args
):
722 for (name
, count
) in self
.ifacecount
:
723 for i
in range(count
):
724 print "mk_conn", name
, i
725 txt
= self
.data
[name
].mk_connection(i
)
728 print self
.data
[name
].mk_connection
730 return '\n'.join(list(filter(None, ret
)))
732 def mk_cellconn(self
):
735 for (name
, count
) in self
.ifacecount
:
736 for i
in range(count
):
737 res
= self
.data
[name
].mk_cellconn(cellcount
, name
, i
)
740 (txt
, cellcount
) = res
742 ret
= '\n'.join(list(filter(None, ret
)))
743 return pinmux_cellrule
.format(ret
)
747 for (name
, count
) in self
.ifacecount
:
748 for i
in range(count
):
749 txt
= self
.data
[name
].mk_pincon(name
, i
)
751 return '\n'.join(list(filter(None, ret
)))
754 class PFactory(object):
755 def getcls(self
, name
):
756 for k
, v
in {'uart': uart
,
766 if name
.startswith(k
):
771 slowfactory
= PFactory()
773 if __name__
== '__main__':
777 i
= PeripheralIface('uart')
779 i
= PeripheralIface('gpioa')