remove manual dictionary, use interface txt file definitions
[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 '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 += ' (Bit#(%s) in)' % self.bitspec
50 else:
51 res += " Bit#(%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 += '(Bit#(%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#(Bit#(%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 """
84
85 def __init__(self, ifacename, pinspecs):
86 self.ifacename = ifacename
87 self.pins = []
88 self.pinspecs = pinspecs
89 for p in pinspecs:
90 _p = {}
91 _p.update(p)
92 if p.get('outen') is True: # special case, generate 3 pins
93 del _p['outen']
94 for psuffix in ['out', 'outen', 'in']:
95 _p['name'] = "%s_%s" % (self.pname(p['name']), psuffix)
96 _p['action'] = psuffix != 'in'
97 self.pins.append(Pin(**_p))
98 else:
99 _p['name'] = self.pname(p['name'])
100 self.pins.append(Pin(**_p))
101
102 def getifacetype(self, name):
103 for p in self.pinspecs:
104 fname = "%s_%s" % (self.ifacename, p['name'])
105 print "search", self.ifacename, name, fname
106 if fname == name:
107 if p.get('action'):
108 return 'out'
109 elif p.get('outen'):
110 return 'inout'
111 return 'input'
112 return None
113
114 def pname(self, name):
115 return '%s{0}_%s' % (self.ifacename, name)
116
117 def wirefmt(self, *args):
118 res = '\n'.join(map(self.wirefmtpin, self.pins)).format(*args)
119 res += '\n'
120 for p in self.pinspecs:
121 name = self.pname(p['name']).format(*args)
122 res += " GenericIOType %s_io = GenericIOType{\n" % name
123 params = []
124 if p.get('outen') is True:
125 outname = self.ifacefmtoutfn(name)
126 params.append('outputval:%s_out,' % outname)
127 params.append('output_en:%s_outen,' % outname)
128 params.append('input_en:~%s_outen,' % outname)
129 elif p.get('action'):
130 outname = self.ifacefmtoutfn(name)
131 params.append('outputval:%s,' % outname)
132 params.append('output_en:1,')
133 params.append('input_en:0,')
134 else:
135 params.append('outputval:0,')
136 params.append('output_en:0,')
137 params.append('input_en:1,')
138 params += ['pullup_en:0,', 'pulldown_en:0,',
139 'pushpull_en:0,', 'drivestrength:0,',
140 'opendrain_en:0']
141 for param in params:
142 res += ' %s\n' % param
143 res += ' };\n'
144 return '\n' + res
145
146 def ifacefmt(self, *args):
147 res = '\n'.join(map(self.ifacefmtdecpin, self.pins)).format(*args)
148 return '\n' + res
149
150 def ifacefmtdecfn(self, name):
151 return name
152
153 def ifacefmtdecfn2(self, name):
154 return name
155
156 def ifacefmtoutfn(self, name):
157 return "wr%s" % name
158
159 def ifacefmtinfn(self, name):
160 return "wr%s" % name
161
162 def wirefmtpin(self, pin):
163 return pin.wirefmt(self.ifacefmtoutfn, self.ifacefmtinfn,
164 self.ifacefmtdecfn2)
165
166 def ifacefmtdecpin(self, pin):
167 return pin.ifacefmt(self.ifacefmtdecfn)
168
169 def ifacefmtpin(self, pin):
170 return pin.ifacedef(self.ifacefmtoutfn, self.ifacefmtinfn,
171 self.ifacefmtdecfn2)
172
173 def ifacedef(self, *args):
174 res = '\n'.join(map(self.ifacefmtpin, self.pins))
175 res = res.format(*args)
176 return '\n' + res + '\n'
177
178
179 class MuxInterface(Interface):
180
181 def wirefmt(self, *args):
182 return muxwire.format(*args)
183
184
185 class IOInterface(Interface):
186
187 def ifacefmtoutfn(self, name):
188 """ for now strip off io{0}_ part """
189 return "cell{0}_mux_out.%s" % name[6:]
190
191 def ifacefmtinfn(self, name):
192 return "cell{0}_mux_in"
193
194 def wirefmt(self, *args):
195 return generic_io.format(*args)
196
197
198 class Interfaces(UserDict):
199 """ contains a list of interface definitions
200 """
201
202 def __init__(self, pth):
203 self.pth = pth
204 self.ifacecount = []
205 UserDict.__init__(self, {})
206 ift = 'interfaces.txt'
207 if pth:
208 ift = os.path.join(pth, ift)
209 with open(ift, 'r') as ifile:
210 for ln in ifile.readlines():
211 ln = ln.strip()
212 ln = ln.split("\t")
213 name = ln[0]
214 count = int(ln[1])
215 spec = self.read_spec(pth, name)
216 self.ifaceadd(name, count, Interface(name, spec))
217
218 def getifacetype(self, fname):
219 # finds the interface type, e.g sd_d0 returns "inout"
220 for iface in self.values():
221 typ = iface.getifacetype(fname)
222 if typ:
223 return typ
224 return None
225
226 def ifaceadd(self, name, count, iface, at=None):
227 if at is None:
228 at = len(self.ifacecount)
229 self.ifacecount.insert(at, (name, count))
230 self[name] = iface
231
232 def read_spec(self, pth, name):
233 spec = []
234 fname = '%s.txt' % name
235 if pth:
236 ift = os.path.join(pth, fname)
237 with open(ift, 'r') as sfile:
238 for ln in sfile.readlines():
239 ln = ln.strip()
240 ln = ln.split("\t")
241 d = {'name': ln[0]}
242 if ln[1] == 'out':
243 d['action'] = True
244 elif ln[1] == 'inout':
245 d['outen'] = True
246 spec.append(d)
247 return spec
248
249 def ifacedef(self, f, *args):
250 for (name, count) in self.ifacecount:
251 for i in range(count):
252 f.write(self.data[name].ifacedef(i))
253
254 def ifacefmt(self, f, *args):
255 comment = '''
256 // interface declaration between %s-{0} and pinmux'''
257 for (name, count) in self.ifacecount:
258 for i in range(count):
259 c = comment % name.upper()
260 f.write(c.format(i))
261 f.write(self.data[name].ifacefmt(i))
262
263 def wirefmt(self, f, *args):
264 comment = '\n // following wires capture signals ' \
265 'to IO CELL if %s-{0} is\n' \
266 ' // allotted to it'
267 for (name, count) in self.ifacecount:
268 for i in range(count):
269 c = comment % name
270 f.write(c.format(i))
271 f.write(self.data[name].wirefmt(i))
272
273
274 # ========= Interface declarations ================ #
275
276 mux_interface = MuxInterface('cell', [{'name': 'mux', 'ready': False,
277 'enabled': False,
278 'bitspec': '{1}', 'action': True}])
279
280 io_interface = IOInterface('io',
281 [{'name': 'outputval', 'enabled': False},
282 {'name': 'output_en', 'enabled': False},
283 {'name': 'input_en', 'enabled': False},
284 {'name': 'pullup_en', 'enabled': False},
285 {'name': 'pulldown_en', 'enabled': False},
286 {'name': 'drivestrength', 'enabled': False},
287 {'name': 'pushpull_en', 'enabled': False},
288 {'name': 'opendrain_en', 'enabled': False},
289 {'name': 'inputval', 'action': True, 'io': True},
290 ])
291
292 # == Peripheral Interface definitions == #
293 # these are the interface of the peripherals to the pin mux
294 # Outputs from the peripherals will be inputs to the pinmux
295 # module. Hence the change in direction for most pins
296
297 # ======================================= #
298
299 # basic test
300 if __name__ == '__main__':
301
302 uartinterface_decl = Interface('uart',
303 [{'name': 'rx'},
304 {'name': 'tx', 'action': True},
305 ])
306
307 twiinterface_decl = Interface('twi',
308 [{'name': 'sda', 'outen': True},
309 {'name': 'scl', 'outen': True},
310 ])
311
312 def _pinmunge(p, sep, repl, dedupe=True):
313 """ munges the text so it's easier to compare.
314 splits by separator, strips out blanks, re-joins.
315 """
316 p = p.strip()
317 p = p.split(sep)
318 if dedupe:
319 p = filter(lambda x: x, p) # filter out blanks
320 return repl.join(p)
321
322 def pinmunge(p):
323 """ munges the text so it's easier to compare.
324 """
325 # first join lines by semicolons, strip out returns
326 p = p.split(";")
327 p = map(lambda x: x.replace('\n', ''), p)
328 p = '\n'.join(p)
329 # now split first by brackets, then spaces (deduping on spaces)
330 p = _pinmunge(p, "(", " ( ", False)
331 p = _pinmunge(p, ")", " ) ", False)
332 p = _pinmunge(p, " ", " ")
333 return p
334
335 def zipcmp(l1, l2):
336 l1 = l1.split("\n")
337 l2 = l2.split("\n")
338 for p1, p2 in zip(l1, l2):
339 print repr(p1)
340 print repr(p2)
341 print
342 assert p1 == p2
343
344 ifaces = Interfaces()
345
346 ifaceuart = ifaces['uart']
347 print ifaceuart.ifacedef(0)
348 print uartinterface_decl.ifacedef(0)
349 assert ifaceuart.ifacedef(0) == uartinterface_decl.ifacedef(0)
350
351 ifacetwi = ifaces['twi']
352 print ifacetwi.ifacedef(0)
353 print twiinterface_decl.ifacedef(0)
354 assert ifacetwi.ifacedef(0) == twiinterface_decl.ifacedef(0)