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