use class iterator for mk_connection (all of them)
[pinmux.git] / src / bsv / peripheral_gen / base.py
1 import types
2
3
4 def li(txt, indent):
5 indent = ' ' * indent
6 istxt = False
7 if isinstance(txt, str):
8 istxt = True
9 txt = txt.split('\n')
10 res = []
11 for line in txt:
12 line = line.split('\n')
13 res += line
14 txt = res
15 res = []
16 for line in txt:
17 res.append(indent + line)
18 if istxt:
19 res = '\n'.join(res)
20 return res
21
22
23 class MMapConfig(object):
24
25 def get_mmap_configs(self):
26 res = []
27 for cfg in self.peripheral.configs:
28 res.append(cfg.get('mmap', None))
29 # XXX HACK! assume all configs same for each peripheral!
30 return res[0]
31
32 def map_to_idx(self, cfg, idx):
33 if isinstance(idx, int):
34 return idx
35 for (i, c) in enumerate(cfg):
36 if c[0] == idx:
37 return i
38 assert "config name %s not found" % s
39
40 def get_mmap_cfg_start(self, idx):
41 cfg = self.get_mmap_configs()
42 if cfg is None:
43 nregs = self.num_axi_regs32()
44 if isinstance(nregs, int) or len(nregs) == 1:
45 return 0
46 return "_%d_" % idx
47 idx = self.map_to_idx(cfg, idx)
48 return cfg[idx][1]
49
50 def get_mmap_cfg_name(self, idx):
51 cfg = self.get_mmap_configs()
52 if cfg is None:
53 nregs = self.num_axi_regs32()
54 if isinstance(nregs, int) or len(nregs) == 1:
55 return ""
56 return "_%d_" % idx
57 return cfg[idx][0]
58
59 def num_axi_regs32cfg(self):
60 cfg = self.get_mmap_configs()
61 if cfg is None:
62 return self.num_axi_regs32()
63 regs = []
64 for c in cfg:
65 regs.append(c[2])
66 return regs
67
68
69 class PBase(MMapConfig):
70 def __init__(self, name):
71 self.name = name
72 MMapConfig.__init__(self)
73
74 def extifdecl(self, name, count):
75 sname = self.get_iname(count)
76 return "interface PeripheralSide%s %s;" % (name.upper(), sname)
77
78 def has_axi_master(self):
79 return False
80
81 def irq_name(self):
82 return ""
83
84 def mk_dma_irq(self, name, count):
85 if not self.irq_name():
86 return ''
87 sname = self.get_iname(count)
88 return "{0}_interrupt".format(sname)
89
90 def mk_dma_rule(self, name, count):
91 irqname = self.mk_dma_irq(name, count)
92 if not irqname:
93 return ''
94 pirqname = self.irq_name().format(count)
95 template = " {0}.send(\n" + \
96 " slow_peripherals.{1});"
97 return template.format(irqname, pirqname)
98
99 def get_clock_reset(self, name, count):
100 return "slow_clock,slow_reset"
101
102 def mk_dma_sync(self, name, count):
103 irqname = self.mk_dma_irq(name, count)
104 if not irqname:
105 return ''
106 sname = self.peripheral.iname().format(count)
107 template = "SyncBitIfc#(Bit#(1)) {0} <-\n" + \
108 " <-mkSyncBitToCC({1});"
109 return template.format(irqname, self.get_clock_reset(name, count))
110
111 def mk_dma_connect(self, name, count):
112 irqname = self.mk_dma_irq(name, count)
113 if not irqname:
114 return ''
115 return "{0}.read".format(irqname)
116
117 def fastifdecl(self, name, count):
118 return ''
119
120 def slowifdeclmux(self, name, count):
121 return ''
122
123 def slowimport(self):
124 return ''
125
126 def num_axi_regs32(self):
127 return 0
128
129 def slowifdecl(self):
130 return ''
131
132 def get_iname(self, inum):
133 return "{0}{1}".format(self.name, self.mksuffix(self.name, inum))
134
135 def axibase(self, name, ifacenum, idx):
136 name = name.upper()
137 return "%(name)s%(ifacenum)d%(idx)sBase" % locals()
138
139 def axiend(self, name, ifacenum, idx):
140 name = name.upper()
141 return "%(name)s%(ifacenum)d%(idx)sEnd" % locals()
142
143 def _axi_reg_def(self, idx, numregs, start, name, ifacenum):
144 name = name.upper()
145 offs = numregs * 4 * 16
146 if offs == 0:
147 return ('', 0)
148 cfgstart = self.get_mmap_cfg_start(idx)
149 if cfgstart:
150 start = cfgstart
151 end = start + offs - 1
152 offs = 0 # don't do contiguous addressing
153 else:
154 end = start + offs - 1
155 bname = self.axibase(name, ifacenum, idx)
156 bend = self.axiend(name, ifacenum, idx)
157 comment = "%d 32-bit regs" % numregs
158 return ("`define %(bname)s 'h%(start)08X\n"
159 "`define %(bend)s 'h%(end)08X // %(comment)s" % locals(),
160 offs)
161
162 def axi_reg_def(self, start, name, ifacenum):
163 offs = self.num_axi_regs32cfg()
164 if offs == 0:
165 return ('', 0)
166 if not isinstance(offs, list):
167 offs = [offs]
168 res = []
169 offstotal = 0
170 print offs
171 for (idx, nregs) in enumerate(offs):
172 cfg = self.get_mmap_cfg_name(idx)
173 (txt, off) = self._axi_reg_def(cfg, nregs, start, name, ifacenum)
174 start += off
175 offstotal += off
176 res.append(txt)
177 return ('\n'.join(res), offstotal)
178
179 def axi_master_name(self, name, ifacenum, typ=''):
180 name = name.upper()
181 return "{0}{1}_master_num".format(name, ifacenum)
182
183 def axi_slave_name(self, idx, name, ifacenum, typ=''):
184 name = name.upper()
185 return "{0}{1}{3}_{2}slave_num".format(name, ifacenum, typ, idx)
186
187 def axi_master_idx(self, idx, name, ifacenum, typ):
188 name = self.axi_master_name(name, ifacenum, typ)
189 return ("typedef {0} {1};".format(idx, name), 1)
190
191 def axi_slave_idx(self, idx, name, ifacenum, typ):
192 offs = self.num_axi_regs32()
193 if offs == 0:
194 return ''
195 if not isinstance(offs, list):
196 offs = [offs]
197 res = []
198 for (i, nregs) in enumerate(offs):
199 cfg = self.get_mmap_cfg_name(i)
200 name_ = self.axi_slave_name(cfg, name, ifacenum, typ)
201 res.append("typedef {0} {1};".format(idx + i, name_))
202 return ('\n'.join(res), len(offs))
203
204 def axi_fastaddr_map(self, name, ifacenum):
205 return self.axi_addr_map(name, ifacenum, 'fast')
206
207 def _axi_addr_map(self, idx, name, ifacenum, typ=""):
208 bname = self.axibase(name, ifacenum, idx)
209 bend = self.axiend(name, ifacenum, idx)
210 name = self.axi_slave_name(idx, name, ifacenum, typ)
211 template = """\
212 if(addr>=`{0} && addr<=`{1})
213 return tuple2(True,fromInteger(valueOf({2})));
214 else"""
215 return template.format(bname, bend, name)
216
217 def axi_addr_map(self, name, ifacenum, typ=""):
218 offs = self.num_axi_regs32()
219 if offs == 0:
220 return ''
221 if not isinstance(offs, list):
222 offs = [offs]
223 res = []
224 for (idx, nregs) in enumerate(offs):
225 cfg = self.get_mmap_cfg_name(idx)
226 res.append(self._axi_addr_map(cfg, name, ifacenum, typ))
227 return '\n'.join(res)
228
229 def _mk_pincon(self, name, count, ptyp):
230 # TODO: really should be using bsv.interface_decl.Interfaces
231 # pin-naming rules.... logic here is hard-coded to duplicate
232 # it (see Interface.__init__ outen)
233 ret = []
234 for p in self.peripheral.pinspecs:
235 typ = p['type']
236 pname = p['name']
237 #n = "{0}{1}".format(self.name, self.mksuffix(name, count))
238 n = name # "{0}{1}".format(self.name, self.mksuffix(name, count))
239 ret.append("//%s %s" % (n, str(p)))
240 if ptyp == 'fast':
241 sname = self.get_iname(count)
242 sname = "{0}.{1}".format(sname, pname)
243 ps = "slow_peripherals.%s" % sname
244 else:
245 sname = self.peripheral.iname().format(count)
246 sname = "{0}.{1}".format(sname, pname)
247 ps = "pinmux.peripheral_side.%s" % sname
248 if typ == 'out' or typ == 'inout':
249 fname = self.pinname_out(pname)
250 if not n.startswith('gpio'): # XXX EURGH! horrible hack
251 n_ = "{0}{1}".format(n, count)
252 else:
253 n_ = n
254 if fname:
255 if p.get('outen'):
256 ps_ = ps + '_out'
257 else:
258 ps_ = ps
259 cn = self._mk_actual_connection('out', name,
260 count, typ,
261 pname, ps_, n_, fname)
262 ret += cn
263 fname = None
264 if p.get('outen'):
265 fname = self.pinname_outen(pname)
266 if fname:
267 if isinstance(fname, str):
268 fname = "{0}.{1}".format(n_, fname)
269 fname = self.pinname_tweak(pname, 'outen', fname)
270 cn = self._mk_actual_connection('outen', name,
271 count, typ,
272 pname, ps, n, fname)
273 ret += cn
274 if typ == 'in' or typ == 'inout':
275 fname = self.pinname_in(pname)
276 if fname:
277 if p.get('outen'):
278 ps_ = ps + '_in'
279 else:
280 ps_ = ps
281 n_ = "{0}{1}".format(n, count)
282 n_ = '{0}.{1}'.format(n_, fname)
283 n_ = self.ifname_tweak(pname, 'in', n_)
284 cn = self._mk_actual_connection('in', name,
285 count, typ,
286 pname, ps_, n_, fname)
287 ret += cn
288 return '\n'.join(ret)
289
290 def _mk_vpincon(self, name, count, ptyp, typ, pname, stype=None):
291 if stype is None:
292 stype = pname
293 ret = []
294 ret.append("//%s %s %s %s %s" % (name, ptyp, typ, pname, stype))
295 if ptyp == 'fast':
296 sname = self.get_iname(count)
297 ps = "slow_peripherals.%s" % sname
298 else:
299 sname = self.peripheral.iname().format(count)
300 ps = "pinmux.peripheral_side.%s" % sname
301 n = self.get_iname(count)
302 if typ == 'in':
303 n = "{0}.{1}".format(n, stype)
304 ps_ = "{0}.{1}".format(ps, pname)
305 ret += self._mk_actual_connection(typ, name, count, typ,
306 pname, ps_, n, stype)
307 return '\n'.join(ret)
308
309 def _mk_actual_connection(self, ctype, name, count, typ,
310 pname, ps, n, fname):
311 ret = []
312 ck = self.get_clock_reset(name, count)
313 if ctype == 'out':
314 if ck == PBase.get_clock_reset(self, name, count):
315 ret.append("mkConnection({0},\n\t\t\t{1}.{2});"
316 .format(ps, n, fname))
317 else:
318 n2 = "{0}{1}".format(name, count)
319 sync = '{0}_{1}_sync'.format(n2, pname)
320 ret.append("mkConnection({0},\n\t\t\t{1}.get);"
321 .format(ps, sync))
322 ret.append("mkConnection({0}.put,\n\t\t\t{1}.{2});"
323 .format(sync, n, fname))
324 elif ctype == 'outen':
325 ret.append("mkConnection({0}_outen,\n\t\t\t{1});"
326 .format(ps, fname))
327 elif ctype == 'in':
328 if ck == PBase.get_clock_reset(self, name, count):
329 ret.append("mkConnection({1},\n\t\t\t{0});".format(
330 ps, n))
331 else:
332 n2 = "{0}{1}".format(name, count)
333 sync = '{0}_{1}_sync'.format(n2, pname)
334 ret.append("mkConnection({1}.put,\n\t\t\t{0});".format(
335 ps, sync))
336 ret.append("mkConnection({1},\n\t\t\t{0}.get);".format(
337 sync, n))
338 return ret
339
340 def _mk_clk_con(self, name, count, ctype):
341 ret = []
342 ck = self.get_clock_reset(name, count)
343 if ck == PBase.get_clock_reset(self, name, count):
344 return ''
345 if ctype == 'slow':
346 spc = self.get_clk_spc(ctype)
347 else:
348 spc = ck
349 ck = self.get_clk_spc(ctype)
350 template = "Ifc_sync#({0}) {1}_sync <-mksyncconnection(\n" + \
351 " {2}, {3});"
352 for p in self.peripheral.pinspecs:
353 typ = p['type']
354 pname = p['name']
355 n = name
356 if typ == 'out' or typ == 'inout':
357 fname = self.pinname_out(pname)
358 if not fname:
359 continue
360 if not n.startswith('gpio'): # XXX EURGH! horrible hack
361 n_ = "{0}{1}".format(n, count)
362 else:
363 n_ = n
364 n_ = '{0}_{1}'.format(n_, pname)
365 ret.append(template.format("Bit#(1)", n_, ck, spc))
366 if typ == 'in' or typ == 'inout':
367 fname = self.pinname_in(pname)
368 if not fname:
369 continue
370 #fname = self.pinname_in(pname)
371 n_ = "{0}{1}".format(n, count)
372 n_ = '{0}_{1}'.format(n_, pname)
373 #n_ = self.ifname_tweak(pname, 'in', n_)
374 ret.append(template.format("Bit#(1)", n_, spc, ck))
375 return '\n'.join(ret)
376
377 def get_clk_spc(self, ctype):
378 if ctype == 'slow':
379 return "sp_clock, sp_reset"
380 else:
381 return "core_clock, core_reset"
382
383 def _mk_clk_vcon(self, name, count, ctype, typ, pname, bitspec):
384 ck = self.get_clock_reset(name, count)
385 if ck == PBase.get_clock_reset(self, name, count):
386 return ''
387 if ctype == 'slow':
388 spc = self.get_clk_spc(ctype)
389 else:
390 spc = ck
391 ck = self.get_clk_spc(ctype)
392 template = "Ifc_sync#({0}) {1}_sync <-mksyncconnection(\n" + \
393 " {2}, {3});"""
394
395 n_ = "{0}{1}".format(name, count)
396 n_ = '{0}_{1}'.format(n_, pname)
397 if typ == 'in' or typ == 'inout':
398 ck, spc = spc, ck
399 return template.format(bitspec, n_, ck, spc)
400
401 def mk_cellconn(self, *args):
402 return ''
403
404 def mkfast_peripheral(self, size=0):
405 return ''
406
407 def mkslow_peripheral(self, size=0):
408 return ''
409
410 def mksuffix(self, name, i):
411 return i
412
413 def __mk_connection(self, con, aname, count, fabricname):
414 txt = "mkConnection ({2}.v_to_slaves\n" + \
415 " [fromInteger(valueOf({1}))],\n" + \
416 " {0});"
417
418 print "PBase __mk_connection", self.name, aname
419 if not con:
420 return ''
421 con = con.format(count, aname)
422 return txt.format(con, aname, fabricname)
423
424 def __mk_master_connection(self, con, aname, count, fabricname):
425 txt = "mkConnection ({0}, {2}.v_from_masters\n" + \
426 " [fromInteger(valueOf({1}))]);\n"
427
428 print "PBase __mk_master_connection", self.name, aname
429 if not con:
430 return ''
431 con = con.format(count, aname)
432 return txt.format(con, aname, fabricname)
433
434 def mk_master_connection(self, name, count, fabricname, typ):
435 if not self.has_axi_master():
436 return ''
437 print "PBase mk_master_conn", self.name, count
438 aname = self.axi_master_name(name, count, typ)
439 ret = []
440 connections = self._mk_connection(name, count, True)
441 if not isinstance(connections, list):
442 connections = [connections]
443 for con in connections:
444 ret.append(self.__mk_master_connection(con, aname, count,
445 fabricname))
446 return '\n'.join(ret)
447
448 def mk_connection(self, name, count, fabricname, typ, name_override=None):
449 if name_override: # needed for GPIO
450 name = name_override
451 print "PBase mk_conn", name, count
452 ret = []
453 connections = self._mk_connection(name, count)
454 if not isinstance(connections, list):
455 connections = [connections]
456 for (idx, con) in enumerate(connections):
457 cfg = self.get_mmap_cfg_name(idx)
458 aname = self.axi_slave_name(cfg, name, count, typ)
459 ret.append(self.__mk_connection(con, aname, count, fabricname))
460 return '\n'.join(ret)
461
462 def _mk_connection(self, name=None, count=0):
463 return ''
464
465 def pinname_out(self, pname):
466 return ''
467
468 def pinname_in(self, pname):
469 return ''
470
471 def pinname_outen(self, pname):
472 return ''
473
474 def ifname_tweak(self, pname, typ, txt):
475 return txt
476
477 def pinname_tweak(self, pname, typ, txt):
478 return txt
479
480 def num_irqs(self):
481 return 0
482
483 def mk_plic(self, inum, irq_offs):
484 res = []
485 print "mk_plic", self.name, inum, irq_offs
486 niq = self.num_irqs()
487 if niq == 0:
488 return ('', irq_offs)
489 name = self.get_iname(inum)
490 res.append("// PLIC rules for {0}".format(name))
491 for idx in range(niq):
492 plic_obj = self.plic_object(name, idx)
493 print "plic_obj", name, idx, plic_obj
494 plic = mkplic_rule.format(name, plic_obj, irq_offs)
495 res.append(plic)
496 irq_offs += 1 # increment to next irq
497 return ('\n'.join(res), irq_offs)
498
499 def mk_ext_ifacedef(self, iname, inum):
500 return ''
501
502 def extfastifinstance(self, name, count):
503 return ''
504
505 def _extifinstance(self, name, count, suffix, prefix, samename=False,
506 ifsuffix=None):
507 if ifsuffix is None:
508 ifsuffix = ''
509 pname = self.get_iname(count)
510 if samename:
511 sname = pname
512 else:
513 sname = self.peripheral.iname().format(count)
514 template = "interface {0}{3} = {2}{1}{4};"
515 return template.format(pname, sname, prefix, suffix, ifsuffix)
516
517 def extifinstance2(self, name, count):
518 return ''
519
520 def extifinstance(self, name, count):
521 return self._extifinstance(name, count, "",
522 "pinmux.peripheral_side.")
523
524
525 mkplic_rule = """\
526 rule rl_connect_{0}_to_plic_{2};
527 if({1} == 1'b1) begin
528 ff_gateway_queue[{2}].enq(1);
529 plic.ifc_external_irq[{2}].irq_frm_gateway(True);
530 end
531 endrule
532 """
533
534 axi_master_declarations = """\
535 typedef 0 Dmem_master_num;
536 typedef 1 Imem_master_num;
537 {0}
538 typedef TAdd#(LastGen_master_num, `ifdef Debug 1 `else 0 `endif )
539 Debug_master_num;
540 typedef TAdd#(Debug_master_num, `ifdef DMA 1 `else 0 `endif )
541 DMA_master_num;
542 typedef TAdd#(DMA_master_num,1)
543 Num_Masters;
544 """
545
546 axi_fastslave_declarations = """\
547 {0}
548 typedef TAdd#(LastGen_fastslave_num,1) Sdram_slave_num;
549 typedef TAdd#(Sdram_slave_num ,`ifdef SDRAM 1 `else 0 `endif )
550 Sdram_cfg_slave_num;
551 typedef TAdd#(Sdram_cfg_slave_num,`ifdef BOOTROM 1 `else 0 `endif )
552 BootRom_slave_num ;
553 typedef TAdd#(BootRom_slave_num ,`ifdef Debug 1 `else 0 `endif )
554 Debug_slave_num ;
555 typedef TAdd#(Debug_slave_num , `ifdef TCMemory 1 `else 0 `endif )
556 TCM_slave_num;
557 typedef TAdd#(TCM_slave_num ,`ifdef DMA 1 `else 0 `endif )
558 Dma_slave_num;
559 typedef TAdd#(Dma_slave_num ,1 ) SlowPeripheral_slave_num;
560 typedef TAdd#(SlowPeripheral_slave_num,`ifdef VME 1 `else 0 `endif )
561 VME_slave_num;
562 typedef TAdd#(VME_slave_num,1) Num_Fast_Slaves;
563 """
564
565 axi_slave_declarations = """\
566 typedef 0 SlowMaster;
567 {0}
568 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
569 CLINT_slave_num;
570 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
571 Plic_slave_num;
572 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
573 AxiExp1_slave_num;
574 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
575 """
576
577 pinmux_cellrule = """\
578 rule connect_select_lines_pinmux;
579 {0}
580 endrule
581 """
582
583
584 class CallFn(object):
585 def __init__(self, peripheral, name):
586 self.peripheral = peripheral
587 self.name = name
588
589 def __call__(self, *args):
590 #print "__call__", self.name, self.peripheral.slow, args
591 if not self.peripheral.slow:
592 return ''
593 return getattr(self.peripheral.slow, self.name)(*args[1:])
594
595
596 class PeripheralIface(object):
597 def __init__(self, ifacename):
598 self.slow = None
599 slow = slowfactory.getcls(ifacename)
600 print "Iface", ifacename, slow
601 if slow:
602 self.slow = slow(ifacename)
603 self.slow.peripheral = self
604 for fname in ['slowimport',
605 'extfastifinstance',
606 'extifinstance2', 'extifinstance', 'extifdecl',
607 'slowifdecl', 'slowifdeclmux',
608 'fastifdecl',
609 'mkslow_peripheral',
610 'mk_dma_sync', 'mk_dma_connect', 'mk_dma_rule',
611 'mkfast_peripheral',
612 'mk_plic', 'mk_ext_ifacedef',
613 '_mk_clk_con', 'mk_ext_ifacedef',
614 'mk_connection', 'mk_master_connection',
615 'mk_cellconn', '_mk_pincon']:
616 fn = CallFn(self, fname)
617 setattr(self, fname, types.MethodType(fn, self))
618
619 #print "PeripheralIface"
620 #print dir(self)
621
622 def mksuffix(self, name, i):
623 if self.slow is None:
624 return i
625 return self.slow.mksuffix(name, i)
626
627 def axi_reg_def(self, start, count):
628 if not self.slow:
629 return ('', 0)
630 return self.slow.axi_reg_def(start, self.ifacename, count)
631
632 def axi_master_idx(self, start, count, typ):
633 if not self.slow or not self.slow.has_axi_master():
634 return ('', 0)
635 return self.slow.axi_master_idx(start, self.ifacename, count, typ)
636
637 def axi_slave_idx(self, start, count, typ):
638 if not self.slow:
639 return ('', 0)
640 return self.slow.axi_slave_idx(start, self.ifacename, count, typ)
641
642 def axi_fastaddr_map(self, count):
643 if not self.slow:
644 return ''
645 return self.slow.axi_fastaddr_map(self.ifacename, count)
646
647 def axi_addr_map(self, count):
648 if not self.slow:
649 return ''
650 return self.slow.axi_addr_map(self.ifacename, count)
651
652
653 class PeripheralInterfaces(object):
654 def __init__(self):
655 self.fastbusmode = False
656
657 def slowimport(self, *args):
658 ret = []
659 for (name, count) in self.ifacecount:
660 #print "slowimport", name, self.data[name].slowimport
661 ret.append(self.data[name].slowimport())
662 return '\n'.join(li(list(filter(None, ret)), 4))
663
664 def extfastifinstance(self, *args):
665 ret = []
666 for (name, count) in self.ifacecount:
667 for i in range(count):
668 if self.is_on_fastbus(name, i):
669 continue
670 ret.append(self.data[name].extfastifinstance(name, i))
671 return '\n'.join(li(list(filter(None, ret)), 8))
672
673 def extifinstance2(self, *args):
674 ret = []
675 for (name, count) in self.ifacecount:
676 for i in range(count):
677 ret.append(self.data[name].extifinstance2(name, i))
678 return '\n'.join(li(list(filter(None, ret)), 8))
679
680 def extifinstance(self, *args):
681 ret = []
682 for (name, count) in self.ifacecount:
683 for i in range(count):
684 if not self.is_on_fastbus(name, i):
685 continue
686 ret.append(self.data[name].extifinstance(name, i))
687 return '\n'.join(li(list(filter(None, ret)), 8))
688
689 def extifdecl(self, *args):
690 ret = []
691 for (name, count) in self.ifacecount:
692 for i in range(count):
693 if not self.is_on_fastbus(name, i):
694 continue
695 ret.append(self.data[name].extifdecl(name, i))
696 return '\n'.join(li(list(filter(None, ret)), 8))
697
698 def slowifdeclmux(self, *args):
699 ret = []
700 for (name, count) in self.ifacecount:
701 for i in range(count):
702 ret.append(self.data[name].slowifdeclmux(name, i))
703 return '\n'.join(li(list(filter(None, ret)), 8))
704
705 def fastifdecl(self, *args):
706 ret = []
707 for (name, count) in self.ifacecount:
708 for i in range(count):
709 print "fastifdecl", name, i, self.is_on_fastbus(name, i)
710 if self.is_on_fastbus(name, i):
711 continue
712 ret.append(self.data[name].fastifdecl(name, i))
713 return '\n'.join(li(list(filter(None, ret)), 4))
714
715 def slowifdecl(self, *args):
716 ret = []
717 for (name, count) in self.ifacecount:
718 for i in range(count):
719 if self.is_on_fastbus(name, i):
720 continue
721 ret.append(self.data[name].slowifdecl().format(i, name))
722 return '\n'.join(list(filter(None, ret)))
723
724 def axi_fastmem_def(self, *args):
725 return self._axi_reg_def(0x50000000, *args)
726
727 def axi_reg_def(self, *args):
728 return self._axi_reg_def(0x00011100, *args)
729
730 def _axi_reg_def(self, start, *args):
731 ret = []
732 for (name, count) in self.ifacecount:
733 for i in range(count):
734 if self.is_on_fastbus(name, i):
735 continue
736 x = self.data[name].axi_reg_def(start, i)
737 #print ("ifc", name, x)
738 (rdef, offs) = x
739 ret.append(rdef)
740 start += offs
741 return '\n'.join(list(filter(None, ret)))
742
743 def _axi_num_idx(self, start, template, typ, idxtype, *args):
744 ret = []
745 for (name, count) in self.ifacecount:
746 for i in range(count):
747 if self.is_on_fastbus(name, i):
748 continue
749 if typ == 'master':
750 fn = self.data[name].axi_master_idx
751 else:
752 fn = self.data[name].axi_slave_idx
753 (rdef, offs) = fn(start, i, idxtype)
754 #print ("ifc", name, rdef, offs)
755 ret.append(rdef)
756 start += offs
757 ret.append("typedef %d LastGen_%s_num;" % (start - 1, typ))
758 decls = '\n'.join(list(filter(None, ret)))
759 return template.format(decls)
760
761 def axi_slave_idx(self, *args):
762 return self._axi_num_idx(0, axi_slave_declarations, 'slave',
763 '', *args)
764
765 def axi_fastslave_idx(self, *args):
766 return self._axi_num_idx(0, axi_fastslave_declarations, 'fastslave',
767 'fast', *args)
768
769 def axi_master_idx(self, *args):
770 return self._axi_num_idx(2, axi_master_declarations, 'master',
771 'master', *args)
772
773 def axi_fastslave_idx(self, *args):
774 return self._axi_num_idx(0, axi_fastslave_declarations, 'fastslave',
775 'fast', *args)
776
777 def axi_fastaddr_map(self, *args):
778 ret = []
779 for (name, count) in self.ifacecount:
780 for i in range(count):
781 if self.is_on_fastbus(name, i):
782 continue
783 ret.append(self.data[name].axi_fastaddr_map(i))
784 return '\n'.join(li(list(filter(None, ret)), 8))
785
786 def axi_addr_map(self, *args):
787 ret = []
788 for (name, count) in self.ifacecount:
789 for i in range(count):
790 if self.is_on_fastbus(name, i):
791 continue
792 ret.append(self.data[name].axi_addr_map(i))
793 return '\n'.join(li(list(filter(None, ret)), 8))
794
795 def mkfast_peripheral(self, *args):
796 ret = []
797 for (name, count) in self.ifacecount:
798 for i in range(count):
799 if self.is_on_fastbus(name, i):
800 continue
801 #print "mkfast", name, count
802 x = self.data[name].mkfast_peripheral()
803 print name, count, x
804 suffix = self.data[name].mksuffix(name, i)
805 ret.append(x.format(suffix))
806 return '\n'.join(li(list(filter(None, ret)), 8))
807
808 def mkslow_peripheral(self, *args):
809 ret = []
810 for (name, count) in self.ifacecount:
811 for i in range(count):
812 if self.is_on_fastbus(name, i):
813 continue
814 #print "mkslow", name, count
815 x = self.data[name].mkslow_peripheral()
816 print name, count, x
817 suffix = self.data[name].mksuffix(name, i)
818 ret.append(x.format(suffix))
819 return '\n'.join(li(list(filter(None, ret)), 8))
820
821 def _mk_connection(self, fabric, typ, indent, master, *args):
822 ret = []
823 for (name, count) in self.ifacecount:
824 ret += list(MkConnection(self, name, count,
825 fabric, typ, master, *args))
826 return '\n'.join(li(list(filter(None, ret)), indent))
827
828 def mk_master_connection(self, *args):
829 return self._mk_connection("fabric", "fast", 8, True, *args)
830
831 def mk_fast_connection(self, *args):
832 return self._mk_connection("fabric", "fast", 12, False, *args)
833
834 def mk_connection(self, *args):
835 return self._mk_connection("slow_fabric", "", 8, False, *args)
836
837 def mk_cellconn(self):
838 ret = []
839 cellcount = 0
840 for (name, count) in self.ifacecount:
841 for i in range(count):
842 if self.is_on_fastbus(name, i):
843 continue
844 res = self.data[name].mk_cellconn(name, i, cellcount)
845 if not res:
846 continue
847 (txt, cellcount) = res
848 ret.append(txt)
849 ret = li('\n'.join(list(filter(None, ret))), 4)
850 return li(pinmux_cellrule.format(ret), 4)
851
852 def mk_pincon(self):
853 return self._mk_pincon("slow")
854
855 def mk_fast_pincon(self):
856 return self._mk_pincon("fast")
857
858 def _mk_pincon(self, typ):
859 ret = []
860 for (name, count) in self.ifacecount:
861 ret += list(MkPinCon(self, name, count, typ))
862 return '\n'.join(li(list(ret), 4))
863
864 def mk_dma_irq(self):
865 ret = []
866 sync = []
867 rules = []
868 cnct = []
869
870 self.dma_count = 0
871
872 for (name, count) in self.ifacecount:
873 ifacerules = []
874 for i in range(count):
875 if not self.is_on_fastbus(name, i):
876 continue
877 txt = self.data[name].mk_dma_sync(name, i)
878 if txt:
879 self.dma_count += 1
880 sync.append(txt)
881 txt = self.data[name].mk_dma_rule(name, i)
882 ifacerules.append(txt)
883 txt = self.data[name].mk_dma_connect(name, i)
884 cnct.append(txt)
885 ifacerules = list(filter(None, ifacerules))
886 if ifacerules:
887 txt = "rule synchronize_%s_interrupts;" % name
888 rules.append(txt)
889 rules += ifacerules
890 rules.append("endrule")
891
892 cnct = list(filter(None, cnct))
893 ct = self.dma_count
894 _cnct = ["rule rl_connect_interrupt_to_DMA;",
895 " Bit #(%d) lv_interrupt_to_DMA={" % ct]
896 spc = " "
897 spcsep = ",\n" + spc
898 cnct = _cnct + [spc + spcsep.join(cnct)]
899 cnct.append(" };")
900 cnct.append(" dma.interrupt_from_peripherals(\n" +
901 " lv_interrupt_to_DMA);")
902 cnct.append("endrule;")
903
904 ret = list(filter(None, sync + rules + cnct))
905 ret = li(ret, 15)
906 return '\n'.join(ret)
907
908 def num_dmachannels(self):
909 return "`define NUM_DMACHANNELS {0}".format(self.dma_count)
910
911 def mk_ext_ifacedef(self):
912 ret = []
913 for (name, count) in self.ifacecount:
914 ret += list(MkExtIface(self, name, count))
915 return '\n'.join(li(list(filter(None, ret)), 8))
916
917 def mk_plic(self):
918 ret = []
919 irq_offs = 8 # XXX: DMA scovers 0-7?
920 for (name, count) in self.ifacecount:
921 for i in range(count):
922 if self.is_on_fastbus(name, i):
923 continue
924 res = self.data[name].mk_plic(i, irq_offs)
925 if not res:
926 continue
927 (txt, irq_offs) = res
928 ret.append(txt)
929 self.num_slow_irqs = irq_offs
930 return '\n'.join(li(list(filter(None, ret)), 4))
931
932 def mk_sloirqsdef(self):
933 return " `define NUM_SLOW_IRQS {0}".format(self.num_slow_irqs)
934
935 def mk_fastclk_con(self):
936 return self._mk_clk_con("fast")
937
938 def mk_slowclk_con(self):
939 return self._mk_clk_con("slow")
940
941 def _mk_clk_con(self, ctype):
942 ret = []
943 for (name, count) in self.ifacecount:
944 ret += list(MkClkCon(self, name, count, ctype))
945 return '\n'.join(li(list(filter(None, ret)), 8))
946
947 def is_on_fastbus(self, name, i):
948 #print "fastbus mode", self.fastbusmode, name, i
949 iname = self.data[name].iname().format(i)
950 if self.fastbusmode:
951 return iname not in self.fastbus
952 return iname in self.fastbus
953
954
955 class IfaceIter(object):
956
957 def __init__(self, name, count, *args):
958 self.i = 0
959 self.name = name
960 self.maxcount = count
961 self.args = args
962
963 def __iter__(self):
964 return self
965
966 def __next__(self):
967 while True:
968 if self.i >= self.maxcount:
969 raise StopIteration
970 if self.check(self.name, self.i):
971 #print self.item, self.args
972 res = self.item(self.name, self.i, *self.args)
973 if res:
974 self.i += 1
975 return res
976 self.i += 1
977
978 def next(self):
979 return self.__next__()
980
981 class MkConnection(IfaceIter):
982
983 def __init__(self, ifaces, name, count, *args):
984 self.ifaces = ifaces
985 IfaceIter.__init__(self, name, count, *args)
986
987 def check(self, name, i):
988 return not self.ifaces.is_on_fastbus(name, i)
989
990 def item(self, name, i, fabric, typ, master):
991 if master:
992 return self.ifaces.data[name].mk_master_connection(name,
993 i, fabric, typ)
994 return self.ifaces.data[name].mk_connection(name, i, fabric, typ)
995
996 class MkExtIface(IfaceIter):
997
998 def __init__(self, ifaces, name, count, *args):
999 self.ifaces = ifaces
1000 IfaceIter.__init__(self, name, count, *args)
1001
1002 def check(self, name, i):
1003 return not self.ifaces.is_on_fastbus(name, i)
1004
1005 def item(self, name, i):
1006 return self.ifaces.data[name].mk_ext_ifacedef(name, i)
1007
1008
1009 class MkPinCon(IfaceIter):
1010
1011 def __init__(self, ifaces, name, count, *args):
1012 self.ifaces = ifaces
1013 IfaceIter.__init__(self, name, count, *args)
1014
1015 def check(self, name, i):
1016 return not self.ifaces.is_on_fastbus(name, i)
1017
1018 def item(self, name, i, typ):
1019 return self.ifaces.data[name]._mk_pincon(name, i, typ)
1020
1021
1022 class MkClkCon(IfaceIter):
1023
1024 def __init__(self, ifaces, name, count, *args):
1025 self.ifaces = ifaces
1026 IfaceIter.__init__(self, name, count, *args)
1027
1028 def check(self, name, i):
1029 return not self.ifaces.is_on_fastbus(name, i)
1030
1031 def item(self, name, i, ctype):
1032 return self.ifaces.data[name]._mk_clk_con(name, i, ctype)
1033
1034
1035 class PFactory(object):
1036 def getcls(self, name):
1037 from uart import uart
1038 from quart import quart
1039 from sdmmc import sdmmc
1040 from emmc import emmc
1041 from pwm import pwm
1042 from eint import eint
1043 from rs232 import rs232
1044 from twi import twi
1045 from eint import eint
1046 from jtag import jtag
1047 from spi import spi, mspi
1048 from qspi import qspi, mqspi
1049 from gpio import gpio
1050 from rgbttl import rgbttl
1051 from flexbus import flexbus
1052 from sdram import sdram
1053
1054 for k, v in {'uart': uart,
1055 'rs232': rs232,
1056 'twi': twi,
1057 'sdr': sdram,
1058 'quart': quart,
1059 'mqspi': mqspi,
1060 'mspi': mspi,
1061 'qspi': qspi,
1062 'spi': spi,
1063 'pwm': pwm,
1064 'eint': eint,
1065 'mmc': sdmmc,
1066 'emmc': emmc,
1067 'jtag': jtag,
1068 'lcd': rgbttl,
1069 'fb': flexbus,
1070 'gpio': gpio
1071 }.items():
1072 if name.startswith(k):
1073 return v
1074 return None
1075
1076
1077 slowfactory = PFactory()
1078
1079 if __name__ == '__main__':
1080 p = uart('uart')
1081 print p.slowimport()
1082 print p.slowifdecl()
1083 i = PeripheralIface('uart')
1084 print i, i.slow
1085 i = PeripheralIface('gpioa')
1086 print i, i.slow