add mkfast_peripherals fn
[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_slave_idx(self, *args):
337 ret = []
338 start = 0
339 for (name, count) in self.ifacecount:
340 for i in range(count):
341 if self.is_on_fastbus(name, i):
342 continue
343 (rdef, offs) = self.data[name].axi_slave_idx(start, i)
344 #print ("ifc", name, rdef, offs)
345 ret.append(rdef)
346 start += offs
347 ret.append("typedef %d LastGen_slave_num;" % (start - 1))
348 decls = '\n'.join(list(filter(None, ret)))
349 return axi_slave_declarations.format(decls)
350
351 def axi_addr_map(self, *args):
352 ret = []
353 for (name, count) in self.ifacecount:
354 for i in range(count):
355 if self.is_on_fastbus(name, i):
356 continue
357 ret.append(self.data[name].axi_addr_map(i))
358 return '\n'.join(list(filter(None, ret)))
359
360 def mkfast_peripheral(self, *args):
361 ret = []
362 for (name, count) in self.ifacecount:
363 for i in range(count):
364 if self.is_on_fastbus(name, i):
365 continue
366 #print "mkfast", name, count
367 x = self.data[name].mkfast_peripheral()
368 print name, count, x
369 suffix = self.data[name].mksuffix(name, i)
370 ret.append(x.format(suffix))
371 return '\n'.join(list(filter(None, ret)))
372
373 def mkslow_peripheral(self, *args):
374 ret = []
375 for (name, count) in self.ifacecount:
376 for i in range(count):
377 if self.is_on_fastbus(name, i):
378 continue
379 #print "mkslow", name, count
380 x = self.data[name].mkslow_peripheral()
381 print name, count, x
382 suffix = self.data[name].mksuffix(name, i)
383 ret.append(x.format(suffix))
384 return '\n'.join(list(filter(None, ret)))
385
386 def mk_connection(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 txt = self.data[name].mk_connection(i)
393 if name == 'gpioa':
394 print "txt", txt
395 print self.data[name].mk_connection
396 ret.append(txt)
397 return '\n'.join(list(filter(None, ret)))
398
399 def mk_cellconn(self):
400 ret = []
401 cellcount = 0
402 for (name, count) in self.ifacecount:
403 for i in range(count):
404 if self.is_on_fastbus(name, i):
405 continue
406 res = self.data[name].mk_cellconn(cellcount, name, i)
407 if not res:
408 continue
409 (txt, cellcount) = res
410 ret.append(txt)
411 ret = '\n'.join(list(filter(None, ret)))
412 return pinmux_cellrule.format(ret)
413
414 def mk_pincon(self):
415 ret = []
416 for (name, count) in self.ifacecount:
417 for i in range(count):
418 if self.is_on_fastbus(name, i):
419 continue
420 txt = self.data[name].mk_pincon(name, i)
421 ret.append(txt)
422 return '\n'.join(list(filter(None, ret)))
423
424 def mk_ext_ifacedef(self):
425 ret = []
426 for (name, count) in self.ifacecount:
427 for i in range(count):
428 if self.is_on_fastbus(name, i):
429 continue
430 txt = self.data[name].mk_ext_ifacedef(name, i)
431 ret.append(txt)
432 return '\n'.join(list(filter(None, ret)))
433
434 def mk_plic(self):
435 ret = []
436 irq_offs = 8 # XXX: DMA scovers 0-7?
437 for (name, count) in self.ifacecount:
438 for i in range(count):
439 if self.is_on_fastbus(name, i):
440 continue
441 res = self.data[name].mk_plic(i, irq_offs)
442 if not res:
443 continue
444 (txt, irq_offs) = res
445 ret.append(txt)
446 self.num_slow_irqs = irq_offs
447 return '\n'.join(list(filter(None, ret)))
448
449 def mk_sloirqsdef(self):
450 return " `define NUM_SLOW_IRQS {0}".format(self.num_slow_irqs)
451
452 def is_on_fastbus(self, name, i):
453 #print "fastbus mode", self.fastbusmode, name, i
454 iname = self.data[name].iname().format(i)
455 if self.fastbusmode:
456 return iname not in self.fastbus
457 return iname in self.fastbus
458
459
460 class PFactory(object):
461 def getcls(self, name):
462 from uart import uart
463 from quart import quart
464 from sdmmc import sdmmc
465 from pwm import pwm
466 from eint import eint
467 from rs232 import rs232
468 from twi import twi
469 from eint import eint
470 from jtag import jtag
471 from spi import spi, mspi
472 from qspi import qspi, mqspi
473 from gpio import gpio
474 from rgbttl import rgbttl
475
476 for k, v in {'uart': uart,
477 'rs232': rs232,
478 'twi': twi,
479 'quart': quart,
480 'mqspi': mqspi,
481 'mspi': mspi,
482 'qspi': qspi,
483 'spi': spi,
484 'pwm': pwm,
485 'eint': eint,
486 'sd': sdmmc,
487 'jtag': jtag,
488 'lcd': rgbttl,
489 'gpio': gpio
490 }.items():
491 if name.startswith(k):
492 return v
493 return None
494
495
496 slowfactory = PFactory()
497
498 if __name__ == '__main__':
499 p = uart('uart')
500 print p.slowimport()
501 print p.slowifdecl()
502 i = PeripheralIface('uart')
503 print i, i.slow
504 i = PeripheralIface('gpioa')
505 print i, i.slow