53b5360b4de126901432f7683add55037ffe7c1b
[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, name, 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, name, 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 ('axi_addr_map', MkAxiAddrMap, 8),
678 ('axi_fastaddr_map', MkAxiFastAddrMap, 8),
679 ):
680 fn = CallIfaceFn(self, kls, indent)
681 setattr(self, fname, types.MethodType(fn, self))
682
683 def slowimport(self, *args):
684 ret = []
685 for (name, count) in self.ifacecount:
686 #print "slowimport", name, self.data[name].slowimport
687 ret.append(self.data[name].slowimport())
688 return '\n'.join(li(list(filter(None, ret)), 4))
689
690 def extfastifinstance(self, *args):
691 ret = []
692 for (name, count) in self.ifacecount:
693 for i in range(count):
694 if self.is_on_fastbus(name, i):
695 continue
696 ret.append(self.data[name].extfastifinstance(name, i))
697 return '\n'.join(li(list(filter(None, ret)), 8))
698
699 def extifinstance2(self, *args):
700 ret = []
701 for (name, count) in self.ifacecount:
702 for i in range(count):
703 ret.append(self.data[name].extifinstance2(name, i))
704 return '\n'.join(li(list(filter(None, ret)), 8))
705
706 def extifinstance(self, *args):
707 ret = []
708 for (name, count) in self.ifacecount:
709 for i in range(count):
710 if not self.is_on_fastbus(name, i):
711 continue
712 ret.append(self.data[name].extifinstance(name, i))
713 return '\n'.join(li(list(filter(None, ret)), 8))
714
715 def extifdecl(self, *args):
716 ret = []
717 for (name, count) in self.ifacecount:
718 for i in range(count):
719 if not self.is_on_fastbus(name, i):
720 continue
721 ret.append(self.data[name].extifdecl(name, i))
722 return '\n'.join(li(list(filter(None, ret)), 8))
723
724 def slowifdeclmux(self, *args):
725 ret = []
726 for (name, count) in self.ifacecount:
727 for i in range(count):
728 ret.append(self.data[name].slowifdeclmux(name, i))
729 return '\n'.join(li(list(filter(None, ret)), 8))
730
731 def fastifdecl(self, *args):
732 ret = []
733 for (name, count) in self.ifacecount:
734 for i in range(count):
735 print "fastifdecl", name, i, self.is_on_fastbus(name, i)
736 if self.is_on_fastbus(name, i):
737 continue
738 ret.append(self.data[name].fastifdecl(name, i))
739 return '\n'.join(li(list(filter(None, ret)), 4))
740
741 def slowifdecl(self, *args):
742 ret = []
743 for (name, count) in self.ifacecount:
744 for i in range(count):
745 if self.is_on_fastbus(name, i):
746 continue
747 ret.append(self.data[name].slowifdecl().format(i, name))
748 return '\n'.join(list(filter(None, ret)))
749
750 def axi_fastmem_def(self, *args):
751 return self._axi_reg_def(0x50000000, *args)
752
753 def axi_reg_def(self, *args):
754 return self._axi_reg_def(0x00011100, *args)
755
756 def _axi_reg_def(self, start, *args):
757 ret = []
758 for (name, count) in self.ifacecount:
759 for i in range(count):
760 if self.is_on_fastbus(name, i):
761 continue
762 x = self.data[name].axi_reg_def(start, i)
763 #print ("ifc", name, x)
764 (rdef, offs) = x
765 ret.append(rdef)
766 start += offs
767 return '\n'.join(list(filter(None, ret)))
768
769 def _axi_num_idx(self, start, template, typ, idxtype, *args):
770 ret = []
771 for (name, count) in self.ifacecount:
772 for i in range(count):
773 if self.is_on_fastbus(name, i):
774 continue
775 if typ == 'master':
776 fn = self.data[name].axi_master_idx
777 else:
778 fn = self.data[name].axi_slave_idx
779 (rdef, offs) = fn(start, i, idxtype)
780 #print ("ifc", name, rdef, offs)
781 ret.append(rdef)
782 start += offs
783 ret.append("typedef %d LastGen_%s_num;" % (start - 1, typ))
784 decls = '\n'.join(list(filter(None, ret)))
785 return template.format(decls)
786
787 def axi_slave_idx(self, *args):
788 return self._axi_num_idx(0, axi_slave_declarations, 'slave',
789 '', *args)
790
791 def axi_fastslave_idx(self, *args):
792 return self._axi_num_idx(0, axi_fastslave_declarations, 'fastslave',
793 'fast', *args)
794
795 def axi_master_idx(self, *args):
796 return self._axi_num_idx(2, axi_master_declarations, 'master',
797 'master', *args)
798
799 def axi_fastslave_idx(self, *args):
800 return self._axi_num_idx(0, axi_fastslave_declarations, 'fastslave',
801 'fast', *args)
802
803 def mkfast_peripheral(self, *args):
804 ret = []
805 for (name, count) in self.ifacecount:
806 for i in range(count):
807 if self.is_on_fastbus(name, i):
808 continue
809 #print "mkfast", name, count
810 x = self.data[name].mkfast_peripheral()
811 print name, count, x
812 suffix = self.data[name].mksuffix(name, i)
813 ret.append(x.format(suffix))
814 return '\n'.join(li(list(filter(None, ret)), 8))
815
816 def mkslow_peripheral(self, *args):
817 ret = []
818 for (name, count) in self.ifacecount:
819 for i in range(count):
820 if self.is_on_fastbus(name, i):
821 continue
822 #print "mkslow", name, count
823 x = self.data[name].mkslow_peripheral()
824 print name, count, x
825 suffix = self.data[name].mksuffix(name, i)
826 ret.append(x.format(suffix))
827 return '\n'.join(li(list(filter(None, ret)), 8))
828
829 def mk_master_connection(self, *args):
830 return self._mk_connection("fabric", "fast", True, *args)
831
832 def mk_fast_connection(self, *args):
833 return self._mk_connection("fabric", "fast", False, *args)
834
835 def mk_connection(self, *args):
836 return self._mk_connection("slow_fabric", "", False, *args)
837
838 def mk_cellconn(self):
839 ret = []
840 cellcount = 0
841 for (name, count) in self.ifacecount:
842 for i in range(count):
843 if self.is_on_fastbus(name, i):
844 continue
845 res = self.data[name].mk_cellconn(name, i, cellcount)
846 if not res:
847 continue
848 (txt, cellcount) = res
849 ret.append(txt)
850 ret = li('\n'.join(list(filter(None, ret))), 4)
851 return li(pinmux_cellrule.format(ret), 4)
852
853 def mk_pincon(self):
854 return self._mk_pincon("slow")
855
856 def mk_fast_pincon(self):
857 return self._mk_pincon("fast")
858
859 def mk_dma_irq(self):
860 ret = []
861 sync = []
862 rules = []
863 cnct = []
864
865 self.dma_count = 0
866
867 for (name, count) in self.ifacecount:
868 ifacerules = []
869 for i in range(count):
870 if not self.is_on_fastbus(name, i):
871 continue
872 txt = self.data[name].mk_dma_sync(name, i)
873 if txt:
874 self.dma_count += 1
875 sync.append(txt)
876 txt = self.data[name].mk_dma_rule(name, i)
877 ifacerules.append(txt)
878 txt = self.data[name].mk_dma_connect(name, i)
879 cnct.append(txt)
880 ifacerules = list(filter(None, ifacerules))
881 if ifacerules:
882 txt = "rule synchronize_%s_interrupts;" % name
883 rules.append(txt)
884 rules += ifacerules
885 rules.append("endrule")
886
887 cnct = list(filter(None, cnct))
888 ct = self.dma_count
889 _cnct = ["rule rl_connect_interrupt_to_DMA;",
890 " Bit #(%d) lv_interrupt_to_DMA={" % ct]
891 spc = " "
892 spcsep = ",\n" + spc
893 cnct = _cnct + [spc + spcsep.join(cnct)]
894 cnct.append(" };")
895 cnct.append(" dma.interrupt_from_peripherals(\n" +
896 " lv_interrupt_to_DMA);")
897 cnct.append("endrule;")
898
899 ret = list(filter(None, sync + rules + cnct))
900 ret = li(ret, 15)
901 return '\n'.join(ret)
902
903 def num_dmachannels(self):
904 return "`define NUM_DMACHANNELS {0}".format(self.dma_count)
905
906 def mk_plic(self):
907 ret = []
908 irq_offs = 8 # XXX: DMA scovers 0-7?
909 for (name, count) in self.ifacecount:
910 for i in range(count):
911 if self.is_on_fastbus(name, i):
912 continue
913 res = self.data[name].mk_plic(i, irq_offs)
914 if not res:
915 continue
916 (txt, irq_offs) = res
917 ret.append(txt)
918 self.num_slow_irqs = irq_offs
919 return '\n'.join(li(list(filter(None, ret)), 4))
920
921 def mk_sloirqsdef(self):
922 return " `define NUM_SLOW_IRQS {0}".format(self.num_slow_irqs)
923
924 def mk_fastclk_con(self):
925 return self._mk_clk_con("fast")
926
927 def mk_slowclk_con(self):
928 return self._mk_clk_con("slow")
929
930 def is_on_fastbus(self, name, i):
931 #print "fastbus mode", self.fastbusmode, name, i
932 iname = self.data[name].iname().format(i)
933 if self.fastbusmode:
934 return iname not in self.fastbus
935 return iname in self.fastbus
936
937
938 class IfaceIter(object):
939
940 def __init__(self, ifaces, name, count, *args):
941 self.ifaces = ifaces
942 self.i = 0
943 self.name = name
944 self.maxcount = count
945 self.args = args
946
947 def __iter__(self):
948 return self
949
950 def __next__(self):
951 while True:
952 if self.i >= self.maxcount:
953 raise StopIteration
954 if self.check(self.name, self.i):
955 #print "iter", self.item
956 #print "item args", self.args
957 res = self.item(self.name, self.i, *self.args)
958 if res:
959 self.i += 1
960 return res
961 self.i += 1
962
963 def next(self):
964 return self.__next__()
965
966
967 class MkAxiFastAddrMap(IfaceIter):
968
969 def check(self, name, i):
970 return not self.ifaces.is_on_fastbus(name, i)
971
972 def item(self, name, i):
973 return self.ifaces.data[name].axi_fastaddr_map(name, i)
974
975
976 class MkAxiAddrMap(IfaceIter):
977
978 def check(self, name, i):
979 return not self.ifaces.is_on_fastbus(name, i)
980
981 def item(self, name, i):
982 return self.ifaces.data[name].axi_addr_map(name, i)
983
984
985 class MkConnection(IfaceIter):
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
997 class MkExtIface(IfaceIter):
998
999 def check(self, name, i):
1000 return not self.ifaces.is_on_fastbus(name, i)
1001
1002 def item(self, name, i):
1003 return self.ifaces.data[name].mk_ext_ifacedef(name, i)
1004
1005
1006 class MkPinCon(IfaceIter):
1007
1008 def check(self, name, i):
1009 return not self.ifaces.is_on_fastbus(name, i)
1010
1011 def item(self, name, i, typ):
1012 return self.ifaces.data[name]._mk_pincon(name, i, typ)
1013
1014
1015 class MkClkCon(IfaceIter):
1016
1017 def check(self, name, i):
1018 return not self.ifaces.is_on_fastbus(name, i)
1019
1020 def item(self, name, i, ctype):
1021 return self.ifaces.data[name]._mk_clk_con(name, i, ctype)
1022
1023
1024 class PFactory(object):
1025 def getcls(self, name):
1026 from uart import uart
1027 from quart import quart
1028 from sdmmc import sdmmc
1029 from emmc import emmc
1030 from pwm import pwm
1031 from eint import eint
1032 from rs232 import rs232
1033 from twi import twi
1034 from eint import eint
1035 from jtag import jtag
1036 from spi import spi, mspi
1037 from qspi import qspi, mqspi
1038 from gpio import gpio
1039 from rgbttl import rgbttl
1040 from flexbus import flexbus
1041 from sdram import sdram
1042
1043 for k, v in {'uart': uart,
1044 'rs232': rs232,
1045 'twi': twi,
1046 'sdr': sdram,
1047 'quart': quart,
1048 'mqspi': mqspi,
1049 'mspi': mspi,
1050 'qspi': qspi,
1051 'spi': spi,
1052 'pwm': pwm,
1053 'eint': eint,
1054 'mmc': sdmmc,
1055 'emmc': emmc,
1056 'jtag': jtag,
1057 'lcd': rgbttl,
1058 'fb': flexbus,
1059 'gpio': gpio
1060 }.items():
1061 if name.startswith(k):
1062 return v
1063 return None
1064
1065
1066 slowfactory = PFactory()
1067
1068 if __name__ == '__main__':
1069 p = uart('uart')
1070 print p.slowimport()
1071 print p.slowifdecl()
1072 i = PeripheralIface('uart')
1073 print i, i.slow
1074 i = PeripheralIface('gpioa')
1075 print i, i.slow