whoops must delete type field before passing to bsv Pin class
[pinmux.git] / src / bsv / interface_decl.py
1 import os.path
2
3 try:
4 from UserDict import UserDict
5 except ImportError:
6 from collections import UserDict
7
8 from bsv.wire_def import generic_io # special case
9 from bsv.wire_def import muxwire # special case
10 from ifacebase import InterfacesBase
11
12
13 class Pin(object):
14 """ pin interface declaration.
15 * name is the name of the pin
16 * ready, enabled and io all create a (* .... *) prefix
17 * action changes it to an "in" if true
18 """
19
20 def __init__(self, name,
21 ready=True,
22 enabled=True,
23 io=False,
24 action=False,
25 bitspec=None,
26 outenmode=False):
27 self.name = name
28 self.ready = ready
29 self.enabled = enabled
30 self.io = io
31 self.action = action
32 self.bitspec = bitspec if bitspec else 'Bit#(1)'
33 self.outenmode = outenmode
34
35 # bsv will look like this (method declaration):
36 """
37 (*always_ready,always_enabled*) method Bit#(1) io0_cell_outen;
38 (*always_ready,always_enabled,result="io"*) method
39 Action io0_inputval (Bit#(1) in);
40 """
41
42 def ifacefmt(self, fmtfn):
43 res = ' '
44 status = []
45 if self.ready:
46 status.append('always_ready')
47 if self.enabled:
48 status.append('always_enabled')
49 if self.io:
50 status.append('result="io"')
51 if status:
52 res += '(*'
53 res += ','.join(status)
54 res += '*)'
55 res += " method "
56 if self.io:
57 res += "\n "
58 name = fmtfn(self.name)
59 if self.action:
60 res += " Action "
61 res += name
62 res += ' (%s in)' % self.bitspec
63 else:
64 res += " %s " % self.bitspec
65 res += name
66 res += ";"
67 return res
68
69 # sample bsv method definition :
70 """
71 method Action cell0_mux(Bit#(2) in);
72 wrcell0_mux<=in;
73 endmethod
74 """
75
76 def ifacedef(self, fmtoutfn, fmtinfn, fmtdecfn):
77 res = ' method '
78 if self.action:
79 fmtname = fmtinfn(self.name)
80 res += "Action "
81 res += fmtdecfn(self.name)
82 res += '(%s in);\n' % self.bitspec
83 res += ' %s<=in;\n' % fmtname
84 res += ' endmethod'
85 else:
86 fmtname = fmtoutfn(self.name)
87 res += "%s=%s;" % (self.name, fmtname)
88 return res
89 # sample bsv wire (wire definiton):
90 """
91 Wire#(Bit#(2)) wrcell0_mux<-mkDWire(0);
92 """
93
94 def wirefmt(self, fmtoutfn, fmtinfn, fmtdecfn):
95 res = ' Wire#(%s) ' % self.bitspec
96 if self.action:
97 res += '%s' % fmtinfn(self.name)
98 else:
99 res += '%s' % fmtoutfn(self.name)
100 res += "<-mkDWire(0);"
101 return res
102
103
104 class Interface(object):
105 """ create an interface from a list of pinspecs.
106 each pinspec is a dictionary, see Pin class arguments
107 single indicates that there is only one of these, and
108 so the name must *not* be extended numerically (see pname)
109 """
110 # sample interface object:
111 """
112 twiinterface_decl = Interface('twi',
113 [{'name': 'sda', 'outen': True},
114 {'name': 'scl', 'outen': True},
115 ])
116 """
117
118 def __init__(self, ifacename, pinspecs, ganged=None, single=False):
119 self.ifacename = ifacename
120 self.ganged = ganged or {}
121 self.pins = [] # a list of instances of class Pin
122 self.pinspecs = pinspecs # a list of dictionary
123 self.single = single
124 for p in pinspecs:
125 _p = {}
126 _p.update(p)
127 if _p.has_key('type'):
128 del _p['type']
129 if p.get('outen') is True: # special case, generate 3 pins
130 del _p['outen']
131 for psuffix in ['out', 'outen', 'in']:
132 # changing the name (like sda) to (twi_sda_out)
133 _p['name'] = "%s_%s" % (self.pname(p['name']), psuffix)
134 _p['action'] = psuffix != 'in'
135 self.pins.append(Pin(**_p))
136 # will look like {'name': 'twi_sda_out', 'action': True}
137 # {'name': 'twi_sda_outen', 'action': True}
138 #{'name': 'twi_sda_in', 'action': False}
139 # NOTice - outen key is removed
140 else:
141 _p['name'] = self.pname(p['name'])
142 self.pins.append(Pin(**_p))
143
144 # sample interface object:
145 """
146 uartinterface_decl = Interface('uart',
147 [{'name': 'rx'},
148 {'name': 'tx', 'action': True},
149 ])
150 """
151 """
152 getifacetype is called multiple times in actual_pinmux.py
153 x = ifaces.getifacetype(temp), where temp is uart_rx, spi_mosi
154 Purpose is to identify is function : input/output/inout
155 """
156
157 def getifacetype(self, name):
158 for p in self.pinspecs:
159 fname = "%s_%s" % (self.ifacename, p['name'])
160 #print "search", self.ifacename, name, fname
161 if fname == name:
162 if p.get('action'):
163 return 'out'
164 elif p.get('outen'):
165 return 'inout'
166 return 'input'
167 return None
168
169 def pname(self, name):
170 """ generates the interface spec e.g. flexbus_ale
171 if there is only one flexbus interface, or
172 sd{0}_cmd if there are several. string format
173 function turns this into sd0_cmd, sd1_cmd as
174 appropriate. single mode stops the numerical extension.
175 """
176 if self.single:
177 return '%s_%s' % (self.ifacename, name)
178 return '%s{0}_%s' % (self.ifacename, name)
179
180 def busfmt(self, *args):
181 """ this function creates a bus "ganging" system based
182 on input from the {interfacename}.txt file.
183 only inout pins that are under the control of the
184 interface may be "ganged" together.
185 """
186 if not self.ganged:
187 return '' # when self.ganged is None
188 #print self.ganged
189 res = []
190 for (k, pnames) in self.ganged.items():
191 name = self.pname('%senable' % k).format(*args)
192 decl = 'Bit#(1) %s = 0;' % name
193 res.append(decl)
194 ganged = []
195 for p in self.pinspecs:
196 if p['name'] not in pnames:
197 continue
198 pname = self.pname(p['name']).format(*args)
199 if p.get('outen') is True:
200 outname = self.ifacefmtoutfn(pname)
201 ganged.append("%s_outen" % outname) # match wirefmt
202
203 gangedfmt = '{%s} = duplicate(%s);'
204 res.append(gangedfmt % (',\n '.join(ganged), name))
205 return '\n'.join(res) + '\n\n'
206
207 def wirefmt(self, *args):
208 res = '\n'.join(map(self.wirefmtpin, self.pins)).format(*args)
209 res += '\n'
210 return '\n' + res
211
212 def ifacefmt(self, *args):
213 res = '\n'.join(map(self.ifacefmtdecpin, self.pins)).format(*args)
214 return '\n' + res # pins is a list
215
216 def ifacefmtdecfn(self, name):
217 return name # like: uart
218
219 def ifacefmtdecfn2(self, name):
220 return name # like: uart
221
222 def ifacefmtdecfn3(self, name):
223 """ HACK! """
224 return "%s_outen" % name # like uart_outen
225
226 def ifacefmtoutfn(self, name):
227 return "wr%s" % name # like wruart
228
229 def ifacefmtinfn(self, name):
230 return "wr%s" % name
231
232 def wirefmtpin(self, pin):
233 return pin.wirefmt(self.ifacefmtoutfn, self.ifacefmtinfn,
234 self.ifacefmtdecfn2)
235
236 def ifacefmtdecpin(self, pin):
237 return pin.ifacefmt(self.ifacefmtdecfn)
238
239 def ifacefmtpin(self, pin):
240 decfn = self.ifacefmtdecfn2
241 outfn = self.ifacefmtoutfn
242 #print pin, pin.outenmode
243 if pin.outenmode:
244 decfn = self.ifacefmtdecfn3
245 outfn = self.ifacefmtoutenfn
246 return pin.ifacedef(outfn, self.ifacefmtinfn,
247 decfn)
248
249 def ifacedef(self, *args):
250 res = '\n'.join(map(self.ifacefmtpin, self.pins))
251 res = res.format(*args)
252 return '\n' + res + '\n'
253
254
255 class MuxInterface(Interface):
256
257 def wirefmt(self, *args):
258 return muxwire.format(*args)
259
260
261 class IOInterface(Interface):
262
263 def ifacefmtoutenfn(self, name):
264 return "cell{0}_mux_outen"
265
266 def ifacefmtoutfn(self, name):
267 """ for now strip off io{0}_ part """
268 return "cell{0}_mux_out"
269
270 def ifacefmtinfn(self, name):
271 return "cell{0}_mux_in"
272
273 def wirefmt(self, *args):
274 return generic_io.format(*args)
275
276
277 class Interfaces(InterfacesBase):
278 """ contains a list of interface definitions
279 """
280
281 def __init__(self, pth=None):
282 InterfacesBase.__init__(self, Interface, pth)
283
284 def ifacedef(self, f, *args):
285 for (name, count) in self.ifacecount:
286 for i in range(count):
287 f.write(self.data[name].ifacedef(i))
288
289 def busfmt(self, f, *args):
290 f.write("import BUtils::*;\n\n")
291 for (name, count) in self.ifacecount:
292 for i in range(count):
293 bf = self.data[name].busfmt(i)
294 f.write(bf)
295
296 def ifacefmt(self, f, *args):
297 comment = '''
298 // interface declaration between %s-{0} and pinmux'''
299 for (name, count) in self.ifacecount:
300 for i in range(count):
301 c = comment % name.upper()
302 f.write(c.format(i))
303 f.write(self.data[name].ifacefmt(i))
304
305 def wirefmt(self, f, *args):
306 comment = '\n // following wires capture signals ' \
307 'to IO CELL if %s-{0} is\n' \
308 ' // allotted to it'
309 for (name, count) in self.ifacecount:
310 for i in range(count):
311 c = comment % name
312 f.write(c.format(i))
313 f.write(self.data[name].wirefmt(i))
314
315
316 # ========= Interface declarations ================ #
317
318 mux_interface = MuxInterface('cell',
319 [{'name': 'mux', 'ready': False, 'enabled': False,
320 'bitspec': '{1}', 'action': True}])
321
322 io_interface = IOInterface(
323 'io',
324 [{'name': 'cell_out', 'enabled': True, },
325 {'name': 'cell_outen', 'enabled': True, 'outenmode': True, },
326 {'name': 'cell_in', 'action': True, 'io': True}, ])
327
328 # == Peripheral Interface definitions == #
329 # these are the interface of the peripherals to the pin mux
330 # Outputs from the peripherals will be inputs to the pinmux
331 # module. Hence the change in direction for most pins
332
333 # ======================================= #
334
335 # basic test
336 if __name__ == '__main__':
337
338 uartinterface_decl = Interface('uart',
339 [{'name': 'rx'},
340 {'name': 'tx', 'action': True},
341 ])
342
343 twiinterface_decl = Interface('twi',
344 [{'name': 'sda', 'outen': True},
345 {'name': 'scl', 'outen': True},
346 ])
347
348 def _pinmunge(p, sep, repl, dedupe=True):
349 """ munges the text so it's easier to compare.
350 splits by separator, strips out blanks, re-joins.
351 """
352 p = p.strip()
353 p = p.split(sep)
354 if dedupe:
355 p = filter(lambda x: x, p) # filter out blanks
356 return repl.join(p)
357
358 def pinmunge(p):
359 """ munges the text so it's easier to compare.
360 """
361 # first join lines by semicolons, strip out returns
362 p = p.split(";")
363 p = map(lambda x: x.replace('\n', ''), p)
364 p = '\n'.join(p)
365 # now split first by brackets, then spaces (deduping on spaces)
366 p = _pinmunge(p, "(", " ( ", False)
367 p = _pinmunge(p, ")", " ) ", False)
368 p = _pinmunge(p, " ", " ")
369 return p
370
371 def zipcmp(l1, l2):
372 l1 = l1.split("\n")
373 l2 = l2.split("\n")
374 for p1, p2 in zip(l1, l2):
375 print (repr(p1))
376 print (repr(p2))
377 print ()
378 assert p1 == p2
379
380 ifaces = Interfaces()
381
382 ifaceuart = ifaces['uart']
383 print (ifaceuart.ifacedef(0))
384 print (uartinterface_decl.ifacedef(0))
385 assert ifaceuart.ifacedef(0) == uartinterface_decl.ifacedef(0)
386
387 ifacetwi = ifaces['twi']
388 print (ifacetwi.ifacedef(0))
389 print (twiinterface_decl.ifacedef(0))
390 assert ifacetwi.ifacedef(0) == twiinterface_decl.ifacedef(0)