add fast bus instance
[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):
214 sname = self.peripheral.iname().format(count)
215 pname = self.get_iname(count)
216 template = " interface {0} = pinmux.peripheral_side.{1};"
217 return template.format(pname, sname)
218
219
220 mkplic_rule = """\
221 rule rl_connect_{0}_to_plic_{2};
222 if({1} == 1'b1) begin
223 ff_gateway_queue[{2}].enq(1);
224 plic.ifc_external_irq[{2}].irq_frm_gateway(True);
225 end
226 endrule
227 """
228
229 axi_master_declarations= """\
230 typedef 0 Dmem_master_num;
231 typedef 1 Imem_master_num;
232 {0}
233 typedef TAdd#(LastGen_master_num, `ifdef Debug 1 `else 0 `endif ) Debug_master_num;
234 typedef TAdd#(Debug_master_num, `ifdef DMA 1 `else 0 `endif ) DMA_master_num;
235 typedef TAdd#(DMA_master_num,1) Num_Masters;
236 """
237
238 axi_fastslave_declarations = """\
239 {0}
240 typedef TAdd#(LastGen_fastslave_num,1) Sdram_cfg_slave_num;
241 typedef TAdd#(Sdram_slave_num ,`ifdef SDRAM 1 `else 0 `endif ) Sdram_cfg_slave_num;
242 typedef TAdd#(Sdram_cfg_slave_num,`ifdef BOOTROM 1 `else 0 `endif ) BootRom_slave_num ;
243 typedef TAdd#(BootRom_slave_num ,`ifdef Debug 1 `else 0 `endif ) Debug_slave_num ;
244 typedef TAdd#(Debug_slave_num , `ifdef TCMemory 1 `else 0 `endif ) TCM_slave_num;
245 typedef TAdd#(TCM_slave_num ,`ifdef DMA 1 `else 0 `endif ) Dma_slave_num;
246 typedef TAdd#(Dma_slave_num ,1 ) SlowPeripheral_slave_num;
247 typedef TAdd#(SlowPeripheral_slave_num,`ifdef VME 1 `else 0 `endif ) VME_slave_num;
248 typedef TAdd#(VME_slave_num,`ifdef FlexBus 1 `else 0 `endif ) FlexBus_slave_num;
249 typedef TAdd#(FlexBus_slave_num,1) Num_Slaves;
250
251 """
252
253 axi_slave_declarations = """\
254 typedef 0 SlowMaster;
255 {0}
256 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
257 CLINT_slave_num;
258 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
259 Plic_slave_num;
260 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
261 AxiExp1_slave_num;
262 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
263 """
264
265 pinmux_cellrule = """\
266 rule connect_select_lines_pinmux;
267 {0}
268 endrule
269 """
270
271
272 class CallFn(object):
273 def __init__(self, peripheral, name):
274 self.peripheral = peripheral
275 self.name = name
276
277 def __call__(self, *args):
278 #print "__call__", self.name, self.peripheral.slow, args
279 if not self.peripheral.slow:
280 return ''
281 return getattr(self.peripheral.slow, self.name)(*args[1:])
282
283
284 class PeripheralIface(object):
285 def __init__(self, ifacename):
286 self.slow = None
287 slow = slowfactory.getcls(ifacename)
288 print "Iface", ifacename, slow
289 if slow:
290 self.slow = slow(ifacename)
291 self.slow.peripheral = self
292 for fname in ['slowimport',
293 'extfastifinstance', 'extifinstance', 'extifdecl',
294 'slowifdecl', 'slowifdeclmux',
295 'fastifdecl',
296 'mkslow_peripheral',
297 'mkfast_peripheral',
298 'mk_plic', 'mk_ext_ifacedef',
299 'mk_connection', 'mk_cellconn', 'mk_pincon']:
300 fn = CallFn(self, fname)
301 setattr(self, fname, types.MethodType(fn, self))
302
303 #print "PeripheralIface"
304 #print dir(self)
305
306 def mksuffix(self, name, i):
307 if self.slow is None:
308 return i
309 return self.slow.mksuffix(name, i)
310
311 def axi_reg_def(self, start, count):
312 if not self.slow:
313 return ('', 0)
314 return self.slow.axi_reg_def(start, self.ifacename, count)
315
316 def axi_master_idx(self, start, count, typ):
317 if not self.slow or not self.slow.has_axi_master():
318 return ('', 0)
319 return self.slow.axi_master_idx(start, self.ifacename, count, typ)
320
321 def axi_slave_idx(self, start, count, typ):
322 if not self.slow:
323 return ('', 0)
324 return self.slow.axi_slave_idx(start, self.ifacename, count, typ)
325
326 def axi_addr_map(self, count):
327 if not self.slow:
328 return ''
329 return self.slow.axi_addr_map(self.ifacename, count)
330
331
332 class PeripheralInterfaces(object):
333 def __init__(self):
334 self.fastbusmode = False
335
336 def slowimport(self, *args):
337 ret = []
338 for (name, count) in self.ifacecount:
339 #print "slowimport", name, self.data[name].slowimport
340 ret.append(self.data[name].slowimport())
341 return '\n'.join(list(filter(None, ret)))
342
343 def extfastifinstance(self, *args):
344 ret = []
345 for (name, count) in self.ifacecount:
346 for i in range(count):
347 iname = self.data[name].iname().format(i)
348 print "extfast", iname, self.is_on_fastbus(name, i)
349 if self.is_on_fastbus(name, i):
350 continue
351 ret.append(self.data[name].extfastifinstance(name, i))
352 return '\n'.join(list(filter(None, ret)))
353
354 def extifinstance(self, *args):
355 ret = []
356 for (name, count) in self.ifacecount:
357 for i in range(count):
358 iname = self.data[name].iname().format(i)
359 if not self.is_on_fastbus(name, i):
360 continue
361 ret.append(self.data[name].extifinstance(name, i))
362 return '\n'.join(list(filter(None, ret)))
363
364 def extifdecl(self, *args):
365 ret = []
366 for (name, count) in self.ifacecount:
367 for i in range(count):
368 if not self.is_on_fastbus(name, i):
369 continue
370 ret.append(self.data[name].extifdecl(name, i))
371 return '\n'.join(list(filter(None, ret)))
372
373 def slowifdeclmux(self, *args):
374 ret = []
375 for (name, count) in self.ifacecount:
376 for i in range(count):
377 ret.append(self.data[name].slowifdeclmux(name, i))
378 return '\n'.join(list(filter(None, ret)))
379
380 def fastifdecl(self, *args):
381 ret = []
382 for (name, count) in self.ifacecount:
383 for i in range(count):
384 print "fastifdecl", name, i, self.is_on_fastbus(name, i)
385 if self.is_on_fastbus(name, i):
386 continue
387 ret.append(self.data[name].fastifdecl(name, i))
388 return '\n'.join(list(filter(None, ret)))
389
390 def slowifdecl(self, *args):
391 ret = []
392 for (name, count) in self.ifacecount:
393 for i in range(count):
394 if self.is_on_fastbus(name, i):
395 continue
396 ret.append(self.data[name].slowifdecl().format(i, name))
397 return '\n'.join(list(filter(None, ret)))
398
399 def axi_reg_def(self, *args):
400 ret = []
401 start = 0x00011100 # start of AXI peripherals address
402 for (name, count) in self.ifacecount:
403 for i in range(count):
404 if self.is_on_fastbus(name, i):
405 continue
406 x = self.data[name].axi_reg_def(start, i)
407 #print ("ifc", name, x)
408 (rdef, offs) = x
409 ret.append(rdef)
410 start += offs
411 return '\n'.join(list(filter(None, ret)))
412
413 def _axi_num_idx(self, start, template, typ, idxtype, *args):
414 ret = []
415 for (name, count) in self.ifacecount:
416 for i in range(count):
417 if self.is_on_fastbus(name, i):
418 continue
419 if typ == 'master':
420 fn = self.data[name].axi_master_idx
421 else:
422 fn = self.data[name].axi_slave_idx
423 (rdef, offs) = fn(start, i, idxtype)
424 #print ("ifc", name, rdef, offs)
425 ret.append(rdef)
426 start += offs
427 ret.append("typedef %d LastGen_%s_num;" % (start - 1, typ))
428 decls = '\n'.join(list(filter(None, ret)))
429 return template.format(decls)
430
431 def axi_slave_idx(self, *args):
432 return self._axi_num_idx(0, axi_slave_declarations, 'slave',
433 '', *args)
434
435 def axi_fastslave_idx(self, *args):
436 return self._axi_num_idx(0, axi_fastslave_declarations, 'fastslave',
437 'fast', *args)
438
439 def axi_master_idx(self, *args):
440 return self._axi_num_idx(2, axi_master_declarations, 'master',
441 'master', *args)
442
443 def axi_fastslave_idx(self, *args):
444 return self._axi_num_idx(0, axi_fastslave_declarations, 'fastslave',
445 'fast', *args)
446
447 def axi_addr_map(self, *args):
448 ret = []
449 for (name, count) in self.ifacecount:
450 for i in range(count):
451 if self.is_on_fastbus(name, i):
452 continue
453 ret.append(self.data[name].axi_addr_map(i))
454 return '\n'.join(list(filter(None, ret)))
455
456 def mkfast_peripheral(self, *args):
457 ret = []
458 for (name, count) in self.ifacecount:
459 for i in range(count):
460 if self.is_on_fastbus(name, i):
461 continue
462 #print "mkfast", name, count
463 x = self.data[name].mkfast_peripheral()
464 print name, count, x
465 suffix = self.data[name].mksuffix(name, i)
466 ret.append(x.format(suffix))
467 return '\n'.join(list(filter(None, ret)))
468
469 def mkslow_peripheral(self, *args):
470 ret = []
471 for (name, count) in self.ifacecount:
472 for i in range(count):
473 if self.is_on_fastbus(name, i):
474 continue
475 #print "mkslow", name, count
476 x = self.data[name].mkslow_peripheral()
477 print name, count, x
478 suffix = self.data[name].mksuffix(name, i)
479 ret.append(x.format(suffix))
480 return '\n'.join(list(filter(None, ret)))
481
482 def mk_fast_connection(self, *args):
483 ret = []
484 for (name, count) in self.ifacecount:
485 for i in range(count):
486 if self.is_on_fastbus(name, i):
487 continue
488 txt = self.data[name].mk_connection(i, "fabric", "fast")
489 if name == 'gpioa':
490 print "txt", txt
491 print self.data[name].mk_connection
492 ret.append(txt)
493 return '\n'.join(list(filter(None, ret)))
494
495 def mk_connection(self, *args):
496 ret = []
497 for (name, count) in self.ifacecount:
498 for i in range(count):
499 if self.is_on_fastbus(name, i):
500 continue
501 txt = self.data[name].mk_connection(i, "slow_fabric", "")
502 if name == 'gpioa':
503 print "txt", txt
504 print self.data[name].mk_connection
505 ret.append(txt)
506 return '\n'.join(list(filter(None, ret)))
507
508 def mk_cellconn(self):
509 ret = []
510 cellcount = 0
511 for (name, count) in self.ifacecount:
512 for i in range(count):
513 if self.is_on_fastbus(name, i):
514 continue
515 res = self.data[name].mk_cellconn(cellcount, name, i)
516 if not res:
517 continue
518 (txt, cellcount) = res
519 ret.append(txt)
520 ret = '\n'.join(list(filter(None, ret)))
521 return pinmux_cellrule.format(ret)
522
523 def mk_pincon(self):
524 ret = []
525 for (name, count) in self.ifacecount:
526 for i in range(count):
527 if self.is_on_fastbus(name, i):
528 continue
529 txt = self.data[name].mk_pincon(name, i)
530 ret.append(txt)
531 return '\n'.join(list(filter(None, ret)))
532
533 def mk_ext_ifacedef(self):
534 ret = []
535 for (name, count) in self.ifacecount:
536 for i in range(count):
537 if self.is_on_fastbus(name, i):
538 continue
539 txt = self.data[name].mk_ext_ifacedef(name, i)
540 ret.append(txt)
541 return '\n'.join(list(filter(None, ret)))
542
543 def mk_plic(self):
544 ret = []
545 irq_offs = 8 # XXX: DMA scovers 0-7?
546 for (name, count) in self.ifacecount:
547 for i in range(count):
548 if self.is_on_fastbus(name, i):
549 continue
550 res = self.data[name].mk_plic(i, irq_offs)
551 if not res:
552 continue
553 (txt, irq_offs) = res
554 ret.append(txt)
555 self.num_slow_irqs = irq_offs
556 return '\n'.join(list(filter(None, ret)))
557
558 def mk_sloirqsdef(self):
559 return " `define NUM_SLOW_IRQS {0}".format(self.num_slow_irqs)
560
561 def is_on_fastbus(self, name, i):
562 #print "fastbus mode", self.fastbusmode, name, i
563 iname = self.data[name].iname().format(i)
564 if self.fastbusmode:
565 return iname not in self.fastbus
566 return iname in self.fastbus
567
568
569 class PFactory(object):
570 def getcls(self, name):
571 from uart import uart
572 from quart import quart
573 from sdmmc import sdmmc
574 from pwm import pwm
575 from eint import eint
576 from rs232 import rs232
577 from twi import twi
578 from eint import eint
579 from jtag import jtag
580 from spi import spi, mspi
581 from qspi import qspi, mqspi
582 from gpio import gpio
583 from rgbttl import rgbttl
584
585 for k, v in {'uart': uart,
586 'rs232': rs232,
587 'twi': twi,
588 'quart': quart,
589 'mqspi': mqspi,
590 'mspi': mspi,
591 'qspi': qspi,
592 'spi': spi,
593 'pwm': pwm,
594 'eint': eint,
595 'sd': sdmmc,
596 'jtag': jtag,
597 'lcd': rgbttl,
598 'gpio': gpio
599 }.items():
600 if name.startswith(k):
601 return v
602 return None
603
604
605 slowfactory = PFactory()
606
607 if __name__ == '__main__':
608 p = uart('uart')
609 print p.slowimport()
610 print p.slowifdecl()
611 i = PeripheralIface('uart')
612 print i, i.slow
613 i = PeripheralIface('gpioa')
614 print i, i.slow