f66e474d4a9d8a52a7768e920da50e753bf3e99e
3 from spec
.pinfunctions
import pinspec
4 from copy
import deepcopy
7 def namesuffix(name
, suffix
, namelist
):
11 names
.append("%s%s_%s" % (name
, suffix
, n
))
13 names
.append("%s_%s" % (name
, suffix
))
18 """ a meta-helper which creates pins from the pinspec
19 and adds them to the pinouts.
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.
25 arguments to __call__ (which ends up as Pinouts.i2s, Pinouts.sdmmc
26 and so on, according to spec.pinfunctions.pinspec) are:
28 suffix: e.g. GPIO or SD or SPI
29 offs : a tuple of (Bank, Bank offset) as a string, integer
30 mux : which column in the multiplexer
31 start : the start of a subset of pins to be inserted
32 limit : the end of the subset (or the number if start also given)
33 spec : *EXTRA* pins to be inserted (at different implicit positions)
35 the pins are inserted with the suffix, starting from the
36 offset position using offs as the row and mux as the column,
37 and working in a constant increment down the rows.
39 spec is slightly complicated, basically there's extra
40 functions that we want to be on the same pin (but a different mux)
41 because their use is mutually-exclusive. without this spec
42 argument the extra pins would need to be MANUALLY moved about
43 during the development of the pinmux, if the "main" pins
44 were also moved about. this would be a pain.
46 so instead, extra pins are given of the form:
47 { 'EXTRA1' : ('PREEXISTING_NAME', MUX_COLUMN),
51 where the function EXTRA1 will always be placed on the SAME ROW
52 as PREEXISTING_NAME, just in MUX_COLUMN. this may be done
53 several times i.e. multiple new EXTRA functions can be added
54 on the same row as PRE_EXISTING_NAME, just with different
57 Note: spec must implicitly be in the same Bank.
60 def __init__(self
, pinouts
, fname
, pinfn
, bankspec
):
61 self
.pinouts
= pinouts
62 self
.bankspec
= bankspec
66 def __call__(self
, suffix
, offs
, mux
,
67 start
=None, limit
=None, spec
=None, origsuffix
=None):
69 pf
= self
.pinfn(suffix
, bank
)
70 print "pf", suffix
, bank
, pf
71 pingroup
, gangedgroup
, clock
= pf
73 self
.pinouts
.clocks
[self
.fname
] = clock
74 if isinstance(pingroup
, tuple):
75 prefix
, pingroup
= pingroup
78 if start
and limit
: # limit turns into an offset from start
80 sk
= "%s:%s" % (self
.fname
, str(suffix
))
81 print "pingroup pre", sk
, pingroup
82 pingroup
= pingroup
[start
:limit
] # see comment in spec.pinfunctions
83 print "pingroup post", sk
, pingroup
84 if self
.pinouts
.byspec
.has_key(sk
):
85 self
.pinouts
.byspec
[sk
] += pingroup
87 self
.pinouts
.byspec
[sk
] = deepcopy(pingroup
)
88 pins
= Pins(prefix
, pingroup
, self
.bankspec
,
89 suffix
, offs
, bank
, mux
,
90 spec
, origsuffix
=suffix
, gangedgrp
=gangedgroup
)
91 fname
= self
.pinouts
.pinmerge(pins
)
92 self
.pinouts
.setganged(fname
, gangedgroup
)
97 class Pinouts(object):
98 def __init__(self
, bankspec
):
99 self
.bankspec
= bankspec
105 for fname
, pinfn
in pinspec
:
106 if isinstance(pinfn
, tuple):
109 name
= pinfn
.__name
__
110 pin
= PinGen(self
, fname
, pinfn
, self
.bankspec
)
111 setattr(self
, name
, pin
)
113 def setganged(self
, fname
, grp
):
114 grp
= map(lambda x
: x
[:-1], grp
)
115 if fname
not in self
.ganged
:
116 self
.ganged
[fname
] = []
117 self
.ganged
[fname
] += grp
119 def __contains__(self
, k
):
120 return k
in self
.pins
122 def has_key(self
, k
):
123 return k
in self
.pins
125 def add_spec(self
, k
, v
):
128 def update(self
, pinidx
, v
):
129 if pinidx
not in self
.pins
:
130 self
.pins
[pinidx
] = v
133 assert k
not in self
.pins
[pinidx
], \
134 "pin %d position %d already taken\n%s\n%s" % \
135 (pinidx
, k
, str(v
), self
.pins
[pinidx
])
136 self
.pins
[pinidx
].update(v
)
139 return self
.pins
.keys()
142 return self
.pins
.items()
148 return len(self
.pins
)
150 def __delitem__(self
, k
):
153 def __getitem__(self
, k
):
156 def pinmerge(self
, fn
):
157 # hack, store the function specs in the pins dict
159 suffix
= fn
.origsuffix
162 if not hasattr(self
, 'fnspec'):
166 assert 'EINT' not in self
167 if fname
not in self
.fnspec
:
168 self
.add_spec(fname
, {})
169 if suffix
or fname
== 'EINT' or fname
== 'PWM':
170 specname
= fname
+ suffix
173 # print "fname bank specname suffix ", fname, bank, specname, repr(
175 if specname
in self
.fnspec
[fname
]:
176 # ok so some declarations may bring in different
177 # names at different stages (EINT, PWM, flexbus1/2)
178 # so we have to merge the names in. main thing is
180 tomerge
= self
.fnspec
[fname
][specname
]
181 for p
in fn
.pingroup
:
182 if p
not in tomerge
.pingroup
:
183 tomerge
.pingroup
.append(p
)
184 tomerge
.pins
.update(fn
.pins
)
185 tomerge
.fntype
.update(fn
.fntype
)
187 self
.fnspec
[fname
][specname
] = deepcopy(fn
)
190 for (pinidx
, v
) in fn
.pins
.items():
191 self
.update(pinidx
, v
)
198 def __init__(self
, fname
, pingroup
, bankspec
, suffix
, offs
, bank
, mux
,
199 spec
=None, limit
=None, origsuffix
=None, gangedgrp
=None):
201 # function type can be in, out or inout, represented by - + *
202 # strip function type out of each pin name
204 for i
in range(len(pingroup
)):
209 if fntype
not in '+-*':
212 fntype
= {'-': 'in', '+': 'out', '*': 'inout'}[fntype
]
213 self
.fntype
[pname
] = fntype
217 self
.pingroup
= pingroup
218 self
.gangedgroup
= gangedgrp
219 self
.bankspec
= bankspec
221 self
.origsuffix
= origsuffix
or suffix
225 # create consistent name suffixes
226 pingroup
= namesuffix(fname
, suffix
, pingroup
)
232 for name
in pingroup
[:limit
]:
234 name_
= "%s_%s" % (name
, suffix
)
237 if spec
and name
in spec
:
239 pin
= {mux
: (name_
, bank
)}
240 offs_bank
, offs_
= offs
243 idx_
+= bankspec
[bank
]
246 for name
in pingroup
:
248 name_
= "%s_%s" % (name
, suffix
)
255 idx_
, mux_
= spec
[name
]
257 pin
= {mux_
: (name_
, bank
)}
259 res
[idx_
].update(pin
)