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,
273 pname
= self
.get_iname(count
)
277 sname
= self
.peripheral
.iname().format(count
)
278 template
= "interface {0}{3} = {2}{1}{4};"
279 return template
.format(pname
, sname
, prefix
, suffix
, ifsuffix
)
281 def extifinstance2(self
, name
, count
):
284 def extifinstance(self
, name
, count
):
285 return self
._extifinstance
(name
, count
, "",
286 "pinmux.peripheral_side.")
290 rule rl_connect_{0}_to_plic_{2};
291 if({1} == 1'b1) begin
292 ff_gateway_queue[{2}].enq(1);
293 plic.ifc_external_irq[{2}].irq_frm_gateway(True);
298 axi_master_declarations
= """\
299 typedef 0 Dmem_master_num;
300 typedef 1 Imem_master_num;
302 typedef TAdd#(LastGen_master_num, `ifdef Debug 1 `else 0 `endif )
304 typedef TAdd#(Debug_master_num, `ifdef DMA 1 `else 0 `endif )
306 typedef TAdd#(DMA_master_num,1)
310 axi_fastslave_declarations
= """\
312 typedef TAdd#(LastGen_fastslave_num,1) Sdram_cfg_slave_num;
313 typedef TAdd#(Sdram_slave_num ,`ifdef SDRAM 1 `else 0 `endif )
315 typedef TAdd#(Sdram_cfg_slave_num,`ifdef BOOTROM 1 `else 0 `endif )
317 typedef TAdd#(BootRom_slave_num ,`ifdef Debug 1 `else 0 `endif )
319 typedef TAdd#(Debug_slave_num , `ifdef TCMemory 1 `else 0 `endif )
321 typedef TAdd#(TCM_slave_num ,`ifdef DMA 1 `else 0 `endif )
323 typedef TAdd#(Dma_slave_num ,1 ) SlowPeripheral_slave_num;
324 typedef TAdd#(SlowPeripheral_slave_num,`ifdef VME 1 `else 0 `endif )
326 typedef TAdd#(VME_slave_num,`ifdef FlexBus 1 `else 0 `endif )
328 typedef TAdd#(FlexBus_slave_num,1)
333 axi_slave_declarations
= """\
334 typedef 0 SlowMaster;
336 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
338 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
340 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
342 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
345 pinmux_cellrule
= """\
346 rule connect_select_lines_pinmux;
352 class CallFn(object):
353 def __init__(self
, peripheral
, name
):
354 self
.peripheral
= peripheral
357 def __call__(self
, *args
):
358 #print "__call__", self.name, self.peripheral.slow, args
359 if not self
.peripheral
.slow
:
361 return getattr(self
.peripheral
.slow
, self
.name
)(*args
[1:])
364 class PeripheralIface(object):
365 def __init__(self
, ifacename
):
367 slow
= slowfactory
.getcls(ifacename
)
368 print "Iface", ifacename
, slow
370 self
.slow
= slow(ifacename
)
371 self
.slow
.peripheral
= self
372 for fname
in ['slowimport',
374 'extifinstance2', 'extifinstance', 'extifdecl',
375 'slowifdecl', 'slowifdeclmux',
378 'mk_dma_sync', 'mk_dma_connect', 'mk_dma_rule',
380 'mk_plic', 'mk_ext_ifacedef',
381 'mk_connection', 'mk_cellconn', 'mk_pincon']:
382 fn
= CallFn(self
, fname
)
383 setattr(self
, fname
, types
.MethodType(fn
, self
))
385 #print "PeripheralIface"
388 def mksuffix(self
, name
, i
):
389 if self
.slow
is None:
391 return self
.slow
.mksuffix(name
, i
)
393 def axi_reg_def(self
, start
, count
):
396 return self
.slow
.axi_reg_def(start
, self
.ifacename
, count
)
398 def axi_master_idx(self
, start
, count
, typ
):
399 if not self
.slow
or not self
.slow
.has_axi_master():
401 return self
.slow
.axi_master_idx(start
, self
.ifacename
, count
, typ
)
403 def axi_slave_idx(self
, start
, count
, typ
):
406 return self
.slow
.axi_slave_idx(start
, self
.ifacename
, count
, typ
)
408 def axi_addr_map(self
, count
):
411 return self
.slow
.axi_addr_map(self
.ifacename
, count
)
414 class PeripheralInterfaces(object):
416 self
.fastbusmode
= False
418 def slowimport(self
, *args
):
420 for (name
, count
) in self
.ifacecount
:
421 #print "slowimport", name, self.data[name].slowimport
422 ret
.append(self
.data
[name
].slowimport())
423 return '\n'.join(li(list(filter(None, ret
)), 4))
425 def extfastifinstance(self
, *args
):
427 for (name
, count
) in self
.ifacecount
:
428 for i
in range(count
):
429 iname
= self
.data
[name
].iname().format(i
)
430 print "extfast", iname
, self
.is_on_fastbus(name
, i
)
431 if self
.is_on_fastbus(name
, i
):
433 ret
.append(self
.data
[name
].extfastifinstance(name
, i
))
434 return '\n'.join(li(list(filter(None, ret
)), 8))
436 def extifinstance2(self
, *args
):
438 for (name
, count
) in self
.ifacecount
:
439 for i
in range(count
):
440 iname
= self
.data
[name
].iname().format(i
)
441 ret
.append(self
.data
[name
].extifinstance2(name
, i
))
442 return '\n'.join(li(list(filter(None, ret
)), 8))
444 def extifinstance(self
, *args
):
446 for (name
, count
) in self
.ifacecount
:
447 for i
in range(count
):
448 iname
= self
.data
[name
].iname().format(i
)
449 if not self
.is_on_fastbus(name
, i
):
451 ret
.append(self
.data
[name
].extifinstance(name
, i
))
452 return '\n'.join(li(list(filter(None, ret
)), 8))
454 def extifdecl(self
, *args
):
456 for (name
, count
) in self
.ifacecount
:
457 for i
in range(count
):
458 if not self
.is_on_fastbus(name
, i
):
460 ret
.append(self
.data
[name
].extifdecl(name
, i
))
461 return '\n'.join(li(list(filter(None, ret
)), 8))
463 def slowifdeclmux(self
, *args
):
465 for (name
, count
) in self
.ifacecount
:
466 for i
in range(count
):
467 ret
.append(self
.data
[name
].slowifdeclmux(name
, i
))
468 return '\n'.join(li(list(filter(None, ret
)), 8))
470 def fastifdecl(self
, *args
):
472 for (name
, count
) in self
.ifacecount
:
473 for i
in range(count
):
474 print "fastifdecl", name
, i
, self
.is_on_fastbus(name
, i
)
475 if self
.is_on_fastbus(name
, i
):
477 ret
.append(self
.data
[name
].fastifdecl(name
, i
))
478 return '\n'.join(li(list(filter(None, ret
)), 4))
480 def slowifdecl(self
, *args
):
482 for (name
, count
) in self
.ifacecount
:
483 for i
in range(count
):
484 if self
.is_on_fastbus(name
, i
):
486 ret
.append(self
.data
[name
].slowifdecl().format(i
, name
))
487 return '\n'.join(list(filter(None, ret
)))
489 def axi_fastmem_def(self
, *args
):
490 return self
._axi
_reg
_def
(0x50000000, *args
)
492 def axi_reg_def(self
, *args
):
493 return self
._axi
_reg
_def
(0x00011100, *args
)
495 def _axi_reg_def(self
, start
, *args
):
497 for (name
, count
) in self
.ifacecount
:
498 for i
in range(count
):
499 if self
.is_on_fastbus(name
, i
):
501 x
= self
.data
[name
].axi_reg_def(start
, i
)
502 #print ("ifc", name, x)
506 return '\n'.join(list(filter(None, ret
)))
508 def _axi_num_idx(self
, start
, template
, typ
, idxtype
, *args
):
510 for (name
, count
) in self
.ifacecount
:
511 for i
in range(count
):
512 if self
.is_on_fastbus(name
, i
):
515 fn
= self
.data
[name
].axi_master_idx
517 fn
= self
.data
[name
].axi_slave_idx
518 (rdef
, offs
) = fn(start
, i
, idxtype
)
519 #print ("ifc", name, rdef, offs)
522 ret
.append("typedef %d LastGen_%s_num;" % (start
- 1, typ
))
523 decls
= '\n'.join(list(filter(None, ret
)))
524 return template
.format(decls
)
526 def axi_slave_idx(self
, *args
):
527 return self
._axi
_num
_idx
(0, axi_slave_declarations
, 'slave',
530 def axi_fastslave_idx(self
, *args
):
531 return self
._axi
_num
_idx
(0, axi_fastslave_declarations
, 'fastslave',
534 def axi_master_idx(self
, *args
):
535 return self
._axi
_num
_idx
(2, axi_master_declarations
, 'master',
538 def axi_fastslave_idx(self
, *args
):
539 return self
._axi
_num
_idx
(0, axi_fastslave_declarations
, 'fastslave',
542 def axi_addr_map(self
, *args
):
544 for (name
, count
) in self
.ifacecount
:
545 for i
in range(count
):
546 if self
.is_on_fastbus(name
, i
):
548 ret
.append(self
.data
[name
].axi_addr_map(i
))
549 return '\n'.join(li(list(filter(None, ret
)), 8))
551 def mkfast_peripheral(self
, *args
):
553 for (name
, count
) in self
.ifacecount
:
554 for i
in range(count
):
555 if self
.is_on_fastbus(name
, i
):
557 #print "mkfast", name, count
558 x
= self
.data
[name
].mkfast_peripheral()
560 suffix
= self
.data
[name
].mksuffix(name
, i
)
561 ret
.append(x
.format(suffix
))
562 return '\n'.join(li(list(filter(None, ret
)), 8))
564 def mkslow_peripheral(self
, *args
):
566 for (name
, count
) in self
.ifacecount
:
567 for i
in range(count
):
568 if self
.is_on_fastbus(name
, i
):
570 #print "mkslow", name, count
571 x
= self
.data
[name
].mkslow_peripheral()
573 suffix
= self
.data
[name
].mksuffix(name
, i
)
574 ret
.append(x
.format(suffix
))
575 return '\n'.join(li(list(filter(None, ret
)), 8))
577 def mk_fast_connection(self
, *args
):
579 for (name
, count
) in self
.ifacecount
:
580 for i
in range(count
):
581 if self
.is_on_fastbus(name
, i
):
583 txt
= self
.data
[name
].mk_connection(i
, "fabric", "fast")
586 print self
.data
[name
].mk_connection
588 return '\n'.join(li(list(filter(None, ret
)), 12))
590 def mk_connection(self
, *args
):
592 for (name
, count
) in self
.ifacecount
:
593 for i
in range(count
):
594 if self
.is_on_fastbus(name
, i
):
596 txt
= self
.data
[name
].mk_connection(i
, "slow_fabric", "")
599 print self
.data
[name
].mk_connection
601 return '\n'.join(li(list(filter(None, ret
)), 8))
603 def mk_cellconn(self
):
606 for (name
, count
) in self
.ifacecount
:
607 for i
in range(count
):
608 if self
.is_on_fastbus(name
, i
):
610 res
= self
.data
[name
].mk_cellconn(cellcount
, name
, i
)
613 (txt
, cellcount
) = res
615 ret
= li('\n'.join(list(filter(None, ret
))), 4)
616 return li(pinmux_cellrule
.format(ret
), 4)
620 for (name
, count
) in self
.ifacecount
:
621 for i
in range(count
):
622 if self
.is_on_fastbus(name
, i
):
624 txt
= self
.data
[name
].mk_pincon(name
, i
)
626 return '\n'.join(li(list(filter(None, ret
)), 4))
628 def mk_dma_irq(self
):
636 for (name
, count
) in self
.ifacecount
:
638 for i
in range(count
):
639 if not self
.is_on_fastbus(name
, i
):
641 txt
= self
.data
[name
].mk_dma_sync(name
, i
)
645 txt
= self
.data
[name
].mk_dma_rule(name
, i
)
646 ifacerules
.append(txt
)
647 txt
= self
.data
[name
].mk_dma_connect(name
, i
)
649 ifacerules
= list(filter(None, ifacerules
))
651 txt
= "rule synchronize_%s_interrupts;" % name
654 rules
.append("endrule")
656 cnct
= list(filter(None, cnct
))
658 _cnct
= ["rule rl_connect_interrupt_to_DMA;",
659 " Bit #(%d) lv_interrupt_to_DMA={" % ct
]
662 cnct
= _cnct
+ [spc
+ spcsep
.join(cnct
)]
664 cnct
.append(" dma.interrupt_from_peripherals(\n" +
665 " lv_interrupt_to_DMA);")
666 cnct
.append("endrule;")
668 ret
= list(filter(None, sync
+ rules
+ cnct
))
670 return '\n'.join(ret
)
672 def num_dmachannels(self
):
673 return "`define NUM_DMACHANNELS {0}".format(self
.dma_count
)
675 def mk_ext_ifacedef(self
):
677 for (name
, count
) in self
.ifacecount
:
678 for i
in range(count
):
679 if self
.is_on_fastbus(name
, i
):
681 txt
= self
.data
[name
].mk_ext_ifacedef(name
, i
)
683 return '\n'.join(li(list(filter(None, ret
)), 8))
687 irq_offs
= 8 # XXX: DMA scovers 0-7?
688 for (name
, count
) in self
.ifacecount
:
689 for i
in range(count
):
690 if self
.is_on_fastbus(name
, i
):
692 res
= self
.data
[name
].mk_plic(i
, irq_offs
)
695 (txt
, irq_offs
) = res
697 self
.num_slow_irqs
= irq_offs
698 return '\n'.join(li(list(filter(None, ret
)), 4))
700 def mk_sloirqsdef(self
):
701 return " `define NUM_SLOW_IRQS {0}".format(self
.num_slow_irqs
)
703 def is_on_fastbus(self
, name
, i
):
704 #print "fastbus mode", self.fastbusmode, name, i
705 iname
= self
.data
[name
].iname().format(i
)
707 return iname
not in self
.fastbus
708 return iname
in self
.fastbus
711 class PFactory(object):
712 def getcls(self
, name
):
713 from uart
import uart
714 from quart
import quart
715 from sdmmc
import sdmmc
717 from eint
import eint
718 from rs232
import rs232
720 from eint
import eint
721 from jtag
import jtag
722 from spi
import spi
, mspi
723 from qspi
import qspi
, mqspi
724 from gpio
import gpio
725 from rgbttl
import rgbttl
726 from flexbus
import flexbus
728 for k
, v
in {'uart': uart
,
744 if name
.startswith(k
):
749 slowfactory
= PFactory()
751 if __name__
== '__main__':
755 i
= PeripheralIface('uart')
757 i
= PeripheralIface('gpioa')