add fastbus system, which stops peripherals from being added to slow
[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 mkslow_peripheral(self, size=0):
118 return ''
119
120 def mksuffix(self, name, i):
121 return i
122
123 def __mk_connection(self, con, aname):
124 txt = " mkConnection (slow_fabric.v_to_slaves\n" + \
125 " [fromInteger(valueOf({1}))],\n" + \
126 " {0});"
127
128 print "PBase __mk_connection", self.name, aname
129 if not con:
130 return ''
131 return txt.format(con, aname)
132
133 def mk_connection(self, count, name=None):
134 if name is None:
135 name = self.name
136 print "PBase mk_conn", self.name, count
137 aname = self.axi_slave_name(name, count)
138 #dname = self.mksuffix(name, count)
139 #dname = "{0}{1}".format(name, dname)
140 con = self._mk_connection(name, count).format(count, aname)
141 return self.__mk_connection(con, aname)
142
143 def _mk_connection(self, name=None, count=0):
144 return ''
145
146 def pinname_out(self, pname):
147 return ''
148
149 def pinname_in(self, pname):
150 return ''
151
152 def pinname_outen(self, pname):
153 return ''
154
155 def ifname_tweak(self, pname, typ, txt):
156 return txt
157
158 def pinname_tweak(self, pname, typ, txt):
159 return txt
160
161 def num_irqs(self):
162 return 0
163
164 def mk_plic(self, inum, irq_offs):
165 res = []
166 print "mk_plic", self.name, inum, irq_offs
167 niq = self.num_irqs()
168 if niq == 0:
169 return ('', irq_offs)
170 name = self.get_iname(inum)
171 res.append(" // PLIC rules for {0}".format(name))
172 for idx in range(niq):
173 plic_obj = self.plic_object(name, idx)
174 print "plic_obj", name, idx, plic_obj
175 plic = mkplic_rule.format(name, plic_obj, irq_offs)
176 res.append(plic)
177 irq_offs += 1 # increment to next irq
178 return ('\n'.join(res), irq_offs)
179
180 def mk_ext_ifacedef(self, iname, inum):
181 return ''
182
183 def extifinstance(self, name, count):
184 sname = self.peripheral.iname().format(count)
185 pname = self.get_iname(count)
186 template = " interface {0} = pinmux.peripheral_side.{1};"
187 return template.format(pname, sname)
188
189
190
191 mkplic_rule = """\
192 rule rl_connect_{0}_to_plic_{2};
193 if({1} == 1'b1) begin
194 ff_gateway_queue[{2}].enq(1);
195 plic.ifc_external_irq[{2}].irq_frm_gateway(True);
196 end
197 endrule
198 """
199
200
201 axi_slave_declarations = """\
202 typedef 0 SlowMaster;
203 {0}
204 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
205 CLINT_slave_num;
206 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
207 Plic_slave_num;
208 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
209 AxiExp1_slave_num;
210 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
211 """
212
213 pinmux_cellrule = """\
214 rule connect_select_lines_pinmux;
215 {0}
216 endrule
217 """
218
219
220 class CallFn(object):
221 def __init__(self, peripheral, name):
222 self.peripheral = peripheral
223 self.name = name
224
225 def __call__(self, *args):
226 #print "__call__", self.name, self.peripheral.slow, args
227 if not self.peripheral.slow:
228 return ''
229 return getattr(self.peripheral.slow, self.name)(*args[1:])
230
231
232 class PeripheralIface(object):
233 def __init__(self, ifacename):
234 self.slow = None
235 slow = slowfactory.getcls(ifacename)
236 print "Iface", ifacename, slow
237 if slow:
238 self.slow = slow(ifacename)
239 self.slow.peripheral = self
240 for fname in ['slowimport',
241 'extifinstance', 'extifdecl',
242 'slowifdecl', 'slowifdeclmux',
243 'mkslow_peripheral', 'mk_plic', 'mk_ext_ifacedef',
244 'mk_connection', 'mk_cellconn', 'mk_pincon']:
245 fn = CallFn(self, fname)
246 setattr(self, fname, types.MethodType(fn, self))
247
248 #print "PeripheralIface"
249 #print dir(self)
250
251 def mksuffix(self, name, i):
252 if self.slow is None:
253 return i
254 return self.slow.mksuffix(name, i)
255
256 def axi_reg_def(self, start, count):
257 if not self.slow:
258 return ('', 0)
259 return self.slow.axi_reg_def(start, self.ifacename, count)
260
261 def axi_slave_idx(self, start, count):
262 if not self.slow:
263 return ('', 0)
264 return self.slow.axi_slave_idx(start, self.ifacename, count)
265
266 def axi_addr_map(self, count):
267 if not self.slow:
268 return ''
269 return self.slow.axi_addr_map(self.ifacename, count)
270
271
272 class PeripheralInterfaces(object):
273 def __init__(self):
274 pass
275
276 def slowimport(self, *args):
277 ret = []
278 for (name, count) in self.ifacecount:
279 #print "slowimport", name, self.data[name].slowimport
280 ret.append(self.data[name].slowimport())
281 return '\n'.join(list(filter(None, ret)))
282
283 def extifinstance(self, *args):
284 ret = []
285 for (name, count) in self.ifacecount:
286 for i in range(count):
287 iname = self.data[name].iname().format(i)
288 if not self.is_on_fastbus(name, i):
289 continue
290 ret.append(self.data[name].extifinstance(name, i))
291 return '\n'.join(list(filter(None, ret)))
292
293 def extifdecl(self, *args):
294 ret = []
295 for (name, count) in self.ifacecount:
296 for i in range(count):
297 if not self.is_on_fastbus(name, i):
298 continue
299 ret.append(self.data[name].extifdecl(name, i))
300 return '\n'.join(list(filter(None, ret)))
301
302 def slowifdeclmux(self, *args):
303 ret = []
304 for (name, count) in self.ifacecount:
305 for i in range(count):
306 ret.append(self.data[name].slowifdeclmux(name, i))
307 return '\n'.join(list(filter(None, ret)))
308
309 def slowifdecl(self, *args):
310 ret = []
311 for (name, count) in self.ifacecount:
312 for i in range(count):
313 if self.is_on_fastbus(name, i):
314 continue
315 ret.append(self.data[name].slowifdecl().format(i, name))
316 return '\n'.join(list(filter(None, ret)))
317
318 def axi_reg_def(self, *args):
319 ret = []
320 start = 0x00011100 # start of AXI peripherals address
321 for (name, count) in self.ifacecount:
322 for i in range(count):
323 if self.is_on_fastbus(name, i):
324 continue
325 x = self.data[name].axi_reg_def(start, i)
326 #print ("ifc", name, x)
327 (rdef, offs) = x
328 ret.append(rdef)
329 start += offs
330 return '\n'.join(list(filter(None, ret)))
331
332 def axi_slave_idx(self, *args):
333 ret = []
334 start = 0
335 for (name, count) in self.ifacecount:
336 for i in range(count):
337 if self.is_on_fastbus(name, i):
338 continue
339 (rdef, offs) = self.data[name].axi_slave_idx(start, i)
340 #print ("ifc", name, rdef, offs)
341 ret.append(rdef)
342 start += offs
343 ret.append("typedef %d LastGen_slave_num;" % (start - 1))
344 decls = '\n'.join(list(filter(None, ret)))
345 return axi_slave_declarations.format(decls)
346
347 def axi_addr_map(self, *args):
348 ret = []
349 for (name, count) in self.ifacecount:
350 for i in range(count):
351 if self.is_on_fastbus(name, i):
352 continue
353 ret.append(self.data[name].axi_addr_map(i))
354 return '\n'.join(list(filter(None, ret)))
355
356 def mkslow_peripheral(self, *args):
357 ret = []
358 for (name, count) in self.ifacecount:
359 for i in range(count):
360 if self.is_on_fastbus(name, i):
361 continue
362 print "mkslow", name, count
363 x = self.data[name].mkslow_peripheral()
364 print name, count, x
365 suffix = self.data[name].mksuffix(name, i)
366 ret.append(x.format(suffix))
367 return '\n'.join(list(filter(None, ret)))
368
369 def mk_connection(self, *args):
370 ret = []
371 for (name, count) in self.ifacecount:
372 for i in range(count):
373 if self.is_on_fastbus(name, i):
374 continue
375 txt = self.data[name].mk_connection(i)
376 if name == 'gpioa':
377 print "txt", txt
378 print self.data[name].mk_connection
379 ret.append(txt)
380 return '\n'.join(list(filter(None, ret)))
381
382 def mk_cellconn(self):
383 ret = []
384 cellcount = 0
385 for (name, count) in self.ifacecount:
386 for i in range(count):
387 if self.is_on_fastbus(name, i):
388 continue
389 res = self.data[name].mk_cellconn(cellcount, name, i)
390 if not res:
391 continue
392 (txt, cellcount) = res
393 ret.append(txt)
394 ret = '\n'.join(list(filter(None, ret)))
395 return pinmux_cellrule.format(ret)
396
397 def mk_pincon(self):
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_pincon(name, i)
404 ret.append(txt)
405 return '\n'.join(list(filter(None, ret)))
406
407 def mk_ext_ifacedef(self):
408 ret = []
409 for (name, count) in self.ifacecount:
410 for i in range(count):
411 if self.is_on_fastbus(name, i):
412 continue
413 txt = self.data[name].mk_ext_ifacedef(name, i)
414 ret.append(txt)
415 return '\n'.join(list(filter(None, ret)))
416
417 def mk_plic(self):
418 ret = []
419 irq_offs = 8 # XXX: DMA scovers 0-7?
420 for (name, count) in self.ifacecount:
421 for i in range(count):
422 if self.is_on_fastbus(name, i):
423 continue
424 res = self.data[name].mk_plic(i, irq_offs)
425 if not res:
426 continue
427 (txt, irq_offs) = res
428 ret.append(txt)
429 self.num_slow_irqs = irq_offs
430 return '\n'.join(list(filter(None, ret)))
431
432 def mk_sloirqsdef(self):
433 return " `define NUM_SLOW_IRQS {0}".format(self.num_slow_irqs)
434
435 def is_on_fastbus(self, name, i):
436 iname = self.data[name].iname().format(i)
437 return iname in self.fastbus
438
439 class PFactory(object):
440 def getcls(self, name):
441 from uart import uart
442 from quart import quart
443 from sdmmc import sdmmc
444 from pwm import pwm
445 from eint import eint
446 from rs232 import rs232
447 from twi import twi
448 from eint import eint
449 from jtag import jtag
450 from spi import spi, mspi
451 from qspi import qspi, mqspi
452 from gpio import gpio
453 from rgbttl import rgbttl
454
455 for k, v in {'uart': uart,
456 'rs232': rs232,
457 'twi': twi,
458 'quart': quart,
459 'mqspi': mqspi,
460 'mspi': mspi,
461 'qspi': qspi,
462 'spi': spi,
463 'pwm': pwm,
464 'eint': eint,
465 'sd': sdmmc,
466 'jtag': jtag,
467 'lcd': rgbttl,
468 'gpio': gpio
469 }.items():
470 if name.startswith(k):
471 return v
472 return None
473
474
475 slowfactory = PFactory()
476
477 if __name__ == '__main__':
478 p = uart('uart')
479 print p.slowimport()
480 print p.slowifdecl()
481 i = PeripheralIface('uart')
482 print i, i.slow
483 i = PeripheralIface('gpioa')
484 print i, i.slow