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_fastaddr_map(self
, name
, ifacenum
):
126 return self
.axi_addr_map(name
, ifacenum
, 'fast')
128 def axi_addr_map(self
, name
, ifacenum
, typ
=""):
129 bname
= self
.axibase(name
, ifacenum
)
130 bend
= self
.axiend(name
, ifacenum
)
131 name
= self
.axi_slave_name(name
, ifacenum
, typ
)
133 if(addr>=`{0} && addr<=`{1})
134 return tuple2(True,fromInteger(valueOf({2})));
136 return template
.format(bname
, bend
, name
)
138 def mk_pincon(self
, name
, count
):
139 # TODO: really should be using bsv.interface_decl.Interfaces
140 # pin-naming rules.... logic here is hard-coded to duplicate
141 # it (see Interface.__init__ outen)
143 for p
in self
.peripheral
.pinspecs
:
146 #n = "{0}{1}".format(self.name, self.mksuffix(name, count))
147 n
= name
# "{0}{1}".format(self.name, self.mksuffix(name, count))
148 ret
.append("//%s %s" % (n
, str(p
)))
149 sname
= self
.peripheral
.iname().format(count
)
150 sname
= "{0}.{1}".format(sname
, pname
)
151 ps
= "pinmux.peripheral_side.%s" % sname
152 if typ
== 'out' or typ
== 'inout':
153 fname
= self
.pinname_out(pname
)
154 if not n
.startswith('gpio'): # XXX EURGH! horrible hack
155 n_
= "{0}{1}".format(n
, count
)
163 ret
.append("mkConnection({0},\n\t\t\t{1}.{2});"
164 .format(ps_
, n_
, fname
))
167 fname
= self
.pinname_outen(pname
)
169 if isinstance(fname
, str):
170 fname
= "{0}.{1}".format(n_
, fname
)
171 fname
= self
.pinname_tweak(pname
, 'outen', fname
)
172 ret
.append("mkConnection({0}_outen,\n\t\t\t{1});"
174 if typ
== 'in' or typ
== 'inout':
175 fname
= self
.pinname_in(pname
)
181 n_
= "{0}{1}".format(n
, count
)
182 n_
= '{0}.{1}'.format(n_
, fname
)
183 n_
= self
.ifname_tweak(pname
, 'in', n_
)
185 "mkConnection({1},\n\t\t\t{0});".format(
187 return '\n'.join(ret
)
189 def mk_cellconn(self
, *args
):
192 def mkfast_peripheral(self
, size
=0):
195 def mkslow_peripheral(self
, size
=0):
198 def mksuffix(self
, name
, i
):
201 def __mk_connection(self
, con
, aname
, fabricname
):
202 txt
= "mkConnection ({2}.v_to_slaves\n" + \
203 " [fromInteger(valueOf({1}))],\n" + \
206 print "PBase __mk_connection", self
.name
, aname
209 return txt
.format(con
, aname
, fabricname
)
211 def __mk_master_connection(self
, con
, aname
):
212 txt
= "mkConnection (slow_fabric.v_to_slaves\n" + \
213 " [fromInteger(valueOf({1}))],\n" + \
216 print "PBase __mk_connection", self
.name
, aname
219 return txt
.format(con
, aname
)
221 def mk_connection(self
, count
, fabricname
, typ
, name
=None):
224 print "PBase mk_conn", self
.name
, count
225 aname
= self
.axi_slave_name(name
, count
, typ
)
226 #dname = self.mksuffix(name, count)
227 #dname = "{0}{1}".format(name, dname)
228 con
= self
._mk
_connection
(name
, count
).format(count
, aname
)
229 return self
.__mk
_connection
(con
, aname
, fabricname
)
231 def _mk_connection(self
, name
=None, count
=0):
234 def pinname_out(self
, pname
):
237 def pinname_in(self
, pname
):
240 def pinname_outen(self
, pname
):
243 def ifname_tweak(self
, pname
, typ
, txt
):
246 def pinname_tweak(self
, pname
, typ
, txt
):
252 def mk_plic(self
, inum
, irq_offs
):
254 print "mk_plic", self
.name
, inum
, irq_offs
255 niq
= self
.num_irqs()
257 return ('', irq_offs
)
258 name
= self
.get_iname(inum
)
259 res
.append("// PLIC rules for {0}".format(name
))
260 for idx
in range(niq
):
261 plic_obj
= self
.plic_object(name
, idx
)
262 print "plic_obj", name
, idx
, plic_obj
263 plic
= mkplic_rule
.format(name
, plic_obj
, irq_offs
)
265 irq_offs
+= 1 # increment to next irq
266 return ('\n'.join(res
), irq_offs
)
268 def mk_ext_ifacedef(self
, iname
, inum
):
271 def extfastifinstance(self
, name
, count
):
274 def _extifinstance(self
, name
, count
, suffix
, prefix
, samename
=False,
278 pname
= self
.get_iname(count
)
282 sname
= self
.peripheral
.iname().format(count
)
283 template
= "interface {0}{3} = {2}{1}{4};"
284 return template
.format(pname
, sname
, prefix
, suffix
, ifsuffix
)
286 def extifinstance2(self
, name
, count
):
289 def extifinstance(self
, name
, count
):
290 return self
._extifinstance
(name
, count
, "",
291 "pinmux.peripheral_side.")
295 rule rl_connect_{0}_to_plic_{2};
296 if({1} == 1'b1) begin
297 ff_gateway_queue[{2}].enq(1);
298 plic.ifc_external_irq[{2}].irq_frm_gateway(True);
303 axi_master_declarations
= """\
304 typedef 0 Dmem_master_num;
305 typedef 1 Imem_master_num;
307 typedef TAdd#(LastGen_master_num, `ifdef Debug 1 `else 0 `endif )
309 typedef TAdd#(Debug_master_num, `ifdef DMA 1 `else 0 `endif )
311 typedef TAdd#(DMA_master_num,1)
315 axi_fastslave_declarations
= """\
317 typedef TAdd#(LastGen_fastslave_num,1) Sdram_slave_num;
318 typedef TAdd#(Sdram_slave_num ,`ifdef SDRAM 1 `else 0 `endif )
320 typedef TAdd#(Sdram_cfg_slave_num,`ifdef BOOTROM 1 `else 0 `endif )
322 typedef TAdd#(BootRom_slave_num ,`ifdef Debug 1 `else 0 `endif )
324 typedef TAdd#(Debug_slave_num , `ifdef TCMemory 1 `else 0 `endif )
326 typedef TAdd#(TCM_slave_num ,`ifdef DMA 1 `else 0 `endif )
328 typedef TAdd#(Dma_slave_num ,1 ) SlowPeripheral_slave_num;
329 typedef TAdd#(SlowPeripheral_slave_num,`ifdef VME 1 `else 0 `endif )
331 typedef TAdd#(VME_slave_num,1) Num_Fast_Slaves;
334 axi_slave_declarations
= """\
335 typedef 0 SlowMaster;
337 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
339 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
341 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
343 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
346 pinmux_cellrule
= """\
347 rule connect_select_lines_pinmux;
353 class CallFn(object):
354 def __init__(self
, peripheral
, name
):
355 self
.peripheral
= peripheral
358 def __call__(self
, *args
):
359 #print "__call__", self.name, self.peripheral.slow, args
360 if not self
.peripheral
.slow
:
362 return getattr(self
.peripheral
.slow
, self
.name
)(*args
[1:])
365 class PeripheralIface(object):
366 def __init__(self
, ifacename
):
368 slow
= slowfactory
.getcls(ifacename
)
369 print "Iface", ifacename
, slow
371 self
.slow
= slow(ifacename
)
372 self
.slow
.peripheral
= self
373 for fname
in ['slowimport',
375 'extifinstance2', 'extifinstance', 'extifdecl',
376 'slowifdecl', 'slowifdeclmux',
379 'mk_dma_sync', 'mk_dma_connect', 'mk_dma_rule',
381 'mk_plic', 'mk_ext_ifacedef',
382 'mk_connection', 'mk_cellconn', 'mk_pincon']:
383 fn
= CallFn(self
, fname
)
384 setattr(self
, fname
, types
.MethodType(fn
, self
))
386 #print "PeripheralIface"
389 def mksuffix(self
, name
, i
):
390 if self
.slow
is None:
392 return self
.slow
.mksuffix(name
, i
)
394 def axi_reg_def(self
, start
, count
):
397 return self
.slow
.axi_reg_def(start
, self
.ifacename
, count
)
399 def axi_master_idx(self
, start
, count
, typ
):
400 if not self
.slow
or not self
.slow
.has_axi_master():
402 return self
.slow
.axi_master_idx(start
, self
.ifacename
, count
, typ
)
404 def axi_slave_idx(self
, start
, count
, typ
):
407 return self
.slow
.axi_slave_idx(start
, self
.ifacename
, count
, typ
)
409 def axi_fastaddr_map(self
, count
):
412 return self
.slow
.axi_fastaddr_map(self
.ifacename
, count
)
414 def axi_addr_map(self
, count
):
417 return self
.slow
.axi_addr_map(self
.ifacename
, count
)
420 class PeripheralInterfaces(object):
422 self
.fastbusmode
= False
424 def slowimport(self
, *args
):
426 for (name
, count
) in self
.ifacecount
:
427 #print "slowimport", name, self.data[name].slowimport
428 ret
.append(self
.data
[name
].slowimport())
429 return '\n'.join(li(list(filter(None, ret
)), 4))
431 def extfastifinstance(self
, *args
):
433 for (name
, count
) in self
.ifacecount
:
434 for i
in range(count
):
435 iname
= self
.data
[name
].iname().format(i
)
436 print "extfast", iname
, self
.is_on_fastbus(name
, i
)
437 if self
.is_on_fastbus(name
, i
):
439 ret
.append(self
.data
[name
].extfastifinstance(name
, i
))
440 return '\n'.join(li(list(filter(None, ret
)), 8))
442 def extifinstance2(self
, *args
):
444 for (name
, count
) in self
.ifacecount
:
445 for i
in range(count
):
446 iname
= self
.data
[name
].iname().format(i
)
447 ret
.append(self
.data
[name
].extifinstance2(name
, i
))
448 return '\n'.join(li(list(filter(None, ret
)), 8))
450 def extifinstance(self
, *args
):
452 for (name
, count
) in self
.ifacecount
:
453 for i
in range(count
):
454 iname
= self
.data
[name
].iname().format(i
)
455 if not self
.is_on_fastbus(name
, i
):
457 ret
.append(self
.data
[name
].extifinstance(name
, i
))
458 return '\n'.join(li(list(filter(None, ret
)), 8))
460 def extifdecl(self
, *args
):
462 for (name
, count
) in self
.ifacecount
:
463 for i
in range(count
):
464 if not self
.is_on_fastbus(name
, i
):
466 ret
.append(self
.data
[name
].extifdecl(name
, i
))
467 return '\n'.join(li(list(filter(None, ret
)), 8))
469 def slowifdeclmux(self
, *args
):
471 for (name
, count
) in self
.ifacecount
:
472 for i
in range(count
):
473 ret
.append(self
.data
[name
].slowifdeclmux(name
, i
))
474 return '\n'.join(li(list(filter(None, ret
)), 8))
476 def fastifdecl(self
, *args
):
478 for (name
, count
) in self
.ifacecount
:
479 for i
in range(count
):
480 print "fastifdecl", name
, i
, self
.is_on_fastbus(name
, i
)
481 if self
.is_on_fastbus(name
, i
):
483 ret
.append(self
.data
[name
].fastifdecl(name
, i
))
484 return '\n'.join(li(list(filter(None, ret
)), 4))
486 def slowifdecl(self
, *args
):
488 for (name
, count
) in self
.ifacecount
:
489 for i
in range(count
):
490 if self
.is_on_fastbus(name
, i
):
492 ret
.append(self
.data
[name
].slowifdecl().format(i
, name
))
493 return '\n'.join(list(filter(None, ret
)))
495 def axi_fastmem_def(self
, *args
):
496 return self
._axi
_reg
_def
(0x50000000, *args
)
498 def axi_reg_def(self
, *args
):
499 return self
._axi
_reg
_def
(0x00011100, *args
)
501 def _axi_reg_def(self
, start
, *args
):
503 for (name
, count
) in self
.ifacecount
:
504 for i
in range(count
):
505 if self
.is_on_fastbus(name
, i
):
507 x
= self
.data
[name
].axi_reg_def(start
, i
)
508 #print ("ifc", name, x)
512 return '\n'.join(list(filter(None, ret
)))
514 def _axi_num_idx(self
, start
, template
, typ
, idxtype
, *args
):
516 for (name
, count
) in self
.ifacecount
:
517 for i
in range(count
):
518 if self
.is_on_fastbus(name
, i
):
521 fn
= self
.data
[name
].axi_master_idx
523 fn
= self
.data
[name
].axi_slave_idx
524 (rdef
, offs
) = fn(start
, i
, idxtype
)
525 #print ("ifc", name, rdef, offs)
528 ret
.append("typedef %d LastGen_%s_num;" % (start
- 1, typ
))
529 decls
= '\n'.join(list(filter(None, ret
)))
530 return template
.format(decls
)
532 def axi_slave_idx(self
, *args
):
533 return self
._axi
_num
_idx
(0, axi_slave_declarations
, 'slave',
536 def axi_fastslave_idx(self
, *args
):
537 return self
._axi
_num
_idx
(0, axi_fastslave_declarations
, 'fastslave',
540 def axi_master_idx(self
, *args
):
541 return self
._axi
_num
_idx
(2, axi_master_declarations
, 'master',
544 def axi_fastslave_idx(self
, *args
):
545 return self
._axi
_num
_idx
(0, axi_fastslave_declarations
, 'fastslave',
548 def axi_fastaddr_map(self
, *args
):
550 for (name
, count
) in self
.ifacecount
:
551 for i
in range(count
):
552 if self
.is_on_fastbus(name
, i
):
554 ret
.append(self
.data
[name
].axi_fastaddr_map(i
))
555 return '\n'.join(li(list(filter(None, ret
)), 8))
557 def axi_addr_map(self
, *args
):
559 for (name
, count
) in self
.ifacecount
:
560 for i
in range(count
):
561 if self
.is_on_fastbus(name
, i
):
563 ret
.append(self
.data
[name
].axi_addr_map(i
))
564 return '\n'.join(li(list(filter(None, ret
)), 8))
566 def mkfast_peripheral(self
, *args
):
568 for (name
, count
) in self
.ifacecount
:
569 for i
in range(count
):
570 if self
.is_on_fastbus(name
, i
):
572 #print "mkfast", name, count
573 x
= self
.data
[name
].mkfast_peripheral()
575 suffix
= self
.data
[name
].mksuffix(name
, i
)
576 ret
.append(x
.format(suffix
))
577 return '\n'.join(li(list(filter(None, ret
)), 8))
579 def mkslow_peripheral(self
, *args
):
581 for (name
, count
) in self
.ifacecount
:
582 for i
in range(count
):
583 if self
.is_on_fastbus(name
, i
):
585 #print "mkslow", name, count
586 x
= self
.data
[name
].mkslow_peripheral()
588 suffix
= self
.data
[name
].mksuffix(name
, i
)
589 ret
.append(x
.format(suffix
))
590 return '\n'.join(li(list(filter(None, ret
)), 8))
592 def mk_fast_connection(self
, *args
):
594 for (name
, count
) in self
.ifacecount
:
595 for i
in range(count
):
596 if self
.is_on_fastbus(name
, i
):
598 txt
= self
.data
[name
].mk_connection(i
, "fabric", "fast")
601 print self
.data
[name
].mk_connection
603 return '\n'.join(li(list(filter(None, ret
)), 12))
605 def mk_connection(self
, *args
):
607 for (name
, count
) in self
.ifacecount
:
608 for i
in range(count
):
609 if self
.is_on_fastbus(name
, i
):
611 txt
= self
.data
[name
].mk_connection(i
, "slow_fabric", "")
614 print self
.data
[name
].mk_connection
616 return '\n'.join(li(list(filter(None, ret
)), 8))
618 def mk_cellconn(self
):
621 for (name
, count
) in self
.ifacecount
:
622 for i
in range(count
):
623 if self
.is_on_fastbus(name
, i
):
625 res
= self
.data
[name
].mk_cellconn(cellcount
, name
, i
)
628 (txt
, cellcount
) = res
630 ret
= li('\n'.join(list(filter(None, ret
))), 4)
631 return li(pinmux_cellrule
.format(ret
), 4)
635 for (name
, count
) in self
.ifacecount
:
636 for i
in range(count
):
637 if self
.is_on_fastbus(name
, i
):
639 txt
= self
.data
[name
].mk_pincon(name
, i
)
641 return '\n'.join(li(list(filter(None, ret
)), 4))
643 def mk_dma_irq(self
):
651 for (name
, count
) in self
.ifacecount
:
653 for i
in range(count
):
654 if not self
.is_on_fastbus(name
, i
):
656 txt
= self
.data
[name
].mk_dma_sync(name
, i
)
660 txt
= self
.data
[name
].mk_dma_rule(name
, i
)
661 ifacerules
.append(txt
)
662 txt
= self
.data
[name
].mk_dma_connect(name
, i
)
664 ifacerules
= list(filter(None, ifacerules
))
666 txt
= "rule synchronize_%s_interrupts;" % name
669 rules
.append("endrule")
671 cnct
= list(filter(None, cnct
))
673 _cnct
= ["rule rl_connect_interrupt_to_DMA;",
674 " Bit #(%d) lv_interrupt_to_DMA={" % ct
]
677 cnct
= _cnct
+ [spc
+ spcsep
.join(cnct
)]
679 cnct
.append(" dma.interrupt_from_peripherals(\n" +
680 " lv_interrupt_to_DMA);")
681 cnct
.append("endrule;")
683 ret
= list(filter(None, sync
+ rules
+ cnct
))
685 return '\n'.join(ret
)
687 def num_dmachannels(self
):
688 return "`define NUM_DMACHANNELS {0}".format(self
.dma_count
)
690 def mk_ext_ifacedef(self
):
692 for (name
, count
) in self
.ifacecount
:
693 for i
in range(count
):
694 if self
.is_on_fastbus(name
, i
):
696 txt
= self
.data
[name
].mk_ext_ifacedef(name
, i
)
698 return '\n'.join(li(list(filter(None, ret
)), 8))
702 irq_offs
= 8 # XXX: DMA scovers 0-7?
703 for (name
, count
) in self
.ifacecount
:
704 for i
in range(count
):
705 if self
.is_on_fastbus(name
, i
):
707 res
= self
.data
[name
].mk_plic(i
, irq_offs
)
710 (txt
, irq_offs
) = res
712 self
.num_slow_irqs
= irq_offs
713 return '\n'.join(li(list(filter(None, ret
)), 4))
715 def mk_sloirqsdef(self
):
716 return " `define NUM_SLOW_IRQS {0}".format(self
.num_slow_irqs
)
718 def is_on_fastbus(self
, name
, i
):
719 #print "fastbus mode", self.fastbusmode, name, i
720 iname
= self
.data
[name
].iname().format(i
)
722 return iname
not in self
.fastbus
723 return iname
in self
.fastbus
726 class PFactory(object):
727 def getcls(self
, name
):
728 from uart
import uart
729 from quart
import quart
730 from sdmmc
import sdmmc
732 from eint
import eint
733 from rs232
import rs232
735 from eint
import eint
736 from jtag
import jtag
737 from spi
import spi
, mspi
738 from qspi
import qspi
, mqspi
739 from gpio
import gpio
740 from rgbttl
import rgbttl
741 from flexbus
import flexbus
743 for k
, v
in {'uart': uart
,
759 if name
.startswith(k
):
764 slowfactory
= PFactory()
766 if __name__
== '__main__':
770 i
= PeripheralIface('uart')
772 i
= PeripheralIface('gpioa')