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