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