5 def __init__(self
, name
):
8 def extifdecl(self
, name
, count
):
9 sname
= self
.get_iname(count
)
10 return " interface PeripheralSide%s %s;" % (name
.upper(), sname
)
12 def slowifdeclmux(self
, name
, count
):
18 def num_axi_regs32(self
):
24 def get_iname(self
, inum
):
25 return "{0}{1}".format(self
.name
, self
.mksuffix(self
.name
, inum
))
27 def axibase(self
, name
, ifacenum
):
29 return "%(name)s%(ifacenum)dBase" % locals()
31 def axiend(self
, name
, ifacenum
):
33 return "%(name)s%(ifacenum)dEnd" % locals()
35 def axi_reg_def(self
, start
, name
, ifacenum
):
37 offs
= self
.num_axi_regs32() * 4 * 16
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(),
48 def axi_slave_name(self
, name
, ifacenum
):
50 return "{0}{1}_slave_num".format(name
, ifacenum
)
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)
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
)
61 if(addr>=`{0} && addr<=`{1})
62 return tuple2(True,fromInteger(valueOf({2})));
63 else""".format(bname
, bend
, name
)
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)
70 for p
in self
.peripheral
.pinspecs
:
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
)
90 ret
.append(" mkConnection({0},\n\t\t\t{1}.{2});"
91 .format(ps_
, n_
, fname
))
94 fname
= self
.pinname_outen(pname
)
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});"
101 if typ
== 'in' or typ
== 'inout':
102 fname
= self
.pinname_in(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(" mkConnection({1}, {0});".format(ps_
, n_
))
112 return '\n'.join(ret
)
114 def mk_cellconn(self
, *args
):
117 def mkslow_peripheral(self
, size
=0):
120 def mksuffix(self
, name
, i
):
123 def __mk_connection(self
, con
, aname
):
124 txt
= " mkConnection (slow_fabric.v_to_slaves\n" + \
125 " [fromInteger(valueOf({1}))],\n" + \
128 print "PBase __mk_connection", self
.name
, aname
131 return txt
.format(con
, aname
)
133 def mk_connection(self
, count
, name
=None):
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
)
143 def _mk_connection(self
, name
=None, count
=0):
146 def pinname_out(self
, pname
):
149 def pinname_in(self
, pname
):
152 def pinname_outen(self
, pname
):
155 def ifname_tweak(self
, pname
, typ
, txt
):
158 def pinname_tweak(self
, pname
, typ
, txt
):
164 def mk_plic(self
, inum
, irq_offs
):
166 print "mk_plic", self
.name
, inum
, irq_offs
167 niq
= self
.num_irqs()
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
)
177 irq_offs
+= 1 # increment to next irq
178 return ('\n'.join(res
), irq_offs
)
180 def mk_ext_ifacedef(self
, iname
, inum
):
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
)
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);
201 axi_slave_declarations
= """\
202 typedef 0 SlowMaster;
204 typedef TAdd#(LastGen_slave_num,`ifdef CLINT 1 `else 0 `endif )
206 typedef TAdd#(CLINT_slave_num ,`ifdef PLIC 1 `else 0 `endif )
208 typedef TAdd#(Plic_slave_num ,`ifdef AXIEXP 1 `else 0 `endif )
210 typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
213 pinmux_cellrule
= """\
214 rule connect_select_lines_pinmux;
220 class CallFn(object):
221 def __init__(self
, peripheral
, name
):
222 self
.peripheral
= peripheral
225 def __call__(self
, *args
):
226 #print "__call__", self.name, self.peripheral.slow, args
227 if not self
.peripheral
.slow
:
229 return getattr(self
.peripheral
.slow
, self
.name
)(*args
[1:])
232 class PeripheralIface(object):
233 def __init__(self
, ifacename
):
235 slow
= slowfactory
.getcls(ifacename
)
236 print "Iface", ifacename
, 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
))
248 #print "PeripheralIface"
251 def mksuffix(self
, name
, i
):
252 if self
.slow
is None:
254 return self
.slow
.mksuffix(name
, i
)
256 def axi_reg_def(self
, start
, count
):
259 return self
.slow
.axi_reg_def(start
, self
.ifacename
, count
)
261 def axi_slave_idx(self
, start
, count
):
264 return self
.slow
.axi_slave_idx(start
, self
.ifacename
, count
)
266 def axi_addr_map(self
, count
):
269 return self
.slow
.axi_addr_map(self
.ifacename
, count
)
272 class PeripheralInterfaces(object):
276 def slowimport(self
, *args
):
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
)))
283 def extifinstance(self
, *args
):
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
):
290 ret
.append(self
.data
[name
].extifinstance(name
, i
))
291 return '\n'.join(list(filter(None, ret
)))
293 def extifdecl(self
, *args
):
295 for (name
, count
) in self
.ifacecount
:
296 for i
in range(count
):
297 if not self
.is_on_fastbus(name
, i
):
299 ret
.append(self
.data
[name
].extifdecl(name
, i
))
300 return '\n'.join(list(filter(None, ret
)))
302 def slowifdeclmux(self
, *args
):
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
)))
309 def slowifdecl(self
, *args
):
311 for (name
, count
) in self
.ifacecount
:
312 for i
in range(count
):
313 if self
.is_on_fastbus(name
, i
):
315 ret
.append(self
.data
[name
].slowifdecl().format(i
, name
))
316 return '\n'.join(list(filter(None, ret
)))
318 def axi_reg_def(self
, *args
):
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
):
325 x
= self
.data
[name
].axi_reg_def(start
, i
)
326 #print ("ifc", name, x)
330 return '\n'.join(list(filter(None, ret
)))
332 def axi_slave_idx(self
, *args
):
335 for (name
, count
) in self
.ifacecount
:
336 for i
in range(count
):
337 if self
.is_on_fastbus(name
, i
):
339 (rdef
, offs
) = self
.data
[name
].axi_slave_idx(start
, i
)
340 #print ("ifc", name, rdef, 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
)
347 def axi_addr_map(self
, *args
):
349 for (name
, count
) in self
.ifacecount
:
350 for i
in range(count
):
351 if self
.is_on_fastbus(name
, i
):
353 ret
.append(self
.data
[name
].axi_addr_map(i
))
354 return '\n'.join(list(filter(None, ret
)))
356 def mkslow_peripheral(self
, *args
):
358 for (name
, count
) in self
.ifacecount
:
359 for i
in range(count
):
360 if self
.is_on_fastbus(name
, i
):
362 print "mkslow", name
, count
363 x
= self
.data
[name
].mkslow_peripheral()
365 suffix
= self
.data
[name
].mksuffix(name
, i
)
366 ret
.append(x
.format(suffix
))
367 return '\n'.join(list(filter(None, ret
)))
369 def mk_connection(self
, *args
):
371 for (name
, count
) in self
.ifacecount
:
372 for i
in range(count
):
373 if self
.is_on_fastbus(name
, i
):
375 txt
= self
.data
[name
].mk_connection(i
)
378 print self
.data
[name
].mk_connection
380 return '\n'.join(list(filter(None, ret
)))
382 def mk_cellconn(self
):
385 for (name
, count
) in self
.ifacecount
:
386 for i
in range(count
):
387 if self
.is_on_fastbus(name
, i
):
389 res
= self
.data
[name
].mk_cellconn(cellcount
, name
, i
)
392 (txt
, cellcount
) = res
394 ret
= '\n'.join(list(filter(None, ret
)))
395 return pinmux_cellrule
.format(ret
)
399 for (name
, count
) in self
.ifacecount
:
400 for i
in range(count
):
401 if self
.is_on_fastbus(name
, i
):
403 txt
= self
.data
[name
].mk_pincon(name
, i
)
405 return '\n'.join(list(filter(None, ret
)))
407 def mk_ext_ifacedef(self
):
409 for (name
, count
) in self
.ifacecount
:
410 for i
in range(count
):
411 if self
.is_on_fastbus(name
, i
):
413 txt
= self
.data
[name
].mk_ext_ifacedef(name
, i
)
415 return '\n'.join(list(filter(None, 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
):
424 res
= self
.data
[name
].mk_plic(i
, irq_offs
)
427 (txt
, irq_offs
) = res
429 self
.num_slow_irqs
= irq_offs
430 return '\n'.join(list(filter(None, ret
)))
432 def mk_sloirqsdef(self
):
433 return " `define NUM_SLOW_IRQS {0}".format(self
.num_slow_irqs
)
435 def is_on_fastbus(self
, name
, i
):
436 iname
= self
.data
[name
].iname().format(i
)
437 return iname
in self
.fastbus
439 class PFactory(object):
440 def getcls(self
, name
):
441 from uart
import uart
442 from quart
import quart
443 from sdmmc
import sdmmc
445 from eint
import eint
446 from rs232
import rs232
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
455 for k
, v
in {'uart': uart
,
470 if name
.startswith(k
):
475 slowfactory
= PFactory()
477 if __name__
== '__main__':
481 i
= PeripheralIface('uart')
483 i
= PeripheralIface('gpioa')