Esempio n. 1
0
def test_identify_clusters():
    """Test the correct assignation of clusters."""
    # Create two vertices
    vertex_A = [Vertex() for _ in range(4)]
    vertex_B = [Vertex() for _ in range(2)]

    # Create placements such that vertex A and B fall on two chips and A[0] and
    # A[1] are on the same chip.
    placements = {
        vertex_A[0]: (0, 0),
        vertex_A[1]: (0, 0),
        vertex_A[2]: (0, 1),
        vertex_A[3]: (0, 1),
        vertex_B[0]: (0, 0),
        vertex_B[1]: (1, 0),
    }

    # Identify groups
    groups = [set(vertex_A), set(vertex_B)]

    # Identify clusters
    utils.identify_clusters(groups, placements)

    # Ensure that appropriate cluster indices are assigned to all vertices
    assert vertex_A[0].cluster == vertex_A[1].cluster  # 1 cluster of A
    assert vertex_A[2].cluster == vertex_A[3].cluster  # The other
    assert vertex_A[0].cluster != vertex_A[2].cluster  # Different IDs

    assert vertex_B[0].cluster != vertex_B[1].cluster  # Different IDs
Esempio n. 2
0
def test_get_net_keyspaces():
    """Test the correct specification of keyspaces for nets."""
    # Create the vertices
    vertex_A = [Vertex() for _ in range(4)]
    vertex_B = Vertex()

    # Create placements such that vertex A and B fall on two chips and A[0] and
    # A[1] are on the same chip.
    placements = {
        vertex_A[0]: (0, 0),
        vertex_A[1]: (0, 0),
        vertex_A[2]: (0, 1),
        vertex_A[3]: (0, 1),
        vertex_B: (0, 0)
    }
    resources = {v: {} for v in placements}
    allocations = {v: {} for v in placements}

    # Create a container for the keyspaces
    ksc = KeyspaceContainer()

    # Create the nets
    nets = [
        NMNet(vertex_A, vertex_B, 1.0, ksc["nengo"](connection_id=0)),
        NMNet(vertex_B, vertex_A, 2.0, ksc["nengo"](connection_id=1)),
        NMNet(vertex_A, vertex_A, 3.0, ksc["spam"]),
    ]

    # Identify groups
    groups = [set(vertex_A)]

    # Identify clusters
    utils.identify_clusters(groups, placements)
    assert vertex_B.cluster is None  # Not clustered

    # Get the routing nets
    _, _, _, _, derived_nets = utils.get_nets_for_routing(
        resources, nets, placements, allocations)

    # Get the net keyspaces
    net_keyspaces = utils.get_net_keyspaces(placements, derived_nets)

    # Check the net keyspaces are correct
    # A -> B
    for xy, vertex in [((0, 0), vertex_A[0]), ((0, 1), vertex_A[2])]:
        net = derived_nets[nets[0]][xy]
        cluster = vertex.cluster
        assert net_keyspaces[net] == nets[0].keyspace(cluster=cluster)

    # B -> A
    net = derived_nets[nets[1]][(0, 0)]
    assert net_keyspaces[net] == nets[1].keyspace(cluster=0)

    # A -> A
    for xy in [(0, 0), (0, 1)]:
        net = derived_nets[nets[2]][xy]
        assert net_keyspaces[net] == nets[2].keyspace  # No change
