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