6 if isinstance(txt
, str):
11 line
= line
.split('\n')
16 res
.append(indent
+ line
)
23 def __init__(self
, name
):
26 def extifdecl(self
, name
, count
):
27 sname
= self
.get_iname(count
)
28 return " interface PeripheralSide%s %s;" % (name
.upper(), sname
)
30 def has_axi_master(self
):
36 def mk_dma_irq(self
, name
, count
):
37 if not self
.irq_name():
39 sname
= self
.get_iname(count
)
40 return "{0}_interrupt".format(sname
)
42 def mk_dma_rule(self
, name
, count
):
43 irqname
= self
.mk_dma_irq(name
, count
)
46 pirqname
= self
.irq_name().format(count
)
47 template
= " {0}_interrupt.send(\n" + \
48 " slow_peripherals.{1});"
49 return template
.format(irqname
, pirqname
)
51 def get_clock_reset(self
, name
, count
):
52 return "slow_clock,slow_reset"
54 def mk_dma_sync(self
, name
, count
):
55 irqname
= self
.mk_dma_irq(name
, count
)
58 sname
= self
.peripheral
.iname().format(count
)
59 template
= "SyncBitIfc#(Bit#(1)) {0} <-\n" + \
60 " <-mkSyncBitToCC({1});"
61 return template
.format(irqname
, self
.get_clock_reset(name
, count
))
63 def mk_dma_connect(self
, name
, count
):
64 irqname
= self
.mk_dma_irq(name
, count
)
67 return "{0}.read".format(irqname
)
69 def fastifdecl(self
, name
, count
):
72 def slowifdeclmux(self
, name
, count
):
78 def num_axi_regs32(self
):
84 def get_iname(self
, inum
):
85 return "{0}{1}".format(self
.name
, self
.mksuffix(self
.name
, inum
))
87 def axibase(self
, name
, ifacenum
):
89 return "%(name)s%(ifacenum)dBase" % locals()
91 def axiend(self
, name
, ifacenum
):
93 return "%(name)s%(ifacenum)dEnd" % locals()
95 def axi_reg_def(self
, start
, name
, ifacenum
):
97 offs
= self
.num_axi_regs32() * 4 * 16
100 end
= start
+ offs
- 1
101 bname
= self
.axibase(name
, ifacenum
)
102 bend
= self
.axiend(name
, ifacenum
)
103 comment
= "%d 32-bit regs" % self
.num_axi_regs32()
104 return (" `define %(bname)s 'h%(start)08X\n"
105 " `define %(bend)s 'h%(end)08X // %(comment)s" % locals(),
108 def axi_master_name(self
, name
, ifacenum
, typ
=''):
110 return "{0}{1}_master_num".format(name
, ifacenum
)
112 def axi_slave_name(self
, name
, ifacenum
, typ
=''):
114 return "{0}{1}_{2}slave_num".format(name
, ifacenum
, typ
)
116 def axi_master_idx(self
, idx
, name
, ifacenum
, typ
):
117 name
= self
.axi_master_name(name
, ifacenum
, typ
)
118 return ("typedef {0} {1};".format(idx
, name
), 1)
120 def axi_slave_idx(self
, idx
, name
, ifacenum
, typ
):
121 name
= self
.axi_slave_name(name
, ifacenum
, typ
)
122 return ("typedef {0} {1};".format(idx
, name
), 1)
124 def axi_addr_map(self
, name
, ifacenum
):
125 bname
= self
.axibase(name
, ifacenum
)
126 bend
= self
.axiend(name
, ifacenum
)
127 name
= self
.axi_slave_name(name
, ifacenum
)
129 if(addr>=`{0} && addr<=`{1})
130 return tuple2(True,fromInteger(valueOf({2})));
131 else""".format(bname
, bend
, name
)
133 def mk_pincon(self
, name
, count
):
134 # TODO: really should be using bsv.interface_decl.Interfaces
135 # pin-naming rules.... logic here is hard-coded to duplicate
136 # it (see Interface.__init__ outen)
138 for p
in self
.peripheral
.pinspecs
:
141 #n = "{0}{1}".format(self.name, self.mksuffix(name, count))
142 n
= name
# "{0}{1}".format(self.name, self.mksuffix(name, count))
143 ret
.append(" //%s %s" % (n
, str(p
)))
144 sname
= self
.peripheral
.iname().format(count
)
145 sname
= "{0}.{1}".format(sname
, pname
)
146 ps
= "pinmux.peripheral_side.%s" % sname
147 if typ
== 'out' or typ
== 'inout':
148 fname
= self
.pinname_out(pname
)
149 if not n
.startswith('gpio'): # XXX EURGH! horrible hack
150 n_
= "{0}{1}".format(n
, count
)
158 ret
.append(" mkConnection({0},\n\t\t\t{1}.{2});"
159 .format(ps_
, n_
, fname
))
162 fname
= self
.pinname_outen(pname
)
164 if isinstance(fname
, str):
165 fname
= "{0}.{1}".format(n_
, fname
)
166 fname
= self
.pinname_tweak(pname
, 'outen', fname
)
167 ret
.append(" mkConnection({0}_outen,\n\t\t\t{1});"
169 if typ
== 'in' or typ
== 'inout':
170 fname
= self
.pinname_in(pname
)
176 n_
= "{0}{1}".format(n
, count
)
177 n_
= '{0}.{1}'.format(n_
, fname
)
178 n_
= self
.ifname_tweak(pname
, 'in', n_
)
179 ret
.append(" mkConnection({1}, {0});".format(ps_
, n_
))
180 return '\n'.join(ret
)
182 def mk_cellconn(self
, *args
):
185 def mkfast_peripheral(self
, size
=0):
188 def mkslow_peripheral(self
, size
=0):
191 def mksuffix(self
, name
, i
):
194 def __mk_connection(self
, con
, aname
, fabricname
):
195 txt
= " mkConnection ({2}.v_to_slaves\n" + \
196 " [fromInteger(valueOf({1}))],\n" + \
199 print "PBase __mk_connection", self
.name
, aname
202 return txt
.format(con
, aname
, fabricname
)
204 def __mk_master_connection(self
, con
, aname
):
205 txt
= " mkConnection (slow_fabric.v_to_slaves\n" + \
206 " [fromInteger(valueOf({1}))],\n" + \
209 print "PBase __mk_connection", self
.name
, aname
212 return txt
.format(con
, aname
)
214 def mk_connection(self
, count
, fabricname
, typ
, name
=None):
217 print "PBase mk_conn", self
.name
, count
218 aname
= self
.axi_slave_name(name
, count
, typ
)
219 #dname = self.mksuffix(name, count)
220 #dname = "{0}{1}".format(name, dname)
221 con
= self
._mk
_connection
(name
, count
).format(count
, aname
)
222 return self
.__mk
_connection
(con
, aname
, fabricname
)
224 def _mk_connection(self
, name
=None, count
=0):
227 def pinname_out(self
, pname
):
230 def pinname_in(self
, pname
):
233 def pinname_outen(self
, pname
):
236 def ifname_tweak(self
, pname
, typ
, txt
):
239 def pinname_tweak(self
, pname
, typ
, txt
):
245 def mk_plic(self
, inum
, irq_offs
):
247 print "mk_plic", self
.name
, inum
, irq_offs
248 niq
= self
.num_irqs()
250 return ('', irq_offs
)
251 name
= self
.get_iname(inum
)
252 res
.append(" // PLIC rules for {0}".format(name
))
253 for idx
in range(niq
):
254 plic_obj
= self
.plic_object(name
, idx
)
255 print "plic_obj", name
, idx
, plic_obj
256 plic
= mkplic_rule
.format(name
, plic_obj
, irq_offs
)
258 irq_offs
+= 1 # increment to next irq
259 return ('\n'.join(res
), irq_offs
)
261 def mk_ext_ifacedef(self
, iname
, inum
):
264 def extfastifinstance(self
, name
, count
):
267 def _extifinstance(self
, name
, count
, suffix
, prefix
, samename
=False):
268 pname
= self
.get_iname(count
)
272 sname
= self
.peripheral
.iname().format(count
)
273 template
= " interface {0}{3} = {2}{1};"
274 return template
.format(pname
, sname
, prefix
, suffix
)
276 def extifinstance(self
, name
, count
):
277 return self
._extifinstance
(name
, count
, "",
278 "pinmux.peripheral_side.")
282 rule rl_connect_{0}_to_plic_{2};
283 if({1} == 1'b1) begin
284 ff_gateway_queue[{2}].enq(1);
285 plic.ifc_external_irq[{2}].irq_frm_gateway(True);
290 axi_master_declarations
= """\
291 typedef 0 Dmem_master_num;
292 typedef 1 Imem_master_num;
294 typedef TAdd#(LastGen_master_num, `ifdef Debug 1 `else 0 `endif )
296 typedef TAdd#(Debug_master_num, `ifdef DMA 1 `else 0 `endif )
298 typedef TAdd#(DMA_master_num,1)
302 axi_fastslave_declarations
= """\
304 typedef TAdd#(LastGen_fastslave_num,1) Sdram_cfg_slave_num;
305 typedef TAdd#(Sdram_slave_num ,`ifdef SDRAM 1 `else 0 `endif )
307 typedef TAdd#(Sdram_cfg_slave_num,`ifdef BOOTROM 1 `else 0 `endif )
309 typedef TAdd#(BootRom_slave_num ,`ifdef Debug 1 `else 0 `endif )
311 typedef TAdd#(Debug_slave_num , `ifdef TCMemory 1 `else 0 `endif )
313 typedef TAdd#(TCM_slave_num ,`ifdef DMA 1 `else 0 `endif )
315 typedef TAdd#(Dma_slave_num ,1 ) SlowPeripheral_slave_num;
316 typedef TAdd#(SlowPeripheral_slave_num,`ifdef VME 1 `else 0 `endif )
318 typedef TAdd#(VME_slave_num,`ifdef FlexBus 1 `else 0 `endif )
320 typedef TAdd#(FlexBus_slave_num,1)
325 axi_slave_declarations
= """\
326 typedef 0 SlowMaster;
328 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
330 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
332 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
334 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
337 pinmux_cellrule
= """\
338 rule connect_select_lines_pinmux;
344 class CallFn(object):
345 def __init__(self
, peripheral
, name
):
346 self
.peripheral
= peripheral
349 def __call__(self
, *args
):
350 #print "__call__", self.name, self.peripheral.slow, args
351 if not self
.peripheral
.slow
:
353 return getattr(self
.peripheral
.slow
, self
.name
)(*args
[1:])
356 class PeripheralIface(object):
357 def __init__(self
, ifacename
):
359 slow
= slowfactory
.getcls(ifacename
)
360 print "Iface", ifacename
, slow
362 self
.slow
= slow(ifacename
)
363 self
.slow
.peripheral
= self
364 for fname
in ['slowimport',
365 'extfastifinstance', 'extifinstance', 'extifdecl',
366 'slowifdecl', 'slowifdeclmux',
369 'mk_dma_sync', 'mk_dma_connect', 'mk_dma_rule',
371 'mk_plic', 'mk_ext_ifacedef',
372 'mk_connection', 'mk_cellconn', 'mk_pincon']:
373 fn
= CallFn(self
, fname
)
374 setattr(self
, fname
, types
.MethodType(fn
, self
))
376 #print "PeripheralIface"
379 def mksuffix(self
, name
, i
):
380 if self
.slow
is None:
382 return self
.slow
.mksuffix(name
, i
)
384 def axi_reg_def(self
, start
, count
):
387 return self
.slow
.axi_reg_def(start
, self
.ifacename
, count
)
389 def axi_master_idx(self
, start
, count
, typ
):
390 if not self
.slow
or not self
.slow
.has_axi_master():
392 return self
.slow
.axi_master_idx(start
, self
.ifacename
, count
, typ
)
394 def axi_slave_idx(self
, start
, count
, typ
):
397 return self
.slow
.axi_slave_idx(start
, self
.ifacename
, count
, typ
)
399 def axi_addr_map(self
, count
):
402 return self
.slow
.axi_addr_map(self
.ifacename
, count
)
405 class PeripheralInterfaces(object):
407 self
.fastbusmode
= False
409 def slowimport(self
, *args
):
411 for (name
, count
) in self
.ifacecount
:
412 #print "slowimport", name, self.data[name].slowimport
413 ret
.append(self
.data
[name
].slowimport())
414 return '\n'.join(list(filter(None, ret
)))
416 def extfastifinstance(self
, *args
):
418 for (name
, count
) in self
.ifacecount
:
419 for i
in range(count
):
420 iname
= self
.data
[name
].iname().format(i
)
421 print "extfast", iname
, self
.is_on_fastbus(name
, i
)
422 if self
.is_on_fastbus(name
, i
):
424 ret
.append(self
.data
[name
].extfastifinstance(name
, i
))
425 return '\n'.join(list(filter(None, ret
)))
427 def extifinstance(self
, *args
):
429 for (name
, count
) in self
.ifacecount
:
430 for i
in range(count
):
431 iname
= self
.data
[name
].iname().format(i
)
432 if not self
.is_on_fastbus(name
, i
):
434 ret
.append(self
.data
[name
].extifinstance(name
, i
))
435 return '\n'.join(list(filter(None, ret
)))
437 def extifdecl(self
, *args
):
439 for (name
, count
) in self
.ifacecount
:
440 for i
in range(count
):
441 if not self
.is_on_fastbus(name
, i
):
443 ret
.append(self
.data
[name
].extifdecl(name
, i
))
444 return '\n'.join(list(filter(None, ret
)))
446 def slowifdeclmux(self
, *args
):
448 for (name
, count
) in self
.ifacecount
:
449 for i
in range(count
):
450 ret
.append(self
.data
[name
].slowifdeclmux(name
, i
))
451 return '\n'.join(list(filter(None, ret
)))
453 def fastifdecl(self
, *args
):
455 for (name
, count
) in self
.ifacecount
:
456 for i
in range(count
):
457 print "fastifdecl", name
, i
, self
.is_on_fastbus(name
, i
)
458 if self
.is_on_fastbus(name
, i
):
460 ret
.append(self
.data
[name
].fastifdecl(name
, i
))
461 return '\n'.join(list(filter(None, ret
)))
463 def slowifdecl(self
, *args
):
465 for (name
, count
) in self
.ifacecount
:
466 for i
in range(count
):
467 if self
.is_on_fastbus(name
, i
):
469 ret
.append(self
.data
[name
].slowifdecl().format(i
, name
))
470 return '\n'.join(list(filter(None, ret
)))
472 def axi_reg_def(self
, *args
):
474 start
= 0x00011100 # start of AXI peripherals address
475 for (name
, count
) in self
.ifacecount
:
476 for i
in range(count
):
477 if self
.is_on_fastbus(name
, i
):
479 x
= self
.data
[name
].axi_reg_def(start
, i
)
480 #print ("ifc", name, x)
484 return '\n'.join(list(filter(None, ret
)))
486 def _axi_num_idx(self
, start
, template
, typ
, idxtype
, *args
):
488 for (name
, count
) in self
.ifacecount
:
489 for i
in range(count
):
490 if self
.is_on_fastbus(name
, i
):
493 fn
= self
.data
[name
].axi_master_idx
495 fn
= self
.data
[name
].axi_slave_idx
496 (rdef
, offs
) = fn(start
, i
, idxtype
)
497 #print ("ifc", name, rdef, offs)
500 ret
.append("typedef %d LastGen_%s_num;" % (start
- 1, typ
))
501 decls
= '\n'.join(list(filter(None, ret
)))
502 return template
.format(decls
)
504 def axi_slave_idx(self
, *args
):
505 return self
._axi
_num
_idx
(0, axi_slave_declarations
, 'slave',
508 def axi_fastslave_idx(self
, *args
):
509 return self
._axi
_num
_idx
(0, axi_fastslave_declarations
, 'fastslave',
512 def axi_master_idx(self
, *args
):
513 return self
._axi
_num
_idx
(2, axi_master_declarations
, 'master',
516 def axi_fastslave_idx(self
, *args
):
517 return self
._axi
_num
_idx
(0, axi_fastslave_declarations
, 'fastslave',
520 def axi_addr_map(self
, *args
):
522 for (name
, count
) in self
.ifacecount
:
523 for i
in range(count
):
524 if self
.is_on_fastbus(name
, i
):
526 ret
.append(self
.data
[name
].axi_addr_map(i
))
527 return '\n'.join(list(filter(None, ret
)))
529 def mkfast_peripheral(self
, *args
):
531 for (name
, count
) in self
.ifacecount
:
532 for i
in range(count
):
533 if self
.is_on_fastbus(name
, i
):
535 #print "mkfast", name, count
536 x
= self
.data
[name
].mkfast_peripheral()
538 suffix
= self
.data
[name
].mksuffix(name
, i
)
539 ret
.append(x
.format(suffix
))
540 return '\n'.join(list(filter(None, ret
)))
542 def mkslow_peripheral(self
, *args
):
544 for (name
, count
) in self
.ifacecount
:
545 for i
in range(count
):
546 if self
.is_on_fastbus(name
, i
):
548 #print "mkslow", name, count
549 x
= self
.data
[name
].mkslow_peripheral()
551 suffix
= self
.data
[name
].mksuffix(name
, i
)
552 ret
.append(x
.format(suffix
))
553 return '\n'.join(list(filter(None, ret
)))
555 def mk_fast_connection(self
, *args
):
557 for (name
, count
) in self
.ifacecount
:
558 for i
in range(count
):
559 if self
.is_on_fastbus(name
, i
):
561 txt
= self
.data
[name
].mk_connection(i
, "fabric", "fast")
564 print self
.data
[name
].mk_connection
566 return '\n'.join(list(filter(None, ret
)))
568 def mk_connection(self
, *args
):
570 for (name
, count
) in self
.ifacecount
:
571 for i
in range(count
):
572 if self
.is_on_fastbus(name
, i
):
574 txt
= self
.data
[name
].mk_connection(i
, "slow_fabric", "")
577 print self
.data
[name
].mk_connection
579 return '\n'.join(list(filter(None, ret
)))
581 def mk_cellconn(self
):
584 for (name
, count
) in self
.ifacecount
:
585 for i
in range(count
):
586 if self
.is_on_fastbus(name
, i
):
588 res
= self
.data
[name
].mk_cellconn(cellcount
, name
, i
)
591 (txt
, cellcount
) = res
593 ret
= '\n'.join(list(filter(None, ret
)))
594 return pinmux_cellrule
.format(ret
)
598 for (name
, count
) in self
.ifacecount
:
599 for i
in range(count
):
600 if self
.is_on_fastbus(name
, i
):
602 txt
= self
.data
[name
].mk_pincon(name
, i
)
604 return '\n'.join(list(filter(None, ret
)))
606 def mk_dma_irq(self
):
614 for (name
, count
) in self
.ifacecount
:
616 for i
in range(count
):
617 if not self
.is_on_fastbus(name
, i
):
619 txt
= self
.data
[name
].mk_dma_sync(name
, i
)
623 txt
= self
.data
[name
].mk_dma_rule(name
, i
)
624 ifacerules
.append(txt
)
625 txt
= self
.data
[name
].mk_dma_connect(name
, i
)
627 ifacerules
= list(filter(None, ifacerules
))
629 txt
= "rule synchronize_%s_interrupts;" % name
632 rules
.append("endrule")
634 cnct
= list(filter(None, cnct
))
636 _cnct
= ["rule rl_connect_interrupt_to_DMA;",
637 " Bit #(%d) lv_interrupt_to_DMA={" % ct
]
640 cnct
= _cnct
+ [spc
+ spcsep
.join(cnct
)]
642 cnct
.append(" dma.interrupt_from_peripherals(\n" + \
643 " lv_interrupt_to_DMA);")
644 cnct
.append("endrule;")
646 ret
= list(filter(None, sync
+ rules
+ cnct
))
648 return '\n'.join(ret
)
650 def num_dmachannels(self
):
651 return "`define NUM_DMACHANNELS {0}".format(self
.dma_count
)
653 def mk_ext_ifacedef(self
):
655 for (name
, count
) in self
.ifacecount
:
656 for i
in range(count
):
657 if self
.is_on_fastbus(name
, i
):
659 txt
= self
.data
[name
].mk_ext_ifacedef(name
, i
)
661 return '\n'.join(list(filter(None, ret
)))
665 irq_offs
= 8 # XXX: DMA scovers 0-7?
666 for (name
, count
) in self
.ifacecount
:
667 for i
in range(count
):
668 if self
.is_on_fastbus(name
, i
):
670 res
= self
.data
[name
].mk_plic(i
, irq_offs
)
673 (txt
, irq_offs
) = res
675 self
.num_slow_irqs
= irq_offs
676 return '\n'.join(list(filter(None, ret
)))
678 def mk_sloirqsdef(self
):
679 return " `define NUM_SLOW_IRQS {0}".format(self
.num_slow_irqs
)
681 def is_on_fastbus(self
, name
, i
):
682 #print "fastbus mode", self.fastbusmode, name, i
683 iname
= self
.data
[name
].iname().format(i
)
685 return iname
not in self
.fastbus
686 return iname
in self
.fastbus
689 class PFactory(object):
690 def getcls(self
, name
):
691 from uart
import uart
692 from quart
import quart
693 from sdmmc
import sdmmc
695 from eint
import eint
696 from rs232
import rs232
698 from eint
import eint
699 from jtag
import jtag
700 from spi
import spi
, mspi
701 from qspi
import qspi
, mqspi
702 from gpio
import gpio
703 from rgbttl
import rgbttl
705 for k
, v
in {'uart': uart
,
720 if name
.startswith(k
):
725 slowfactory
= PFactory()
727 if __name__
== '__main__':
731 i
= PeripheralIface('uart')
733 i
= PeripheralIface('gpioa')