put jtag interface straight out, not with bscan etc
[pinmux.git] / src / bsv / peripheral_gen / base.py
1 import types
2
3
4 class PBase(object):
5 def __init__(self, name):
6 self.name = name
7
8 def extifdecl(self, name, count):
9 sname = self.get_iname(count)
10 return " interface PeripheralSide%s %s;" % (name.upper(), sname)
11
12 def has_axi_master(self):
13 return False
14
15 def fastifdecl(self, name, count):
16 return ''
17
18 def slowifdeclmux(self, name, count):
19 return ''
20
21 def slowimport(self):
22 return ''
23
24 def num_axi_regs32(self):
25 return 0
26
27 def slowifdecl(self):
28 return ''
29
30 def get_iname(self, inum):
31 return "{0}{1}".format(self.name, self.mksuffix(self.name, inum))
32
33 def axibase(self, name, ifacenum):
34 name = name.upper()
35 return "%(name)s%(ifacenum)dBase" % locals()
36
37 def axiend(self, name, ifacenum):
38 name = name.upper()
39 return "%(name)s%(ifacenum)dEnd" % locals()
40
41 def axi_reg_def(self, start, name, ifacenum):
42 name = name.upper()
43 offs = self.num_axi_regs32() * 4 * 16
44 if offs == 0:
45 return ('', 0)
46 end = start + offs - 1
47 bname = self.axibase(name, ifacenum)
48 bend = self.axiend(name, ifacenum)
49 comment = "%d 32-bit regs" % self.num_axi_regs32()
50 return (" `define %(bname)s 'h%(start)08X\n"
51 " `define %(bend)s 'h%(end)08X // %(comment)s" % locals(),
52 offs)
53
54 def axi_master_name(self, name, ifacenum, typ=''):
55 name = name.upper()
56 return "{0}{1}_master_num".format(name, ifacenum)
57
58 def axi_slave_name(self, name, ifacenum, typ=''):
59 name = name.upper()
60 return "{0}{1}_{2}slave_num".format(name, ifacenum, typ)
61
62 def axi_master_idx(self, idx, name, ifacenum, typ):
63 name = self.axi_master_name(name, ifacenum, typ)
64 return ("typedef {0} {1};".format(idx, name), 1)
65
66 def axi_slave_idx(self, idx, name, ifacenum, typ):
67 name = self.axi_slave_name(name, ifacenum, typ)
68 return ("typedef {0} {1};".format(idx, name), 1)
69
70 def axi_addr_map(self, name, ifacenum):
71 bname = self.axibase(name, ifacenum)
72 bend = self.axiend(name, ifacenum)
73 name = self.axi_slave_name(name, ifacenum)
74 return """\
75 if(addr>=`{0} && addr<=`{1})
76 return tuple2(True,fromInteger(valueOf({2})));
77 else""".format(bname, bend, name)
78
79 def mk_pincon(self, name, count):
80 # TODO: really should be using bsv.interface_decl.Interfaces
81 # pin-naming rules.... logic here is hard-coded to duplicate
82 # it (see Interface.__init__ outen)
83 ret = []
84 for p in self.peripheral.pinspecs:
85 typ = p['type']
86 pname = p['name']
87 #n = "{0}{1}".format(self.name, self.mksuffix(name, count))
88 n = name # "{0}{1}".format(self.name, self.mksuffix(name, count))
89 ret.append(" //%s %s" % (n, str(p)))
90 sname = self.peripheral.iname().format(count)
91 sname = "{0}.{1}".format(sname, pname)
92 ps = "pinmux.peripheral_side.%s" % sname
93 if typ == 'out' or typ == 'inout':
94 fname = self.pinname_out(pname)
95 if not n.startswith('gpio'): # XXX EURGH! horrible hack
96 n_ = "{0}{1}".format(n, count)
97 else:
98 n_ = n
99 if fname:
100 if p.get('outen'):
101 ps_ = ps + '_out'
102 else:
103 ps_ = ps
104 ret.append(" mkConnection({0},\n\t\t\t{1}.{2});"
105 .format(ps_, n_, fname))
106 fname = None
107 if p.get('outen'):
108 fname = self.pinname_outen(pname)
109 if fname:
110 if isinstance(fname, str):
111 fname = "{0}.{1}".format(n_, fname)
112 fname = self.pinname_tweak(pname, 'outen', fname)
113 ret.append(" mkConnection({0}_outen,\n\t\t\t{1});"
114 .format(ps, fname))
115 if typ == 'in' or typ == 'inout':
116 fname = self.pinname_in(pname)
117 if fname:
118 if p.get('outen'):
119 ps_ = ps + '_in'
120 else:
121 ps_ = ps
122 n_ = "{0}{1}".format(n, count)
123 n_ = '{0}.{1}'.format(n_, fname)
124 n_ = self.ifname_tweak(pname, 'in', n_)
125 ret.append(" mkConnection({1}, {0});".format(ps_, n_))
126 return '\n'.join(ret)
127
128 def mk_cellconn(self, *args):
129 return ''
130
131 def mkfast_peripheral(self, size=0):
132 return ''
133
134 def mkslow_peripheral(self, size=0):
135 return ''
136
137 def mksuffix(self, name, i):
138 return i
139
140 def __mk_connection(self, con, aname, fabricname):
141 txt = " mkConnection ({2}.v_to_slaves\n" + \
142 " [fromInteger(valueOf({1}))],\n" + \
143 " {0});"
144
145 print "PBase __mk_connection", self.name, aname
146 if not con:
147 return ''
148 return txt.format(con, aname, fabricname)
149
150 def __mk_master_connection(self, con, aname):
151 txt = " mkConnection (slow_fabric.v_to_slaves\n" + \
152 " [fromInteger(valueOf({1}))],\n" + \
153 " {0});"
154
155 print "PBase __mk_connection", self.name, aname
156 if not con:
157 return ''
158 return txt.format(con, aname)
159
160 def mk_connection(self, count, fabricname, typ, name=None):
161 if name is None:
162 name = self.name
163 print "PBase mk_conn", self.name, count
164 aname = self.axi_slave_name(name, count, typ)
165 #dname = self.mksuffix(name, count)
166 #dname = "{0}{1}".format(name, dname)
167 con = self._mk_connection(name, count).format(count, aname)
168 return self.__mk_connection(con, aname, fabricname)
169
170 def _mk_connection(self, name=None, count=0):
171 return ''
172
173 def pinname_out(self, pname):
174 return ''
175
176 def pinname_in(self, pname):
177 return ''
178
179 def pinname_outen(self, pname):
180 return ''
181
182 def ifname_tweak(self, pname, typ, txt):
183 return txt
184
185 def pinname_tweak(self, pname, typ, txt):
186 return txt
187
188 def num_irqs(self):
189 return 0
190
191 def mk_plic(self, inum, irq_offs):
192 res = []
193 print "mk_plic", self.name, inum, irq_offs
194 niq = self.num_irqs()
195 if niq == 0:
196 return ('', irq_offs)
197 name = self.get_iname(inum)
198 res.append(" // PLIC rules for {0}".format(name))
199 for idx in range(niq):
200 plic_obj = self.plic_object(name, idx)
201 print "plic_obj", name, idx, plic_obj
202 plic = mkplic_rule.format(name, plic_obj, irq_offs)
203 res.append(plic)
204 irq_offs += 1 # increment to next irq
205 return ('\n'.join(res), irq_offs)
206
207 def mk_ext_ifacedef(self, iname, inum):
208 return ''
209
210 def extfastifinstance(self, name, count):
211 return ''
212
213 def _extifinstance(self, name, count, suffix, prefix, samename=False):
214 pname = self.get_iname(count)
215 if samename:
216 sname = pname
217 else:
218 sname = self.peripheral.iname().format(count)
219 template = " interface {0}{3} = {2}{1};"
220 return template.format(pname, sname, prefix, suffix)
221
222 def extifinstance(self, name, count):
223 return self._extifinstance(name, count, "",
224 "pinmux.peripheral_side.")
225
226
227 mkplic_rule = """\
228 rule rl_connect_{0}_to_plic_{2};
229 if({1} == 1'b1) begin
230 ff_gateway_queue[{2}].enq(1);
231 plic.ifc_external_irq[{2}].irq_frm_gateway(True);
232 end
233 endrule
234 """
235
236 axi_master_declarations= """\
237 typedef 0 Dmem_master_num;
238 typedef 1 Imem_master_num;
239 {0}
240 typedef TAdd#(LastGen_master_num, `ifdef Debug 1 `else 0 `endif ) Debug_master_num;
241 typedef TAdd#(Debug_master_num, `ifdef DMA 1 `else 0 `endif ) DMA_master_num;
242 typedef TAdd#(DMA_master_num,1) Num_Masters;
243 """
244
245 axi_fastslave_declarations = """\
246 {0}
247 typedef TAdd#(LastGen_fastslave_num,1) Sdram_cfg_slave_num;
248 typedef TAdd#(Sdram_slave_num ,`ifdef SDRAM 1 `else 0 `endif ) Sdram_cfg_slave_num;
249 typedef TAdd#(Sdram_cfg_slave_num,`ifdef BOOTROM 1 `else 0 `endif ) BootRom_slave_num ;
250 typedef TAdd#(BootRom_slave_num ,`ifdef Debug 1 `else 0 `endif ) Debug_slave_num ;
251 typedef TAdd#(Debug_slave_num , `ifdef TCMemory 1 `else 0 `endif ) TCM_slave_num;
252 typedef TAdd#(TCM_slave_num ,`ifdef DMA 1 `else 0 `endif ) Dma_slave_num;
253 typedef TAdd#(Dma_slave_num ,1 ) SlowPeripheral_slave_num;
254 typedef TAdd#(SlowPeripheral_slave_num,`ifdef VME 1 `else 0 `endif ) VME_slave_num;
255 typedef TAdd#(VME_slave_num,`ifdef FlexBus 1 `else 0 `endif ) FlexBus_slave_num;
256 typedef TAdd#(FlexBus_slave_num,1) Num_Slaves;
257
258 """
259
260 axi_slave_declarations = """\
261 typedef 0 SlowMaster;
262 {0}
263 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
264 CLINT_slave_num;
265 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
266 Plic_slave_num;
267 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
268 AxiExp1_slave_num;
269 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
270 """
271
272 pinmux_cellrule = """\
273 rule connect_select_lines_pinmux;
274 {0}
275 endrule
276 """
277
278
279 class CallFn(object):
280 def __init__(self, peripheral, name):
281 self.peripheral = peripheral
282 self.name = name
283
284 def __call__(self, *args):
285 #print "__call__", self.name, self.peripheral.slow, args
286 if not self.peripheral.slow:
287 return ''
288 return getattr(self.peripheral.slow, self.name)(*args[1:])
289
290
291 class PeripheralIface(object):
292 def __init__(self, ifacename):
293 self.slow = None
294 slow = slowfactory.getcls(ifacename)
295 print "Iface", ifacename, slow
296 if slow:
297 self.slow = slow(ifacename)
298 self.slow.peripheral = self
299 for fname in ['slowimport',
300 'extfastifinstance', 'extifinstance', 'extifdecl',
301 'slowifdecl', 'slowifdeclmux',
302 'fastifdecl',
303 'mkslow_peripheral',
304 'mkfast_peripheral',
305 'mk_plic', 'mk_ext_ifacedef',
306 'mk_connection', 'mk_cellconn', 'mk_pincon']:
307 fn = CallFn(self, fname)
308 setattr(self, fname, types.MethodType(fn, self))
309
310 #print "PeripheralIface"
311 #print dir(self)
312
313 def mksuffix(self, name, i):
314 if self.slow is None:
315 return i
316 return self.slow.mksuffix(name, i)
317
318 def axi_reg_def(self, start, count):
319 if not self.slow:
320 return ('', 0)
321 return self.slow.axi_reg_def(start, self.ifacename, count)
322
323 def axi_master_idx(self, start, count, typ):
324 if not self.slow or not self.slow.has_axi_master():
325 return ('', 0)
326 return self.slow.axi_master_idx(start, self.ifacename, count, typ)
327
328 def axi_slave_idx(self, start, count, typ):
329 if not self.slow:
330 return ('', 0)
331 return self.slow.axi_slave_idx(start, self.ifacename, count, typ)
332
333 def axi_addr_map(self, count):
334 if not self.slow:
335 return ''
336 return self.slow.axi_addr_map(self.ifacename, count)
337
338
339 class PeripheralInterfaces(object):
340 def __init__(self):
341 self.fastbusmode = False
342
343 def slowimport(self, *args):
344 ret = []
345 for (name, count) in self.ifacecount:
346 #print "slowimport", name, self.data[name].slowimport
347 ret.append(self.data[name].slowimport())
348 return '\n'.join(list(filter(None, ret)))
349
350 def extfastifinstance(self, *args):
351 ret = []
352 for (name, count) in self.ifacecount:
353 for i in range(count):
354 iname = self.data[name].iname().format(i)
355 print "extfast", iname, self.is_on_fastbus(name, i)
356 if self.is_on_fastbus(name, i):
357 continue
358 ret.append(self.data[name].extfastifinstance(name, i))
359 return '\n'.join(list(filter(None, ret)))
360
361 def extifinstance(self, *args):
362 ret = []
363 for (name, count) in self.ifacecount:
364 for i in range(count):
365 iname = self.data[name].iname().format(i)
366 if not self.is_on_fastbus(name, i):
367 continue
368 ret.append(self.data[name].extifinstance(name, i))
369 return '\n'.join(list(filter(None, ret)))
370
371 def extifdecl(self, *args):
372 ret = []
373 for (name, count) in self.ifacecount:
374 for i in range(count):
375 if not self.is_on_fastbus(name, i):
376 continue
377 ret.append(self.data[name].extifdecl(name, i))
378 return '\n'.join(list(filter(None, ret)))
379
380 def slowifdeclmux(self, *args):
381 ret = []
382 for (name, count) in self.ifacecount:
383 for i in range(count):
384 ret.append(self.data[name].slowifdeclmux(name, i))
385 return '\n'.join(list(filter(None, ret)))
386
387 def fastifdecl(self, *args):
388 ret = []
389 for (name, count) in self.ifacecount:
390 for i in range(count):
391 print "fastifdecl", name, i, self.is_on_fastbus(name, i)
392 if self.is_on_fastbus(name, i):
393 continue
394 ret.append(self.data[name].fastifdecl(name, i))
395 return '\n'.join(list(filter(None, ret)))
396
397 def slowifdecl(self, *args):
398 ret = []
399 for (name, count) in self.ifacecount:
400 for i in range(count):
401 if self.is_on_fastbus(name, i):
402 continue
403 ret.append(self.data[name].slowifdecl().format(i, name))
404 return '\n'.join(list(filter(None, ret)))
405
406 def axi_reg_def(self, *args):
407 ret = []
408 start = 0x00011100 # start of AXI peripherals address
409 for (name, count) in self.ifacecount:
410 for i in range(count):
411 if self.is_on_fastbus(name, i):
412 continue
413 x = self.data[name].axi_reg_def(start, i)
414 #print ("ifc", name, x)
415 (rdef, offs) = x
416 ret.append(rdef)
417 start += offs
418 return '\n'.join(list(filter(None, ret)))
419
420 def _axi_num_idx(self, start, template, typ, idxtype, *args):
421 ret = []
422 for (name, count) in self.ifacecount:
423 for i in range(count):
424 if self.is_on_fastbus(name, i):
425 continue
426 if typ == 'master':
427 fn = self.data[name].axi_master_idx
428 else:
429 fn = self.data[name].axi_slave_idx
430 (rdef, offs) = fn(start, i, idxtype)
431 #print ("ifc", name, rdef, offs)
432 ret.append(rdef)
433 start += offs
434 ret.append("typedef %d LastGen_%s_num;" % (start - 1, typ))
435 decls = '\n'.join(list(filter(None, ret)))
436 return template.format(decls)
437
438 def axi_slave_idx(self, *args):
439 return self._axi_num_idx(0, axi_slave_declarations, 'slave',
440 '', *args)
441
442 def axi_fastslave_idx(self, *args):
443 return self._axi_num_idx(0, axi_fastslave_declarations, 'fastslave',
444 'fast', *args)
445
446 def axi_master_idx(self, *args):
447 return self._axi_num_idx(2, axi_master_declarations, 'master',
448 'master', *args)
449
450 def axi_fastslave_idx(self, *args):
451 return self._axi_num_idx(0, axi_fastslave_declarations, 'fastslave',
452 'fast', *args)
453
454 def axi_addr_map(self, *args):
455 ret = []
456 for (name, count) in self.ifacecount:
457 for i in range(count):
458 if self.is_on_fastbus(name, i):
459 continue
460 ret.append(self.data[name].axi_addr_map(i))
461 return '\n'.join(list(filter(None, ret)))
462
463 def mkfast_peripheral(self, *args):
464 ret = []
465 for (name, count) in self.ifacecount:
466 for i in range(count):
467 if self.is_on_fastbus(name, i):
468 continue
469 #print "mkfast", name, count
470 x = self.data[name].mkfast_peripheral()
471 print name, count, x
472 suffix = self.data[name].mksuffix(name, i)
473 ret.append(x.format(suffix))
474 return '\n'.join(list(filter(None, ret)))
475
476 def mkslow_peripheral(self, *args):
477 ret = []
478 for (name, count) in self.ifacecount:
479 for i in range(count):
480 if self.is_on_fastbus(name, i):
481 continue
482 #print "mkslow", name, count
483 x = self.data[name].mkslow_peripheral()
484 print name, count, x
485 suffix = self.data[name].mksuffix(name, i)
486 ret.append(x.format(suffix))
487 return '\n'.join(list(filter(None, ret)))
488
489 def mk_fast_connection(self, *args):
490 ret = []
491 for (name, count) in self.ifacecount:
492 for i in range(count):
493 if self.is_on_fastbus(name, i):
494 continue
495 txt = self.data[name].mk_connection(i, "fabric", "fast")
496 if name == 'gpioa':
497 print "txt", txt
498 print self.data[name].mk_connection
499 ret.append(txt)
500 return '\n'.join(list(filter(None, ret)))
501
502 def mk_connection(self, *args):
503 ret = []
504 for (name, count) in self.ifacecount:
505 for i in range(count):
506 if self.is_on_fastbus(name, i):
507 continue
508 txt = self.data[name].mk_connection(i, "slow_fabric", "")
509 if name == 'gpioa':
510 print "txt", txt
511 print self.data[name].mk_connection
512 ret.append(txt)
513 return '\n'.join(list(filter(None, ret)))
514
515 def mk_cellconn(self):
516 ret = []
517 cellcount = 0
518 for (name, count) in self.ifacecount:
519 for i in range(count):
520 if self.is_on_fastbus(name, i):
521 continue
522 res = self.data[name].mk_cellconn(cellcount, name, i)
523 if not res:
524 continue
525 (txt, cellcount) = res
526 ret.append(txt)
527 ret = '\n'.join(list(filter(None, ret)))
528 return pinmux_cellrule.format(ret)
529
530 def mk_pincon(self):
531 ret = []
532 for (name, count) in self.ifacecount:
533 for i in range(count):
534 if self.is_on_fastbus(name, i):
535 continue
536 txt = self.data[name].mk_pincon(name, i)
537 ret.append(txt)
538 return '\n'.join(list(filter(None, ret)))
539
540 def mk_ext_ifacedef(self):
541 ret = []
542 for (name, count) in self.ifacecount:
543 for i in range(count):
544 if self.is_on_fastbus(name, i):
545 continue
546 txt = self.data[name].mk_ext_ifacedef(name, i)
547 ret.append(txt)
548 return '\n'.join(list(filter(None, ret)))
549
550 def mk_plic(self):
551 ret = []
552 irq_offs = 8 # XXX: DMA scovers 0-7?
553 for (name, count) in self.ifacecount:
554 for i in range(count):
555 if self.is_on_fastbus(name, i):
556 continue
557 res = self.data[name].mk_plic(i, irq_offs)
558 if not res:
559 continue
560 (txt, irq_offs) = res
561 ret.append(txt)
562 self.num_slow_irqs = irq_offs
563 return '\n'.join(list(filter(None, ret)))
564
565 def mk_sloirqsdef(self):
566 return " `define NUM_SLOW_IRQS {0}".format(self.num_slow_irqs)
567
568 def is_on_fastbus(self, name, i):
569 #print "fastbus mode", self.fastbusmode, name, i
570 iname = self.data[name].iname().format(i)
571 if self.fastbusmode:
572 return iname not in self.fastbus
573 return iname in self.fastbus
574
575
576 class PFactory(object):
577 def getcls(self, name):
578 from uart import uart
579 from quart import quart
580 from sdmmc import sdmmc
581 from pwm import pwm
582 from eint import eint
583 from rs232 import rs232
584 from twi import twi
585 from eint import eint
586 from jtag import jtag
587 from spi import spi, mspi
588 from qspi import qspi, mqspi
589 from gpio import gpio
590 from rgbttl import rgbttl
591
592 for k, v in {'uart': uart,
593 'rs232': rs232,
594 'twi': twi,
595 'quart': quart,
596 'mqspi': mqspi,
597 'mspi': mspi,
598 'qspi': qspi,
599 'spi': spi,
600 'pwm': pwm,
601 'eint': eint,
602 'sd': sdmmc,
603 'jtag': jtag,
604 'lcd': rgbttl,
605 'gpio': gpio
606 }.items():
607 if name.startswith(k):
608 return v
609 return None
610
611
612 slowfactory = PFactory()
613
614 if __name__ == '__main__':
615 p = uart('uart')
616 print p.slowimport()
617 print p.slowifdecl()
618 i = PeripheralIface('uart')
619 print i, i.slow
620 i = PeripheralIface('gpioa')
621 print i, i.slow