e6f9a53f84219c9a8513f59dabdea874aa2ce87d
[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 = """\
351 Ifc_sync#({0}) {1}_sync <-mksyncconnection(
352 {2}, {3});"""
353 for p in self.peripheral.pinspecs:
354 typ = p['type']
355 pname = p['name']
356 n = name
357 if typ == 'out' or typ == 'inout':
358 fname = self.pinname_out(pname)
359 if not fname:
360 continue
361 if not n.startswith('gpio'): # XXX EURGH! horrible hack
362 n_ = "{0}{1}".format(n, count)
363 else:
364 n_ = n
365 n_ = '{0}_{1}'.format(n_, pname)
366 ret.append(template.format("Bit#(1)", n_, ck, spc))
367 if typ == 'in' or typ == 'inout':
368 fname = self.pinname_in(pname)
369 if not fname:
370 continue
371 #fname = self.pinname_in(pname)
372 n_ = "{0}{1}".format(n, count)
373 n_ = '{0}_{1}'.format(n_, pname)
374 #n_ = self.ifname_tweak(pname, 'in', n_)
375 ret.append(template.format("Bit#(1)", n_, spc, ck))
376 return '\n'.join(ret)
377
378 def get_clk_spc(self, ctype):
379 if ctype == 'slow':
380 return "sp_clock, sp_reset"
381 else:
382 return "core_clock, core_reset"
383
384 def _mk_clk_vcon(self, name, count, ctype, typ, pname, bitspec):
385 ck = self.get_clock_reset(name, count)
386 if ck == PBase.get_clock_reset(self, name, count):
387 return ''
388 if ctype == 'slow':
389 spc = self.get_clk_spc(ctype)
390 else:
391 spc = ck
392 ck = self.get_clk_spc(ctype)
393 template = """\
394 Ifc_sync#({0}) {1}_sync <-mksyncconnection(
395 {2}, {3});"""
396
397 n_ = "{0}{1}".format(name, count)
398 n_ = '{0}_{1}'.format(n_, pname)
399 if typ == 'in' or typ == 'inout':
400 ck, spc = spc, ck
401 return template.format(bitspec, n_, ck, spc)
402
403 def mk_cellconn(self, *args):
404 return ''
405
406 def mkfast_peripheral(self, size=0):
407 return ''
408
409 def mkslow_peripheral(self, size=0):
410 return ''
411
412 def mksuffix(self, name, i):
413 return i
414
415 def __mk_connection(self, con, aname, count, fabricname):
416 txt = "mkConnection ({2}.v_to_slaves\n" + \
417 " [fromInteger(valueOf({1}))],\n" + \
418 " {0});"
419
420 print "PBase __mk_connection", self.name, aname
421 if not con:
422 return ''
423 con = con.format(count, aname)
424 return txt.format(con, aname, fabricname)
425
426 def __mk_master_connection(self, con, aname, count, fabricname):
427 txt = "mkConnection ({0}, {2}.v_from_masters\n" + \
428 " [fromInteger(valueOf({1}))]);\n"
429
430 print "PBase __mk_master_connection", self.name, aname
431 if not con:
432 return ''
433 con = con.format(count, aname)
434 return txt.format(con, aname, fabricname)
435
436 def mk_master_connection(self, count, fabricname, typ, name=None):
437 if not self.has_axi_master():
438 return ''
439 if name is None:
440 name = self.name
441 print "PBase mk_master_conn", self.name, count
442 aname = self.axi_master_name(name, count, typ)
443 ret = []
444 connections = self._mk_connection(name, count, True)
445 if not isinstance(connections, list):
446 connections = [connections]
447 for con in connections:
448 ret.append(self.__mk_master_connection(con, aname, count,
449 fabricname))
450 return '\n'.join(ret)
451
452 def mk_connection(self, count, fabricname, typ, name=None):
453 if name is None:
454 name = self.name
455 print "PBase mk_conn", self.name, count
456 ret = []
457 connections = self._mk_connection(name, count)
458 if not isinstance(connections, list):
459 connections = [connections]
460 for (idx, con) in enumerate(connections):
461 if len(connections) == 1:
462 idx = ""
463 else:
464 idx = "_%d_" % idx
465 aname = self.axi_slave_name(idx, name, count, typ)
466 ret.append(self.__mk_connection(con, aname, count, fabricname))
467 return '\n'.join(ret)
468
469 def _mk_connection(self, name=None, count=0):
470 return ''
471
472 def pinname_out(self, pname):
473 return ''
474
475 def pinname_in(self, pname):
476 return ''
477
478 def pinname_outen(self, pname):
479 return ''
480
481 def ifname_tweak(self, pname, typ, txt):
482 return txt
483
484 def pinname_tweak(self, pname, typ, txt):
485 return txt
486
487 def num_irqs(self):
488 return 0
489
490 def mk_plic(self, inum, irq_offs):
491 res = []
492 print "mk_plic", self.name, inum, irq_offs
493 niq = self.num_irqs()
494 if niq == 0:
495 return ('', irq_offs)
496 name = self.get_iname(inum)
497 res.append("// PLIC rules for {0}".format(name))
498 for idx in range(niq):
499 plic_obj = self.plic_object(name, idx)
500 print "plic_obj", name, idx, plic_obj
501 plic = mkplic_rule.format(name, plic_obj, irq_offs)
502 res.append(plic)
503 irq_offs += 1 # increment to next irq
504 return ('\n'.join(res), irq_offs)
505
506 def mk_ext_ifacedef(self, iname, inum):
507 return ''
508
509 def extfastifinstance(self, name, count):
510 return ''
511
512 def _extifinstance(self, name, count, suffix, prefix, samename=False,
513 ifsuffix=None):
514 if ifsuffix is None:
515 ifsuffix = ''
516 pname = self.get_iname(count)
517 if samename:
518 sname = pname
519 else:
520 sname = self.peripheral.iname().format(count)
521 template = "interface {0}{3} = {2}{1}{4};"
522 return template.format(pname, sname, prefix, suffix, ifsuffix)
523
524 def extifinstance2(self, name, count):
525 return ''
526
527 def extifinstance(self, name, count):
528 return self._extifinstance(name, count, "",
529 "pinmux.peripheral_side.")
530
531
532 mkplic_rule = """\
533 rule rl_connect_{0}_to_plic_{2};
534 if({1} == 1'b1) begin
535 ff_gateway_queue[{2}].enq(1);
536 plic.ifc_external_irq[{2}].irq_frm_gateway(True);
537 end
538 endrule
539 """
540
541 axi_master_declarations = """\
542 typedef 0 Dmem_master_num;
543 typedef 1 Imem_master_num;
544 {0}
545 typedef TAdd#(LastGen_master_num, `ifdef Debug 1 `else 0 `endif )
546 Debug_master_num;
547 typedef TAdd#(Debug_master_num, `ifdef DMA 1 `else 0 `endif )
548 DMA_master_num;
549 typedef TAdd#(DMA_master_num,1)
550 Num_Masters;
551 """
552
553 axi_fastslave_declarations = """\
554 {0}
555 typedef TAdd#(LastGen_fastslave_num,1) Sdram_slave_num;
556 typedef TAdd#(Sdram_slave_num ,`ifdef SDRAM 1 `else 0 `endif )
557 Sdram_cfg_slave_num;
558 typedef TAdd#(Sdram_cfg_slave_num,`ifdef BOOTROM 1 `else 0 `endif )
559 BootRom_slave_num ;
560 typedef TAdd#(BootRom_slave_num ,`ifdef Debug 1 `else 0 `endif )
561 Debug_slave_num ;
562 typedef TAdd#(Debug_slave_num , `ifdef TCMemory 1 `else 0 `endif )
563 TCM_slave_num;
564 typedef TAdd#(TCM_slave_num ,`ifdef DMA 1 `else 0 `endif )
565 Dma_slave_num;
566 typedef TAdd#(Dma_slave_num ,1 ) SlowPeripheral_slave_num;
567 typedef TAdd#(SlowPeripheral_slave_num,`ifdef VME 1 `else 0 `endif )
568 VME_slave_num;
569 typedef TAdd#(VME_slave_num,1) Num_Fast_Slaves;
570 """
571
572 axi_slave_declarations = """\
573 typedef 0 SlowMaster;
574 {0}
575 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
576 CLINT_slave_num;
577 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
578 Plic_slave_num;
579 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
580 AxiExp1_slave_num;
581 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
582 """
583
584 pinmux_cellrule = """\
585 rule connect_select_lines_pinmux;
586 {0}
587 endrule
588 """
589
590
591 class CallFn(object):
592 def __init__(self, peripheral, name):
593 self.peripheral = peripheral
594 self.name = name
595
596 def __call__(self, *args):
597 #print "__call__", self.name, self.peripheral.slow, args
598 if not self.peripheral.slow:
599 return ''
600 return getattr(self.peripheral.slow, self.name)(*args[1:])
601
602
603 class PeripheralIface(object):
604 def __init__(self, ifacename):
605 self.slow = None
606 slow = slowfactory.getcls(ifacename)
607 print "Iface", ifacename, slow
608 if slow:
609 self.slow = slow(ifacename)
610 self.slow.peripheral = self
611 for fname in ['slowimport',
612 'extfastifinstance',
613 'extifinstance2', 'extifinstance', 'extifdecl',
614 'slowifdecl', 'slowifdeclmux',
615 'fastifdecl',
616 'mkslow_peripheral',
617 'mk_dma_sync', 'mk_dma_connect', 'mk_dma_rule',
618 'mkfast_peripheral',
619 'mk_plic', 'mk_ext_ifacedef',
620 '_mk_clk_con', 'mk_ext_ifacedef',
621 'mk_connection', 'mk_master_connection',
622 'mk_cellconn', '_mk_pincon']:
623 fn = CallFn(self, fname)
624 setattr(self, fname, types.MethodType(fn, self))
625
626 #print "PeripheralIface"
627 #print dir(self)
628
629 def mksuffix(self, name, i):
630 if self.slow is None:
631 return i
632 return self.slow.mksuffix(name, i)
633
634 def axi_reg_def(self, start, count):
635 if not self.slow:
636 return ('', 0)
637 return self.slow.axi_reg_def(start, self.ifacename, count)
638
639 def axi_master_idx(self, start, count, typ):
640 if not self.slow or not self.slow.has_axi_master():
641 return ('', 0)
642 return self.slow.axi_master_idx(start, self.ifacename, count, typ)
643
644 def axi_slave_idx(self, start, count, typ):
645 if not self.slow:
646 return ('', 0)
647 return self.slow.axi_slave_idx(start, self.ifacename, count, typ)
648
649 def axi_fastaddr_map(self, count):
650 if not self.slow:
651 return ''
652 return self.slow.axi_fastaddr_map(self.ifacename, count)
653
654 def axi_addr_map(self, count):
655 if not self.slow:
656 return ''
657 return self.slow.axi_addr_map(self.ifacename, count)
658
659
660 class PeripheralInterfaces(object):
661 def __init__(self):
662 self.fastbusmode = False
663
664 def slowimport(self, *args):
665 ret = []
666 for (name, count) in self.ifacecount:
667 #print "slowimport", name, self.data[name].slowimport
668 ret.append(self.data[name].slowimport())
669 return '\n'.join(li(list(filter(None, ret)), 4))
670
671 def extfastifinstance(self, *args):
672 ret = []
673 for (name, count) in self.ifacecount:
674 for i in range(count):
675 iname = self.data[name].iname().format(i)
676 print "extfast", iname, self.is_on_fastbus(name, i)
677 if self.is_on_fastbus(name, i):
678 continue
679 ret.append(self.data[name].extfastifinstance(name, i))
680 return '\n'.join(li(list(filter(None, ret)), 8))
681
682 def extifinstance2(self, *args):
683 ret = []
684 for (name, count) in self.ifacecount:
685 for i in range(count):
686 iname = self.data[name].iname().format(i)
687 ret.append(self.data[name].extifinstance2(name, i))
688 return '\n'.join(li(list(filter(None, ret)), 8))
689
690 def extifinstance(self, *args):
691 ret = []
692 for (name, count) in self.ifacecount:
693 for i in range(count):
694 iname = self.data[name].iname().format(i)
695 if not self.is_on_fastbus(name, i):
696 continue
697 ret.append(self.data[name].extifinstance(name, i))
698 return '\n'.join(li(list(filter(None, ret)), 8))
699
700 def extifdecl(self, *args):
701 ret = []
702 for (name, count) in self.ifacecount:
703 for i in range(count):
704 if not self.is_on_fastbus(name, i):
705 continue
706 ret.append(self.data[name].extifdecl(name, i))
707 return '\n'.join(li(list(filter(None, ret)), 8))
708
709 def slowifdeclmux(self, *args):
710 ret = []
711 for (name, count) in self.ifacecount:
712 for i in range(count):
713 ret.append(self.data[name].slowifdeclmux(name, i))
714 return '\n'.join(li(list(filter(None, ret)), 8))
715
716 def fastifdecl(self, *args):
717 ret = []
718 for (name, count) in self.ifacecount:
719 for i in range(count):
720 print "fastifdecl", name, i, self.is_on_fastbus(name, i)
721 if self.is_on_fastbus(name, i):
722 continue
723 ret.append(self.data[name].fastifdecl(name, i))
724 return '\n'.join(li(list(filter(None, ret)), 4))
725
726 def slowifdecl(self, *args):
727 ret = []
728 for (name, count) in self.ifacecount:
729 for i in range(count):
730 if self.is_on_fastbus(name, i):
731 continue
732 ret.append(self.data[name].slowifdecl().format(i, name))
733 return '\n'.join(list(filter(None, ret)))
734
735 def axi_fastmem_def(self, *args):
736 return self._axi_reg_def(0x50000000, *args)
737
738 def axi_reg_def(self, *args):
739 return self._axi_reg_def(0x00011100, *args)
740
741 def _axi_reg_def(self, start, *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 x = self.data[name].axi_reg_def(start, i)
748 #print ("ifc", name, x)
749 (rdef, offs) = x
750 ret.append(rdef)
751 start += offs
752 return '\n'.join(list(filter(None, ret)))
753
754 def _axi_num_idx(self, start, template, typ, idxtype, *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 if typ == 'master':
761 fn = self.data[name].axi_master_idx
762 else:
763 fn = self.data[name].axi_slave_idx
764 (rdef, offs) = fn(start, i, idxtype)
765 #print ("ifc", name, rdef, offs)
766 ret.append(rdef)
767 start += offs
768 ret.append("typedef %d LastGen_%s_num;" % (start - 1, typ))
769 decls = '\n'.join(list(filter(None, ret)))
770 return template.format(decls)
771
772 def axi_slave_idx(self, *args):
773 return self._axi_num_idx(0, axi_slave_declarations, 'slave',
774 '', *args)
775
776 def axi_fastslave_idx(self, *args):
777 return self._axi_num_idx(0, axi_fastslave_declarations, 'fastslave',
778 'fast', *args)
779
780 def axi_master_idx(self, *args):
781 return self._axi_num_idx(2, axi_master_declarations, 'master',
782 'master', *args)
783
784 def axi_fastslave_idx(self, *args):
785 return self._axi_num_idx(0, axi_fastslave_declarations, 'fastslave',
786 'fast', *args)
787
788 def axi_fastaddr_map(self, *args):
789 ret = []
790 for (name, count) in self.ifacecount:
791 for i in range(count):
792 if self.is_on_fastbus(name, i):
793 continue
794 ret.append(self.data[name].axi_fastaddr_map(i))
795 return '\n'.join(li(list(filter(None, ret)), 8))
796
797 def axi_addr_map(self, *args):
798 ret = []
799 for (name, count) in self.ifacecount:
800 for i in range(count):
801 if self.is_on_fastbus(name, i):
802 continue
803 ret.append(self.data[name].axi_addr_map(i))
804 return '\n'.join(li(list(filter(None, ret)), 8))
805
806 def mkfast_peripheral(self, *args):
807 ret = []
808 for (name, count) in self.ifacecount:
809 for i in range(count):
810 if self.is_on_fastbus(name, i):
811 continue
812 #print "mkfast", name, count
813 x = self.data[name].mkfast_peripheral()
814 print name, count, x
815 suffix = self.data[name].mksuffix(name, i)
816 ret.append(x.format(suffix))
817 return '\n'.join(li(list(filter(None, ret)), 8))
818
819 def mkslow_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 "mkslow", name, count
826 x = self.data[name].mkslow_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 _mk_connection(self, fabric, typ, indent, master, *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 if master:
839 txt = self.data[name].mk_master_connection(i, fabric, typ)
840 else:
841 txt = self.data[name].mk_connection(i, fabric, typ)
842 if name == 'gpioa':
843 print "txt", txt
844 ret.append(txt)
845 return '\n'.join(li(list(filter(None, ret)), indent))
846
847 def mk_master_connection(self, *args):
848 return self._mk_connection("fabric", "fast", 8, True, *args)
849
850 def mk_fast_connection(self, *args):
851 return self._mk_connection("fabric", "fast", 12, False, *args)
852
853 def mk_connection(self, *args):
854 return self._mk_connection("slow_fabric", "", 8, False, *args)
855
856 def mk_cellconn(self):
857 ret = []
858 cellcount = 0
859 for (name, count) in self.ifacecount:
860 for i in range(count):
861 if self.is_on_fastbus(name, i):
862 continue
863 res = self.data[name].mk_cellconn(cellcount, name, i)
864 if not res:
865 continue
866 (txt, cellcount) = res
867 ret.append(txt)
868 ret = li('\n'.join(list(filter(None, ret))), 4)
869 return li(pinmux_cellrule.format(ret), 4)
870
871 def mk_pincon(self):
872 return self._mk_pincon("slow")
873
874 def mk_fast_pincon(self):
875 return self._mk_pincon("fast")
876
877 def _mk_pincon(self, typ):
878 ret = []
879 for (name, count) in self.ifacecount:
880 for i in range(count):
881 if self.is_on_fastbus(name, i):
882 continue
883 txt = self.data[name]._mk_pincon(name, i, typ)
884 ret.append(txt)
885 return '\n'.join(li(list(filter(None, ret)), 4))
886
887 def mk_dma_irq(self):
888 ret = []
889 sync = []
890 rules = []
891 cnct = []
892
893 self.dma_count = 0
894
895 for (name, count) in self.ifacecount:
896 ifacerules = []
897 for i in range(count):
898 if not self.is_on_fastbus(name, i):
899 continue
900 txt = self.data[name].mk_dma_sync(name, i)
901 if txt:
902 self.dma_count += 1
903 sync.append(txt)
904 txt = self.data[name].mk_dma_rule(name, i)
905 ifacerules.append(txt)
906 txt = self.data[name].mk_dma_connect(name, i)
907 cnct.append(txt)
908 ifacerules = list(filter(None, ifacerules))
909 if ifacerules:
910 txt = "rule synchronize_%s_interrupts;" % name
911 rules.append(txt)
912 rules += ifacerules
913 rules.append("endrule")
914
915 cnct = list(filter(None, cnct))
916 ct = self.dma_count
917 _cnct = ["rule rl_connect_interrupt_to_DMA;",
918 " Bit #(%d) lv_interrupt_to_DMA={" % ct]
919 spc = " "
920 spcsep = ",\n" + spc
921 cnct = _cnct + [spc + spcsep.join(cnct)]
922 cnct.append(" };")
923 cnct.append(" dma.interrupt_from_peripherals(\n" +
924 " lv_interrupt_to_DMA);")
925 cnct.append("endrule;")
926
927 ret = list(filter(None, sync + rules + cnct))
928 ret = li(ret, 15)
929 return '\n'.join(ret)
930
931 def num_dmachannels(self):
932 return "`define NUM_DMACHANNELS {0}".format(self.dma_count)
933
934 def mk_ext_ifacedef(self):
935 ret = []
936 for (name, count) in self.ifacecount:
937 for i in range(count):
938 if self.is_on_fastbus(name, i):
939 continue
940 txt = self.data[name].mk_ext_ifacedef(name, i)
941 ret.append(txt)
942 return '\n'.join(li(list(filter(None, ret)), 8))
943
944 def mk_plic(self):
945 ret = []
946 irq_offs = 8 # XXX: DMA scovers 0-7?
947 for (name, count) in self.ifacecount:
948 for i in range(count):
949 if self.is_on_fastbus(name, i):
950 continue
951 res = self.data[name].mk_plic(i, irq_offs)
952 if not res:
953 continue
954 (txt, irq_offs) = res
955 ret.append(txt)
956 self.num_slow_irqs = irq_offs
957 return '\n'.join(li(list(filter(None, ret)), 4))
958
959 def mk_sloirqsdef(self):
960 return " `define NUM_SLOW_IRQS {0}".format(self.num_slow_irqs)
961
962 def mk_fastclk_con(self):
963 return self._mk_clk_con("fast")
964
965 def mk_slowclk_con(self):
966 return self._mk_clk_con("slow")
967
968 def _mk_clk_con(self, ctype):
969 ret = []
970 for (name, count) in self.ifacecount:
971 for i in range(count):
972 if self.is_on_fastbus(name, i):
973 continue
974 txt = self.data[name]._mk_clk_con(name, i, ctype)
975 ret.append(txt)
976 return '\n'.join(li(list(filter(None, ret)), 8))
977
978 def is_on_fastbus(self, name, i):
979 #print "fastbus mode", self.fastbusmode, name, i
980 iname = self.data[name].iname().format(i)
981 if self.fastbusmode:
982 return iname not in self.fastbus
983 return iname in self.fastbus
984
985
986 class PFactory(object):
987 def getcls(self, name):
988 from uart import uart
989 from quart import quart
990 from sdmmc import sdmmc
991 from pwm import pwm
992 from eint import eint
993 from rs232 import rs232
994 from twi import twi
995 from eint import eint
996 from jtag import jtag
997 from spi import spi, mspi
998 from qspi import qspi, mqspi
999 from gpio import gpio
1000 from rgbttl import rgbttl
1001 from flexbus import flexbus
1002 from sdram import sdram
1003
1004 for k, v in {'uart': uart,
1005 'rs232': rs232,
1006 'twi': twi,
1007 'sdr': sdram,
1008 'quart': quart,
1009 'mqspi': mqspi,
1010 'mspi': mspi,
1011 'qspi': qspi,
1012 'spi': spi,
1013 'pwm': pwm,
1014 'eint': eint,
1015 'mmc': sdmmc,
1016 'jtag': jtag,
1017 'lcd': rgbttl,
1018 'fb': flexbus,
1019 'gpio': gpio
1020 }.items():
1021 if name.startswith(k):
1022 return v
1023 return None
1024
1025
1026 slowfactory = PFactory()
1027
1028 if __name__ == '__main__':
1029 p = uart('uart')
1030 print p.slowimport()
1031 print p.slowifdecl()
1032 i = PeripheralIface('uart')
1033 print i, i.slow
1034 i = PeripheralIface('gpioa')
1035 print i, i.slow