eee4cf7eac90a0d2269c7fb8c96bb657f3ed10ae
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
290 def axi_slave_name(self
, name
, ifacenum
):
293 def axi_slave_idx(self
, idx
, name
, ifacenum
):
296 def axi_addr_map(self
, name
, ifacenum
):
299 def ifname_tweak(self
, pname
, typ
, txt
):
302 print "ifnameweak", pname
, typ
, txt
303 return "wr_interrupt[{0}] <= ".format(pname
)
305 def mk_pincon(self
, name
, count
):
306 ret
= [PBase
.mk_pincon(self
, name
, count
)]
307 size
= len(self
.peripheral
.pinspecs
)
308 ret
.append(eint_pincon_template
.format(size
))
309 ret
.append(" rule con_%s%d_io_in;" % (name
, count
))
310 ret
.append(" wr_interrupt <= ({")
311 for idx
, p
in enumerate(self
.peripheral
.pinspecs
):
313 sname
= self
.peripheral
.pname(pname
).format(count
)
314 ps
= "pinmux.peripheral_side.%s" % sname
315 comma
= '' if idx
== size
- 1 else ','
316 ret
.append(" {0}{1}".format(ps
, comma
))
318 ret
.append(" endrule")
320 return '\n'.join(ret
)
323 eint_pincon_template
= '''\
324 // TODO: offset i by the number of eints already used
325 for(Integer i=0;i<{0};i=i+ 1)begin
326 rule connect_int_to_plic(wr_interrupt[i]==1);
327 ff_gateway_queue[i].enq(1);
328 plic.ifc_external_irq[i].irq_frm_gateway(True);
336 def slowimport(self
):
337 return " import sdcard_dummy :: *;"
339 def slowifdecl(self
):
340 return " interface QSPI_out sd{0}_out;\n" + \
341 " method Bit#(1) sd{0}_isint;"
343 def num_axi_regs32(self
):
346 def mkslow_peripheral(self
):
347 return " Ifc_sdcard_dummy sd{0} <- mksdcard_dummy();"
349 def _mk_connection(self
, name
=None, count
=0):
352 def pinname_in(self
, pname
):
353 return "%s_in" % pname
355 def pinname_out(self
, pname
):
356 if pname
.startswith('d'):
357 return "%s_out" % pname
360 def pinname_outen(self
, pname
):
361 if pname
.startswith('d'):
362 return "%s_outen" % pname
367 def slowimport(self
):
368 return " import qspi :: *;"
370 def slowifdecl(self
):
371 return " interface QSPI_out spi{0}_out;\n" + \
372 " method Bit#(1) spi{0}_isint;"
374 def num_axi_regs32(self
):
377 def mkslow_peripheral(self
):
378 return " Ifc_qspi spi{0} <- mkqspi();"
380 def _mk_connection(self
, name
=None, count
=0):
381 return "spi{0}.slave"
383 def pinname_out(self
, pname
):
384 return {'clk': 'out.clk_o',
386 'mosi': 'out.io_o[0]',
387 'miso': 'out.io_o[1]',
390 def pinname_outen(self
, pname
):
393 'mosi': 'out.io_enable[0]',
394 'miso': 'out.io_enable[1]',
397 def mk_pincon(self
, name
, count
):
398 ret
= [PBase
.mk_pincon(self
, name
, count
)]
399 # special-case for gpio in, store in a temporary vector
400 plen
= len(self
.peripheral
.pinspecs
)
401 ret
.append(" // XXX NSS and CLK are hard-coded master")
402 ret
.append(" // TODO: must add spi slave-mode")
403 ret
.append(" // all ins done in one rule from 4-bitfield")
404 ret
.append(" rule con_%s%d_io_in;" % (name
, count
))
405 ret
.append(" {0}{1}.out.io_i({{".format(name
, count
))
406 for idx
, pname
in enumerate(['mosi', 'miso']):
407 sname
= self
.peripheral
.pname(pname
).format(count
)
408 ps
= "pinmux.peripheral_side.%s_in" % sname
409 ret
.append(" {0},".format(ps
))
410 ret
.append(" 1'b0,1'b0")
412 ret
.append(" endrule")
413 return '\n'.join(ret
)
418 def slowimport(self
):
419 return " import qspi :: *;"
421 def slowifdecl(self
):
422 return " interface QSPI_out qspi{0}_out;\n" + \
423 " method Bit#(1) qspi{0}_isint;"
425 def num_axi_regs32(self
):
428 def mkslow_peripheral(self
, size
=0):
429 return " Ifc_qspi qspi{0} <- mkqspi();"
431 def _mk_connection(self
, name
=None, count
=0):
432 return "qspi{0}.slave"
434 def pinname_out(self
, pname
):
435 return {'ck': 'out.clk_o',
437 'io0': 'out.io_o[0]',
438 'io1': 'out.io_o[1]',
439 'io2': 'out.io_o[2]',
440 'io3': 'out.io_o[3]',
443 def pinname_outen(self
, pname
):
446 'io0': 'out.io_enable[0]',
447 'io1': 'out.io_enable[1]',
448 'io2': 'out.io_enable[2]',
449 'io3': 'out.io_enable[3]',
452 def mk_pincon(self
, name
, count
):
453 ret
= [PBase
.mk_pincon(self
, name
, count
)]
454 # special-case for gpio in, store in a temporary vector
455 plen
= len(self
.peripheral
.pinspecs
)
456 ret
.append(" // XXX NSS and CLK are hard-coded master")
457 ret
.append(" // TODO: must add qspi slave-mode")
458 ret
.append(" // all ins done in one rule from 4-bitfield")
459 ret
.append(" rule con_%s%d_io_in;" % (name
, count
))
460 ret
.append(" {0}{1}.out.io_i({{".format(name
, count
))
461 for i
, p
in enumerate(self
.peripheral
.pinspecs
):
464 if not pname
.startswith('io'):
468 sname
= self
.peripheral
.pname(pname
).format(count
)
469 ps
= "pinmux.peripheral_side.%s_in" % sname
470 comma
= '' if i
== 5 else ','
471 ret
.append(" {0}{1}".format(ps
, comma
))
473 ret
.append(" endrule")
474 return '\n'.join(ret
)
479 def slowimport(self
):
480 return " import pwm::*;"
482 def slowifdecl(self
):
483 return " interface PWMIO pwm{0}_io;"
485 def num_axi_regs32(self
):
488 def mkslow_peripheral(self
, size
=0):
489 return " Ifc_PWM_bus pwm{0} <- mkPWM_bus(sp_clock);"
491 def _mk_connection(self
, name
=None, count
=0):
492 return "pwm{0}.axi4_slave"
494 def pinname_out(self
, pname
):
495 return {'out': 'pwm_io.pwm_o'}.get(pname
, '')
500 def slowimport(self
):
501 return " import pinmux::*;\n" + \
502 " import mux::*;\n" + \
505 def slowifdeclmux(self
):
506 size
= len(self
.peripheral
.pinspecs
)
507 return " interface GPIO_config#(%d) pad_config{0};" % size
509 def num_axi_regs32(self
):
512 def axi_slave_idx(self
, idx
, name
, ifacenum
):
513 """ generates AXI slave number definition, except
514 GPIO also has a muxer per bank
517 mname
= 'mux' + name
[4:]
518 mname
= mname
.upper()
519 print "AXIslavenum", name
, mname
520 (ret
, x
) = PBase
.axi_slave_idx(self
, idx
, name
, ifacenum
)
521 (ret2
, x
) = PBase
.axi_slave_idx(self
, idx
+ 1, mname
, ifacenum
)
522 return ("%s\n%s" % (ret
, ret2
), 2)
524 def mkslow_peripheral(self
, size
=0):
525 print "gpioslow", self
.peripheral
, dir(self
.peripheral
)
526 size
= len(self
.peripheral
.pinspecs
)
527 return " MUX#(%d) mux{0} <- mkmux();\n" % size
+ \
528 " GPIO#(%d) gpio{0} <- mkgpio();" % size
530 def mk_connection(self
, count
):
531 print "GPIO mk_conn", self
.name
, count
533 dname
= self
.mksuffix(self
.name
, count
)
534 for i
, n
in enumerate(['gpio' + dname
, 'mux' + dname
]):
535 res
.append(PBase
.mk_connection(self
, count
, n
))
536 return '\n'.join(res
)
538 def _mk_connection(self
, name
=None, count
=0):
539 n
= self
.mksuffix(name
, count
)
540 if name
.startswith('gpio'):
541 return "gpio{0}.axi_slave".format(n
)
542 if name
.startswith('mux'):
543 return "mux{0}.axi_slave".format(n
)
545 def mksuffix(self
, name
, i
):
546 if name
.startswith('mux'):
550 def mk_cellconn(self
, cellnum
, name
, count
):
552 bank
= self
.mksuffix(name
, count
)
553 txt
= " pinmux.mux_lines.cell{0}_mux(mux{1}.mux_config.mux[{2}]);"
554 for p
in self
.peripheral
.pinspecs
:
555 ret
.append(txt
.format(cellnum
, bank
, p
['name'][1:]))
557 return ("\n".join(ret
), cellnum
)
559 def pinname_out(self
, pname
):
560 return "func.gpio_out[{0}]".format(pname
[1:])
562 def pinname_outen(self
, pname
):
563 return "func.gpio_out_en[{0}]".format(pname
[1:])
565 def mk_pincon(self
, name
, count
):
566 ret
= [PBase
.mk_pincon(self
, name
, count
)]
567 # special-case for gpio in, store in a temporary vector
568 plen
= len(self
.peripheral
.pinspecs
)
569 ret
.append(" rule con_%s%d_in;" % (name
, count
))
570 ret
.append(" Vector#({0},Bit#(1)) temp;".format(plen
))
571 for p
in self
.peripheral
.pinspecs
:
576 sname
= self
.peripheral
.pname(pname
).format(count
)
577 ps
= "pinmux.peripheral_side.%s_in" % sname
578 ret
.append(" temp[{0}]={1};".format(idx
, ps
))
579 ret
.append(" {0}.func.gpio_in(temp);".format(name
))
580 ret
.append(" endrule")
581 return '\n'.join(ret
)
584 axi_slave_declarations
= """\
585 typedef 0 SlowMaster;
587 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
589 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
591 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
593 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
596 pinmux_cellrule
= """\
597 rule connect_select_lines_pinmux;
603 class CallFn(object):
604 def __init__(self
, peripheral
, name
):
605 self
.peripheral
= peripheral
608 def __call__(self
, *args
):
609 #print "__call__", self.name, self.peripheral.slow, args
610 if not self
.peripheral
.slow
:
612 return getattr(self
.peripheral
.slow
, self
.name
)(*args
[1:])
615 class PeripheralIface(object):
616 def __init__(self
, ifacename
):
618 slow
= slowfactory
.getcls(ifacename
)
619 print "Iface", ifacename
, slow
621 self
.slow
= slow(ifacename
)
622 self
.slow
.peripheral
= self
623 for fname
in ['slowimport', 'slowifdecl', 'slowifdeclmux',
625 'mk_connection', 'mk_cellconn', 'mk_pincon']:
626 fn
= CallFn(self
, fname
)
627 setattr(self
, fname
, types
.MethodType(fn
, self
))
629 #print "PeripheralIface"
632 def mksuffix(self
, name
, i
):
633 if self
.slow
is None:
635 return self
.slow
.mksuffix(name
, i
)
637 def axi_reg_def(self
, start
, count
):
640 return self
.slow
.axi_reg_def(start
, self
.ifacename
, count
)
642 def axi_slave_idx(self
, start
, count
):
645 return self
.slow
.axi_slave_idx(start
, self
.ifacename
, count
)
647 def axi_addr_map(self
, count
):
650 return self
.slow
.axi_addr_map(self
.ifacename
, count
)
653 class PeripheralInterfaces(object):
657 def slowimport(self
, *args
):
659 for (name
, count
) in self
.ifacecount
:
660 #print "slowimport", name, self.data[name].slowimport
661 ret
.append(self
.data
[name
].slowimport())
662 return '\n'.join(list(filter(None, ret
)))
664 def slowifdeclmux(self
, *args
):
666 for (name
, count
) in self
.ifacecount
:
667 for i
in range(count
):
668 ret
.append(self
.data
[name
].slowifdeclmux().format(i
, name
))
669 return '\n'.join(list(filter(None, ret
)))
671 def slowifdecl(self
, *args
):
673 for (name
, count
) in self
.ifacecount
:
674 for i
in range(count
):
675 ret
.append(self
.data
[name
].slowifdecl().format(i
, name
))
676 return '\n'.join(list(filter(None, ret
)))
678 def axi_reg_def(self
, *args
):
680 start
= 0x00011100 # start of AXI peripherals address
681 for (name
, count
) in self
.ifacecount
:
682 for i
in range(count
):
683 x
= self
.data
[name
].axi_reg_def(start
, i
)
684 #print ("ifc", name, x)
688 return '\n'.join(list(filter(None, ret
)))
690 def axi_slave_idx(self
, *args
):
693 for (name
, count
) in self
.ifacecount
:
694 for i
in range(count
):
695 (rdef
, offs
) = self
.data
[name
].axi_slave_idx(start
, i
)
696 #print ("ifc", name, rdef, offs)
699 ret
.append("typedef %d LastGen_slave_num;" % (start
- 1))
700 decls
= '\n'.join(list(filter(None, ret
)))
701 return axi_slave_declarations
.format(decls
)
703 def axi_addr_map(self
, *args
):
705 for (name
, count
) in self
.ifacecount
:
706 for i
in range(count
):
707 ret
.append(self
.data
[name
].axi_addr_map(i
))
708 return '\n'.join(list(filter(None, ret
)))
710 def mkslow_peripheral(self
, *args
):
712 for (name
, count
) in self
.ifacecount
:
713 for i
in range(count
):
714 print "mkslow", name
, count
715 x
= self
.data
[name
].mkslow_peripheral()
717 suffix
= self
.data
[name
].mksuffix(name
, i
)
718 ret
.append(x
.format(suffix
))
719 return '\n'.join(list(filter(None, ret
)))
721 def mk_connection(self
, *args
):
723 for (name
, count
) in self
.ifacecount
:
724 for i
in range(count
):
725 print "mk_conn", name
, i
726 txt
= self
.data
[name
].mk_connection(i
)
729 print self
.data
[name
].mk_connection
731 return '\n'.join(list(filter(None, ret
)))
733 def mk_cellconn(self
):
736 for (name
, count
) in self
.ifacecount
:
737 for i
in range(count
):
738 res
= self
.data
[name
].mk_cellconn(cellcount
, name
, i
)
741 (txt
, cellcount
) = res
743 ret
= '\n'.join(list(filter(None, ret
)))
744 return pinmux_cellrule
.format(ret
)
748 for (name
, count
) in self
.ifacecount
:
749 for i
in range(count
):
750 txt
= self
.data
[name
].mk_pincon(name
, i
)
752 return '\n'.join(list(filter(None, ret
)))
755 class PFactory(object):
756 def getcls(self
, name
):
757 for k
, v
in {'uart': uart
,
767 if name
.startswith(k
):
772 slowfactory
= PFactory()
774 if __name__
== '__main__':
778 i
= PeripheralIface('uart')
780 i
= PeripheralIface('gpioa')