autopep8 whitespace cleanup
[pinmux.git] / src / spec / interfaces.py
1 #!/usr/bin/env python
2
3 from spec.pinfunctions import pinspec
4 from copy import deepcopy
5
6
7 def namesuffix(name, suffix, namelist):
8 names = []
9 for n in namelist:
10 if n:
11 names.append("%s%s_%s" % (name, suffix, n))
12 else:
13 names.append("%s_%s" % (name, suffix))
14 return names
15
16
17 class PinGen(object):
18 """ a meta-helper which creates pins from the pinspec
19 and adds them to the pinouts.
20
21 __call__ is used to effectively create a lambda function, which
22 in combination with setattr (below) gives the function a name
23 in the Pinouts class, according to the pinspec.
24 """
25
26 def __init__(self, pinouts, fname, pinfn, bankspec):
27 self.pinouts = pinouts
28 self.bankspec = bankspec
29 self.pinfn = pinfn
30 self.fname = fname
31
32 def __call__(self, suffix, offs, bank, mux,
33 start=None, limit=None, spec=None, origsuffix=None):
34 pingroup = self.pinfn(suffix, bank)
35 if isinstance(pingroup, tuple):
36 prefix, pingroup = pingroup
37 else:
38 prefix = self.fname
39 if start and limit: # limit turns into an offset from start
40 limit = start + limit
41 pingroup = pingroup[start:limit] # see comment in spec.pinfunctions
42 pins = Pins(prefix, pingroup, self.bankspec,
43 suffix, offs, bank, mux,
44 spec, origsuffix=suffix)
45 self.pinouts.pinmerge(pins)
46
47 # pinouts class
48
49
50 class Pinouts(object):
51 def __init__(self, bankspec):
52 self.bankspec = bankspec
53 self.pins = {}
54 self.fnspec = {}
55 for fname, pinfn in pinspec:
56 if isinstance(pinfn, tuple):
57 name, pinfn = pinfn
58 else:
59 name = pinfn.__name__
60 setattr(self, name, PinGen(self, fname, pinfn, self.bankspec))
61
62 def __contains__(self, k):
63 return k in self.pins
64
65 def has_key(self, k):
66 return k in self.pins
67
68 def add_spec(self, k, v):
69 self.fnspec[k] = v
70
71 def update(self, pinidx, v):
72 if pinidx not in self.pins:
73 self.pins[pinidx] = v
74 else:
75 for k in v:
76 assert k not in self.pins[pinidx], \
77 "pin %d position %d already taken\n%s\n%s" % \
78 (pinidx, k, str(v), self.pins[pinidx])
79 self.pins[pinidx].update(v)
80
81 def keys(self):
82 return self.pins.keys()
83
84 def items(self):
85 return self.pins.items()
86
87 def get(self, k):
88 return self.pins[k]
89
90 def __len__(self):
91 return len(self.pins)
92
93 def __delitem__(self, k):
94 del self.pins[k]
95
96 def __getitem__(self, k):
97 return self.pins[k]
98
99 def pinmerge(self, fn):
100 # hack, store the function specs in the pins dict
101 fname = fn.fname
102 suffix = fn.origsuffix
103 bank = fn.bank
104
105 if not hasattr(self, 'fnspec'):
106 self.fnspec = pins
107 if fname == 'GPIO':
108 fname = fname + bank
109 assert 'EINT' not in self
110 if fname not in self.fnspec:
111 self.add_spec(fname, {})
112 if suffix or fname == 'EINT' or fname == 'PWM':
113 specname = fname + suffix
114 else:
115 specname = fname
116 # print "fname bank specname suffix ", fname, bank, specname, repr(
117 # suffix)
118 if specname in self.fnspec[fname]:
119 # ok so some declarations may bring in different
120 # names at different stages (EINT, PWM, flexbus1/2)
121 # so we have to merge the names in. main thing is
122 # the pingroup
123 tomerge = self.fnspec[fname][specname]
124 for p in fn.pingroup:
125 if p not in tomerge.pingroup:
126 tomerge.pingroup.append(p)
127 tomerge.pins.update(fn.pins)
128 tomerge.fntype.update(fn.fntype)
129 else:
130 self.fnspec[fname][specname] = deepcopy(fn)
131
132 # merge actual pins
133 for (pinidx, v) in fn.pins.items():
134 self.update(pinidx, v)
135
136
137 class Pins(object):
138
139 def __init__(self, fname, pingroup, bankspec, suffix, offs, bank, mux,
140 spec=None, limit=None, origsuffix=None):
141
142 # function type can be in, out or inout, represented by - + *
143 # strip function type out of each pin name
144 self.fntype = {}
145 for i in range(len(pingroup)):
146 pname = pingroup[i]
147 if not pname:
148 continue
149 fntype = pname[-1]
150 if fntype not in '+-*':
151 continue
152 pname = pname[:-1]
153 fntype = {'-': 'in', '+': 'out', '*': 'inout'}[fntype]
154 self.fntype[pname] = fntype
155 pingroup[i] = pname
156
157 self.fname = fname
158 self.pingroup = pingroup
159 self.bankspec = bankspec
160 self.suffix = suffix
161 self.origsuffix = origsuffix or suffix
162 self.bank = bank
163 self.mux = mux
164
165 # create consistent name suffixes
166 pingroup = namesuffix(fname, suffix, pingroup)
167 suffix = '' # hack
168
169 res = {}
170 names = {}
171 idx = 0
172 for name in pingroup[:limit]:
173 if suffix and name:
174 name_ = "%s_%s" % (name, suffix)
175 else:
176 name_ = name
177 if spec and name in spec:
178 continue
179 pin = {mux: (name_, bank)}
180 offs_bank, offs_ = offs
181 idx_ = offs_ + idx
182 idx += 1
183 idx_ += bankspec[bank]
184 res[idx_] = pin
185 names[name] = idx_
186 for name in pingroup:
187 if suffix and name:
188 name_ = "%s_%s" % (name, suffix)
189 else:
190 name_ = name
191 if not spec:
192 continue
193 if name not in spec:
194 continue
195 idx_, mux_, bank_ = spec[name]
196 idx_ = names[idx_]
197 pin = {mux_: (name_, bank_)}
198 if idx_ in res:
199 res[idx_].update(pin)
200 else:
201 res[idx_] = pin
202
203 self.pins = res