+ # note: the starting points where each IOConn is placed into
+ # the Shift Register depends *specifically* on the type (parameters)
+ # of each IOConn, and therefore on all IOConn(s) that came before it
+ # [prior calls to add_io]. this function consistently follows
+ # the exact same pattern in the exact same sequence every time,
+ # to compute consistent offsets. developers must do the same:
+ # note that each length depends on *all* parameters:
+ # IOtype, banksel, pullup *and* pulldown.
+
+ # pre-compute the length of the IO shift registers needed.
+ length = 0
+ for conn in self._ios:
+ length += IOConn.lengths[conn._iotype] + conn._banksel
+ if conn._pullup:
+ length += 1
+ if conn._pulldown:
+ length += 1