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