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