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