def test_get_net_keyspaces_fails_for_inconsistent_cluster():
    """Test specification of keyspaces for nets fails in the case that
    inconsistent cluster IDs are assigned (this is unlikely to happen unless a
    Net somehow ends up having two different Nengo objects in its source
    list)."""
    # Create the vertices
    vertex_A = [Vertex() for _ in range(4)]
    vertex_B = Vertex()

    # Create placements such that vertex A and B fall on two chips and A[0] and
    # A[1] are on the same chip.
    placements = {
        vertex_A[0]: (0, 0),
        vertex_A[1]: (0, 0),
        vertex_A[2]: (0, 1),
        vertex_A[3]: (0, 1),
        vertex_B: (0, 0)
    }
    resources = {v: {} for v in placements}
    allocations = {v: {} for v in placements}

    # Create a container for the keyspaces
    ksc = KeyspaceContainer()

    # Create the signals and nets
    signal_a = Signal(object(), [],
                      SignalParameters(keyspace=ksc["nengo"](connection_id=0)))
    signal_b = Signal(object(), [],
                      SignalParameters(keyspace=ksc["nengo"](connection_id=1)))
    signal_c = Signal(object(), [], SignalParameters(keyspace=ksc["spam"]))

    nets = {
        signal_a: NMNet(vertex_A, vertex_B, 1.0),
        signal_b: NMNet(vertex_B, vertex_A, 2.0),
        signal_c: NMNet(vertex_A, vertex_A, 3.0),
    }

    # Identify groups
    groups = [set(vertex_A)]

    # Manually identify clusters (and do it such that it is inconsistent)
    vertex_A[0].cluster = 0
    vertex_A[1].cluster = 1
    vertex_A[2].cluster = 2
    vertex_A[3].cluster = 3

    # Get the routing nets
    _, _, _, _, derived_nets = utils.get_nets_for_routing(
        resources, nets, placements, allocations)

    # Get the net keyspaces
    with pytest.raises(AssertionError):
        utils.get_net_keyspaces(placements, nets, derived_nets)
    def make_vertices(self, model, *args, **kwargs):
        """Create vertices that will simulate the SDPTransmitter."""
        # Build the system region
        self._sys_region = SystemRegion(model.machine_timestep, self.size_in,
                                        1)

        # Build the filter regions
        in_sigs = model.get_signals_to_object(self)[InputPort.standard]
        self._filter_region, self._routing_region = make_filter_regions(
            in_sigs, model.dt, True, model.keyspaces.filter_routing_tag)

        # Get the resources
        resources = {
            Cores:
            1,
            SDRAM:
            region_utils.sizeof_regions(
                [self._sys_region, self._filter_region, self._routing_region],
                None)
        }

        # Create the vertex
        self._vertex = Vertex(self._label, get_application("tx"), resources)

        # Return the netlist specification
        return netlistspec(
            (self._vertex, ),  # Tuple is required
            load_function=self.load_to_machine)
    def make_vertices(self, model, n_steps):  # TODO remove n_steps
        """Construct the data which can be loaded into the memory of a
        SpiNNaker machine.
        """
        # Extract all the filters from the incoming connections to build the
        # filter regions.
        signals_conns = model.get_signals_to_object(self)[InputPort.standard]
        self.filter_region, self.filter_routing_region = make_filter_regions(
            signals_conns, model.dt, True, model.keyspaces.filter_routing_tag)

        # Use a matrix region to record into (slightly unpleasant)
        self.recording_region = regions.MatrixRegion(
            np.zeros((self.size_in, n_steps), dtype=np.uint32))

        # This isn't partitioned, so we just compute the SDRAM requirement and
        # return a new vertex.
        self.system_region = SystemRegion(model.machine_timestep, self.size_in)

        self.regions = [None] * 15
        self.regions[0] = self.system_region
        self.regions[1] = self.filter_region
        self.regions[2] = self.filter_routing_region
        self.regions[14] = self.recording_region  # **YUCK**
        resources = {
            Cores: 1,
            SDRAM: regions.utils.sizeof_regions(self.regions, None)
        }

        self.vertex = Vertex(get_application("value_sink"), resources)

        # Return the spec
        return netlistspec(self.vertex,
                           self.load_to_machine,
                           after_simulation_function=self.after_simulation)
Esempio n. 6
0
    def make_vertices(self, model, *args, **kwargs):
        """Create vertices that will simulate the SDPReceiver."""
        # NOTE This approach will result in more routes being created than are
        # actually necessary; the way to avoid this is to modify how the
        # builder deals with signals when creating netlists.

        # Get all outgoing signals and their associated transmission parameters
        for signal, transmission_params in \
                model.get_signals_from_object(self)[OutputPort.standard]:
            # Get the transform, and from this the keys
            transform = transmission_params.full_transform(slice_out=False)
            keys = [(signal, {"index": i}) for i in
                    range(transform.shape[0])]

            # Create a vertex for this connection (assuming its size out <= 64)
            if len(keys) > 64:
                raise NotImplementedError(
                    "Connection is too wide to transmit to SpiNNaker. "
                    "Consider breaking the connection up or making the "
                    "originating node a function of time Node."
                )

            # Create the regions for the system
            sys_region = SystemRegion(model.machine_timestep, len(keys))
            keys_region = KeyspacesRegion(keys,
                                          [KeyField({"cluster": "cluster"})])

            # Get the resources
            resources = {
                Cores: 1,
                SDRAM: region_utils.sizeof_regions([sys_region, keys_region],
                                                   None)
            }

            # Create the vertex
            v = self.connection_vertices[transmission_params] = \
                Vertex(self._label, get_application("rx"), resources)
            self._sys_regions[v] = sys_region
            self._key_regions[v] = keys_region

        # Return the netlist specification
        return netlistspec(list(self.connection_vertices.values()),
                           load_function=self.load_to_machine)
