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