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