Improved Connection logic

Consolidated all Connection logic in `utils/connections.py`. 

A `Connections` object accepts a list of Nengo `Connection` objects and determines which are equivalent from the point of view of `function` and `transform` (i.e., the outgoing differences).  A `ConnectionsWithSolver` does the same but adds in the criteria of `solver` and `eval_points`.

This simplifies (and enables testing of :grinning:) a lot of shared code.  As a result decoder calculation has changed (now listens to `solver` and `eval_points` in a way it didn't before), the Ethernet code and related code for the `SDPReceiveVertex` is simplified and listens to the `function` and `transform` options in a way they didn't before.  Moreover all connections should now take account of padding from `full_transform`.

We now have a central location to manage having various key spaces, I'll put some work into this prior to Telluride.

Loosely the same thing now happens with `Filters`, so there's some simplification of code there also.

- [ ] Modify the `Simulator` to use new Connection logic
- Modify the SpiNNlinkUSB IO
  - [x] Slightly changed API
  - [ ] To use Connection logic

As far as matching previous functionality goes, the examples in `examples/` are happy.