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