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