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