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 ret
.append(" {1}.{2}({0});".format(ps_
, n_
, fname
))
106 ret
.append(" endrule")
107 return '\n'.join(ret
)
109 def mk_cellconn(self
, *args
):
112 def mkslow_peripheral(self
, size
=0):
115 def mksuffix(self
, name
, i
):
118 def __mk_connection(self
, con
, aname
):
119 txt
= " mkConnection (slow_fabric.v_to_slaves\n" + \
120 " [fromInteger(valueOf({1}))],\n" + \
123 print "PBase __mk_connection", self
.name
, aname
126 return txt
.format(con
, aname
)
128 def mk_connection(self
, count
, name
=None):
131 print "PBase mk_conn", self
.name
, count
132 aname
= self
.axi_slave_name(name
, count
)
133 #dname = self.mksuffix(name, count)
134 #dname = "{0}{1}".format(name, dname)
135 con
= self
._mk
_connection
(name
, count
).format(count
, aname
)
136 return self
.__mk
_connection
(con
, aname
)
138 def _mk_connection(self
, name
=None, count
=0):
141 def pinname_out(self
, pname
):
144 def pinname_in(self
, pname
):
147 def pinname_outen(self
, pname
):
150 def pinname_tweak(self
, pname
, typ
, txt
):
156 def slowimport(self
):
157 return " import Uart_bs :: *;\n" + \
158 " import RS232_modified::*;"
160 def slowifdecl(self
):
161 return " interface RS232 uart{0}_coe;\n" + \
162 " method Bit#(1) uart{0}_intr;"
164 def num_axi_regs32(self
):
167 def mkslow_peripheral(self
, size
=0):
168 return " Ifc_Uart_bs uart{0} <- \n" + \
169 " mkUart_bs(clocked_by sp_clock,\n" + \
170 " reset_by uart_reset, sp_clock, sp_reset);"
172 def _mk_connection(self
, name
=None, count
=0):
173 return "uart{0}.slave_axi_uart"
175 def pinname_out(self
, pname
):
176 return {'tx': 'coe_rs232.sout'}.get(pname
, '')
178 def pinname_in(self
, pname
):
179 return {'rx': 'coe_rs232.sin'}.get(pname
, '')
184 def slowimport(self
):
185 return " import Uart16550 :: *;"
187 def slowifdecl(self
):
188 return " interface RS232_PHY_Ifc uart{0}_coe;\n" + \
189 " method Bit#(1) uart{0}_intr;"
191 def num_axi_regs32(self
):
194 def mkslow_peripheral(self
, size
=0):
195 return " Uart16550_AXI4_Lite_Ifc uart{0} <- \n" + \
196 " mkUart16550(clocked_by sp_clock,\n" + \
197 " reset_by uart_reset, sp_clock, sp_reset);"
199 def _mk_connection(self
, name
=None, count
=0):
200 return "uart{0}.slave_axi_uart"
202 def pinname_out(self
, pname
):
203 return {'tx': 'coe_rs232.sout'}.get(pname
, '')
205 def pinname_in(self
, pname
):
206 return {'rx': 'coe_rs232.sin'}.get(pname
, '')
211 def slowimport(self
):
212 return " import Uart_bs::*;\n" + \
213 " import RS232_modified::*;"
215 def slowifdecl(self
):
216 return " interface RS232 uart{0}_coe;"
218 def num_axi_regs32(self
):
221 def mkslow_peripheral(self
, size
=0):
222 return " //Ifc_Uart_bs uart{0} <-" + \
223 " // mkUart_bs(clocked_by uart_clock,\n" + \
224 " // reset_by uart_reset,sp_clock, sp_reset);" +\
225 " Ifc_Uart_bs uart{0} <-" + \
226 " mkUart_bs(clocked_by sp_clock,\n" + \
227 " reset_by sp_reset, sp_clock, sp_reset);"
229 def _mk_connection(self
, name
=None, count
=0):
230 return "uart{0}.slave_axi_uart"
232 def pinname_out(self
, pname
):
233 return {'tx': 'coe_rs232.sout'}.get(pname
, '')
235 def pinname_in(self
, pname
):
236 return {'rx': 'coe_rs232.sin'}.get(pname
, '')
241 def slowimport(self
):
242 return " import I2C_top :: *;"
244 def slowifdecl(self
):
245 return " interface I2C_out twi{0}_out;\n" + \
246 " method Bit#(1) twi{0}_isint;"
248 def num_axi_regs32(self
):
251 def mkslow_peripheral(self
, size
=0):
252 return " I2C_IFC twi{0} <- mkI2CController();"
254 def _mk_connection(self
, name
=None, count
=0):
255 return "twi{0}.slave_i2c_axi"
257 def pinname_out(self
, pname
):
258 return {'sda': 'out.sda_out',
259 'scl': 'out.scl_out'}.get(pname
, '')
261 def pinname_in(self
, pname
):
262 return {'sda': 'out.sda_in',
263 'scl': 'out.scl_in'}.get(pname
, '')
265 def pinname_outen(self
, pname
):
266 return {'sda': 'out.sda_out_en',
267 'scl': 'out.scl_out_en'}.get(pname
, '')
269 def pinname_tweak(self
, pname
, typ
, txt
):
271 return "pack({0})".format(txt
)
277 def mkslow_peripheral(self
, size
=0):
278 size
= len(self
.peripheral
.pinspecs
)
279 return " Wire#(Bit#(%d)) wr_interrupt <- mkWire();" % size
282 def axi_slave_name(self
, name
, ifacenum
):
285 def axi_slave_idx(self
, idx
, name
, ifacenum
):
288 def axi_addr_map(self
, name
, ifacenum
):
291 def _pinname_out(self
, pname
):
292 return {'sda': 'out.sda_out',
293 'scl': 'out.scl_out'}.get(pname
, '')
295 def _pinname_in(self
, pname
):
296 return {'sda': 'out.sda_in',
297 'scl': 'out.scl_in'}.get(pname
, '')
299 def _pinname_outen(self
, pname
):
300 return {'sda': 'out.sda_out_en',
301 'scl': 'out.scl_out_en'}.get(pname
, '')
303 def mk_pincon(self
, name
, count
):
304 size
= len(self
.peripheral
.pinspecs
)
306 ret
.append(eint_pincon_template
.format(size
))
308 ret
.append(" rule con_%s%d_io_out;" % (name
, count
))
309 for idx
, p
in enumerate(self
.peripheral
.pinspecs
):
311 sname
= self
.peripheral
.pname(pname
).format(count
)
312 ps
= "pinmux.peripheral_side.%s_out" % sname
313 ret
.append(" wr_interript[{0}] <= {1};".format(idx
, ps
))
314 for idx
, p
in enumerate(self
.peripheral
.pinspecs
):
316 sname
= self
.peripheral
.pname(pname
).format(count
)
317 ps
= "pinmux.peripheral_side.%s_out_en" % sname
318 ret
.append(" {0} <= 1'b1;".format(ps
))
319 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 qspi :: *;"
339 def slowifdecl(self
):
340 return " interface QSPI_out spi{0}_out;\n" + \
341 " method Bit#(1) spi{0}_isint;"
343 def num_axi_regs32(self
):
346 def mkslow_peripheral(self
):
347 return " Ifc_qspi spi{0} <- mkqspi();"
349 def _mk_connection(self
, name
=None, count
=0):
350 return "spi{0}.slave"
352 def pinname_out(self
, pname
):
353 return {'clk': 'out.clk_o',
355 'mosi': 'out.io_o[0]',
356 'miso': 'out.io_o[1]',
359 def pinname_outen(self
, pname
):
362 'mosi': 'out.io_enable[0]',
363 'miso': 'out.io_enable[1]',
366 def mk_pincon(self
, name
, count
):
367 ret
= [PBase
.mk_pincon(self
, name
, count
)]
368 # special-case for gpio in, store in a temporary vector
369 plen
= len(self
.peripheral
.pinspecs
)
370 ret
.append(" // XXX NSS and CLK are hard-coded master")
371 ret
.append(" // TODO: must add spi slave-mode")
372 ret
.append(" // all ins done in one rule from 4-bitfield")
373 ret
.append(" rule con_%s%d_io_in;" % (name
, count
))
374 ret
.append(" {0}{1}.out.io_i({{".format(name
, count
))
375 for idx
, pname
in enumerate(['mosi', 'miso']):
376 sname
= self
.peripheral
.pname(pname
).format(count
)
377 ps
= "pinmux.peripheral_side.%s_in" % sname
378 ret
.append(" {0},".format(ps
))
379 ret
.append(" 1'b0,1'b0")
381 ret
.append(" endrule")
382 return '\n'.join(ret
)
387 def slowimport(self
):
388 return " import qspi :: *;"
390 def slowifdecl(self
):
391 return " interface QSPI_out qspi{0}_out;\n" + \
392 " method Bit#(1) qspi{0}_isint;"
394 def num_axi_regs32(self
):
397 def mkslow_peripheral(self
, size
=0):
398 return " Ifc_qspi qspi{0} <- mkqspi();"
400 def _mk_connection(self
, name
=None, count
=0):
401 return "qspi{0}.slave"
403 def pinname_out(self
, pname
):
404 return {'ck': 'out.clk_o',
406 'io0': 'out.io_o[0]',
407 'io1': 'out.io_o[1]',
408 'io2': 'out.io_o[2]',
409 'io3': 'out.io_o[3]',
412 def pinname_outen(self
, pname
):
415 'io0': 'out.io_enable[0]',
416 'io1': 'out.io_enable[1]',
417 'io2': 'out.io_enable[2]',
418 'io3': 'out.io_enable[3]',
421 def mk_pincon(self
, name
, count
):
422 ret
= [PBase
.mk_pincon(self
, name
, count
)]
423 # special-case for gpio in, store in a temporary vector
424 plen
= len(self
.peripheral
.pinspecs
)
425 ret
.append(" // XXX NSS and CLK are hard-coded master")
426 ret
.append(" // TODO: must add qspi slave-mode")
427 ret
.append(" // all ins done in one rule from 4-bitfield")
428 ret
.append(" rule con_%s%d_io_in;" % (name
, count
))
429 ret
.append(" {0}{1}.out.io_i({{".format(name
, count
))
430 for i
, p
in enumerate(self
.peripheral
.pinspecs
):
433 if not pname
.startswith('io'):
437 sname
= self
.peripheral
.pname(pname
).format(count
)
438 ps
= "pinmux.peripheral_side.%s_in" % sname
439 comma
= '' if i
== 5 else ','
440 ret
.append(" {0}{1}".format(ps
, comma
))
442 ret
.append(" endrule")
443 return '\n'.join(ret
)
448 def slowimport(self
):
449 return " import pwm::*;"
451 def slowifdecl(self
):
452 return " interface PWMIO pwm{0}_io;"
454 def num_axi_regs32(self
):
457 def mkslow_peripheral(self
, size
=0):
458 return " Ifc_PWM_bus pwm{0} <- mkPWM_bus(sp_clock);"
460 def _mk_connection(self
, name
=None, count
=0):
461 return "pwm{0}.axi4_slave"
463 def pinname_out(self
, pname
):
464 return {'out': 'pwm_io.pwm_o'}.get(pname
, '')
469 def slowimport(self
):
470 return " import pinmux::*;\n" + \
471 " import mux::*;\n" + \
474 def slowifdeclmux(self
):
475 size
= len(self
.peripheral
.pinspecs
)
476 return " interface GPIO_config#(%d) pad_config{0};" % size
478 def num_axi_regs32(self
):
481 def axi_slave_idx(self
, idx
, name
, ifacenum
):
482 """ generates AXI slave number definition, except
483 GPIO also has a muxer per bank
486 mname
= 'mux' + name
[4:]
487 mname
= mname
.upper()
488 print "AXIslavenum", name
, mname
489 (ret
, x
) = PBase
.axi_slave_idx(self
, idx
, name
, ifacenum
)
490 (ret2
, x
) = PBase
.axi_slave_idx(self
, idx
+1, mname
, ifacenum
)
491 return ("%s\n%s" % (ret
, ret2
), 2)
493 def mkslow_peripheral(self
, size
=0):
494 print "gpioslow", self
.peripheral
, dir(self
.peripheral
)
495 size
= len(self
.peripheral
.pinspecs
)
496 return " MUX#(%d) mux{0} <- mkmux();\n" % size
+ \
497 " GPIO#(%d) gpio{0} <- mkgpio();" % size
499 def mk_connection(self
, count
):
500 print "GPIO mk_conn", self
.name
, count
502 dname
= self
.mksuffix(self
.name
, count
)
503 for i
, n
in enumerate(['gpio' + dname
, 'mux' + dname
]):
504 res
.append(PBase
.mk_connection(self
, count
, n
))
505 return '\n'.join(res
)
507 def _mk_connection(self
, name
=None, count
=0):
508 n
= self
.mksuffix(name
, count
)
509 if name
.startswith('gpio'):
510 return "gpio{0}.axi_slave".format(n
)
511 if name
.startswith('mux'):
512 return "mux{0}.axi_slave".format(n
)
514 def mksuffix(self
, name
, i
):
515 if name
.startswith('mux'):
519 def mk_cellconn(self
, cellnum
, name
, count
):
521 bank
= self
.mksuffix(name
, count
)
522 txt
= " pinmux.mux_lines.cell{0}_mux(mux{1}.mux_config.mux[{2}]);"
523 for p
in self
.peripheral
.pinspecs
:
524 ret
.append(txt
.format(cellnum
, bank
, p
['name'][1:]))
526 return ("\n".join(ret
), cellnum
)
528 def pinname_out(self
, pname
):
529 return "func.gpio_out[{0}]".format(pname
[1:])
531 def pinname_outen(self
, pname
):
532 return "func.gpio_out_en[{0}]".format(pname
[1:])
534 def mk_pincon(self
, name
, count
):
535 ret
= [PBase
.mk_pincon(self
, name
, count
)]
536 # special-case for gpio in, store in a temporary vector
537 plen
= len(self
.peripheral
.pinspecs
)
538 ret
.append(" rule con_%s%d_in;" % (name
, count
))
539 ret
.append(" Vector#({0},Bit#(1)) temp;".format(plen
))
540 for p
in self
.peripheral
.pinspecs
:
545 sname
= self
.peripheral
.pname(pname
).format(count
)
546 ps
= "pinmux.peripheral_side.%s_in" % sname
547 ret
.append(" temp[{0}]={1};".format(idx
, ps
))
548 ret
.append(" {0}.func.gpio_in(temp);".format(name
))
549 ret
.append(" endrule")
550 return '\n'.join(ret
)
553 axi_slave_declarations
= """\
554 typedef 0 SlowMaster;
556 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
558 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
560 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
562 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
565 pinmux_cellrule
= """\
566 rule connect_select_lines_pinmux;
572 class CallFn(object):
573 def __init__(self
, peripheral
, name
):
574 self
.peripheral
= peripheral
577 def __call__(self
, *args
):
578 #print "__call__", self.name, self.peripheral.slow, args
579 if not self
.peripheral
.slow
:
581 return getattr(self
.peripheral
.slow
, self
.name
)(*args
[1:])
584 class PeripheralIface(object):
585 def __init__(self
, ifacename
):
587 slow
= slowfactory
.getcls(ifacename
)
588 print "Iface", ifacename
, slow
590 self
.slow
= slow(ifacename
)
591 self
.slow
.peripheral
= self
592 for fname
in ['slowimport', 'slowifdecl', 'slowifdeclmux',
594 'mk_connection', 'mk_cellconn', 'mk_pincon']:
595 fn
= CallFn(self
, fname
)
596 setattr(self
, fname
, types
.MethodType(fn
, self
))
598 #print "PeripheralIface"
601 def mksuffix(self
, name
, i
):
602 if self
.slow
is None:
604 return self
.slow
.mksuffix(name
, i
)
606 def axi_reg_def(self
, start
, count
):
609 return self
.slow
.axi_reg_def(start
, self
.ifacename
, count
)
611 def axi_slave_idx(self
, start
, count
):
614 return self
.slow
.axi_slave_idx(start
, self
.ifacename
, count
)
616 def axi_addr_map(self
, count
):
619 return self
.slow
.axi_addr_map(self
.ifacename
, count
)
622 class PeripheralInterfaces(object):
626 def slowimport(self
, *args
):
628 for (name
, count
) in self
.ifacecount
:
629 #print "slowimport", name, self.data[name].slowimport
630 ret
.append(self
.data
[name
].slowimport())
631 return '\n'.join(list(filter(None, ret
)))
633 def slowifdeclmux(self
, *args
):
635 for (name
, count
) in self
.ifacecount
:
636 for i
in range(count
):
637 ret
.append(self
.data
[name
].slowifdeclmux().format(i
, name
))
638 return '\n'.join(list(filter(None, ret
)))
640 def slowifdecl(self
, *args
):
642 for (name
, count
) in self
.ifacecount
:
643 for i
in range(count
):
644 ret
.append(self
.data
[name
].slowifdecl().format(i
, name
))
645 return '\n'.join(list(filter(None, ret
)))
647 def axi_reg_def(self
, *args
):
649 start
= 0x00011100 # start of AXI peripherals address
650 for (name
, count
) in self
.ifacecount
:
651 for i
in range(count
):
652 x
= self
.data
[name
].axi_reg_def(start
, i
)
653 #print ("ifc", name, x)
657 return '\n'.join(list(filter(None, ret
)))
659 def axi_slave_idx(self
, *args
):
662 for (name
, count
) in self
.ifacecount
:
663 for i
in range(count
):
664 (rdef
, offs
) = self
.data
[name
].axi_slave_idx(start
, i
)
665 #print ("ifc", name, rdef, offs)
668 ret
.append("typedef %d LastGen_slave_num;" % (start
- 1))
669 decls
= '\n'.join(list(filter(None, ret
)))
670 return axi_slave_declarations
.format(decls
)
672 def axi_addr_map(self
, *args
):
674 for (name
, count
) in self
.ifacecount
:
675 for i
in range(count
):
676 ret
.append(self
.data
[name
].axi_addr_map(i
))
677 return '\n'.join(list(filter(None, ret
)))
679 def mkslow_peripheral(self
, *args
):
681 for (name
, count
) in self
.ifacecount
:
682 for i
in range(count
):
683 print "mkslow", name
, count
684 x
= self
.data
[name
].mkslow_peripheral()
686 suffix
= self
.data
[name
].mksuffix(name
, i
)
687 ret
.append(x
.format(suffix
))
688 return '\n'.join(list(filter(None, ret
)))
690 def mk_connection(self
, *args
):
692 for (name
, count
) in self
.ifacecount
:
693 for i
in range(count
):
694 print "mk_conn", name
, i
695 txt
= self
.data
[name
].mk_connection(i
)
698 print self
.data
[name
].mk_connection
700 return '\n'.join(list(filter(None, ret
)))
702 def mk_cellconn(self
):
705 for (name
, count
) in self
.ifacecount
:
706 for i
in range(count
):
707 res
= self
.data
[name
].mk_cellconn(cellcount
, name
, i
)
710 (txt
, cellcount
) = res
712 ret
= '\n'.join(list(filter(None, ret
)))
713 return pinmux_cellrule
.format(ret
)
717 for (name
, count
) in self
.ifacecount
:
718 for i
in range(count
):
719 txt
= self
.data
[name
].mk_pincon(name
, i
)
721 return '\n'.join(list(filter(None, ret
)))
724 class PFactory(object):
725 def getcls(self
, name
):
726 for k
, v
in {'uart': uart
,
735 if name
.startswith(k
):
740 slowfactory
= PFactory()
742 if __name__
== '__main__':
746 i
= PeripheralIface('uart')
748 i
= PeripheralIface('gpioa')