7 if isinstance(txt
, str):
12 line
= line
.split('\n')
17 res
.append(indent
+ line
)
24 def __init__(self
, name
):
27 def extifdecl(self
, name
, count
):
28 sname
= self
.get_iname(count
)
29 return "interface PeripheralSide%s %s;" % (name
.upper(), sname
)
31 def has_axi_master(self
):
37 def mk_dma_irq(self
, name
, count
):
38 if not self
.irq_name():
40 sname
= self
.get_iname(count
)
41 return "{0}_interrupt".format(sname
)
43 def mk_dma_rule(self
, name
, count
):
44 irqname
= self
.mk_dma_irq(name
, count
)
47 pirqname
= self
.irq_name().format(count
)
48 template
= " {0}_interrupt.send(\n" + \
49 " slow_peripherals.{1});"
50 return template
.format(irqname
, pirqname
)
52 def get_clock_reset(self
, name
, count
):
53 return "slow_clock,slow_reset"
55 def mk_dma_sync(self
, name
, count
):
56 irqname
= self
.mk_dma_irq(name
, count
)
59 sname
= self
.peripheral
.iname().format(count
)
60 template
= "SyncBitIfc#(Bit#(1)) {0} <-\n" + \
61 " <-mkSyncBitToCC({1});"
62 return template
.format(irqname
, self
.get_clock_reset(name
, count
))
64 def mk_dma_connect(self
, name
, count
):
65 irqname
= self
.mk_dma_irq(name
, count
)
68 return "{0}.read".format(irqname
)
70 def fastifdecl(self
, name
, count
):
73 def slowifdeclmux(self
, name
, count
):
79 def num_axi_regs32(self
):
85 def get_iname(self
, inum
):
86 return "{0}{1}".format(self
.name
, self
.mksuffix(self
.name
, inum
))
88 def axibase(self
, name
, ifacenum
):
90 return "%(name)s%(ifacenum)dBase" % locals()
92 def axiend(self
, name
, ifacenum
):
94 return "%(name)s%(ifacenum)dEnd" % locals()
96 def axi_reg_def(self
, start
, name
, ifacenum
):
98 offs
= self
.num_axi_regs32() * 4 * 16
101 end
= start
+ offs
- 1
102 bname
= self
.axibase(name
, ifacenum
)
103 bend
= self
.axiend(name
, ifacenum
)
104 comment
= "%d 32-bit regs" % self
.num_axi_regs32()
105 return (" `define %(bname)s 'h%(start)08X\n"
106 " `define %(bend)s 'h%(end)08X // %(comment)s" % locals(),
109 def axi_master_name(self
, name
, ifacenum
, typ
=''):
111 return "{0}{1}_master_num".format(name
, ifacenum
)
113 def axi_slave_name(self
, name
, ifacenum
, typ
=''):
115 return "{0}{1}_{2}slave_num".format(name
, ifacenum
, typ
)
117 def axi_master_idx(self
, idx
, name
, ifacenum
, typ
):
118 name
= self
.axi_master_name(name
, ifacenum
, typ
)
119 return ("typedef {0} {1};".format(idx
, name
), 1)
121 def axi_slave_idx(self
, idx
, name
, ifacenum
, typ
):
122 name
= self
.axi_slave_name(name
, ifacenum
, typ
)
123 return ("typedef {0} {1};".format(idx
, name
), 1)
125 def axi_addr_map(self
, name
, ifacenum
):
126 bname
= self
.axibase(name
, ifacenum
)
127 bend
= self
.axiend(name
, ifacenum
)
128 name
= self
.axi_slave_name(name
, ifacenum
)
130 if(addr>=`{0} && addr<=`{1})
131 return tuple2(True,fromInteger(valueOf({2})));
133 return template
.format(bname
, bend
, name
)
135 def mk_pincon(self
, name
, count
):
136 # TODO: really should be using bsv.interface_decl.Interfaces
137 # pin-naming rules.... logic here is hard-coded to duplicate
138 # it (see Interface.__init__ outen)
140 for p
in self
.peripheral
.pinspecs
:
143 #n = "{0}{1}".format(self.name, self.mksuffix(name, count))
144 n
= name
# "{0}{1}".format(self.name, self.mksuffix(name, count))
145 ret
.append("//%s %s" % (n
, str(p
)))
146 sname
= self
.peripheral
.iname().format(count
)
147 sname
= "{0}.{1}".format(sname
, pname
)
148 ps
= "pinmux.peripheral_side.%s" % sname
149 if typ
== 'out' or typ
== 'inout':
150 fname
= self
.pinname_out(pname
)
151 if not n
.startswith('gpio'): # XXX EURGH! horrible hack
152 n_
= "{0}{1}".format(n
, count
)
160 ret
.append("mkConnection({0},\n\t\t\t{1}.{2});"
161 .format(ps_
, n_
, fname
))
164 fname
= self
.pinname_outen(pname
)
166 if isinstance(fname
, str):
167 fname
= "{0}.{1}".format(n_
, fname
)
168 fname
= self
.pinname_tweak(pname
, 'outen', fname
)
169 ret
.append("mkConnection({0}_outen,\n\t\t\t{1});"
171 if typ
== 'in' or typ
== 'inout':
172 fname
= self
.pinname_in(pname
)
178 n_
= "{0}{1}".format(n
, count
)
179 n_
= '{0}.{1}'.format(n_
, fname
)
180 n_
= self
.ifname_tweak(pname
, 'in', n_
)
181 ret
.append("mkConnection({1},\n\t\t\t{0});".format(ps_
, n_
))
182 return '\n'.join(ret
)
184 def mk_cellconn(self
, *args
):
187 def mkfast_peripheral(self
, size
=0):
190 def mkslow_peripheral(self
, size
=0):
193 def mksuffix(self
, name
, i
):
196 def __mk_connection(self
, con
, aname
, fabricname
):
197 txt
= "mkConnection ({2}.v_to_slaves\n" + \
198 " [fromInteger(valueOf({1}))],\n" + \
201 print "PBase __mk_connection", self
.name
, aname
204 return txt
.format(con
, aname
, fabricname
)
206 def __mk_master_connection(self
, con
, aname
):
207 txt
= "mkConnection (slow_fabric.v_to_slaves\n" + \
208 " [fromInteger(valueOf({1}))],\n" + \
211 print "PBase __mk_connection", self
.name
, aname
214 return txt
.format(con
, aname
)
216 def mk_connection(self
, count
, fabricname
, typ
, name
=None):
219 print "PBase mk_conn", self
.name
, count
220 aname
= self
.axi_slave_name(name
, count
, typ
)
221 #dname = self.mksuffix(name, count)
222 #dname = "{0}{1}".format(name, dname)
223 con
= self
._mk
_connection
(name
, count
).format(count
, aname
)
224 return self
.__mk
_connection
(con
, aname
, fabricname
)
226 def _mk_connection(self
, name
=None, count
=0):
229 def pinname_out(self
, pname
):
232 def pinname_in(self
, pname
):
235 def pinname_outen(self
, pname
):
238 def ifname_tweak(self
, pname
, typ
, txt
):
241 def pinname_tweak(self
, pname
, typ
, txt
):
247 def mk_plic(self
, inum
, irq_offs
):
249 print "mk_plic", self
.name
, inum
, irq_offs
250 niq
= self
.num_irqs()
252 return ('', irq_offs
)
253 name
= self
.get_iname(inum
)
254 res
.append("// PLIC rules for {0}".format(name
))
255 for idx
in range(niq
):
256 plic_obj
= self
.plic_object(name
, idx
)
257 print "plic_obj", name
, idx
, plic_obj
258 plic
= mkplic_rule
.format(name
, plic_obj
, irq_offs
)
260 irq_offs
+= 1 # increment to next irq
261 return ('\n'.join(res
), irq_offs
)
263 def mk_ext_ifacedef(self
, iname
, inum
):
266 def extfastifinstance(self
, name
, count
):
269 def _extifinstance(self
, name
, count
, suffix
, prefix
, samename
=False):
270 pname
= self
.get_iname(count
)
274 sname
= self
.peripheral
.iname().format(count
)
275 template
= "interface {0}{3} = {2}{1};"
276 return template
.format(pname
, sname
, prefix
, suffix
)
278 def extifinstance2(self
, name
, count
):
281 def extifinstance(self
, name
, count
):
282 return self
._extifinstance
(name
, count
, "",
283 "pinmux.peripheral_side.")
287 rule rl_connect_{0}_to_plic_{2};
288 if({1} == 1'b1) begin
289 ff_gateway_queue[{2}].enq(1);
290 plic.ifc_external_irq[{2}].irq_frm_gateway(True);
295 axi_master_declarations
= """\
296 typedef 0 Dmem_master_num;
297 typedef 1 Imem_master_num;
299 typedef TAdd#(LastGen_master_num, `ifdef Debug 1 `else 0 `endif )
301 typedef TAdd#(Debug_master_num, `ifdef DMA 1 `else 0 `endif )
303 typedef TAdd#(DMA_master_num,1)
307 axi_fastslave_declarations
= """\
309 typedef TAdd#(LastGen_fastslave_num,1) Sdram_cfg_slave_num;
310 typedef TAdd#(Sdram_slave_num ,`ifdef SDRAM 1 `else 0 `endif )
312 typedef TAdd#(Sdram_cfg_slave_num,`ifdef BOOTROM 1 `else 0 `endif )
314 typedef TAdd#(BootRom_slave_num ,`ifdef Debug 1 `else 0 `endif )
316 typedef TAdd#(Debug_slave_num , `ifdef TCMemory 1 `else 0 `endif )
318 typedef TAdd#(TCM_slave_num ,`ifdef DMA 1 `else 0 `endif )
320 typedef TAdd#(Dma_slave_num ,1 ) SlowPeripheral_slave_num;
321 typedef TAdd#(SlowPeripheral_slave_num,`ifdef VME 1 `else 0 `endif )
323 typedef TAdd#(VME_slave_num,`ifdef FlexBus 1 `else 0 `endif )
325 typedef TAdd#(FlexBus_slave_num,1)
330 axi_slave_declarations
= """\
331 typedef 0 SlowMaster;
333 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
335 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
337 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
339 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
342 pinmux_cellrule
= """\
343 rule connect_select_lines_pinmux;
349 class CallFn(object):
350 def __init__(self
, peripheral
, name
):
351 self
.peripheral
= peripheral
354 def __call__(self
, *args
):
355 #print "__call__", self.name, self.peripheral.slow, args
356 if not self
.peripheral
.slow
:
358 return getattr(self
.peripheral
.slow
, self
.name
)(*args
[1:])
361 class PeripheralIface(object):
362 def __init__(self
, ifacename
):
364 slow
= slowfactory
.getcls(ifacename
)
365 print "Iface", ifacename
, slow
367 self
.slow
= slow(ifacename
)
368 self
.slow
.peripheral
= self
369 for fname
in ['slowimport',
371 'extifinstance2', 'extifinstance', 'extifdecl',
372 'slowifdecl', 'slowifdeclmux',
375 'mk_dma_sync', 'mk_dma_connect', 'mk_dma_rule',
377 'mk_plic', 'mk_ext_ifacedef',
378 'mk_connection', 'mk_cellconn', 'mk_pincon']:
379 fn
= CallFn(self
, fname
)
380 setattr(self
, fname
, types
.MethodType(fn
, self
))
382 #print "PeripheralIface"
385 def mksuffix(self
, name
, i
):
386 if self
.slow
is None:
388 return self
.slow
.mksuffix(name
, i
)
390 def axi_reg_def(self
, start
, count
):
393 return self
.slow
.axi_reg_def(start
, self
.ifacename
, count
)
395 def axi_master_idx(self
, start
, count
, typ
):
396 if not self
.slow
or not self
.slow
.has_axi_master():
398 return self
.slow
.axi_master_idx(start
, self
.ifacename
, count
, typ
)
400 def axi_slave_idx(self
, start
, count
, typ
):
403 return self
.slow
.axi_slave_idx(start
, self
.ifacename
, count
, typ
)
405 def axi_addr_map(self
, count
):
408 return self
.slow
.axi_addr_map(self
.ifacename
, count
)
411 class PeripheralInterfaces(object):
413 self
.fastbusmode
= False
415 def slowimport(self
, *args
):
417 for (name
, count
) in self
.ifacecount
:
418 #print "slowimport", name, self.data[name].slowimport
419 ret
.append(self
.data
[name
].slowimport())
420 return '\n'.join(li(list(filter(None, ret
)), 4))
422 def extfastifinstance(self
, *args
):
424 for (name
, count
) in self
.ifacecount
:
425 for i
in range(count
):
426 iname
= self
.data
[name
].iname().format(i
)
427 print "extfast", iname
, self
.is_on_fastbus(name
, i
)
428 if self
.is_on_fastbus(name
, i
):
430 ret
.append(self
.data
[name
].extfastifinstance(name
, i
))
431 return '\n'.join(li(list(filter(None, ret
)), 8))
433 def extifinstance2(self
, *args
):
435 for (name
, count
) in self
.ifacecount
:
436 for i
in range(count
):
437 iname
= self
.data
[name
].iname().format(i
)
438 ret
.append(self
.data
[name
].extifinstance2(name
, i
))
439 return '\n'.join(li(list(filter(None, ret
)), 8))
441 def extifinstance(self
, *args
):
443 for (name
, count
) in self
.ifacecount
:
444 for i
in range(count
):
445 iname
= self
.data
[name
].iname().format(i
)
446 if not self
.is_on_fastbus(name
, i
):
448 ret
.append(self
.data
[name
].extifinstance(name
, i
))
449 return '\n'.join(li(list(filter(None, ret
)), 8))
451 def extifdecl(self
, *args
):
453 for (name
, count
) in self
.ifacecount
:
454 for i
in range(count
):
455 if not self
.is_on_fastbus(name
, i
):
457 ret
.append(self
.data
[name
].extifdecl(name
, i
))
458 return '\n'.join(li(list(filter(None, ret
)), 8))
460 def slowifdeclmux(self
, *args
):
462 for (name
, count
) in self
.ifacecount
:
463 for i
in range(count
):
464 ret
.append(self
.data
[name
].slowifdeclmux(name
, i
))
465 return '\n'.join(li(list(filter(None, ret
)), 8))
467 def fastifdecl(self
, *args
):
469 for (name
, count
) in self
.ifacecount
:
470 for i
in range(count
):
471 print "fastifdecl", name
, i
, self
.is_on_fastbus(name
, i
)
472 if self
.is_on_fastbus(name
, i
):
474 ret
.append(self
.data
[name
].fastifdecl(name
, i
))
475 return '\n'.join(li(list(filter(None, ret
)), 4))
477 def slowifdecl(self
, *args
):
479 for (name
, count
) in self
.ifacecount
:
480 for i
in range(count
):
481 if self
.is_on_fastbus(name
, i
):
483 ret
.append(self
.data
[name
].slowifdecl().format(i
, name
))
484 return '\n'.join(list(filter(None, ret
)))
486 def axi_reg_def(self
, *args
):
488 start
= 0x00011100 # start of AXI peripherals address
489 for (name
, count
) in self
.ifacecount
:
490 for i
in range(count
):
491 if self
.is_on_fastbus(name
, i
):
493 x
= self
.data
[name
].axi_reg_def(start
, i
)
494 #print ("ifc", name, x)
498 return '\n'.join(list(filter(None, ret
)))
500 def _axi_num_idx(self
, start
, template
, typ
, idxtype
, *args
):
502 for (name
, count
) in self
.ifacecount
:
503 for i
in range(count
):
504 if self
.is_on_fastbus(name
, i
):
507 fn
= self
.data
[name
].axi_master_idx
509 fn
= self
.data
[name
].axi_slave_idx
510 (rdef
, offs
) = fn(start
, i
, idxtype
)
511 #print ("ifc", name, rdef, offs)
514 ret
.append("typedef %d LastGen_%s_num;" % (start
- 1, typ
))
515 decls
= '\n'.join(list(filter(None, ret
)))
516 return template
.format(decls
)
518 def axi_slave_idx(self
, *args
):
519 return self
._axi
_num
_idx
(0, axi_slave_declarations
, 'slave',
522 def axi_fastslave_idx(self
, *args
):
523 return self
._axi
_num
_idx
(0, axi_fastslave_declarations
, 'fastslave',
526 def axi_master_idx(self
, *args
):
527 return self
._axi
_num
_idx
(2, axi_master_declarations
, 'master',
530 def axi_fastslave_idx(self
, *args
):
531 return self
._axi
_num
_idx
(0, axi_fastslave_declarations
, 'fastslave',
534 def axi_addr_map(self
, *args
):
536 for (name
, count
) in self
.ifacecount
:
537 for i
in range(count
):
538 if self
.is_on_fastbus(name
, i
):
540 ret
.append(self
.data
[name
].axi_addr_map(i
))
541 return '\n'.join(li(list(filter(None, ret
)), 8))
543 def mkfast_peripheral(self
, *args
):
545 for (name
, count
) in self
.ifacecount
:
546 for i
in range(count
):
547 if self
.is_on_fastbus(name
, i
):
549 #print "mkfast", name, count
550 x
= self
.data
[name
].mkfast_peripheral()
552 suffix
= self
.data
[name
].mksuffix(name
, i
)
553 ret
.append(x
.format(suffix
))
554 return '\n'.join(li(list(filter(None, ret
)), 8))
556 def mkslow_peripheral(self
, *args
):
558 for (name
, count
) in self
.ifacecount
:
559 for i
in range(count
):
560 if self
.is_on_fastbus(name
, i
):
562 #print "mkslow", name, count
563 x
= self
.data
[name
].mkslow_peripheral()
565 suffix
= self
.data
[name
].mksuffix(name
, i
)
566 ret
.append(x
.format(suffix
))
567 return '\n'.join(li(list(filter(None, ret
)), 8))
569 def mk_fast_connection(self
, *args
):
571 for (name
, count
) in self
.ifacecount
:
572 for i
in range(count
):
573 if self
.is_on_fastbus(name
, i
):
575 txt
= self
.data
[name
].mk_connection(i
, "fabric", "fast")
578 print self
.data
[name
].mk_connection
580 return '\n'.join(li(list(filter(None, ret
)), 12))
582 def mk_connection(self
, *args
):
584 for (name
, count
) in self
.ifacecount
:
585 for i
in range(count
):
586 if self
.is_on_fastbus(name
, i
):
588 txt
= self
.data
[name
].mk_connection(i
, "slow_fabric", "")
591 print self
.data
[name
].mk_connection
593 return '\n'.join(li(list(filter(None, ret
)), 8))
595 def mk_cellconn(self
):
598 for (name
, count
) in self
.ifacecount
:
599 for i
in range(count
):
600 if self
.is_on_fastbus(name
, i
):
602 res
= self
.data
[name
].mk_cellconn(cellcount
, name
, i
)
605 (txt
, cellcount
) = res
607 ret
= li('\n'.join(list(filter(None, ret
))), 4)
608 return li(pinmux_cellrule
.format(ret
), 4)
612 for (name
, count
) in self
.ifacecount
:
613 for i
in range(count
):
614 if self
.is_on_fastbus(name
, i
):
616 txt
= self
.data
[name
].mk_pincon(name
, i
)
618 return '\n'.join(li(list(filter(None, ret
)), 4))
620 def mk_dma_irq(self
):
628 for (name
, count
) in self
.ifacecount
:
630 for i
in range(count
):
631 if not self
.is_on_fastbus(name
, i
):
633 txt
= self
.data
[name
].mk_dma_sync(name
, i
)
637 txt
= self
.data
[name
].mk_dma_rule(name
, i
)
638 ifacerules
.append(txt
)
639 txt
= self
.data
[name
].mk_dma_connect(name
, i
)
641 ifacerules
= list(filter(None, ifacerules
))
643 txt
= "rule synchronize_%s_interrupts;" % name
646 rules
.append("endrule")
648 cnct
= list(filter(None, cnct
))
650 _cnct
= ["rule rl_connect_interrupt_to_DMA;",
651 " Bit #(%d) lv_interrupt_to_DMA={" % ct
]
654 cnct
= _cnct
+ [spc
+ spcsep
.join(cnct
)]
656 cnct
.append(" dma.interrupt_from_peripherals(\n" +
657 " lv_interrupt_to_DMA);")
658 cnct
.append("endrule;")
660 ret
= list(filter(None, sync
+ rules
+ cnct
))
662 return '\n'.join(ret
)
664 def num_dmachannels(self
):
665 return "`define NUM_DMACHANNELS {0}".format(self
.dma_count
)
667 def mk_ext_ifacedef(self
):
669 for (name
, count
) in self
.ifacecount
:
670 for i
in range(count
):
671 if self
.is_on_fastbus(name
, i
):
673 txt
= self
.data
[name
].mk_ext_ifacedef(name
, i
)
675 return '\n'.join(li(list(filter(None, ret
)), 8))
679 irq_offs
= 8 # XXX: DMA scovers 0-7?
680 for (name
, count
) in self
.ifacecount
:
681 for i
in range(count
):
682 if self
.is_on_fastbus(name
, i
):
684 res
= self
.data
[name
].mk_plic(i
, irq_offs
)
687 (txt
, irq_offs
) = res
689 self
.num_slow_irqs
= irq_offs
690 return '\n'.join(li(list(filter(None, ret
)), 4))
692 def mk_sloirqsdef(self
):
693 return " `define NUM_SLOW_IRQS {0}".format(self
.num_slow_irqs
)
695 def is_on_fastbus(self
, name
, i
):
696 #print "fastbus mode", self.fastbusmode, name, i
697 iname
= self
.data
[name
].iname().format(i
)
699 return iname
not in self
.fastbus
700 return iname
in self
.fastbus
703 class PFactory(object):
704 def getcls(self
, name
):
705 from uart
import uart
706 from quart
import quart
707 from sdmmc
import sdmmc
709 from eint
import eint
710 from rs232
import rs232
712 from eint
import eint
713 from jtag
import jtag
714 from spi
import spi
, mspi
715 from qspi
import qspi
, mqspi
716 from gpio
import gpio
717 from rgbttl
import rgbttl
719 for k
, v
in {'uart': uart
,
734 if name
.startswith(k
):
739 slowfactory
= PFactory()
741 if __name__
== '__main__':
745 i
= PeripheralIface('uart')
747 i
= PeripheralIface('gpioa')