add slave and master for rgbttl
[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):
138 txt = " mkConnection (slow_fabric.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)
146
147 def mk_connection(self, count, name=None):
148 if name is None:
149 name = self.name
150 print "PBase mk_conn", self.name, count
151 aname = self.axi_slave_name(name, count)
152 #dname = self.mksuffix(name, count)
153 #dname = "{0}{1}".format(name, dname)
154 con = self._mk_connection(name, count).format(count, aname)
155 return self.__mk_connection(con, aname)
156
157 def _mk_connection(self, name=None, count=0):
158 return ''
159
160 def pinname_out(self, pname):
161 return ''
162
163 def pinname_in(self, pname):
164 return ''
165
166 def pinname_outen(self, pname):
167 return ''
168
169 def ifname_tweak(self, pname, typ, txt):
170 return txt
171
172 def pinname_tweak(self, pname, typ, txt):
173 return txt
174
175 def num_irqs(self):
176 return 0
177
178 def mk_plic(self, inum, irq_offs):
179 res = []
180 print "mk_plic", self.name, inum, irq_offs
181 niq = self.num_irqs()
182 if niq == 0:
183 return ('', irq_offs)
184 name = self.get_iname(inum)
185 res.append(" // PLIC rules for {0}".format(name))
186 for idx in range(niq):
187 plic_obj = self.plic_object(name, idx)
188 print "plic_obj", name, idx, plic_obj
189 plic = mkplic_rule.format(name, plic_obj, irq_offs)
190 res.append(plic)
191 irq_offs += 1 # increment to next irq
192 return ('\n'.join(res), irq_offs)
193
194 def mk_ext_ifacedef(self, iname, inum):
195 return ''
196
197 def extifinstance(self, name, count):
198 sname = self.peripheral.iname().format(count)
199 pname = self.get_iname(count)
200 template = " interface {0} = pinmux.peripheral_side.{1};"
201 return template.format(pname, sname)
202
203
204 mkplic_rule = """\
205 rule rl_connect_{0}_to_plic_{2};
206 if({1} == 1'b1) begin
207 ff_gateway_queue[{2}].enq(1);
208 plic.ifc_external_irq[{2}].irq_frm_gateway(True);
209 end
210 endrule
211 """
212
213 axi_master_declarations= """\
214 typedef 0 Dmem_master_num;
215 typedef 1 Imem_master_num;
216 {0}
217 typedef TAdd#(LastGen_master_num, `ifdef Debug 1 `else 0 `endif ) Debug_master_num;
218 typedef TAdd#(Debug_master_num, `ifdef DMA 1 `else 0 `endif ) DMA_master_num;
219 typedef TAdd#(DMA_master_num,1) Num_Masters;
220 """
221
222 axi_fastslave_declarations = """\
223 {0}
224 typedef TAdd#(LastGen_fastslave_num,1) Sdram_cfg_slave_num;
225 typedef TAdd#(Sdram_slave_num ,`ifdef SDRAM 1 `else 0 `endif ) Sdram_cfg_slave_num;
226 typedef TAdd#(Sdram_cfg_slave_num,`ifdef BOOTROM 1 `else 0 `endif ) BootRom_slave_num ;
227 typedef TAdd#(BootRom_slave_num ,`ifdef Debug 1 `else 0 `endif ) Debug_slave_num ;
228 typedef TAdd#(Debug_slave_num , `ifdef TCMemory 1 `else 0 `endif ) TCM_slave_num;
229 typedef TAdd#(TCM_slave_num ,`ifdef DMA 1 `else 0 `endif ) Dma_slave_num;
230 typedef TAdd#(Dma_slave_num ,1 ) SlowPeripheral_slave_num;
231 typedef TAdd#(SlowPeripheral_slave_num,`ifdef VME 1 `else 0 `endif ) VME_slave_num;
232 typedef TAdd#(VME_slave_num,`ifdef FlexBus 1 `else 0 `endif ) FlexBus_slave_num;
233 typedef TAdd#(FlexBus_slave_num,1) Num_Slaves;
234
235 """
236
237 axi_slave_declarations = """\
238 typedef 0 SlowMaster;
239 {0}
240 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
241 CLINT_slave_num;
242 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
243 Plic_slave_num;
244 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
245 AxiExp1_slave_num;
246 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
247 """
248
249 pinmux_cellrule = """\
250 rule connect_select_lines_pinmux;
251 {0}
252 endrule
253 """
254
255
256 class CallFn(object):
257 def __init__(self, peripheral, name):
258 self.peripheral = peripheral
259 self.name = name
260
261 def __call__(self, *args):
262 #print "__call__", self.name, self.peripheral.slow, args
263 if not self.peripheral.slow:
264 return ''
265 return getattr(self.peripheral.slow, self.name)(*args[1:])
266
267
268 class PeripheralIface(object):
269 def __init__(self, ifacename):
270 self.slow = None
271 slow = slowfactory.getcls(ifacename)
272 print "Iface", ifacename, slow
273 if slow:
274 self.slow = slow(ifacename)
275 self.slow.peripheral = self
276 for fname in ['slowimport',
277 'extifinstance', 'extifdecl',
278 'slowifdecl', 'slowifdeclmux',
279 'mkslow_peripheral',
280 'mkfast_peripheral',
281 'mk_plic', 'mk_ext_ifacedef',
282 'mk_connection', 'mk_cellconn', 'mk_pincon']:
283 fn = CallFn(self, fname)
284 setattr(self, fname, types.MethodType(fn, self))
285
286 #print "PeripheralIface"
287 #print dir(self)
288
289 def mksuffix(self, name, i):
290 if self.slow is None:
291 return i
292 return self.slow.mksuffix(name, i)
293
294 def axi_reg_def(self, start, count):
295 if not self.slow:
296 return ('', 0)
297 return self.slow.axi_reg_def(start, self.ifacename, count)
298
299 def axi_master_idx(self, start, count, typ):
300 if not self.slow or not self.slow.has_axi_master():
301 return ('', 0)
302 return self.slow.axi_master_idx(start, self.ifacename, count, typ)
303
304 def axi_slave_idx(self, start, count, typ):
305 if not self.slow:
306 return ('', 0)
307 return self.slow.axi_slave_idx(start, self.ifacename, count, typ)
308
309 def axi_addr_map(self, count):
310 if not self.slow:
311 return ''
312 return self.slow.axi_addr_map(self.ifacename, count)
313
314
315 class PeripheralInterfaces(object):
316 def __init__(self):
317 self.fastbusmode = False
318
319 def slowimport(self, *args):
320 ret = []
321 for (name, count) in self.ifacecount:
322 #print "slowimport", name, self.data[name].slowimport
323 ret.append(self.data[name].slowimport())
324 return '\n'.join(list(filter(None, ret)))
325
326 def extifinstance(self, *args):
327 ret = []
328 for (name, count) in self.ifacecount:
329 for i in range(count):
330 iname = self.data[name].iname().format(i)
331 if not self.is_on_fastbus(name, i):
332 continue
333 ret.append(self.data[name].extifinstance(name, i))
334 return '\n'.join(list(filter(None, ret)))
335
336 def extifdecl(self, *args):
337 ret = []
338 for (name, count) in self.ifacecount:
339 for i in range(count):
340 if not self.is_on_fastbus(name, i):
341 continue
342 ret.append(self.data[name].extifdecl(name, i))
343 return '\n'.join(list(filter(None, ret)))
344
345 def slowifdeclmux(self, *args):
346 ret = []
347 for (name, count) in self.ifacecount:
348 for i in range(count):
349 ret.append(self.data[name].slowifdeclmux(name, i))
350 return '\n'.join(list(filter(None, ret)))
351
352 def slowifdecl(self, *args):
353 ret = []
354 for (name, count) in self.ifacecount:
355 for i in range(count):
356 if self.is_on_fastbus(name, i):
357 continue
358 ret.append(self.data[name].slowifdecl().format(i, name))
359 return '\n'.join(list(filter(None, ret)))
360
361 def axi_reg_def(self, *args):
362 ret = []
363 start = 0x00011100 # start of AXI peripherals address
364 for (name, count) in self.ifacecount:
365 for i in range(count):
366 if self.is_on_fastbus(name, i):
367 continue
368 x = self.data[name].axi_reg_def(start, i)
369 #print ("ifc", name, x)
370 (rdef, offs) = x
371 ret.append(rdef)
372 start += offs
373 return '\n'.join(list(filter(None, ret)))
374
375 def _axi_num_idx(self, start, template, typ, idxtype, *args):
376 ret = []
377 for (name, count) in self.ifacecount:
378 for i in range(count):
379 if self.is_on_fastbus(name, i):
380 continue
381 if typ == 'master':
382 fn = self.data[name].axi_master_idx
383 else:
384 fn = self.data[name].axi_slave_idx
385 (rdef, offs) = fn(start, i, idxtype)
386 #print ("ifc", name, rdef, offs)
387 ret.append(rdef)
388 start += offs
389 ret.append("typedef %d LastGen_%s_num;" % (start - 1, typ))
390 decls = '\n'.join(list(filter(None, ret)))
391 return template.format(decls)
392
393 def axi_slave_idx(self, *args):
394 return self._axi_num_idx(0, axi_slave_declarations, 'slave',
395 '', *args)
396
397 def axi_fastslave_idx(self, *args):
398 return self._axi_num_idx(0, axi_fastslave_declarations, 'fastslave',
399 'fast', *args)
400
401 def axi_master_idx(self, *args):
402 return self._axi_num_idx(2, axi_master_declarations, 'master',
403 'master', *args)
404
405 def axi_fastslave_idx(self, *args):
406 return self._axi_num_idx(0, axi_fastslave_declarations, 'fastslave',
407 'fast', *args)
408
409 def axi_addr_map(self, *args):
410 ret = []
411 for (name, count) in self.ifacecount:
412 for i in range(count):
413 if self.is_on_fastbus(name, i):
414 continue
415 ret.append(self.data[name].axi_addr_map(i))
416 return '\n'.join(list(filter(None, ret)))
417
418 def mkfast_peripheral(self, *args):
419 ret = []
420 for (name, count) in self.ifacecount:
421 for i in range(count):
422 if self.is_on_fastbus(name, i):
423 continue
424 #print "mkfast", name, count
425 x = self.data[name].mkfast_peripheral()
426 print name, count, x
427 suffix = self.data[name].mksuffix(name, i)
428 ret.append(x.format(suffix))
429 return '\n'.join(list(filter(None, ret)))
430
431 def mkslow_peripheral(self, *args):
432 ret = []
433 for (name, count) in self.ifacecount:
434 for i in range(count):
435 if self.is_on_fastbus(name, i):
436 continue
437 #print "mkslow", name, count
438 x = self.data[name].mkslow_peripheral()
439 print name, count, x
440 suffix = self.data[name].mksuffix(name, i)
441 ret.append(x.format(suffix))
442 return '\n'.join(list(filter(None, ret)))
443
444 def mk_connection(self, *args):
445 ret = []
446 for (name, count) in self.ifacecount:
447 for i in range(count):
448 if self.is_on_fastbus(name, i):
449 continue
450 txt = self.data[name].mk_connection(i)
451 if name == 'gpioa':
452 print "txt", txt
453 print self.data[name].mk_connection
454 ret.append(txt)
455 return '\n'.join(list(filter(None, ret)))
456
457 def mk_cellconn(self):
458 ret = []
459 cellcount = 0
460 for (name, count) in self.ifacecount:
461 for i in range(count):
462 if self.is_on_fastbus(name, i):
463 continue
464 res = self.data[name].mk_cellconn(cellcount, name, i)
465 if not res:
466 continue
467 (txt, cellcount) = res
468 ret.append(txt)
469 ret = '\n'.join(list(filter(None, ret)))
470 return pinmux_cellrule.format(ret)
471
472 def mk_pincon(self):
473 ret = []
474 for (name, count) in self.ifacecount:
475 for i in range(count):
476 if self.is_on_fastbus(name, i):
477 continue
478 txt = self.data[name].mk_pincon(name, i)
479 ret.append(txt)
480 return '\n'.join(list(filter(None, ret)))
481
482 def mk_ext_ifacedef(self):
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_ext_ifacedef(name, i)
489 ret.append(txt)
490 return '\n'.join(list(filter(None, ret)))
491
492 def mk_plic(self):
493 ret = []
494 irq_offs = 8 # XXX: DMA scovers 0-7?
495 for (name, count) in self.ifacecount:
496 for i in range(count):
497 if self.is_on_fastbus(name, i):
498 continue
499 res = self.data[name].mk_plic(i, irq_offs)
500 if not res:
501 continue
502 (txt, irq_offs) = res
503 ret.append(txt)
504 self.num_slow_irqs = irq_offs
505 return '\n'.join(list(filter(None, ret)))
506
507 def mk_sloirqsdef(self):
508 return " `define NUM_SLOW_IRQS {0}".format(self.num_slow_irqs)
509
510 def is_on_fastbus(self, name, i):
511 #print "fastbus mode", self.fastbusmode, name, i
512 iname = self.data[name].iname().format(i)
513 if self.fastbusmode:
514 return iname not in self.fastbus
515 return iname in self.fastbus
516
517
518 class PFactory(object):
519 def getcls(self, name):
520 from uart import uart
521 from quart import quart
522 from sdmmc import sdmmc
523 from pwm import pwm
524 from eint import eint
525 from rs232 import rs232
526 from twi import twi
527 from eint import eint
528 from jtag import jtag
529 from spi import spi, mspi
530 from qspi import qspi, mqspi
531 from gpio import gpio
532 from rgbttl import rgbttl
533
534 for k, v in {'uart': uart,
535 'rs232': rs232,
536 'twi': twi,
537 'quart': quart,
538 'mqspi': mqspi,
539 'mspi': mspi,
540 'qspi': qspi,
541 'spi': spi,
542 'pwm': pwm,
543 'eint': eint,
544 'sd': sdmmc,
545 'jtag': jtag,
546 'lcd': rgbttl,
547 'gpio': gpio
548 }.items():
549 if name.startswith(k):
550 return v
551 return None
552
553
554 slowfactory = PFactory()
555
556 if __name__ == '__main__':
557 p = uart('uart')
558 print p.slowimport()
559 print p.slowifdecl()
560 i = PeripheralIface('uart')
561 print i, i.slow
562 i = PeripheralIface('gpioa')
563 print i, i.slow