Nengo `Connection`s mapped to Loihi H/W

I think the problem is you can’t have a learning_rule_type on your connection. The only learning_rule_type we support is PES, and with that we do some funny stuff internally to pass the error in. (We actually split the Connection object into two, so when you try to look up the model objects for your original conn object, it returns an empty dict.)

If you don’t have a learning rule, then this works as expected. Here’s a minimal example:

import nengo
import nengo_loihi

with nengo.Network() as net:
    a = nengo.Ensemble(100, 1)
    b = nengo.Ensemble(100, 1)
    conn = nengo.Connection(a, b)

with nengo_loihi.Simulator(net) as sim:
    board = sim.sims["loihi"].board
    nxsdk_board = sim.sims["loihi"].nxsdk_board
    synapse = sim.model.objs[conn]["decoders"]
    assert isinstance(synapse, nengo_loihi.block.Synapse)
    chip_idx, core_idx, syn_idxs = board.find_synapse(synapse)
    nxsdk_chip = nxsdk_board.n2Chips[chip_idx]
    nxsdk_core = nxsdk_chip.n2CoresAsList[core_idx]
    # TODO: set up the learning here

Looking more at what would be involved for setting up that learning, though, and it seems like this might be difficult to hack in the way that you’re proposing. You can see in the hardware builder where we set the learning rule itself, but if you search through that file for synapse.learning, you can see all the other changes that need to be made for a learning synapse, and it might be difficult to do those all post hoc.

I think the better way to go is to more properly build your learning rule into the builder. So for example here, where we make modifications for the PES learning rule, you’d add your learning rule. There’s still going to be a number of changes that need to be made throughout the codebase, since right now we basically assume a PES learning rule for all our learning.

The third way to do it, which is perhaps the most hacky but probably also the quickest, is to find a way to get the actual Connection object that does the learning (after we break that original connection into two). This works for my basic example (but would break e.g. if you have two connections coming out of a):

import nengo
import nengo_loihi

with nengo.Network() as net:
    a = nengo.Ensemble(100, 1)
    b = nengo.Ensemble(100, 1)
    conn = nengo.Connection(a, b, learning_rule_type=nengo.PES())

with nengo_loihi.Simulator(net) as sim:
    (new_conn,) = [
        obj
        for obj in sim.model.objs
        if isinstance(obj, nengo.Connection) and obj.pre is a
    ]
    synapse = sim.model.objs[new_conn]["decoders"]
    assert isinstance(synapse, nengo_loihi.block.Synapse)

    board = sim.sims["loihi"].board
    chip_idx, core_idx, syn_idxs = board.find_synapse(synapse)

    nxsdk_board = sim.sims["loihi"].nxsdk_board
    nxsdk_chip = nxsdk_board.n2Chips[chip_idx]
    nxsdk_core = nxsdk_chip.n2CoresAsList[core_idx]

    # TODO: set up the learning here