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,
70 pf
= self
.pinfn(suffix
, bank
)
71 print ("pf", suffix
, bank
, pf
)
72 pingroup
, gangedgroup
, clock
= pf
74 self
.pinouts
.clocks
[self
.fname
] = clock
75 if isinstance(pingroup
, tuple):
76 prefix
, pingroup
= pingroup
79 if start
and limit
: # limit turns into an offset from start
81 sk
= "%s:%s" % (self
.fname
, str(suffix
))
82 print ("pingroup pre", sk
, pingroup
)
83 pingroup
= pingroup
[start
:limit
] # see comment in spec.pinfunctions
85 # reverse order of pingroup
87 print ("pingroup post", sk
, pingroup
)
88 if sk
in self
.pinouts
.byspec
:
89 self
.pinouts
.byspec
[sk
] += pingroup
91 self
.pinouts
.byspec
[sk
] = deepcopy(pingroup
)
92 pins
= Pins(prefix
, pingroup
, self
.bankspec
,
93 suffix
, offs
, bank
, mux
,
94 spec
, origsuffix
=suffix
, gangedgrp
=gangedgroup
)
95 fname
= self
.pinouts
.pinmerge(pins
)
96 self
.pinouts
.setganged(fname
, gangedgroup
)
101 class Pinouts(object):
102 def __init__(self
, bankspec
):
103 self
.bankspec
= bankspec
109 for fname
, pinfn
in pinspec
:
110 if isinstance(pinfn
, tuple):
113 name
= pinfn
.__name
__
114 pin
= PinGen(self
, fname
, pinfn
, self
.bankspec
)
115 setattr(self
, name
, pin
)
117 def setganged(self
, fname
, grp
):
118 grp
= map(lambda x
: x
[:-1], grp
)
119 if fname
not in self
.ganged
:
120 self
.ganged
[fname
] = []
121 self
.ganged
[fname
] += grp
123 def __contains__(self
, k
):
124 return k
in self
.pins
126 def has_key(self
, k
):
127 return k
in self
.pins
129 def add_spec(self
, k
, v
):
132 def update(self
, pinidx
, v
):
133 if pinidx
not in self
.pins
:
134 self
.pins
[pinidx
] = v
137 assert k
not in self
.pins
[pinidx
], \
138 "pin %d position %d already taken\n%s\n%s" % \
139 (pinidx
, k
, str(v
), self
.pins
[pinidx
])
140 self
.pins
[pinidx
].update(v
)
143 return self
.pins
.keys()
146 return self
.pins
.items()
152 return len(self
.pins
)
154 def __delitem__(self
, k
):
157 def __getitem__(self
, k
):
160 def pinmerge(self
, fn
):
161 # hack, store the function specs in the pins dict
163 suffix
= fn
.origsuffix
166 if not hasattr(self
, 'fnspec'):
170 assert 'EINT' not in self
171 if fname
not in self
.fnspec
:
172 self
.add_spec(fname
, {})
173 if suffix
or fname
== 'EINT' or fname
== 'PWM':
174 specname
= fname
+ suffix
177 # print "fname bank specname suffix ", fname, bank, specname, repr(
179 if specname
in self
.fnspec
[fname
]:
180 # ok so some declarations may bring in different
181 # names at different stages (EINT, PWM, flexbus1/2)
182 # so we have to merge the names in. main thing is
184 tomerge
= self
.fnspec
[fname
][specname
]
185 for p
in fn
.pingroup
:
186 if p
not in tomerge
.pingroup
:
187 tomerge
.pingroup
.append(p
)
188 tomerge
.pins
.update(fn
.pins
)
189 tomerge
.fntype
.update(fn
.fntype
)
191 self
.fnspec
[fname
][specname
] = deepcopy(fn
)
194 for (pinidx
, v
) in fn
.pins
.items():
195 self
.update(pinidx
, v
)
202 def __init__(self
, fname
, pingroup
, bankspec
, suffix
, offs
, bank
, mux
,
203 spec
=None, limit
=None, origsuffix
=None, gangedgrp
=None):
205 # function type can be in, out or inout, represented by - + *
206 # strip function type out of each pin name
208 for i
in range(len(pingroup
)):
213 if fntype
not in '+-*':
216 fntype
= {'-': 'in', '+': 'out', '*': 'inout'}[fntype
]
217 self
.fntype
[pname
] = fntype
221 self
.pingroup
= pingroup
222 self
.gangedgroup
= gangedgrp
223 self
.bankspec
= bankspec
225 self
.origsuffix
= origsuffix
or suffix
229 # create consistent name suffixes
230 pingroup
= namesuffix(fname
, suffix
, pingroup
)
236 for name
in pingroup
[:limit
]:
238 name_
= "%s_%s" % (name
, suffix
)
241 if spec
and name
in spec
:
243 pin
= {mux
: (name_
, bank
)}
244 offs_bank
, offs_
= offs
247 idx_
+= bankspec
[bank
]
250 for name
in pingroup
:
252 name_
= "%s_%s" % (name
, suffix
)
259 idx_
, mux_
= spec
[name
]
261 pin
= {mux_
: (name_
, bank
)}
263 res
[idx_
].update(pin
)