ac508c47717d2304866f28314131f52767aa404c
[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 CallIfaceFn(object):
654 def __init__(self, ifaces, kls, indent):
655 self.ifaces = ifaces
656 self.kls = kls
657 self.indent = indent
658
659 def __call__(self, ifaces, *args):
660 ret = []
661 for (name, count) in self.ifaces.ifacecount:
662 print "CallIfaceFn", self.kls, self.ifaces
663 print "CallIfaceFn args", name, count, args
664 ret += list(self.kls(self.ifaces, name, count, *args))
665 return '\n'.join(li(list(filter(None, ret)), self.indent))
666
667
668 class PeripheralInterfaces(object):
669 def __init__(self):
670 self.fastbusmode = False
671
672 for (fname, kls, indent) in (
673 ('_mk_connection', MkConnection, 8),
674 ('_mk_pincon', MkPinCon, 4),
675 ('_mk_clk_con', MkClkCon, 8),
676 ('mk_ext_ifacedef', MkExtIface, 8),
677 ):
678 fn = CallIfaceFn(self, kls, indent)
679 setattr(self, fname, types.MethodType(fn, self))
680
681 def slowimport(self, *args):
682 ret = []
683 for (name, count) in self.ifacecount:
684 #print "slowimport", name, self.data[name].slowimport
685 ret.append(self.data[name].slowimport())
686 return '\n'.join(li(list(filter(None, ret)), 4))
687
688 def extfastifinstance(self, *args):
689 ret = []
690 for (name, count) in self.ifacecount:
691 for i in range(count):
692 if self.is_on_fastbus(name, i):
693 continue
694 ret.append(self.data[name].extfastifinstance(name, i))
695 return '\n'.join(li(list(filter(None, ret)), 8))
696
697 def extifinstance2(self, *args):
698 ret = []
699 for (name, count) in self.ifacecount:
700 for i in range(count):
701 ret.append(self.data[name].extifinstance2(name, i))
702 return '\n'.join(li(list(filter(None, ret)), 8))
703
704 def extifinstance(self, *args):
705 ret = []
706 for (name, count) in self.ifacecount:
707 for i in range(count):
708 if not self.is_on_fastbus(name, i):
709 continue
710 ret.append(self.data[name].extifinstance(name, i))
711 return '\n'.join(li(list(filter(None, ret)), 8))
712
713 def extifdecl(self, *args):
714 ret = []
715 for (name, count) in self.ifacecount:
716 for i in range(count):
717 if not self.is_on_fastbus(name, i):
718 continue
719 ret.append(self.data[name].extifdecl(name, i))
720 return '\n'.join(li(list(filter(None, ret)), 8))
721
722 def slowifdeclmux(self, *args):
723 ret = []
724 for (name, count) in self.ifacecount:
725 for i in range(count):
726 ret.append(self.data[name].slowifdeclmux(name, i))
727 return '\n'.join(li(list(filter(None, ret)), 8))
728
729 def fastifdecl(self, *args):
730 ret = []
731 for (name, count) in self.ifacecount:
732 for i in range(count):
733 print "fastifdecl", name, i, self.is_on_fastbus(name, i)
734 if self.is_on_fastbus(name, i):
735 continue
736 ret.append(self.data[name].fastifdecl(name, i))
737 return '\n'.join(li(list(filter(None, ret)), 4))
738
739 def slowifdecl(self, *args):
740 ret = []
741 for (name, count) in self.ifacecount:
742 for i in range(count):
743 if self.is_on_fastbus(name, i):
744 continue
745 ret.append(self.data[name].slowifdecl().format(i, name))
746 return '\n'.join(list(filter(None, ret)))
747
748 def axi_fastmem_def(self, *args):
749 return self._axi_reg_def(0x50000000, *args)
750
751 def axi_reg_def(self, *args):
752 return self._axi_reg_def(0x00011100, *args)
753
754 def _axi_reg_def(self, start, *args):
755 ret = []
756 for (name, count) in self.ifacecount:
757 for i in range(count):
758 if self.is_on_fastbus(name, i):
759 continue
760 x = self.data[name].axi_reg_def(start, i)
761 #print ("ifc", name, x)
762 (rdef, offs) = x
763 ret.append(rdef)
764 start += offs
765 return '\n'.join(list(filter(None, ret)))
766
767 def _axi_num_idx(self, start, template, typ, idxtype, *args):
768 ret = []
769 for (name, count) in self.ifacecount:
770 for i in range(count):
771 if self.is_on_fastbus(name, i):
772 continue
773 if typ == 'master':
774 fn = self.data[name].axi_master_idx
775 else:
776 fn = self.data[name].axi_slave_idx
777 (rdef, offs) = fn(start, i, idxtype)
778 #print ("ifc", name, rdef, offs)
779 ret.append(rdef)
780 start += offs
781 ret.append("typedef %d LastGen_%s_num;" % (start - 1, typ))
782 decls = '\n'.join(list(filter(None, ret)))
783 return template.format(decls)
784
785 def axi_slave_idx(self, *args):
786 return self._axi_num_idx(0, axi_slave_declarations, 'slave',
787 '', *args)
788
789 def axi_fastslave_idx(self, *args):
790 return self._axi_num_idx(0, axi_fastslave_declarations, 'fastslave',
791 'fast', *args)
792
793 def axi_master_idx(self, *args):
794 return self._axi_num_idx(2, axi_master_declarations, 'master',
795 'master', *args)
796
797 def axi_fastslave_idx(self, *args):
798 return self._axi_num_idx(0, axi_fastslave_declarations, 'fastslave',
799 'fast', *args)
800
801 def axi_fastaddr_map(self, *args):
802 ret = []
803 for (name, count) in self.ifacecount:
804 for i in range(count):
805 if self.is_on_fastbus(name, i):
806 continue
807 ret.append(self.data[name].axi_fastaddr_map(i))
808 return '\n'.join(li(list(filter(None, ret)), 8))
809
810 def axi_addr_map(self, *args):
811 ret = []
812 for (name, count) in self.ifacecount:
813 for i in range(count):
814 if self.is_on_fastbus(name, i):
815 continue
816 ret.append(self.data[name].axi_addr_map(i))
817 return '\n'.join(li(list(filter(None, ret)), 8))
818
819 def mkfast_peripheral(self, *args):
820 ret = []
821 for (name, count) in self.ifacecount:
822 for i in range(count):
823 if self.is_on_fastbus(name, i):
824 continue
825 #print "mkfast", name, count
826 x = self.data[name].mkfast_peripheral()
827 print name, count, x
828 suffix = self.data[name].mksuffix(name, i)
829 ret.append(x.format(suffix))
830 return '\n'.join(li(list(filter(None, ret)), 8))
831
832 def mkslow_peripheral(self, *args):
833 ret = []
834 for (name, count) in self.ifacecount:
835 for i in range(count):
836 if self.is_on_fastbus(name, i):
837 continue
838 #print "mkslow", name, count
839 x = self.data[name].mkslow_peripheral()
840 print name, count, x
841 suffix = self.data[name].mksuffix(name, i)
842 ret.append(x.format(suffix))
843 return '\n'.join(li(list(filter(None, ret)), 8))
844
845 def mk_master_connection(self, *args):
846 return self._mk_connection("fabric", "fast", True, *args)
847
848 def mk_fast_connection(self, *args):
849 return self._mk_connection("fabric", "fast", False, *args)
850
851 def mk_connection(self, *args):
852 return self._mk_connection("slow_fabric", "", False, *args)
853
854 def mk_cellconn(self):
855 ret = []
856 cellcount = 0
857 for (name, count) in self.ifacecount:
858 for i in range(count):
859 if self.is_on_fastbus(name, i):
860 continue
861 res = self.data[name].mk_cellconn(name, i, cellcount)
862 if not res:
863 continue
864 (txt, cellcount) = res
865 ret.append(txt)
866 ret = li('\n'.join(list(filter(None, ret))), 4)
867 return li(pinmux_cellrule.format(ret), 4)
868
869 def mk_pincon(self):
870 return self._mk_pincon("slow")
871
872 def mk_fast_pincon(self):
873 return self._mk_pincon("fast")
874
875 def mk_dma_irq(self):
876 ret = []
877 sync = []
878 rules = []
879 cnct = []
880
881 self.dma_count = 0
882
883 for (name, count) in self.ifacecount:
884 ifacerules = []
885 for i in range(count):
886 if not self.is_on_fastbus(name, i):
887 continue
888 txt = self.data[name].mk_dma_sync(name, i)
889 if txt:
890 self.dma_count += 1
891 sync.append(txt)
892 txt = self.data[name].mk_dma_rule(name, i)
893 ifacerules.append(txt)
894 txt = self.data[name].mk_dma_connect(name, i)
895 cnct.append(txt)
896 ifacerules = list(filter(None, ifacerules))
897 if ifacerules:
898 txt = "rule synchronize_%s_interrupts;" % name
899 rules.append(txt)
900 rules += ifacerules
901 rules.append("endrule")
902
903 cnct = list(filter(None, cnct))
904 ct = self.dma_count
905 _cnct = ["rule rl_connect_interrupt_to_DMA;",
906 " Bit #(%d) lv_interrupt_to_DMA={" % ct]
907 spc = " "
908 spcsep = ",\n" + spc
909 cnct = _cnct + [spc + spcsep.join(cnct)]
910 cnct.append(" };")
911 cnct.append(" dma.interrupt_from_peripherals(\n" +
912 " lv_interrupt_to_DMA);")
913 cnct.append("endrule;")
914
915 ret = list(filter(None, sync + rules + cnct))
916 ret = li(ret, 15)
917 return '\n'.join(ret)
918
919 def num_dmachannels(self):
920 return "`define NUM_DMACHANNELS {0}".format(self.dma_count)
921
922 def mk_plic(self):
923 ret = []
924 irq_offs = 8 # XXX: DMA scovers 0-7?
925 for (name, count) in self.ifacecount:
926 for i in range(count):
927 if self.is_on_fastbus(name, i):
928 continue
929 res = self.data[name].mk_plic(i, irq_offs)
930 if not res:
931 continue
932 (txt, irq_offs) = res
933 ret.append(txt)
934 self.num_slow_irqs = irq_offs
935 return '\n'.join(li(list(filter(None, ret)), 4))
936
937 def mk_sloirqsdef(self):
938 return " `define NUM_SLOW_IRQS {0}".format(self.num_slow_irqs)
939
940 def mk_fastclk_con(self):
941 return self._mk_clk_con("fast")
942
943 def mk_slowclk_con(self):
944 return self._mk_clk_con("slow")
945
946 def is_on_fastbus(self, name, i):
947 #print "fastbus mode", self.fastbusmode, name, i
948 iname = self.data[name].iname().format(i)
949 if self.fastbusmode:
950 return iname not in self.fastbus
951 return iname in self.fastbus
952
953
954 class IfaceIter(object):
955
956 def __init__(self, name, count, *args):
957 self.i = 0
958 self.name = name
959 self.maxcount = count
960 self.args = args
961
962 def __iter__(self):
963 return self
964
965 def __next__(self):
966 while True:
967 if self.i >= self.maxcount:
968 raise StopIteration
969 if self.check(self.name, self.i):
970 #print "iter", self.item
971 #print "item args", 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