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 slowifdeclmux(self
):
287 size
= len(self
.peripheral
.pinspecs
)
288 return " method Action external_int(Bit#(%d) in);" % size
290 def mkslow_peripheral(self
, size
=0):
291 size
= len(self
.peripheral
.pinspecs
)
292 return " Wire#(Bit#(%d)) wr_interrupt <- mkWire();" % size
295 def axi_slave_name(self
, name
, ifacenum
):
298 def axi_slave_idx(self
, idx
, name
, ifacenum
):
301 def axi_addr_map(self
, name
, ifacenum
):
304 def ifname_tweak(self
, pname
, typ
, txt
):
307 print "ifnameweak", pname
, typ
, txt
308 return "wr_interrupt[{0}] <= ".format(pname
)
310 def mk_pincon(self
, name
, count
):
311 ret
= [PBase
.mk_pincon(self
, name
, count
)]
312 size
= len(self
.peripheral
.pinspecs
)
313 ret
.append(eint_pincon_template
.format(size
))
314 ret
.append(" rule con_%s%d_io_in;" % (name
, count
))
315 ret
.append(" wr_interrupt({")
316 for idx
, p
in enumerate(self
.peripheral
.pinspecs
):
318 sname
= self
.peripheral
.pname(pname
).format(count
)
319 ps
= "pinmux.peripheral_side.%s" % sname
320 comma
= '' if idx
== size
-1 else ','
321 ret
.append(" {0}{1}".format(ps
, comma
))
323 ret
.append(" endrule")
325 return '\n'.join(ret
)
328 eint_pincon_template
= '''\
329 // TODO: offset i by the number of eints already used
330 for(Integer i=0;i<{0};i=i+ 1)begin
331 rule connect_int_to_plic(wr_interrupt[i]==1);
332 ff_gateway_queue[i].enq(1);
333 plic.ifc_external_irq[i].irq_frm_gateway(True);
341 def slowimport(self
):
342 return " import qspi :: *;"
344 def slowifdecl(self
):
345 return " interface QSPI_out spi{0}_out;\n" + \
346 " method Bit#(1) spi{0}_isint;"
348 def num_axi_regs32(self
):
351 def mkslow_peripheral(self
):
352 return " Ifc_qspi spi{0} <- mkqspi();"
354 def _mk_connection(self
, name
=None, count
=0):
355 return "spi{0}.slave"
357 def pinname_out(self
, pname
):
358 return {'clk': 'out.clk_o',
360 'mosi': 'out.io_o[0]',
361 'miso': 'out.io_o[1]',
364 def pinname_outen(self
, pname
):
367 'mosi': 'out.io_enable[0]',
368 'miso': 'out.io_enable[1]',
371 def mk_pincon(self
, name
, count
):
372 ret
= [PBase
.mk_pincon(self
, name
, count
)]
373 # special-case for gpio in, store in a temporary vector
374 plen
= len(self
.peripheral
.pinspecs
)
375 ret
.append(" // XXX NSS and CLK are hard-coded master")
376 ret
.append(" // TODO: must add spi slave-mode")
377 ret
.append(" // all ins done in one rule from 4-bitfield")
378 ret
.append(" rule con_%s%d_io_in;" % (name
, count
))
379 ret
.append(" {0}{1}.out.io_i({{".format(name
, count
))
380 for idx
, pname
in enumerate(['mosi', 'miso']):
381 sname
= self
.peripheral
.pname(pname
).format(count
)
382 ps
= "pinmux.peripheral_side.%s_in" % sname
383 ret
.append(" {0},".format(ps
))
384 ret
.append(" 1'b0,1'b0")
386 ret
.append(" endrule")
387 return '\n'.join(ret
)
392 def slowimport(self
):
393 return " import qspi :: *;"
395 def slowifdecl(self
):
396 return " interface QSPI_out qspi{0}_out;\n" + \
397 " method Bit#(1) qspi{0}_isint;"
399 def num_axi_regs32(self
):
402 def mkslow_peripheral(self
, size
=0):
403 return " Ifc_qspi qspi{0} <- mkqspi();"
405 def _mk_connection(self
, name
=None, count
=0):
406 return "qspi{0}.slave"
408 def pinname_out(self
, pname
):
409 return {'ck': 'out.clk_o',
411 'io0': 'out.io_o[0]',
412 'io1': 'out.io_o[1]',
413 'io2': 'out.io_o[2]',
414 'io3': 'out.io_o[3]',
417 def pinname_outen(self
, pname
):
420 'io0': 'out.io_enable[0]',
421 'io1': 'out.io_enable[1]',
422 'io2': 'out.io_enable[2]',
423 'io3': 'out.io_enable[3]',
426 def mk_pincon(self
, name
, count
):
427 ret
= [PBase
.mk_pincon(self
, name
, count
)]
428 # special-case for gpio in, store in a temporary vector
429 plen
= len(self
.peripheral
.pinspecs
)
430 ret
.append(" // XXX NSS and CLK are hard-coded master")
431 ret
.append(" // TODO: must add qspi slave-mode")
432 ret
.append(" // all ins done in one rule from 4-bitfield")
433 ret
.append(" rule con_%s%d_io_in;" % (name
, count
))
434 ret
.append(" {0}{1}.out.io_i({{".format(name
, count
))
435 for i
, p
in enumerate(self
.peripheral
.pinspecs
):
438 if not pname
.startswith('io'):
442 sname
= self
.peripheral
.pname(pname
).format(count
)
443 ps
= "pinmux.peripheral_side.%s_in" % sname
444 comma
= '' if i
== 5 else ','
445 ret
.append(" {0}{1}".format(ps
, comma
))
447 ret
.append(" endrule")
448 return '\n'.join(ret
)
453 def slowimport(self
):
454 return " import pwm::*;"
456 def slowifdecl(self
):
457 return " interface PWMIO pwm{0}_io;"
459 def num_axi_regs32(self
):
462 def mkslow_peripheral(self
, size
=0):
463 return " Ifc_PWM_bus pwm{0} <- mkPWM_bus(sp_clock);"
465 def _mk_connection(self
, name
=None, count
=0):
466 return "pwm{0}.axi4_slave"
468 def pinname_out(self
, pname
):
469 return {'out': 'pwm_io.pwm_o'}.get(pname
, '')
474 def slowimport(self
):
475 return " import pinmux::*;\n" + \
476 " import mux::*;\n" + \
479 def slowifdeclmux(self
):
480 size
= len(self
.peripheral
.pinspecs
)
481 return " interface GPIO_config#(%d) pad_config{0};" % size
483 def num_axi_regs32(self
):
486 def axi_slave_idx(self
, idx
, name
, ifacenum
):
487 """ generates AXI slave number definition, except
488 GPIO also has a muxer per bank
491 mname
= 'mux' + name
[4:]
492 mname
= mname
.upper()
493 print "AXIslavenum", name
, mname
494 (ret
, x
) = PBase
.axi_slave_idx(self
, idx
, name
, ifacenum
)
495 (ret2
, x
) = PBase
.axi_slave_idx(self
, idx
+1, mname
, ifacenum
)
496 return ("%s\n%s" % (ret
, ret2
), 2)
498 def mkslow_peripheral(self
, size
=0):
499 print "gpioslow", self
.peripheral
, dir(self
.peripheral
)
500 size
= len(self
.peripheral
.pinspecs
)
501 return " MUX#(%d) mux{0} <- mkmux();\n" % size
+ \
502 " GPIO#(%d) gpio{0} <- mkgpio();" % size
504 def mk_connection(self
, count
):
505 print "GPIO mk_conn", self
.name
, count
507 dname
= self
.mksuffix(self
.name
, count
)
508 for i
, n
in enumerate(['gpio' + dname
, 'mux' + dname
]):
509 res
.append(PBase
.mk_connection(self
, count
, n
))
510 return '\n'.join(res
)
512 def _mk_connection(self
, name
=None, count
=0):
513 n
= self
.mksuffix(name
, count
)
514 if name
.startswith('gpio'):
515 return "gpio{0}.axi_slave".format(n
)
516 if name
.startswith('mux'):
517 return "mux{0}.axi_slave".format(n
)
519 def mksuffix(self
, name
, i
):
520 if name
.startswith('mux'):
524 def mk_cellconn(self
, cellnum
, name
, count
):
526 bank
= self
.mksuffix(name
, count
)
527 txt
= " pinmux.mux_lines.cell{0}_mux(mux{1}.mux_config.mux[{2}]);"
528 for p
in self
.peripheral
.pinspecs
:
529 ret
.append(txt
.format(cellnum
, bank
, p
['name'][1:]))
531 return ("\n".join(ret
), cellnum
)
533 def pinname_out(self
, pname
):
534 return "func.gpio_out[{0}]".format(pname
[1:])
536 def pinname_outen(self
, pname
):
537 return "func.gpio_out_en[{0}]".format(pname
[1:])
539 def mk_pincon(self
, name
, count
):
540 ret
= [PBase
.mk_pincon(self
, name
, count
)]
541 # special-case for gpio in, store in a temporary vector
542 plen
= len(self
.peripheral
.pinspecs
)
543 ret
.append(" rule con_%s%d_in;" % (name
, count
))
544 ret
.append(" Vector#({0},Bit#(1)) temp;".format(plen
))
545 for p
in self
.peripheral
.pinspecs
:
550 sname
= self
.peripheral
.pname(pname
).format(count
)
551 ps
= "pinmux.peripheral_side.%s_in" % sname
552 ret
.append(" temp[{0}]={1};".format(idx
, ps
))
553 ret
.append(" {0}.func.gpio_in(temp);".format(name
))
554 ret
.append(" endrule")
555 return '\n'.join(ret
)
558 axi_slave_declarations
= """\
559 typedef 0 SlowMaster;
561 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
563 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
565 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
567 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
570 pinmux_cellrule
= """\
571 rule connect_select_lines_pinmux;
577 class CallFn(object):
578 def __init__(self
, peripheral
, name
):
579 self
.peripheral
= peripheral
582 def __call__(self
, *args
):
583 #print "__call__", self.name, self.peripheral.slow, args
584 if not self
.peripheral
.slow
:
586 return getattr(self
.peripheral
.slow
, self
.name
)(*args
[1:])
589 class PeripheralIface(object):
590 def __init__(self
, ifacename
):
592 slow
= slowfactory
.getcls(ifacename
)
593 print "Iface", ifacename
, slow
595 self
.slow
= slow(ifacename
)
596 self
.slow
.peripheral
= self
597 for fname
in ['slowimport', 'slowifdecl', 'slowifdeclmux',
599 'mk_connection', 'mk_cellconn', 'mk_pincon']:
600 fn
= CallFn(self
, fname
)
601 setattr(self
, fname
, types
.MethodType(fn
, self
))
603 #print "PeripheralIface"
606 def mksuffix(self
, name
, i
):
607 if self
.slow
is None:
609 return self
.slow
.mksuffix(name
, i
)
611 def axi_reg_def(self
, start
, count
):
614 return self
.slow
.axi_reg_def(start
, self
.ifacename
, count
)
616 def axi_slave_idx(self
, start
, count
):
619 return self
.slow
.axi_slave_idx(start
, self
.ifacename
, count
)
621 def axi_addr_map(self
, count
):
624 return self
.slow
.axi_addr_map(self
.ifacename
, count
)
627 class PeripheralInterfaces(object):
631 def slowimport(self
, *args
):
633 for (name
, count
) in self
.ifacecount
:
634 #print "slowimport", name, self.data[name].slowimport
635 ret
.append(self
.data
[name
].slowimport())
636 return '\n'.join(list(filter(None, ret
)))
638 def slowifdeclmux(self
, *args
):
640 for (name
, count
) in self
.ifacecount
:
641 for i
in range(count
):
642 ret
.append(self
.data
[name
].slowifdeclmux().format(i
, name
))
643 return '\n'.join(list(filter(None, ret
)))
645 def slowifdecl(self
, *args
):
647 for (name
, count
) in self
.ifacecount
:
648 for i
in range(count
):
649 ret
.append(self
.data
[name
].slowifdecl().format(i
, name
))
650 return '\n'.join(list(filter(None, ret
)))
652 def axi_reg_def(self
, *args
):
654 start
= 0x00011100 # start of AXI peripherals address
655 for (name
, count
) in self
.ifacecount
:
656 for i
in range(count
):
657 x
= self
.data
[name
].axi_reg_def(start
, i
)
658 #print ("ifc", name, x)
662 return '\n'.join(list(filter(None, ret
)))
664 def axi_slave_idx(self
, *args
):
667 for (name
, count
) in self
.ifacecount
:
668 for i
in range(count
):
669 (rdef
, offs
) = self
.data
[name
].axi_slave_idx(start
, i
)
670 #print ("ifc", name, rdef, offs)
673 ret
.append("typedef %d LastGen_slave_num;" % (start
- 1))
674 decls
= '\n'.join(list(filter(None, ret
)))
675 return axi_slave_declarations
.format(decls
)
677 def axi_addr_map(self
, *args
):
679 for (name
, count
) in self
.ifacecount
:
680 for i
in range(count
):
681 ret
.append(self
.data
[name
].axi_addr_map(i
))
682 return '\n'.join(list(filter(None, ret
)))
684 def mkslow_peripheral(self
, *args
):
686 for (name
, count
) in self
.ifacecount
:
687 for i
in range(count
):
688 print "mkslow", name
, count
689 x
= self
.data
[name
].mkslow_peripheral()
691 suffix
= self
.data
[name
].mksuffix(name
, i
)
692 ret
.append(x
.format(suffix
))
693 return '\n'.join(list(filter(None, ret
)))
695 def mk_connection(self
, *args
):
697 for (name
, count
) in self
.ifacecount
:
698 for i
in range(count
):
699 print "mk_conn", name
, i
700 txt
= self
.data
[name
].mk_connection(i
)
703 print self
.data
[name
].mk_connection
705 return '\n'.join(list(filter(None, ret
)))
707 def mk_cellconn(self
):
710 for (name
, count
) in self
.ifacecount
:
711 for i
in range(count
):
712 res
= self
.data
[name
].mk_cellconn(cellcount
, name
, i
)
715 (txt
, cellcount
) = res
717 ret
= '\n'.join(list(filter(None, ret
)))
718 return pinmux_cellrule
.format(ret
)
722 for (name
, count
) in self
.ifacecount
:
723 for i
in range(count
):
724 txt
= self
.data
[name
].mk_pincon(name
, i
)
726 return '\n'.join(list(filter(None, ret
)))
729 class PFactory(object):
730 def getcls(self
, name
):
731 for k
, v
in {'uart': uart
,
740 if name
.startswith(k
):
745 slowfactory
= PFactory()
747 if __name__
== '__main__':
751 i
= PeripheralIface('uart')
753 i
= PeripheralIface('gpioa')