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