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 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)
예제 #3
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():
    """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
예제 #5
0
    def place_and_route(self, system_info,
                        place=place_and_route.place,
                        place_kwargs={},
                        allocate=place_and_route.allocate,
                        allocate_kwargs={},
                        route=place_and_route.route,
                        route_kwargs={}):
        """Place and route the netlist onto the given SpiNNaker machine.

        Parameters
        ----------
        system_info : \
                :py:class:`~rig.machine_control.MachineController.SystemInfo`
            Describes the system onto which the netlist should be placed and
            routed.

        Other Parameters
        ----------------
        place : function
            Placement function. Must support the interface defined by Rig.
        place_kwargs : dict
            Keyword arguments for the placement method.
        allocate : function
            Resource allocation function. Must support the interface defined by
            Rig.
        allocate_kwargs : dict
            Keyword arguments for the allocation function.
        route : function
            Router function. Must support the interface defined by Rig.
        route_kwargs : dict
            Keyword arguments for the router function.
        """
        # Generate a Machine and set of core-reserving constraints to prevent
        # the use of non-idle cores.
        machine = build_machine(system_info)
        core_constraints = build_core_constraints(system_info)
        constraints = self.constraints + core_constraints

        # Build a map of vertices to the resources they require, get a list of
        # constraints.
        vertices_resources = {v: v.resources for v in self.vertices}

        # Perform placement and allocation
        place_nets = list(utils.get_nets_for_placement(self.nets))
        self.placements = place(vertices_resources, place_nets, machine,
                                constraints, **place_kwargs)
        self.allocations = allocate(vertices_resources, place_nets, machine,
                                    constraints, self.placements,
                                    **allocate_kwargs)

        # Identify clusters and modify vertices appropriately
        utils.identify_clusters(self.groups, self.placements)

        # Get the nets for routing
        (route_nets,
         vertices_resources,  # Can safely overwrite the resource dictionary
         extended_placements,
         extended_allocations,
         derived_nets) = utils.get_nets_for_routing(
            vertices_resources, self.nets, self.placements, self.allocations)

        # Get a map from the nets we will route with to keyspaces
        self.net_keyspaces = utils.get_net_keyspaces(self.placements,
                                                     derived_nets)

        # Fix all keyspaces
        self.keyspaces.assign_fields()

        # Finally, route all nets using the extended resource dictionary,
        # placements and allocations.
        self.routes = route(vertices_resources, route_nets, machine,
                            constraints, extended_placements,
                            extended_allocations, **route_kwargs)
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
예제 #7
0
    def place_and_route(self,
                        system_info,
                        place=place_and_route.place,
                        place_kwargs={},
                        allocate=place_and_route.allocate,
                        allocate_kwargs={},
                        route=place_and_route.route,
                        route_kwargs={}):
        """Place and route the netlist onto the given SpiNNaker machine.

        Parameters
        ----------
        system_info : \
                :py:class:`~rig.machine_control.MachineController.SystemInfo`
            Describes the system onto which the netlist should be placed and
            routed.

        Other Parameters
        ----------------
        place : function
            Placement function. Must support the interface defined by Rig.
        place_kwargs : dict
            Keyword arguments for the placement method.
        allocate : function
            Resource allocation function. Must support the interface defined by
            Rig.
        allocate_kwargs : dict
            Keyword arguments for the allocation function.
        route : function
            Router function. Must support the interface defined by Rig.
        route_kwargs : dict
            Keyword arguments for the router function.
        """
        # Generate a Machine and set of core-reserving constraints to prevent
        # the use of non-idle cores.
        machine = build_machine(system_info)
        core_constraints = build_core_constraints(system_info)
        constraints = self.constraints + core_constraints

        # Build a map of vertices to the resources they require, get a list of
        # constraints.
        vertices_resources = {v: v.resources for v in self.vertices}

        # Perform placement and allocation
        place_nets = list(utils.get_nets_for_placement(itervalues(self.nets)))
        self.placements = place(vertices_resources, place_nets, machine,
                                constraints, **place_kwargs)
        self.allocations = allocate(vertices_resources, place_nets, machine,
                                    constraints, self.placements,
                                    **allocate_kwargs)

        # Get the nets for routing
        (
            route_nets,
            vertices_resources,  # Can safely overwrite the resource dictionary
            extended_placements,
            extended_allocations,
            derived_nets) = utils.get_nets_for_routing(vertices_resources,
                                                       self.nets,
                                                       self.placements,
                                                       self.allocations)

        # Finally, route all nets using the extended resource dictionary,
        # placements and allocations.
        self.routes = route(vertices_resources, route_nets, machine,
                            constraints, extended_placements,
                            extended_allocations, **route_kwargs)

        # Assign keyspaces based on the placement
        signal_routes = collections.defaultdict(collections.deque)
        for signal, nmnet in iteritems(self.nets):
            for net in itervalues(derived_nets[nmnet]):
                signal_routes[signal].append(self.routes[net])

        key_allocation.allocate_signal_keyspaces(signal_routes,
                                                 self.signal_id_constraints,
                                                 self.keyspaces)

        # Assign cluster IDs based on the placement and the routing
        key_allocation.assign_cluster_ids(self.operator_vertices,
                                          signal_routes, self.placements)

        # Get a map from the nets we will route with to keyspaces
        self.net_keyspaces = utils.get_net_keyspaces(self.placements,
                                                     self.nets, derived_nets)

        # Fix all keyspaces
        self.keyspaces.assign_fields()
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