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