Esempio n. 7
0
    def test_multiple_source_vertices(self):
        """Test that each of the vertices associated with a source is correctly
        included in the sources of a net.
        """
        class MyVertexSlice(VertexSlice):
            def __init__(self, *args, **kwargs):
                super(MyVertexSlice, self).__init__(*args, **kwargs)
                self.args = None

            def transmits_signal(self, signal_parameters,
                                 transmission_parameters):
                self.args = (signal_parameters, transmission_parameters)
                return False

        # Create the first operator
        vertex_a0 = VertexSlice(slice(0, 1))
        vertex_a1 = VertexSlice(slice(1, 2))
        vertex_a2 = MyVertexSlice(slice(2, 3))
        load_fn_a = mock.Mock(name="load function A")
        pre_fn_a = mock.Mock(name="pre function A")
        post_fn_a = mock.Mock(name="post function A")

        object_a = mock.Mock(name="object A")
        operator_a = mock.Mock(name="operator A", spec_set=["make_vertices"])
        operator_a.make_vertices.return_value = \
            netlistspec([vertex_a0, vertex_a1, vertex_a2],
                        load_fn_a, pre_fn_a, post_fn_a)

        # Create the second operator
        vertex_b = Vertex()
        load_fn_b = mock.Mock(name="load function B")

        object_b = mock.Mock(name="object B")
        operator_b = mock.Mock(name="operator B", spec_set=["make_vertices"])
        operator_b.make_vertices.return_value = \
            netlistspec((vertex_b, ), load_fn_b)

        # Create a signal between the operators
        keyspace = mock.Mock(name="keyspace")
        keyspace.length = 32
        signal_ab_parameters = SignalParameters(keyspace=keyspace, weight=43)

        # Create the model, add the items and then generate the netlist
        model = Model()
        model.object_operators[object_a] = operator_a
        model.object_operators[object_b] = operator_b
        model.connection_map.add_connection(operator_a, None,
                                            signal_ab_parameters, None,
                                            operator_b, None, None)
        netlist = model.make_netlist()

        # Check that the netlist is as expected
        assert netlist.operator_vertices == {
            operator_a: (vertex_a0, vertex_a1, vertex_a2),
            operator_b: (vertex_b, ),
        }
        assert len(netlist.nets) == 1
        for net in itervalues(netlist.nets):
            assert net.sources == [vertex_a0, vertex_a1]
            assert net.sinks == [vertex_b]

        assert len(netlist.constraints) == 0

        # Check that `transmit_signal` was called correctly
        sig, tp = vertex_a2.args
        assert sig.keyspace is keyspace
        assert tp is None
def test_get_net_keyspaces():
    """Test the correct specification of keyspaces for nets."""
    # Create the vertices
    vertex_A = [Vertex() for _ in range(4)]
    vertex_B = Vertex()

    # Create placements such that vertex A and B fall on two chips and A[0] and
    # A[1] are on the same chip.
    placements = {
        vertex_A[0]: (0, 0),
        vertex_A[1]: (0, 0),
        vertex_A[2]: (0, 1),
        vertex_A[3]: (0, 1),
        vertex_B: (0, 0)
    }
    resources = {v: {} for v in placements}
    allocations = {v: {} for v in placements}

    # Manually assign cluster IDs
    vertex_A[0].cluster = 0
    vertex_A[1].cluster = 0
    vertex_A[2].cluster = 1
    vertex_A[3].cluster = 1

    # Create a container for the keyspaces
    ksc = KeyspaceContainer()

    # Create the signals and nets
    signal_a = Signal(object(), [],
                      SignalParameters(keyspace=ksc["nengo"](connection_id=0)))
    signal_b = Signal(object(), [],
                      SignalParameters(keyspace=ksc["nengo"](connection_id=1)))
    signal_c = Signal(object(), [], SignalParameters(keyspace=ksc["spam"]))

    nets = {
        signal_a: NMNet(vertex_A, vertex_B, 1.0),
        signal_b: NMNet(vertex_B, vertex_A, 2.0),
        signal_c: NMNet(vertex_A, vertex_A, 3.0),
    }

    # Get the routing nets
    _, _, _, _, derived_nets = utils.get_nets_for_routing(
        resources, nets, placements, allocations)

    # Get the net keyspaces
    net_keyspaces = utils.get_net_keyspaces(placements, nets, derived_nets)

    # Check the net keyspaces are correct
    # A -> B
    for xy, vertex in [((0, 0), vertex_A[0]), ((0, 1), vertex_A[2])]:
        net = derived_nets[nets[signal_a]][xy]
        cluster = vertex.cluster
        assert net_keyspaces[net] == signal_a.keyspace(cluster=cluster)

    # B -> A
    net = derived_nets[nets[signal_b]][(0, 0)]
    assert net_keyspaces[net] == signal_b.keyspace(cluster=0)

    # A -> A
    for xy in [(0, 0), (0, 1)]:
        net = derived_nets[nets[signal_c]][xy]
        assert net_keyspaces[net] == signal_c.keyspace  # No change