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