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 _pinname_out(self
, pname
):
283 return {'sda': 'out.sda_out',
284 'scl': 'out.scl_out'}.get(pname
, '')
286 def _pinname_in(self
, pname
):
287 return {'sda': 'out.sda_in',
288 'scl': 'out.scl_in'}.get(pname
, '')
290 def _pinname_outen(self
, pname
):
291 return {'sda': 'out.sda_out_en',
292 'scl': 'out.scl_out_en'}.get(pname
, '')
294 def mk_pincon(self
, name
, count
):
295 size
= len(self
.peripheral
.pinspecs
)
297 ret
.append(eint_pincon_template
.format(size
))
298 return '\n'.join(ret
)
301 eint_pincon_template
= '''\
302 // TODO: offset i by the number of eints already used
303 for(Integer i=0;i<{0};i=i+ 1)begin
304 rule connect_int_to_plic(wr_interrupt[i]==1);
305 ff_gateway_queue[i].enq(1);
306 plic.ifc_external_irq[i].irq_frm_gateway(True);
314 def slowimport(self
):
315 return " import qspi :: *;"
317 def slowifdecl(self
):
318 return " interface QSPI_out spi{0}_out;\n" + \
319 " method Bit#(1) spi{0}_isint;"
321 def num_axi_regs32(self
):
324 def mkslow_peripheral(self
):
325 return " Ifc_qspi spi{0} <- mkqspi();"
327 def _mk_connection(self
, name
=None, count
=0):
328 return "spi{0}.slave"
330 def pinname_out(self
, pname
):
331 return {'clk': 'out.clk_o',
333 'mosi': 'out.io_o[0]',
334 'miso': 'out.io_o[1]',
337 def pinname_outen(self
, pname
):
340 'mosi': 'out.io_enable[0]',
341 'miso': 'out.io_enable[1]',
344 def mk_pincon(self
, name
, count
):
345 ret
= [PBase
.mk_pincon(self
, name
, count
)]
346 # special-case for gpio in, store in a temporary vector
347 plen
= len(self
.peripheral
.pinspecs
)
348 ret
.append(" // XXX NSS and CLK are hard-coded master")
349 ret
.append(" // TODO: must add spi slave-mode")
350 ret
.append(" // all ins done in one rule from 4-bitfield")
351 ret
.append(" rule con_%s%d_io_in;" % (name
, count
))
352 ret
.append(" {0}{1}.out.io_i({{".format(name
, count
))
353 for idx
, pname
in enumerate(['mosi', 'miso']):
354 sname
= self
.peripheral
.pname(pname
).format(count
)
355 ps
= "pinmux.peripheral_side.%s_in" % sname
356 ret
.append(" {0},".format(ps
))
357 ret
.append(" 1'b0,1'b0")
359 ret
.append(" endrule")
360 return '\n'.join(ret
)
365 def slowimport(self
):
366 return " import qspi :: *;"
368 def slowifdecl(self
):
369 return " interface QSPI_out qspi{0}_out;\n" + \
370 " method Bit#(1) qspi{0}_isint;"
372 def num_axi_regs32(self
):
375 def mkslow_peripheral(self
, size
=0):
376 return " Ifc_qspi qspi{0} <- mkqspi();"
378 def _mk_connection(self
, name
=None, count
=0):
379 return "qspi{0}.slave"
381 def pinname_out(self
, pname
):
382 return {'ck': 'out.clk_o',
384 'io0': 'out.io_o[0]',
385 'io1': 'out.io_o[1]',
386 'io2': 'out.io_o[2]',
387 'io3': 'out.io_o[3]',
390 def pinname_outen(self
, pname
):
393 'io0': 'out.io_enable[0]',
394 'io1': 'out.io_enable[1]',
395 'io2': 'out.io_enable[2]',
396 'io3': 'out.io_enable[3]',
399 def mk_pincon(self
, name
, count
):
400 ret
= [PBase
.mk_pincon(self
, name
, count
)]
401 # special-case for gpio in, store in a temporary vector
402 plen
= len(self
.peripheral
.pinspecs
)
403 ret
.append(" // XXX NSS and CLK are hard-coded master")
404 ret
.append(" // TODO: must add qspi slave-mode")
405 ret
.append(" // all ins done in one rule from 4-bitfield")
406 ret
.append(" rule con_%s%d_io_in;" % (name
, count
))
407 ret
.append(" {0}{1}.out.io_i({{".format(name
, count
))
408 for i
, p
in enumerate(self
.peripheral
.pinspecs
):
411 if not pname
.startswith('io'):
415 sname
= self
.peripheral
.pname(pname
).format(count
)
416 ps
= "pinmux.peripheral_side.%s_in" % sname
417 comma
= '' if i
== 5 else ','
418 ret
.append(" {0}{1}".format(ps
, comma
))
420 ret
.append(" endrule")
421 return '\n'.join(ret
)
426 def slowimport(self
):
427 return " import pwm::*;"
429 def slowifdecl(self
):
430 return " interface PWMIO pwm{0}_io;"
432 def num_axi_regs32(self
):
435 def mkslow_peripheral(self
, size
=0):
436 return " Ifc_PWM_bus pwm{0} <- mkPWM_bus(sp_clock);"
438 def _mk_connection(self
, name
=None, count
=0):
439 return "pwm{0}.axi4_slave"
441 def pinname_out(self
, pname
):
442 return {'out': 'pwm_io.pwm_o'}.get(pname
, '')
447 def slowimport(self
):
448 return " import pinmux::*;\n" + \
449 " import mux::*;\n" + \
452 def slowifdeclmux(self
):
453 size
= len(self
.peripheral
.pinspecs
)
454 return " interface GPIO_config#(%d) pad_config{0};" % size
456 def num_axi_regs32(self
):
459 def axi_slave_idx(self
, idx
, name
, ifacenum
):
460 """ generates AXI slave number definition, except
461 GPIO also has a muxer per bank
464 mname
= 'mux' + name
[4:]
465 mname
= mname
.upper()
466 print "AXIslavenum", name
, mname
467 (ret
, x
) = PBase
.axi_slave_idx(self
, idx
, name
, ifacenum
)
468 (ret2
, x
) = PBase
.axi_slave_idx(self
, idx
+1, mname
, ifacenum
)
469 return ("%s\n%s" % (ret
, ret2
), 2)
471 def mkslow_peripheral(self
, size
=0):
472 print "gpioslow", self
.peripheral
, dir(self
.peripheral
)
473 size
= len(self
.peripheral
.pinspecs
)
474 return " MUX#(%d) mux{0} <- mkmux();\n" % size
+ \
475 " GPIO#(%d) gpio{0} <- mkgpio();" % size
477 def mk_connection(self
, count
):
478 print "GPIO mk_conn", self
.name
, count
480 dname
= self
.mksuffix(self
.name
, count
)
481 for i
, n
in enumerate(['gpio' + dname
, 'mux' + dname
]):
482 res
.append(PBase
.mk_connection(self
, count
, n
))
483 return '\n'.join(res
)
485 def _mk_connection(self
, name
=None, count
=0):
486 n
= self
.mksuffix(name
, count
)
487 if name
.startswith('gpio'):
488 return "gpio{0}.axi_slave".format(n
)
489 if name
.startswith('mux'):
490 return "mux{0}.axi_slave".format(n
)
492 def mksuffix(self
, name
, i
):
493 if name
.startswith('mux'):
497 def mk_cellconn(self
, cellnum
, name
, count
):
499 bank
= self
.mksuffix(name
, count
)
500 txt
= " pinmux.mux_lines.cell{0}_mux(mux{1}.mux_config.mux[{2}]);"
501 for p
in self
.peripheral
.pinspecs
:
502 ret
.append(txt
.format(cellnum
, bank
, p
['name'][1:]))
504 return ("\n".join(ret
), cellnum
)
506 def pinname_out(self
, pname
):
507 return "func.gpio_out[{0}]".format(pname
[1:])
509 def pinname_outen(self
, pname
):
510 return "func.gpio_out_en[{0}]".format(pname
[1:])
512 def mk_pincon(self
, name
, count
):
513 ret
= [PBase
.mk_pincon(self
, name
, count
)]
514 # special-case for gpio in, store in a temporary vector
515 plen
= len(self
.peripheral
.pinspecs
)
516 ret
.append(" rule con_%s%d_in;" % (name
, count
))
517 ret
.append(" Vector#({0},Bit#(1)) temp;".format(plen
))
518 for p
in self
.peripheral
.pinspecs
:
523 sname
= self
.peripheral
.pname(pname
).format(count
)
524 ps
= "pinmux.peripheral_side.%s_in" % sname
525 ret
.append(" temp[{0}]={1};".format(idx
, ps
))
526 ret
.append(" {0}.func.gpio_in(temp);".format(name
))
527 ret
.append(" endrule")
528 return '\n'.join(ret
)
531 axi_slave_declarations
= """\
532 typedef 0 SlowMaster;
534 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
536 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
538 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
540 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
543 pinmux_cellrule
= """\
544 rule connect_select_lines_pinmux;
550 class CallFn(object):
551 def __init__(self
, peripheral
, name
):
552 self
.peripheral
= peripheral
555 def __call__(self
, *args
):
556 #print "__call__", self.name, self.peripheral.slow, args
557 if not self
.peripheral
.slow
:
559 return getattr(self
.peripheral
.slow
, self
.name
)(*args
[1:])
562 class PeripheralIface(object):
563 def __init__(self
, ifacename
):
565 slow
= slowfactory
.getcls(ifacename
)
566 print "Iface", ifacename
, slow
568 self
.slow
= slow(ifacename
)
569 self
.slow
.peripheral
= self
570 for fname
in ['slowimport', 'slowifdecl', 'slowifdeclmux',
572 'mk_connection', 'mk_cellconn', 'mk_pincon']:
573 fn
= CallFn(self
, fname
)
574 setattr(self
, fname
, types
.MethodType(fn
, self
))
576 #print "PeripheralIface"
579 def mksuffix(self
, name
, i
):
580 if self
.slow
is None:
582 return self
.slow
.mksuffix(name
, i
)
584 def axi_reg_def(self
, start
, count
):
587 return self
.slow
.axi_reg_def(start
, self
.ifacename
, count
)
589 def axi_slave_idx(self
, start
, count
):
592 return self
.slow
.axi_slave_idx(start
, self
.ifacename
, count
)
594 def axi_addr_map(self
, count
):
597 return self
.slow
.axi_addr_map(self
.ifacename
, count
)
600 class PeripheralInterfaces(object):
604 def slowimport(self
, *args
):
606 for (name
, count
) in self
.ifacecount
:
607 #print "slowimport", name, self.data[name].slowimport
608 ret
.append(self
.data
[name
].slowimport())
609 return '\n'.join(list(filter(None, ret
)))
611 def slowifdeclmux(self
, *args
):
613 for (name
, count
) in self
.ifacecount
:
614 for i
in range(count
):
615 ret
.append(self
.data
[name
].slowifdeclmux().format(i
, name
))
616 return '\n'.join(list(filter(None, ret
)))
618 def slowifdecl(self
, *args
):
620 for (name
, count
) in self
.ifacecount
:
621 for i
in range(count
):
622 ret
.append(self
.data
[name
].slowifdecl().format(i
, name
))
623 return '\n'.join(list(filter(None, ret
)))
625 def axi_reg_def(self
, *args
):
627 start
= 0x00011100 # start of AXI peripherals address
628 for (name
, count
) in self
.ifacecount
:
629 for i
in range(count
):
630 x
= self
.data
[name
].axi_reg_def(start
, i
)
631 #print ("ifc", name, x)
635 return '\n'.join(list(filter(None, ret
)))
637 def axi_slave_idx(self
, *args
):
640 for (name
, count
) in self
.ifacecount
:
641 for i
in range(count
):
642 (rdef
, offs
) = self
.data
[name
].axi_slave_idx(start
, i
)
643 #print ("ifc", name, rdef, offs)
646 ret
.append("typedef %d LastGen_slave_num;" % (start
- 1))
647 decls
= '\n'.join(list(filter(None, ret
)))
648 return axi_slave_declarations
.format(decls
)
650 def axi_addr_map(self
, *args
):
652 for (name
, count
) in self
.ifacecount
:
653 for i
in range(count
):
654 ret
.append(self
.data
[name
].axi_addr_map(i
))
655 return '\n'.join(list(filter(None, ret
)))
657 def mkslow_peripheral(self
, *args
):
659 for (name
, count
) in self
.ifacecount
:
660 for i
in range(count
):
661 print "mkslow", name
, count
662 x
= self
.data
[name
].mkslow_peripheral()
664 suffix
= self
.data
[name
].mksuffix(name
, i
)
665 ret
.append(x
.format(suffix
))
666 return '\n'.join(list(filter(None, ret
)))
668 def mk_connection(self
, *args
):
670 for (name
, count
) in self
.ifacecount
:
671 for i
in range(count
):
672 print "mk_conn", name
, i
673 txt
= self
.data
[name
].mk_connection(i
)
676 print self
.data
[name
].mk_connection
678 return '\n'.join(list(filter(None, ret
)))
680 def mk_cellconn(self
):
683 for (name
, count
) in self
.ifacecount
:
684 for i
in range(count
):
685 res
= self
.data
[name
].mk_cellconn(cellcount
, name
, i
)
688 (txt
, cellcount
) = res
690 ret
= '\n'.join(list(filter(None, ret
)))
691 return pinmux_cellrule
.format(ret
)
695 for (name
, count
) in self
.ifacecount
:
696 for i
in range(count
):
697 txt
= self
.data
[name
].mk_pincon(name
, i
)
699 return '\n'.join(list(filter(None, ret
)))
702 class PFactory(object):
703 def getcls(self
, name
):
704 for k
, v
in {'uart': uart
,
713 if name
.startswith(k
):
718 slowfactory
= PFactory()
720 if __name__
== '__main__':
724 i
= PeripheralIface('uart')
726 i
= PeripheralIface('gpioa')