refactor peripheral_gen, split out interface classes
[pinmux.git] / src / bsv / peripheral_gen / base.py
1 import types
2
3 class PBase(object):
4 def __init__(self, name):
5 self.name = name
6
7 def slowifdeclmux(self):
8 return ''
9
10 def slowifinstance(self):
11 return ''
12
13 def slowimport(self):
14 return ''
15
16 def num_axi_regs32(self):
17 return 0
18
19 def slowifdecl(self):
20 return ''
21
22 def get_iname(self, inum):
23 return "{0}{1}".format(self.name, self.mksuffix(self.name, inum))
24
25 def axibase(self, name, ifacenum):
26 name = name.upper()
27 return "%(name)s%(ifacenum)dBase" % locals()
28
29 def axiend(self, name, ifacenum):
30 name = name.upper()
31 return "%(name)s%(ifacenum)dEnd" % locals()
32
33 def axi_reg_def(self, start, name, ifacenum):
34 name = name.upper()
35 offs = self.num_axi_regs32() * 4 * 16
36 if offs == 0:
37 return ('', 0)
38 end = start + offs - 1
39 bname = self.axibase(name, ifacenum)
40 bend = self.axiend(name, ifacenum)
41 comment = "%d 32-bit regs" % self.num_axi_regs32()
42 return (" `define %(bname)s 'h%(start)08X\n"
43 " `define %(bend)s 'h%(end)08X // %(comment)s" % locals(),
44 offs)
45
46 def axi_slave_name(self, name, ifacenum):
47 name = name.upper()
48 return "{0}{1}_slave_num".format(name, ifacenum)
49
50 def axi_slave_idx(self, idx, name, ifacenum):
51 name = self.axi_slave_name(name, ifacenum)
52 return ("typedef {0} {1};".format(idx, name), 1)
53
54 def axi_addr_map(self, name, ifacenum):
55 bname = self.axibase(name, ifacenum)
56 bend = self.axiend(name, ifacenum)
57 name = self.axi_slave_name(name, ifacenum)
58 return """\
59 if(addr>=`{0} && addr<=`{1})
60 return tuple2(True,fromInteger(valueOf({2})));
61 else""".format(bname, bend, name)
62
63 def mk_pincon(self, name, count):
64 # TODO: really should be using bsv.interface_decl.Interfaces
65 # pin-naming rules.... logic here is hard-coded to duplicate
66 # it (see Interface.__init__ outen)
67 ret = []
68 for p in self.peripheral.pinspecs:
69 typ = p['type']
70 pname = p['name']
71 #n = "{0}{1}".format(self.name, self.mksuffix(name, count))
72 n = name # "{0}{1}".format(self.name, self.mksuffix(name, count))
73 ret.append(" //%s %s" % (n, str(p)))
74 sname = self.peripheral.pname(pname).format(count)
75 ps = "pinmux.peripheral_side.%s" % sname
76 if typ == 'out' or typ == 'inout':
77 ret.append(" rule con_%s%d_%s_out;" % (name, count, pname))
78 fname = self.pinname_out(pname)
79 if not n.startswith('gpio'): # XXX EURGH! horrible hack
80 n_ = "{0}{1}".format(n, count)
81 else:
82 n_ = n
83 if fname:
84 if p.get('outen'):
85 ps_ = ps + '_out'
86 else:
87 ps_ = ps
88 ret.append(" {0}({1}.{2});".format(ps_, n_, fname))
89 fname = None
90 if p.get('outen'):
91 fname = self.pinname_outen(pname)
92 if fname:
93 if isinstance(fname, str):
94 fname = "{0}.{1}".format(n_, fname)
95 fname = self.pinname_tweak(pname, 'outen', fname)
96 ret.append(" {0}_outen({1});".format(ps, fname))
97 ret.append(" endrule")
98 if typ == 'in' or typ == 'inout':
99 fname = self.pinname_in(pname)
100 if fname:
101 if p.get('outen'):
102 ps_ = ps + '_in'
103 else:
104 ps_ = ps
105 ret.append(
106 " rule con_%s%d_%s_in;" %
107 (name, count, pname))
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(" {1}({0});".format(ps_, n_))
112 ret.append(" endrule")
113 return '\n'.join(ret)
114
115 def mk_cellconn(self, *args):
116 return ''
117
118 def mkslow_peripheral(self, size=0):
119 return ''
120
121 def mksuffix(self, name, i):
122 return i
123
124 def __mk_connection(self, con, aname):
125 txt = " mkConnection (slow_fabric.v_to_slaves\n" + \
126 " [fromInteger(valueOf({1}))],\n" + \
127 " {0});"
128
129 print "PBase __mk_connection", self.name, aname
130 if not con:
131 return ''
132 return txt.format(con, aname)
133
134 def mk_connection(self, count, name=None):
135 if name is None:
136 name = self.name
137 print "PBase mk_conn", self.name, count
138 aname = self.axi_slave_name(name, count)
139 #dname = self.mksuffix(name, count)
140 #dname = "{0}{1}".format(name, dname)
141 con = self._mk_connection(name, count).format(count, aname)
142 return self.__mk_connection(con, aname)
143
144 def _mk_connection(self, name=None, count=0):
145 return ''
146
147 def pinname_out(self, pname):
148 return ''
149
150 def pinname_in(self, pname):
151 return ''
152
153 def pinname_outen(self, pname):
154 return ''
155
156 def ifname_tweak(self, pname, typ, txt):
157 return txt
158
159 def pinname_tweak(self, pname, typ, txt):
160 return txt
161
162 def num_irqs(self):
163 return 0
164
165 def mk_plic(self, inum, irq_offs):
166 res = []
167 print "mk_plic", self.name, inum, irq_offs
168 niq = self.num_irqs()
169 if niq == 0:
170 return ('', irq_offs)
171 name = self.get_iname(inum)
172 res.append(" // PLIC rules for {0}".format(name))
173 for idx in range(niq):
174 plic_obj = self.plic_object(name, idx)
175 print "plic_obj", name, idx, plic_obj
176 plic = mkplic_rule.format(name, plic_obj, irq_offs)
177 res.append(plic)
178 irq_offs += 1 # increment to next irq
179 return ('\n'.join(res), irq_offs)
180
181 def mk_ext_ifacedef(self, iname, inum):
182 return ''
183
184
185 mkplic_rule = """\
186 rule rl_connect_{0}_to_plic_{2};
187 if({1} == 1'b1) begin
188 ff_gateway_queue[{2}].enq(1);
189 plic.ifc_external_irq[{2}].irq_frm_gateway(True);
190 end
191 endrule
192 """
193
194
195 axi_slave_declarations = """\
196 typedef 0 SlowMaster;
197 {0}
198 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
199 CLINT_slave_num;
200 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
201 Plic_slave_num;
202 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
203 AxiExp1_slave_num;
204 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
205 """
206
207 pinmux_cellrule = """\
208 rule connect_select_lines_pinmux;
209 {0}
210 endrule
211 """
212
213
214 class CallFn(object):
215 def __init__(self, peripheral, name):
216 self.peripheral = peripheral
217 self.name = name
218
219 def __call__(self, *args):
220 #print "__call__", self.name, self.peripheral.slow, args
221 if not self.peripheral.slow:
222 return ''
223 return getattr(self.peripheral.slow, self.name)(*args[1:])
224
225
226 class PeripheralIface(object):
227 def __init__(self, ifacename):
228 self.slow = None
229 slow = slowfactory.getcls(ifacename)
230 print "Iface", ifacename, slow
231 if slow:
232 self.slow = slow(ifacename)
233 self.slow.peripheral = self
234 for fname in ['slowimport',
235 'slowifinstance', 'slowifdecl', 'slowifdeclmux',
236 'mkslow_peripheral', 'mk_plic', 'mk_ext_ifacedef',
237 'mk_connection', 'mk_cellconn', 'mk_pincon']:
238 fn = CallFn(self, fname)
239 setattr(self, fname, types.MethodType(fn, self))
240
241 #print "PeripheralIface"
242 #print dir(self)
243
244 def mksuffix(self, name, i):
245 if self.slow is None:
246 return i
247 return self.slow.mksuffix(name, i)
248
249 def axi_reg_def(self, start, count):
250 if not self.slow:
251 return ('', 0)
252 return self.slow.axi_reg_def(start, self.ifacename, count)
253
254 def axi_slave_idx(self, start, count):
255 if not self.slow:
256 return ('', 0)
257 return self.slow.axi_slave_idx(start, self.ifacename, count)
258
259 def axi_addr_map(self, count):
260 if not self.slow:
261 return ''
262 return self.slow.axi_addr_map(self.ifacename, count)
263
264
265 class PeripheralInterfaces(object):
266 def __init__(self):
267 pass
268
269 def slowimport(self, *args):
270 ret = []
271 for (name, count) in self.ifacecount:
272 #print "slowimport", name, self.data[name].slowimport
273 ret.append(self.data[name].slowimport())
274 return '\n'.join(list(filter(None, ret)))
275
276 def slowifinstance(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].slowifinstance())
281 return '\n'.join(list(filter(None, ret)))
282
283 def slowifdeclmux(self, *args):
284 ret = []
285 for (name, count) in self.ifacecount:
286 for i in range(count):
287 ret.append(self.data[name].slowifdeclmux().format(i, name))
288 return '\n'.join(list(filter(None, ret)))
289
290 def slowifdecl(self, *args):
291 ret = []
292 for (name, count) in self.ifacecount:
293 for i in range(count):
294 ret.append(self.data[name].slowifdecl().format(i, name))
295 return '\n'.join(list(filter(None, ret)))
296
297 def axi_reg_def(self, *args):
298 ret = []
299 start = 0x00011100 # start of AXI peripherals address
300 for (name, count) in self.ifacecount:
301 for i in range(count):
302 x = self.data[name].axi_reg_def(start, i)
303 #print ("ifc", name, x)
304 (rdef, offs) = x
305 ret.append(rdef)
306 start += offs
307 return '\n'.join(list(filter(None, ret)))
308
309 def axi_slave_idx(self, *args):
310 ret = []
311 start = 0
312 for (name, count) in self.ifacecount:
313 for i in range(count):
314 (rdef, offs) = self.data[name].axi_slave_idx(start, i)
315 #print ("ifc", name, rdef, offs)
316 ret.append(rdef)
317 start += offs
318 ret.append("typedef %d LastGen_slave_num;" % (start - 1))
319 decls = '\n'.join(list(filter(None, ret)))
320 return axi_slave_declarations.format(decls)
321
322 def axi_addr_map(self, *args):
323 ret = []
324 for (name, count) in self.ifacecount:
325 for i in range(count):
326 ret.append(self.data[name].axi_addr_map(i))
327 return '\n'.join(list(filter(None, ret)))
328
329 def mkslow_peripheral(self, *args):
330 ret = []
331 for (name, count) in self.ifacecount:
332 for i in range(count):
333 print "mkslow", name, count
334 x = self.data[name].mkslow_peripheral()
335 print name, count, x
336 suffix = self.data[name].mksuffix(name, i)
337 ret.append(x.format(suffix))
338 return '\n'.join(list(filter(None, ret)))
339
340 def mk_connection(self, *args):
341 ret = []
342 for (name, count) in self.ifacecount:
343 for i in range(count):
344 print "mk_conn", name, i
345 txt = self.data[name].mk_connection(i)
346 if name == 'gpioa':
347 print "txt", txt
348 print self.data[name].mk_connection
349 ret.append(txt)
350 return '\n'.join(list(filter(None, ret)))
351
352 def mk_cellconn(self):
353 ret = []
354 cellcount = 0
355 for (name, count) in self.ifacecount:
356 for i in range(count):
357 res = self.data[name].mk_cellconn(cellcount, name, i)
358 if not res:
359 continue
360 (txt, cellcount) = res
361 ret.append(txt)
362 ret = '\n'.join(list(filter(None, ret)))
363 return pinmux_cellrule.format(ret)
364
365 def mk_pincon(self):
366 ret = []
367 for (name, count) in self.ifacecount:
368 for i in range(count):
369 txt = self.data[name].mk_pincon(name, i)
370 ret.append(txt)
371 return '\n'.join(list(filter(None, ret)))
372
373 def mk_ext_ifacedef(self):
374 ret = []
375 for (name, count) in self.ifacecount:
376 for i in range(count):
377 txt = self.data[name].mk_ext_ifacedef(name, i)
378 ret.append(txt)
379 return '\n'.join(list(filter(None, ret)))
380
381
382 def mk_plic(self):
383 ret = []
384 irq_offs = 8 # XXX: DMA scovers 0-7?
385 for (name, count) in self.ifacecount:
386 for i in range(count):
387 res = self.data[name].mk_plic(i, irq_offs)
388 if not res:
389 continue
390 (txt, irq_offs) = res
391 ret.append(txt)
392 self.num_slow_irqs = irq_offs
393 return '\n'.join(list(filter(None, ret)))
394
395 def mk_sloirqsdef(self):
396 return " `define NUM_SLOW_IRQS {0}".format(self.num_slow_irqs)
397
398
399 class PFactory(object):
400 def getcls(self, name):
401 from uart import uart
402 from quart import quart
403 from sdmmc import sdmmc
404 from pwm import pwm
405 from eint import eint
406 from rs232 import rs232
407 from twi import twi
408 from eint import eint
409 from jtag import jtag
410 from spi import spi
411 from qspi import qspi
412 from gpio import gpio
413
414 for k, v in {'uart': uart,
415 'rs232': rs232,
416 'twi': twi,
417 'quart': quart,
418 'qspi': qspi,
419 'spi': spi,
420 'pwm': pwm,
421 'eint': eint,
422 'sd': sdmmc,
423 'jtag': jtag,
424 'gpio': gpio
425 }.items():
426 if name.startswith(k):
427 return v
428 return None
429
430 slowfactory = PFactory()
431
432 if __name__ == '__main__':
433 p = uart('uart')
434 print p.slowimport()
435 print p.slowifdecl()
436 i = PeripheralIface('uart')
437 print i, i.slow
438 i = PeripheralIface('gpioa')
439 print i, i.slow