code-shuffle to use axi slave fast bus
[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_slave_declarations = """\
208 typedef 0 SlowMaster;
209 {0}
210 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
211 CLINT_slave_num;
212 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
213 Plic_slave_num;
214 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
215 AxiExp1_slave_num;
216 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
217 """
218
219 pinmux_cellrule = """\
220 rule connect_select_lines_pinmux;
221 {0}
222 endrule
223 """
224
225
226 class CallFn(object):
227 def __init__(self, peripheral, name):
228 self.peripheral = peripheral
229 self.name = name
230
231 def __call__(self, *args):
232 #print "__call__", self.name, self.peripheral.slow, args
233 if not self.peripheral.slow:
234 return ''
235 return getattr(self.peripheral.slow, self.name)(*args[1:])
236
237
238 class PeripheralIface(object):
239 def __init__(self, ifacename):
240 self.slow = None
241 slow = slowfactory.getcls(ifacename)
242 print "Iface", ifacename, slow
243 if slow:
244 self.slow = slow(ifacename)
245 self.slow.peripheral = self
246 for fname in ['slowimport',
247 'extifinstance', 'extifdecl',
248 'slowifdecl', 'slowifdeclmux',
249 'mkslow_peripheral',
250 'mkfast_peripheral',
251 'mk_plic', 'mk_ext_ifacedef',
252 'mk_connection', 'mk_cellconn', 'mk_pincon']:
253 fn = CallFn(self, fname)
254 setattr(self, fname, types.MethodType(fn, self))
255
256 #print "PeripheralIface"
257 #print dir(self)
258
259 def mksuffix(self, name, i):
260 if self.slow is None:
261 return i
262 return self.slow.mksuffix(name, i)
263
264 def axi_reg_def(self, start, count):
265 if not self.slow:
266 return ('', 0)
267 return self.slow.axi_reg_def(start, self.ifacename, count)
268
269 def axi_slave_idx(self, start, count, typ):
270 if not self.slow:
271 return ('', 0)
272 return self.slow.axi_slave_idx(start, self.ifacename, count, typ)
273
274 def axi_addr_map(self, count):
275 if not self.slow:
276 return ''
277 return self.slow.axi_addr_map(self.ifacename, count)
278
279
280 class PeripheralInterfaces(object):
281 def __init__(self):
282 self.fastbusmode = False
283
284 def slowimport(self, *args):
285 ret = []
286 for (name, count) in self.ifacecount:
287 #print "slowimport", name, self.data[name].slowimport
288 ret.append(self.data[name].slowimport())
289 return '\n'.join(list(filter(None, ret)))
290
291 def extifinstance(self, *args):
292 ret = []
293 for (name, count) in self.ifacecount:
294 for i in range(count):
295 iname = self.data[name].iname().format(i)
296 if not self.is_on_fastbus(name, i):
297 continue
298 ret.append(self.data[name].extifinstance(name, i))
299 return '\n'.join(list(filter(None, ret)))
300
301 def extifdecl(self, *args):
302 ret = []
303 for (name, count) in self.ifacecount:
304 for i in range(count):
305 if not self.is_on_fastbus(name, i):
306 continue
307 ret.append(self.data[name].extifdecl(name, i))
308 return '\n'.join(list(filter(None, ret)))
309
310 def slowifdeclmux(self, *args):
311 ret = []
312 for (name, count) in self.ifacecount:
313 for i in range(count):
314 ret.append(self.data[name].slowifdeclmux(name, i))
315 return '\n'.join(list(filter(None, ret)))
316
317 def slowifdecl(self, *args):
318 ret = []
319 for (name, count) in self.ifacecount:
320 for i in range(count):
321 if self.is_on_fastbus(name, i):
322 continue
323 ret.append(self.data[name].slowifdecl().format(i, name))
324 return '\n'.join(list(filter(None, ret)))
325
326 def axi_reg_def(self, *args):
327 ret = []
328 start = 0x00011100 # start of AXI peripherals address
329 for (name, count) in self.ifacecount:
330 for i in range(count):
331 if self.is_on_fastbus(name, i):
332 continue
333 x = self.data[name].axi_reg_def(start, i)
334 #print ("ifc", name, x)
335 (rdef, offs) = x
336 ret.append(rdef)
337 start += offs
338 return '\n'.join(list(filter(None, ret)))
339
340 def _axi_num_idx(self, start, template, typ, idxtype, *args):
341 ret = []
342 for (name, count) in self.ifacecount:
343 for i in range(count):
344 if self.is_on_fastbus(name, i):
345 continue
346 (rdef, offs) = self.data[name].axi_slave_idx(start, i, idxtype)
347 #print ("ifc", name, rdef, offs)
348 ret.append(rdef)
349 start += offs
350 ret.append("typedef %d LastGen_%s_num;" % (start - 1, typ))
351 decls = '\n'.join(list(filter(None, ret)))
352 return template.format(decls)
353
354 def axi_slave_idx(self, *args):
355 return self._axi_num_idx(0, axi_slave_declarations, 'slave',
356 '', *args)
357
358 def axi_fastslave_idx(self, *args):
359 return self._axi_num_idx(0, axi_fastslave_declarations, 'fastslave',
360 'fast', *args)
361
362 def axi_addr_map(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].axi_addr_map(i))
369 return '\n'.join(list(filter(None, ret)))
370
371 def mkfast_peripheral(self, *args):
372 ret = []
373 for (name, count) in self.ifacecount:
374 for i in range(count):
375 if self.is_on_fastbus(name, i):
376 continue
377 #print "mkfast", name, count
378 x = self.data[name].mkfast_peripheral()
379 print name, count, x
380 suffix = self.data[name].mksuffix(name, i)
381 ret.append(x.format(suffix))
382 return '\n'.join(list(filter(None, ret)))
383
384 def mkslow_peripheral(self, *args):
385 ret = []
386 for (name, count) in self.ifacecount:
387 for i in range(count):
388 if self.is_on_fastbus(name, i):
389 continue
390 #print "mkslow", name, count
391 x = self.data[name].mkslow_peripheral()
392 print name, count, x
393 suffix = self.data[name].mksuffix(name, i)
394 ret.append(x.format(suffix))
395 return '\n'.join(list(filter(None, ret)))
396
397 def mk_connection(self, *args):
398 ret = []
399 for (name, count) in self.ifacecount:
400 for i in range(count):
401 if self.is_on_fastbus(name, i):
402 continue
403 txt = self.data[name].mk_connection(i)
404 if name == 'gpioa':
405 print "txt", txt
406 print self.data[name].mk_connection
407 ret.append(txt)
408 return '\n'.join(list(filter(None, ret)))
409
410 def mk_cellconn(self):
411 ret = []
412 cellcount = 0
413 for (name, count) in self.ifacecount:
414 for i in range(count):
415 if self.is_on_fastbus(name, i):
416 continue
417 res = self.data[name].mk_cellconn(cellcount, name, i)
418 if not res:
419 continue
420 (txt, cellcount) = res
421 ret.append(txt)
422 ret = '\n'.join(list(filter(None, ret)))
423 return pinmux_cellrule.format(ret)
424
425 def mk_pincon(self):
426 ret = []
427 for (name, count) in self.ifacecount:
428 for i in range(count):
429 if self.is_on_fastbus(name, i):
430 continue
431 txt = self.data[name].mk_pincon(name, i)
432 ret.append(txt)
433 return '\n'.join(list(filter(None, ret)))
434
435 def mk_ext_ifacedef(self):
436 ret = []
437 for (name, count) in self.ifacecount:
438 for i in range(count):
439 if self.is_on_fastbus(name, i):
440 continue
441 txt = self.data[name].mk_ext_ifacedef(name, i)
442 ret.append(txt)
443 return '\n'.join(list(filter(None, ret)))
444
445 def mk_plic(self):
446 ret = []
447 irq_offs = 8 # XXX: DMA scovers 0-7?
448 for (name, count) in self.ifacecount:
449 for i in range(count):
450 if self.is_on_fastbus(name, i):
451 continue
452 res = self.data[name].mk_plic(i, irq_offs)
453 if not res:
454 continue
455 (txt, irq_offs) = res
456 ret.append(txt)
457 self.num_slow_irqs = irq_offs
458 return '\n'.join(list(filter(None, ret)))
459
460 def mk_sloirqsdef(self):
461 return " `define NUM_SLOW_IRQS {0}".format(self.num_slow_irqs)
462
463 def is_on_fastbus(self, name, i):
464 #print "fastbus mode", self.fastbusmode, name, i
465 iname = self.data[name].iname().format(i)
466 if self.fastbusmode:
467 return iname not in self.fastbus
468 return iname in self.fastbus
469
470
471 class PFactory(object):
472 def getcls(self, name):
473 from uart import uart
474 from quart import quart
475 from sdmmc import sdmmc
476 from pwm import pwm
477 from eint import eint
478 from rs232 import rs232
479 from twi import twi
480 from eint import eint
481 from jtag import jtag
482 from spi import spi, mspi
483 from qspi import qspi, mqspi
484 from gpio import gpio
485 from rgbttl import rgbttl
486
487 for k, v in {'uart': uart,
488 'rs232': rs232,
489 'twi': twi,
490 'quart': quart,
491 'mqspi': mqspi,
492 'mspi': mspi,
493 'qspi': qspi,
494 'spi': spi,
495 'pwm': pwm,
496 'eint': eint,
497 'sd': sdmmc,
498 'jtag': jtag,
499 'lcd': rgbttl,
500 'gpio': gpio
501 }.items():
502 if name.startswith(k):
503 return v
504 return None
505
506
507 slowfactory = PFactory()
508
509 if __name__ == '__main__':
510 p = uart('uart')
511 print p.slowimport()
512 print p.slowifdecl()
513 i = PeripheralIface('uart')
514 print i, i.slow
515 i = PeripheralIface('gpioa')
516 print i, i.slow