def __call__(self, subgraph, n_keys_map, routing_paths):

        # check that this algorithm supports the constraints
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=subgraph.subedges,
            supported_constraints=[
                KeyAllocatorFixedMaskConstraint,
                KeyAllocatorFixedKeyAndMaskConstraint,
                KeyAllocatorContiguousRangeContraint],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        routing_tables = MulticastRoutingTables()

        # Get the partitioned edges grouped by those that require the same key
        same_key_groups = \
            routing_info_allocator_utilities.get_edge_groups(subgraph)

        # Go through the groups and allocate keys
        progress_bar = ProgressBar(len(same_key_groups),
                                   "Allocating routing keys")
        routing_infos = RoutingInfo()
        for group in same_key_groups:
            # Check how many keys are needed for the edges of the group
            edge_n_keys = None
            for edge in group:
                n_keys = n_keys_map.n_keys_for_partitioned_edge(edge)
                if edge_n_keys is None:
                    edge_n_keys = n_keys
                elif edge_n_keys != n_keys:
                    raise PacmanRouteInfoAllocationException(
                        "Two edges require the same keys but request a"
                        " different number of keys")

            # Get any fixed keys and masks from the group and attempt to
            # allocate them
            keys_and_masks = routing_info_allocator_utilities.\
                get_fixed_key_and_mask(group)
            fixed_mask, fields = \
                routing_info_allocator_utilities.get_fixed_mask(group)

            if keys_and_masks is not None:

                self._allocate_fixed_keys_and_masks(keys_and_masks, fixed_mask)
            else:
                keys_and_masks = self._allocate_keys_and_masks(
                    fixed_mask, fields, edge_n_keys)

            # Allocate the routing information
            for edge in group:
                subedge_info = SubedgeRoutingInfo(keys_and_masks, edge)
                routing_infos.add_subedge_info(subedge_info)

                # update routing tables with entries
                routing_info_allocator_utilities.add_routing_key_entries(
                    routing_paths, subedge_info, edge, routing_tables)

            progress_bar.update()
        progress_bar.end()
        return {'routing_infos': routing_infos,
                'routing_tables': routing_tables}
 def test_get_subedge_information_from_subedge(self):
     subv1 = PartitionedVertex(None, "")
     subv2 = PartitionedVertex(None, "")
     sube = MultiCastPartitionedEdge(subv1, subv2)
     keys_and_masks = list()
     keys_and_masks.append(BaseKeyAndMask(0x0012, 0x00ff))
     sri = SubedgeRoutingInfo(keys_and_masks, sube)
     ri = RoutingInfo([sri])
     self.assertEqual(ri.get_subedge_information_from_subedge(sri.subedge),
                      sri)
 def test_get_key_from_subedge_info_not_matching(self):
     subv1 = PartitionedVertex(None, "")
     subv2 = PartitionedVertex(None, "")
     sube = MultiCastPartitionedEdge(subv1, subv2)
     subz = MultiCastPartitionedEdge(subv2, subv1)
     keys_and_masks = list()
     keys_and_masks.append(BaseKeyAndMask(0x0012, 0x00ff))
     sri = SubedgeRoutingInfo(keys_and_masks, sube)
     ri = RoutingInfo([sri])
     ri_keys_and_masks = ri.get_keys_and_masks_from_subedge(subz)
     self.assertEqual(ri_keys_and_masks, None)
    def test_full_machine_routing(self):
        placements = Placements()
        self.placement1 = Placement(x=1, y=0, p=2, subvertex=self.subvert1)
        self.placement2 = Placement(x=1, y=0, p=3, subvertex=self.subvert2)
        subvertices = list()
        for i in range(4 * 17): #51 atoms per each processor on 20 chips
            subvertices.append(PartitionedVertex(
                0, 50, get_resources_used_by_atoms(0, 50, []),
                "Subvertex " + str(i)))
        subedges = list()
        for i in range(len(subvertices)):
            subedges.append(AbstractPartitionedEdge(
                subvertices[i], subvertices[(i + 1)%len(subvertices)]))
        subgraph = PartitionedGraph("Subgraph", subvertices, subedges)
        p = 1
        x = 0
        y = 0
        for subvert in subvertices:
            placements.add_placement(Placement(subvert, x, y, p))
            p = (p + 1) % 18
            if p == 0:
                p += 1
                y += 1
                if y == 2:
                    y = 0
                    x += 1

        routing_info = RoutingInfo()
        subedge_routing_info = list()
        for i in range(len(subedges)):
            subedge_routing_info.append(SubedgeRoutingInfo(
                subedges[i], i<<11, constants.DEFAULT_MASK))

        for subedge_info in subedge_routing_info:
            routing_info.add_subedge_info(subedge_info)


        self.set_up_4_node_board()

        dijkstra_router = BasicDijkstraRouting()
        routing_tables = dijkstra_router.route(
            machine=self.machine, placements=placements,
            partitioned_graph=subgraph,
            routing_info_allocation=routing_info)

        for entry in routing_tables.routing_tables:
            print entry.x, entry.y
            for routing_entry in entry.multicast_routing_entries:
                print "\t\tProcessor_ids:{}, Link_ids:{}".format(
                    routing_entry.processor_ids,
                    routing_entry.link_ids)
 def test_get_subedge_info_by_key_not_matching(self):
     """
     check that trying to locate a subedge info with an invalid key and mask
     results in no subedge info being returned
     :return:
     """
     subv1 = PartitionedVertex(None, "")
     subv2 = PartitionedVertex(None, "")
     sube = MultiCastPartitionedEdge(subv1, subv2)
     keys_and_masks = list()
     keys_and_masks.append(BaseKeyAndMask(0x0012, 0x00ff))
     sri = SubedgeRoutingInfo(keys_and_masks, sube)
     ri = RoutingInfo([sri])
     self.assertEqual(ri.get_subedge_infos_by_key(0xff12, 0x000f), None)
 def test_get_subedge_info_by_key_matching(self):
     """
     check that you can get a subedge routing info from a routing info
     based off key
     :return:
     """
     subv1 = PartitionedVertex(None, "")
     subv2 = PartitionedVertex(None, "")
     sube = MultiCastPartitionedEdge(subv1, subv2)
     keys_and_masks = list()
     keys_and_masks.append(BaseKeyAndMask(0x0012, 0x00ff))
     sri = SubedgeRoutingInfo(keys_and_masks, sube)
     ri = RoutingInfo([sri])
     self.assertIn(sri, ri.get_subedge_infos_by_key(0xff12, 0x00ff))
    def test_get_key_from_subedge_info(self):
        """

        :return:
        """
        subv1 = PartitionedVertex(None, "")
        subv2 = PartitionedVertex(None, "")
        sube = MultiCastPartitionedEdge(subv1, subv2)
        keys_and_masks = list()
        keys_and_masks.append(BaseKeyAndMask(0x0012, 0x00ff))
        sri = SubedgeRoutingInfo(keys_and_masks, sube)
        ri = RoutingInfo([sri])
        ri_keys_and_masks = ri.get_keys_and_masks_from_subedge(sri.subedge)
        for key_and_mask in ri_keys_and_masks:
            self.assertEqual(key_and_mask.key, 0x0012)
    def test_routing_on_chip_custom_4_node_machine(self):
        self.placements = Placements()
        self.placement1 = Placement(x=1, y=0, p=2, subvertex=self.subvert1)
        self.placement2 = Placement(x=1, y=0, p=3, subvertex=self.subvert2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        # sort out routing infos
        self.routing_info = RoutingInfo()
        self.subedge_routing_info1 = \
            SubedgeRoutingInfo(key=2 << 11, mask=constants.DEFAULT_MASK,
                               subedge=self.subedge)
        self.routing_info.add_subedge_info(self.subedge_routing_info1)

        self.set_up_4_node_board()

        dijkstra_router = BasicDijkstraRouting()
        routing_tables = dijkstra_router.route(
            machine=self.machine, placements=self.placements,
            partitioned_graph=self.subgraph,
            routing_info_allocation=self.routing_info)

        for entry in routing_tables.routing_tables:
            print entry.x, entry.y
            for routing_entry in entry.multicast_routing_entries:
                print "\t\tProcessor_ids:{}, Link_ids:{}".format(
                    routing_entry.processor_ids,
                    routing_entry.link_ids)
    def setUp(self):
        # sort out graph
        self.vert1 = Vertex(10, "New AbstractConstrainedVertex 1")
        self.vert2 = Vertex(5, "New AbstractConstrainedVertex 2")
        self.edge1 = AbstractPartitionableEdge(self.vert1, self.vert2, "First edge")
        self.verts = [self.vert1, self.vert2]
        self.edges = [self.edge1]
        self.graph = PartitionableGraph("Graph", self.verts, self.edges)
        # sort out subgraph
        self.subgraph = PartitionedGraph()
        self.subvert1 = PartitionedVertex(
            0, 10, get_resources_used_by_atoms(0, 10, []))
        self.subvert2 = PartitionedVertex(
            0, 5, get_resources_used_by_atoms(0, 10, []))
        self.subedge = AbstractPartitionedEdge(self.subvert1, self.subvert2)
        self.subgraph.add_subvertex(self.subvert1)
        self.subgraph.add_subvertex(self.subvert2)
        self.subgraph.add_subedge(self.subedge)
        # sort out placements
        self.placements = Placements()
        self.placement1 = Placement(x=0, y=0, p=2, subvertex=self.subvert1)
        self.placement2 = Placement(x=1, y=1, p=2, subvertex=self.subvert2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        # sort out routing infos
        self.routing_info = RoutingInfo()
        self.subedge_routing_info1 = \
            SubedgeRoutingInfo(key=2 << 11, mask=constants.DEFAULT_MASK,
                               subedge=self.subedge)
        self.routing_info.add_subedge_info(self.subedge_routing_info1)
        # create machine
        flops = 1000
        (e, ne, n, w, sw, s) = range(6)

        processors = list()
        for i in range(18):
            processors.append(Processor(i, flops))
        _sdram = SDRAM(128 * (2 ** 20))
        ip = "192.162.240.253"
        chips = list()
        for x in range(10):
            for y in range(10):
                links = list()

                links.append(Link(x, y, 0, (x + 1) % 10, y, n, n))
                links.append(Link(x, y, 1, (x + 1) % 10, (y + 1) % 10, s, s))
                links.append(Link(x, y, 2, x, (y + 1) % 10, n, n))
                links.append(Link(x, y, 3, (x - 1) % 10, y, s, s))
                links.append(Link(x, y, 4, (x - 1) % 10, (y - 1) % 10, n, n))
                links.append(Link(x, y, 5, x, (y - 1) % 10, s, s))

                r = Router(links, False, 100, 1024)
                chips.append(Chip(x, y, processors, r, _sdram, ip))

        self.machine = Machine(chips)
Example #10
0
 def test_router_with_one_hop_route_all_default_link_5(self):
     self.placements = Placements()
     self.placement1 = Placement(x=0, y=2, p=2, subvertex=self.subvert1)
     self.placement2 = Placement(x=0, y=0, p=2, subvertex=self.subvert2)
     self.placements.add_placement(self.placement1)
     self.placements.add_placement(self.placement2)
     #sort out routing infos
     self.routing_info = RoutingInfo()
     self.subedge_routing_info1 = \
         SubedgeRoutingInfo(key=2 << 11, mask=constants.DEFAULT_MASK,
                            subedge=self.subedge)
     self.routing_info.add_subedge_info(self.subedge_routing_info1)
     #create machine
     self.machine = VirtualMachine(10, 10, False)
     self.routing = BasicDijkstraRouting()
     self.routing.route(
         machine=self.machine, placements=self.placements,
         partitioned_graph=self.subgraph,
         routing_info_allocation=self.routing_info)
    def __call__(self, subgraph, placements, n_keys_map, routing_paths):
        """
        Allocates routing information to the partitioned edges in a\
        partitioned graph

        :param subgraph: The partitioned graph to allocate the routing info for
        :type subgraph:\
                    :py:class:`pacman.model.partitioned_graph.partitioned_graph.PartitionedGraph`
        :param placements: The placements of the subvertices
        :type placements:\
                    :py:class:`pacman.model.placements.placements.Placements`
        :param n_keys_map: A map between the partitioned edges and the number\
                    of keys required by the edges
        :type n_keys_map:\
                    :py:class:`pacman.model.routing_info.abstract_partitioned_edge_n_keys_map.AbstractPartitionedEdgeNKeysMap`
        :param routing_paths: the paths each partitioned edge takes to get\
                from source to destination.
        :type routing_paths:
            :py:class:`pacman.model.routing_paths.multicast_routing_paths.MulticastRoutingPaths
        :return: The routing information
        :rtype: :py:class:`pacman.model.routing_info.routing_info.RoutingInfo`,
                :py:class:`pacman.model.routing_tables.multicast_routing_table.MulticastRoutingTable
        :raise pacman.exceptions.PacmanRouteInfoAllocationException: If\
                   something goes wrong with the allocation
        """

        # check that this algorithm supports the constraints put onto the
        # partitioned_edges
        supported_constraints = [RequiresRoutingInfoPartitionedVertex]
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=subgraph.subedges,
            supported_constraints=supported_constraints,
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # take each subedge and create keys from its placement
        progress_bar = ProgressBar(len(subgraph.subvertices),
                                   "Allocating routing keys")
        routing_infos = RoutingInfo()
        routing_tables = MulticastRoutingTables()
        for subvert in subgraph.subvertices:
            out_going_subedges = subgraph.outgoing_subedges_from_subvertex(
                subvert)
            for out_going_subedge in out_going_subedges:
                n_keys = n_keys_map.n_keys_for_partitioned_edge(
                    out_going_subedge)
                if n_keys > MAX_KEYS_SUPPORTED:
                    raise PacmanRouteInfoAllocationException(
                        "This routing info allocator can only support up to {}"
                        " keys for any given subedge; cannot therefore"
                        " allocate keys to {}, which is requesting {} keys"
                        .format(MAX_KEYS_SUPPORTED, out_going_subedge, n_keys))
                placement = placements.get_placement_of_subvertex(subvert)
                if placement is not None:
                    key = self._get_key_from_placement(placement)
                    keys_and_masks = list([BaseKeyAndMask(base_key=key,
                                                          mask=MASK)])
                    subedge_routing_info = SubedgeRoutingInfo(
                        keys_and_masks, out_going_subedge)
                    routing_infos.add_subedge_info(subedge_routing_info)
                else:
                    raise PacmanRouteInfoAllocationException(
                        "This subvertex '{}' has no placement! this should "
                        "never occur, please fix and try again."
                        .format(subvert))
                # update routing tables with entries
                routing_info_allocator_utilities.add_routing_key_entries(
                    routing_paths, subedge_routing_info, out_going_subedge,
                    routing_tables)
            progress_bar.update()
        progress_bar.end()

        return {'routing_infos': routing_infos,
                'routing_tables': routing_tables}
    def test_write_synaptic_matrix_and_master_population_table(self):
        MockSimulator.setup()

        default_config_paths = os.path.join(
            os.path.dirname(abstract_spinnaker_common.__file__),
            AbstractSpiNNakerCommon.CONFIG_FILE_NAME)

        config = conf_loader.load_config(
            AbstractSpiNNakerCommon.CONFIG_FILE_NAME, default_config_paths)
        config.set("Simulation", "one_to_one_connection_dtcm_max_bytes", 40)

        machine_time_step = 1000.0

        pre_app_vertex = SimpleApplicationVertex(10)
        pre_vertex = SimpleMachineVertex(resources=None)
        pre_vertex_slice = Slice(0, 9)
        post_app_vertex = SimpleApplicationVertex(10)
        post_vertex = SimpleMachineVertex(resources=None)
        post_vertex_slice = Slice(0, 9)
        post_slice_index = 0
        one_to_one_connector_1 = OneToOneConnector(None)
        one_to_one_connector_1.set_projection_information(
            pre_app_vertex, post_app_vertex, None, machine_time_step)
        one_to_one_connector_1.set_weights_and_delays(1.5, 1.0)
        one_to_one_connector_2 = OneToOneConnector(None)
        one_to_one_connector_2.set_projection_information(
            pre_app_vertex, post_app_vertex, None, machine_time_step)
        one_to_one_connector_2.set_weights_and_delays(2.5, 2.0)
        all_to_all_connector = AllToAllConnector(None)
        all_to_all_connector.set_projection_information(
            pre_app_vertex, post_app_vertex, None, machine_time_step)
        all_to_all_connector.set_weights_and_delays(4.5, 4.0)
        direct_synapse_information_1 = SynapseInformation(
            one_to_one_connector_1, SynapseDynamicsStatic(), 0)
        direct_synapse_information_2 = SynapseInformation(
            one_to_one_connector_2, SynapseDynamicsStatic(), 1)
        all_to_all_synapse_information = SynapseInformation(
            all_to_all_connector, SynapseDynamicsStatic(), 0)
        app_edge = ProjectionApplicationEdge(
            pre_app_vertex, post_app_vertex, direct_synapse_information_1)
        app_edge.add_synapse_information(direct_synapse_information_2)
        app_edge.add_synapse_information(all_to_all_synapse_information)
        machine_edge = ProjectionMachineEdge(
            app_edge.synapse_information, pre_vertex, post_vertex)
        partition_name = "TestPartition"

        graph = MachineGraph("Test")
        graph.add_vertex(pre_vertex)
        graph.add_vertex(post_vertex)
        graph.add_edge(machine_edge, partition_name)

        graph_mapper = GraphMapper()
        graph_mapper.add_vertex_mapping(
            pre_vertex, pre_vertex_slice, pre_app_vertex)
        graph_mapper.add_vertex_mapping(
            post_vertex, post_vertex_slice, post_app_vertex)
        graph_mapper.add_edge_mapping(machine_edge, app_edge)

        weight_scales = [4096.0, 4096.0]

        key = 0
        routing_info = RoutingInfo()
        routing_info.add_partition_info(PartitionRoutingInfo(
            [BaseKeyAndMask(key, 0xFFFFFFF0)],
            graph.get_outgoing_edge_partition_starting_at_vertex(
                pre_vertex, partition_name)))

        temp_spec = tempfile.mktemp()
        spec_writer = FileDataWriter(temp_spec)
        spec = DataSpecificationGenerator(spec_writer, None)
        master_pop_sz = 1000
        master_pop_region = 0
        all_syn_block_sz = 2000
        synapse_region = 1
        spec.reserve_memory_region(master_pop_region, master_pop_sz)
        spec.reserve_memory_region(synapse_region, all_syn_block_sz)

        synapse_type = MockSynapseType()

        synaptic_manager = SynapticManager(
            synapse_type=synapse_type, ring_buffer_sigma=5.0,
            spikes_per_second=100.0, config=config)
        synaptic_manager._write_synaptic_matrix_and_master_population_table(
            spec, [post_vertex_slice], post_slice_index, post_vertex,
            post_vertex_slice, all_syn_block_sz, weight_scales,
            master_pop_region, synapse_region, routing_info, graph_mapper,
            graph, machine_time_step)
        spec.end_specification()
        spec_writer.close()

        spec_reader = FileDataReader(temp_spec)
        executor = DataSpecificationExecutor(
            spec_reader, master_pop_sz + all_syn_block_sz)
        executor.execute()

        master_pop_table = executor.get_region(0)
        synaptic_matrix = executor.get_region(1)

        all_data = bytearray()
        all_data.extend(master_pop_table.region_data[
            :master_pop_table.max_write_pointer])
        all_data.extend(synaptic_matrix.region_data[
            :synaptic_matrix.max_write_pointer])
        master_pop_table_address = 0
        synaptic_matrix_address = master_pop_table.max_write_pointer
        direct_synapses_address = struct.unpack_from(
            "<I", synaptic_matrix.region_data)[0]
        direct_synapses_address += synaptic_matrix_address + 8
        indirect_synapses_address = synaptic_matrix_address + 4
        placement = Placement(None, 0, 0, 1)
        transceiver = MockTransceiverRawData(all_data)

        # Get the master population table details
        items = synaptic_manager._poptable_type\
            .extract_synaptic_matrix_data_location(
                key, master_pop_table_address, transceiver,
                placement.x, placement.y)

        # The first entry should be direct, but the rest should be indirect;
        # the second is potentially direct, but has been restricted by the
        # restriction on the size of the direct matrix
        assert len(items) == 3

        # TODO: This has been changed because direct matrices are disabled!
        assert not items[0][2]
        assert not items[1][2]
        assert not items[2][2]

        data_1, row_len_1 = synaptic_manager._retrieve_synaptic_block(
            transceiver=transceiver, placement=placement,
            master_pop_table_address=master_pop_table_address,
            indirect_synapses_address=indirect_synapses_address,
            direct_synapses_address=direct_synapses_address, key=key,
            n_rows=pre_vertex_slice.n_atoms, index=0,
            using_extra_monitor_cores=False)
        connections_1 = synaptic_manager._synapse_io.read_synapses(
            direct_synapse_information_1, pre_vertex_slice, post_vertex_slice,
            row_len_1, 0, 2, weight_scales, data_1, None,
            app_edge.n_delay_stages, machine_time_step)

        # The first matrix is a 1-1 matrix, so row length is 1
        assert row_len_1 == 1

        # Check that all the connections have the right weight and delay
        assert len(connections_1) == post_vertex_slice.n_atoms
        assert all([conn["weight"] == 1.5 for conn in connections_1])
        assert all([conn["delay"] == 1.0 for conn in connections_1])

        data_2, row_len_2 = synaptic_manager._retrieve_synaptic_block(
            transceiver=transceiver, placement=placement,
            master_pop_table_address=master_pop_table_address,
            indirect_synapses_address=indirect_synapses_address,
            direct_synapses_address=direct_synapses_address, key=key,
            n_rows=pre_vertex_slice.n_atoms, index=1,
            using_extra_monitor_cores=False)
        connections_2 = synaptic_manager._synapse_io.read_synapses(
            direct_synapse_information_2, pre_vertex_slice, post_vertex_slice,
            row_len_2, 0, 2, weight_scales, data_2, None,
            app_edge.n_delay_stages, machine_time_step)

        # The second matrix is a 1-1 matrix, so row length is 1
        assert row_len_2 == 1

        # Check that all the connections have the right weight and delay
        assert len(connections_2) == post_vertex_slice.n_atoms
        assert all([conn["weight"] == 2.5 for conn in connections_2])
        assert all([conn["delay"] == 2.0 for conn in connections_2])

        data_3, row_len_3 = synaptic_manager._retrieve_synaptic_block(
            transceiver=transceiver, placement=placement,
            master_pop_table_address=master_pop_table_address,
            indirect_synapses_address=indirect_synapses_address,
            direct_synapses_address=direct_synapses_address, key=key,
            n_rows=pre_vertex_slice.n_atoms, index=2,
            using_extra_monitor_cores=False)
        connections_3 = synaptic_manager._synapse_io.read_synapses(
            all_to_all_synapse_information, pre_vertex_slice,
            post_vertex_slice, row_len_3, 0, 2, weight_scales, data_3, None,
            app_edge.n_delay_stages, machine_time_step)

        # The third matrix is an all-to-all matrix, so length is n_atoms
        assert row_len_3 == post_vertex_slice.n_atoms

        # Check that all the connections have the right weight and delay
        assert len(connections_3) == \
            post_vertex_slice.n_atoms * pre_vertex_slice.n_atoms
        assert all([conn["weight"] == 4.5 for conn in connections_3])
        assert all([conn["delay"] == 4.0 for conn in connections_3])
Example #13
0
    def __call__(self, subgraph, placements, n_keys_map, routing_paths):
        """
        Allocates routing information to the partitioned edges in a\
        partitioned graph

        :param subgraph: The partitioned graph to allocate the routing info for
        :type subgraph:\
                    :py:class:`pacman.model.partitioned_graph.partitioned_graph.PartitionedGraph`
        :param placements: The placements of the subvertices
        :type placements:\
                    :py:class:`pacman.model.placements.placements.Placements`
        :param n_keys_map: A map between the partitioned edges and the number\
                    of keys required by the edges
        :type n_keys_map:\
                    :py:class:`pacman.model.routing_info.abstract_partitioned_edge_n_keys_map.AbstractPartitionedEdgeNKeysMap`
        :param routing_paths: the paths each partitioned edge takes to get\
                from source to destination.
        :type routing_paths:
            :py:class:`pacman.model.routing_paths.multicast_routing_paths.MulticastRoutingPaths
        :return: The routing information
        :rtype: :py:class:`pacman.model.routing_info.routing_info.RoutingInfo`,
                :py:class:`pacman.model.routing_tables.multicast_routing_table.MulticastRoutingTable
        :raise pacman.exceptions.PacmanRouteInfoAllocationException: If\
                   something goes wrong with the allocation
        """

        # check that this algorithm supports the constraints put onto the
        # partitioned_edges
        supported_constraints = []
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=subgraph.subedges,
            supported_constraints=supported_constraints,
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # take each subedge and create keys from its placement
        progress_bar = ProgressBar(len(subgraph.subedges),
                                   "Allocating routing keys")
        routing_infos = RoutingInfo()
        routing_tables = MulticastRoutingTables()

        for subedge in subgraph.subedges:
            destination = subedge.post_subvertex
            placement = placements.get_placement_of_subvertex(destination)
            key = self._get_key_from_placement(placement)
            keys_and_masks = list(
                [BaseKeyAndMask(base_key=key, mask=self.MASK)])
            n_keys = n_keys_map.n_keys_for_partitioned_edge(subedge)
            if n_keys > self.MAX_KEYS_SUPPORTED:
                raise exceptions.PacmanConfigurationException(
                    "Only edges which require less than {} keys are supported".
                    format(self.MAX_KEYS_SUPPORTED))

            partition_info = PartitionRoutingInfo(keys_and_masks, subedge)
            routing_infos.add_partition_info(partition_info)

            progress_bar.update()
        progress_bar.end()

        return {
            'routing_infos': routing_infos,
            'routing_tables': routing_tables
        }
class MyTestCase(unittest.TestCase):
    def setUp(self):
        # sort out graph
        self.vert1 = Vertex(10, "New AbstractConstrainedVertex 1")
        self.vert2 = Vertex(5, "New AbstractConstrainedVertex 2")
        self.edge1 = AbstractPartitionableEdge(self.vert1, self.vert2, "First edge")
        self.verts = [self.vert1, self.vert2]
        self.edges = [self.edge1]
        self.graph = PartitionableGraph("Graph", self.verts, self.edges)
        # sort out subgraph
        self.subgraph = PartitionedGraph()
        self.subvert1 = PartitionedVertex(
            0, 10, get_resources_used_by_atoms(0, 10, []))
        self.subvert2 = PartitionedVertex(
            0, 5, get_resources_used_by_atoms(0, 10, []))
        self.subedge = AbstractPartitionedEdge(self.subvert1, self.subvert2)
        self.subgraph.add_subvertex(self.subvert1)
        self.subgraph.add_subvertex(self.subvert2)
        self.subgraph.add_subedge(self.subedge)
        # sort out placements
        self.placements = Placements()
        self.placement1 = Placement(x=0, y=0, p=2, subvertex=self.subvert1)
        self.placement2 = Placement(x=1, y=1, p=2, subvertex=self.subvert2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        # sort out routing infos
        self.routing_info = RoutingInfo()
        self.subedge_routing_info1 = \
            SubedgeRoutingInfo(key=2 << 11, mask=constants.DEFAULT_MASK,
                               subedge=self.subedge)
        self.routing_info.add_subedge_info(self.subedge_routing_info1)
        # create machine
        flops = 1000
        (e, ne, n, w, sw, s) = range(6)

        processors = list()
        for i in range(18):
            processors.append(Processor(i, flops))
        _sdram = SDRAM(128 * (2 ** 20))
        ip = "192.162.240.253"
        chips = list()
        for x in range(10):
            for y in range(10):
                links = list()

                links.append(Link(x, y, 0, (x + 1) % 10, y, n, n))
                links.append(Link(x, y, 1, (x + 1) % 10, (y + 1) % 10, s, s))
                links.append(Link(x, y, 2, x, (y + 1) % 10, n, n))
                links.append(Link(x, y, 3, (x - 1) % 10, y, s, s))
                links.append(Link(x, y, 4, (x - 1) % 10, (y - 1) % 10, n, n))
                links.append(Link(x, y, 5, x, (y - 1) % 10, s, s))

                r = Router(links, False, 100, 1024)
                chips.append(Chip(x, y, processors, r, _sdram, ip))

        self.machine = Machine(chips)

    @unittest.skip("demonstrating skipping")
    def set_up_4_node_board(self):
        flops = 1000
        (e, ne, n, w, sw, s) = range(6)

        processors = list()
        for i in range(18):
            processors.append(Processor(i, flops))
        _sdram = SDRAM(128 * (2 ** 20))
        ip = "192.162.240.253"
        chips = list()
        for x in range(2):
            for y in range(2):
                links = list()

                links.append(Link(x, y, 0, (x + 1) % 2, y, n, n))
                links.append(Link(x, y, 1, (x + 1) % 2, (y + 1) % 2, s, s))
                links.append(Link(x, y, 2, x, (y + 1) % 2, n, n))
                links.append(Link(x, y, 3, (x - 1) % 2, y, s, s))
                links.append(Link(x, y, 4, (x - 1) % 2, (y - 1) % 2, n, n))
                links.append(Link(x, y, 5, x, (y - 1) % 2, s, s))

                r = Router(links, False, 100, 1024)
                chips.append(Chip(x, y, processors, r, _sdram, ip))

        self.machine = Machine(chips)

    @unittest.skip("demonstrating skipping")
    def test_new_basic_router(self):
        dijkstra_router = BasicDijkstraRouting()
        self.assertEqual(dijkstra_router._k, 1)
        self.assertEqual(dijkstra_router._l, 0)
        self.assertEqual(dijkstra_router._m, 0)
        self.assertEqual(dijkstra_router._bw_per_route_entry,
                         dijkstra_router.BW_PER_ROUTE_ENTRY)
        self.assertEqual(dijkstra_router._max_bw, dijkstra_router.MAX_BW)

    @unittest.skip("demonstrating skipping")
    def test_run_basic_routing_off_chip_custom_100_node_machine(self):
        dijkstra_router = BasicDijkstraRouting()
        routing_tables = dijkstra_router.route(
            machine=self.machine, placements=self.placements,
            partitioned_graph=self.subgraph,
            routing_info_allocation=self.routing_info)
        for entry in routing_tables.routing_tables:
            print entry.x, entry.y
            for routing_entry in entry.multicast_routing_entries:
                print "\t\tProcessor_ids:{}, Link_ids:{}".format(
                    routing_entry.processor_ids,
                    routing_entry.link_ids)

    @unittest.skip("demonstrating skipping")
    def test_run_basic_routing_off_chip_custom_4_node_machine(self):
        self.set_up_4_node_board()
        dijkstra_router = BasicDijkstraRouting()
        routing_tables = dijkstra_router.route(
            machine=self.machine, placements=self.placements,
            partitioned_graph=self.subgraph,
            routing_info_allocation=self.routing_info)

        for entry in routing_tables.routing_tables:
            print entry.x, entry.y
            for routing_entry in entry.multicast_routing_entries:
                print "\t\tProcessor_ids:{}, Link_ids:{}".format(
                    routing_entry.processor_ids,
                    routing_entry.link_ids)

    @unittest.skip("demonstrating skipping")
    def test_bad_machine_setup(self):
        # create machine
        flops = 1000
        (e, ne, n, w, sw, s) = range(6)

        processors = list()
        for i in range(18):
            processors.append(Processor(i, flops))

        links = list()
        links.append(Link(0, 0, 0, 0, 1, s, s))

        _sdram = SDRAM(128 * (2 ** 20))

        links = list()

        links.append(Link(0, 0, 0, 1, 1, n, n))
        links.append(Link(0, 1, 1, 1, 0, s, s))
        links.append(Link(1, 1, 2, 0, 0, e, e))
        links.append(Link(1, 0, 3, 0, 1, w, w))
        r = Router(links, False, 100, 1024)

        ip = "192.162.240.253"
        chips = list()
        for x in range(5):
            for y in range(5):
                chips.append(Chip(x, y, processors, r, _sdram, ip))
        self.machine = Machine(chips)
        dijkstra_router = BasicDijkstraRouting()

        with self.assertRaises(PacmanRoutingException):
            dijkstra_router.route(
                machine=self.machine, placements=self.placements,
                partitioned_graph=self.subgraph,
                routing_info_allocation=self.routing_info)

    @unittest.skip("demonstrating skipping")
    def test_routing_on_chip_custom_4_node_machine(self):
        self.placements = Placements()
        self.placement1 = Placement(x=1, y=0, p=2, subvertex=self.subvert1)
        self.placement2 = Placement(x=1, y=0, p=3, subvertex=self.subvert2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        # sort out routing infos
        self.routing_info = RoutingInfo()
        self.subedge_routing_info1 = \
            SubedgeRoutingInfo(key=2 << 11, mask=constants.DEFAULT_MASK,
                               subedge=self.subedge)
        self.routing_info.add_subedge_info(self.subedge_routing_info1)

        self.set_up_4_node_board()

        dijkstra_router = BasicDijkstraRouting()
        routing_tables = dijkstra_router.route(
            machine=self.machine, placements=self.placements,
            partitioned_graph=self.subgraph,
            routing_info_allocation=self.routing_info)

        for entry in routing_tables.routing_tables:
            print entry.x, entry.y
            for routing_entry in entry.multicast_routing_entries:
                print "\t\tProcessor_ids:{}, Link_ids:{}".format(
                    routing_entry.processor_ids,
                    routing_entry.link_ids)

    @unittest.skip("demonstrating skipping")
    def test_full_machine_routing(self):
        placements = Placements()
        self.placement1 = Placement(x=1, y=0, p=2, subvertex=self.subvert1)
        self.placement2 = Placement(x=1, y=0, p=3, subvertex=self.subvert2)
        subvertices = list()
        for i in range(4 * 17): #51 atoms per each processor on 20 chips
            subvertices.append(PartitionedVertex(
                0, 50, get_resources_used_by_atoms(0, 50, []),
                "Subvertex " + str(i)))
        subedges = list()
        for i in range(len(subvertices)):
            subedges.append(AbstractPartitionedEdge(
                subvertices[i], subvertices[(i + 1)%len(subvertices)]))
        subgraph = PartitionedGraph("Subgraph", subvertices, subedges)
        p = 1
        x = 0
        y = 0
        for subvert in subvertices:
            placements.add_placement(Placement(subvert, x, y, p))
            p = (p + 1) % 18
            if p == 0:
                p += 1
                y += 1
                if y == 2:
                    y = 0
                    x += 1

        routing_info = RoutingInfo()
        subedge_routing_info = list()
        for i in range(len(subedges)):
            subedge_routing_info.append(SubedgeRoutingInfo(
                subedges[i], i<<11, constants.DEFAULT_MASK))

        for subedge_info in subedge_routing_info:
            routing_info.add_subedge_info(subedge_info)


        self.set_up_4_node_board()

        dijkstra_router = BasicDijkstraRouting()
        routing_tables = dijkstra_router.route(
            machine=self.machine, placements=placements,
            partitioned_graph=subgraph,
            routing_info_allocation=routing_info)

        for entry in routing_tables.routing_tables:
            print entry.x, entry.y
            for routing_entry in entry.multicast_routing_entries:
                print "\t\tProcessor_ids:{}, Link_ids:{}".format(
                    routing_entry.processor_ids,
                    routing_entry.link_ids)

    @unittest.skip("demonstrating skipping")
    def test_routing_to_other_machine(self):
        self.assertEqual(True, False, "Test not implemented yet")
Example #15
0
    def __call__(self, subgraph, n_keys_map, graph_mapper=None):

        # check that this algorithm supports the constraints
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=subgraph.partitions,
            supported_constraints=[
                KeyAllocatorFixedMaskConstraint,
                KeyAllocatorFixedKeyAndMaskConstraint,
                KeyAllocatorContiguousRangeContraint
            ],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # verify that no edge has more than 1 of a constraint ,and that
        # constraints are compatible
        routing_info_allocator_utilities.\
            check_types_of_edge_constraint(subgraph)

        routing_infos = RoutingInfo()

        # Get the partitioned edges grouped by those that require the same key
        (fixed_key_groups, fixed_mask_groups, fixed_field_groups,
         flexi_field_groups, continuous_groups, none_continuous_groups) = \
            routing_info_allocator_utilities.get_edge_groups(subgraph)

        # Even non-continuous keys will be continuous
        for group in none_continuous_groups:
            continuous_groups.add(group)

        # Go through the groups and allocate keys
        progress_bar = ProgressBar(len(subgraph.partitions),
                                   "Allocating routing keys")

        # allocate the groups that have fixed keys
        for group in fixed_key_groups:  # fixed keys groups

            # Get any fixed keys and masks from the group and attempt to
            # allocate them
            fixed_mask = None
            fixed_key_and_mask_constraint = \
                utility_calls.locate_constraints_of_type(
                    group.constraints,
                    KeyAllocatorFixedKeyAndMaskConstraint)[0]

            # attempt to allocate them
            self._allocate_fixed_keys_and_masks(
                fixed_key_and_mask_constraint.keys_and_masks, fixed_mask)

            # update the pacman data objects
            self._update_routing_objects(
                fixed_key_and_mask_constraint.keys_and_masks, routing_infos,
                group)

            continuous_groups.remove(group)

            progress_bar.update()

        for group in fixed_mask_groups:  # fixed mask groups

            # get mask and fields if need be
            fixed_mask = utility_calls.locate_constraints_of_type(
                group.constraints, KeyAllocatorFixedMaskConstraint)[0].mask

            fields = None
            if group in fixed_field_groups:
                fields = utility_calls.locate_constraints_of_type(
                    group.constraints,
                    KeyAllocatorFixedFieldConstraint)[0].fields
                fixed_field_groups.remove(group)

            # try to allocate
            keys_and_masks = self._allocate_keys_and_masks(
                fixed_mask, fields, n_keys_map.n_keys_for_partition(group))

            # update the pacman data objects
            self._update_routing_objects(keys_and_masks, routing_infos, group)

            continuous_groups.remove(group)

            progress_bar.update()

        for group in fixed_field_groups:
            fields = utility_calls.locate_constraints_of_type(
                group.constraints, KeyAllocatorFixedFieldConstraint)[0].fields

            # try to allocate
            keys_and_masks = self._allocate_keys_and_masks(
                None, fields, n_keys_map.n_keys_for_partition(group))

            # update the pacman data objects
            self._update_routing_objects(keys_and_masks, routing_infos, group)

            continuous_groups.remove(group)

            progress_bar.update()

        if len(flexi_field_groups) != 0:
            raise exceptions.PacmanConfigurationException(
                "MallocBasedRoutingInfoAllocator does not support FlexiField")

        # If there is a graph, group by source vertex and sort by vertex slice
        # (lo_atom)
        if graph_mapper is not None:
            vertex_groups = defaultdict(list)
            for partition in continuous_groups:
                vertex = graph_mapper.get_vertex_from_subvertex(
                    partition.edges[0].pre_subvertex)
                vertex_groups[vertex].append(partition)
            vertex_partitions = list()
            for vertex_group in vertex_groups.itervalues():
                sorted_partitions = sorted(
                    vertex_group,
                    key=lambda part: graph_mapper.get_subvertex_slice(
                        part.edges[0].pre_subvertex))
                vertex_partitions.extend(sorted_partitions)
            continuous_groups = vertex_partitions

        for group in continuous_groups:
            keys_and_masks = self._allocate_keys_and_masks(
                None, None, n_keys_map.n_keys_for_partition(group))

            # update the pacman data objects
            self._update_routing_objects(keys_and_masks, routing_infos, group)

        progress_bar.end()
        return {'routing_infos': routing_infos}
Example #16
0
    def __call__(self, partitioned_graph, placements, n_keys_map):
        """
        Allocates routing information to the partitioned edges in a\
        partitioned graph

        :param partitioned_graph: The partitioned graph to allocate the \
                    outing info for
        :type partitioned_graph:\
                    :py:class:`pacman.model.partitioned_graph.partitioned_graph.PartitionedGraph`
        :param placements: The placements of the subvertices
        :type placements:\
                    :py:class:`pacman.model.placements.placements.Placements`
        :param n_keys_map: A map between the partitioned edges and the number\
                    of keys required by the edges
        :type n_keys_map:\
                    :py:class:`pacman.model.routing_info.abstract_partitioned_edge_n_keys_map.AbstractPartitionedEdgeNKeysMap`
        :return: The routing information
        :rtype: :py:class:`pacman.model.routing_info.routing_info.RoutingInfo`,
                :py:class:`pacman.model.routing_tables.multicast_routing_table.MulticastRoutingTable
        :raise pacman.exceptions.PacmanRouteInfoAllocationException: If\
                   something goes wrong with the allocation
        """

        # check that this algorithm supports the constraints put onto the
        # partitioned_edges
        supported_constraints = [KeyAllocatorContiguousRangeContraint]
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=partitioned_graph.partitions,
            supported_constraints=supported_constraints,
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # take each subedge and create keys from its placement
        progress_bar = ProgressBar(len(partitioned_graph.subvertices),
                                   "Allocating routing keys")
        routing_infos = RoutingInfo()
        for subvert in partitioned_graph.subvertices:
            partitions = partitioned_graph.\
                outgoing_edges_partitions_from_vertex(subvert)
            for partition in partitions.values():
                n_keys = n_keys_map.n_keys_for_partition(partition)
                if n_keys > MAX_KEYS_SUPPORTED:
                    raise PacmanRouteInfoAllocationException(
                        "This routing info allocator can only support up to {}"
                        " keys for any given subedge; cannot therefore"
                        " allocate keys to {}, which is requesting {} keys".
                        format(MAX_KEYS_SUPPORTED, partition, n_keys))
                placement = placements.get_placement_of_subvertex(subvert)
                if placement is not None:
                    key = self._get_key_from_placement(placement)
                    keys_and_masks = list(
                        [BaseKeyAndMask(base_key=key, mask=MASK)])
                    subedge_routing_info = PartitionRoutingInfo(
                        keys_and_masks, partition)
                    routing_infos.add_partition_info(subedge_routing_info)
                else:
                    raise PacmanRouteInfoAllocationException(
                        "This subvertex '{}' has no placement! this should "
                        "never occur, please fix and try again.".format(
                            subvert))

            progress_bar.update()
        progress_bar.end()

        return {'routing_infos': routing_infos}
Example #17
0
class TestRouter(unittest.TestCase):

    def setUp(self):
        #sort out graph
        self.vert1 = Vertex(10, "New AbstractConstrainedVertex 1")
        self.vert2 = Vertex(5, "New AbstractConstrainedVertex 2")
        self.edge1 = AbstractPartitionableEdge(self.vert1, self.vert2, "First edge")
        self.verts = [self.vert1, self.vert2]
        self.edges = [self.edge1]
        self.graph = PartitionableGraph("Graph", self.verts, self.edges)
        #sort out subgraph
        self.subgraph = PartitionedGraph()
        self.subvert1 = PartitionedVertex(
            0, 10, self.vert1.get_resources_used_by_atoms(0, 10, []))
        self.subvert2 = PartitionedVertex(
            0, 5, self.vert2.get_resources_used_by_atoms(0, 10, []))
        self.subedge = AbstractPartitionedEdge(self.subvert1, self.subvert2)
        self.subgraph.add_subvertex(self.subvert1)
        self.subgraph.add_subvertex(self.subvert2)
        self.subgraph.add_subedge(self.subedge)

    @unittest.skip("demonstrating skipping")
    def test_router_with_same_chip_route(self):
        #sort out placements
        self.placements = Placements()
        self.placement1 = Placement(x=0, y=0, p=2, subvertex=self.subvert1)
        self.placement2 = Placement(x=0, y=0, p=3, subvertex=self.subvert2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        #sort out routing infos
        self.routing_info = RoutingInfo()
        self.subedge_routing_info1 = \
            SubedgeRoutingInfo(key=2 << 11, mask=constants.DEFAULT_MASK,
                               subedge=self.subedge)
        self.routing_info.add_subedge_info(self.subedge_routing_info1)
        #create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(
            machine=self.machine, placements=self.placements,
            partitioned_graph=self.subgraph,
            routing_info_allocation=self.routing_info)

    @unittest.skip("demonstrating skipping")
    def test_router_with_neighbour_chip(self):
        #sort out placements
        self.placements = Placements()
        self.placement1 = Placement(x=0, y=0, p=2, subvertex=self.subvert1)
        self.placement2 = Placement(x=1, y=1, p=2, subvertex=self.subvert2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        #sort out routing infos
        self.routing_info = RoutingInfo()
        self.subedge_routing_info1 = \
            SubedgeRoutingInfo(key=2 << 11, mask=constants.DEFAULT_MASK,
                               subedge=self.subedge)
        self.routing_info.add_subedge_info(self.subedge_routing_info1)
        #create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(
            machine=self.machine, placements=self.placements,
            partitioned_graph=self.subgraph,
            routing_info_allocation=self.routing_info)

    @unittest.skip("demonstrating skipping")
    def test_router_with_one_hop_route_all_default_link_0(self):
        #sort out placements
        self.placements = Placements()
        self.placement1 = Placement(x=0, y=0, p=2, subvertex=self.subvert1)
        self.placement2 = Placement(x=2, y=0, p=2, subvertex=self.subvert2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        #sort out routing infos
        self.routing_info = RoutingInfo()
        self.subedge_routing_info1 = \
            SubedgeRoutingInfo(key=2 << 11, mask=constants.DEFAULT_MASK,
                               subedge=self.subedge)
        self.routing_info.add_subedge_info(self.subedge_routing_info1)
        #create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(
            machine=self.machine, placements=self.placements,
            partitioned_graph=self.subgraph,
            routing_info_allocation=self.routing_info)

    @unittest.skip("demonstrating skipping")
    def test_router_with_one_hop_route_all_default_link_1(self):
        self.placements = Placements()
        self.placement1 = Placement(x=0, y=0, p=2, subvertex=self.subvert1)
        self.placement2 = Placement(x=2, y=2, p=2, subvertex=self.subvert2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        #sort out routing infos
        self.routing_info = RoutingInfo()
        self.subedge_routing_info1 = \
            SubedgeRoutingInfo(key=2 << 11, mask=constants.DEFAULT_MASK,
                               subedge=self.subedge)
        self.routing_info.add_subedge_info(self.subedge_routing_info1)
        #create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(
            machine=self.machine, placements=self.placements,
            partitioned_graph=self.subgraph,
            routing_info_allocation=self.routing_info)

    @unittest.skip("demonstrating skipping")
    def test_router_with_one_hop_route_all_default_link_2(self):
        self.placements = Placements()
        self.placement1 = Placement(x=0, y=0, p=2, subvertex=self.subvert1)
        self.placement2 = Placement(x=0, y=2, p=2, subvertex=self.subvert2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        #sort out routing infos
        self.routing_info = RoutingInfo()
        self.subedge_routing_info1 = \
            SubedgeRoutingInfo(key=2 << 11, mask=constants.DEFAULT_MASK,
                               subedge=self.subedge)
        self.routing_info.add_subedge_info(self.subedge_routing_info1)
        #create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(
            machine=self.machine, placements=self.placements,
            partitioned_graph=self.subgraph,
            routing_info_allocation=self.routing_info)

    @unittest.skip("demonstrating skipping")
    def test_router_with_one_hop_route_all_default_link_3(self):
        self.placements = Placements()
        self.placement1 = Placement(x=2, y=0, p=2, subvertex=self.subvert1)
        self.placement2 = Placement(x=0, y=0, p=2, subvertex=self.subvert2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        #sort out routing infos
        self.routing_info = RoutingInfo()
        self.subedge_routing_info1 = \
            SubedgeRoutingInfo(key=2 << 11, mask=constants.DEFAULT_MASK,
                               subedge=self.subedge)
        self.routing_info.add_subedge_info(self.subedge_routing_info1)
        #create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(
            machine=self.machine, placements=self.placements,
            partitioned_graph=self.subgraph,
            routing_info_allocation=self.routing_info)

    @unittest.skip("demonstrating skipping")
    def test_router_with_one_hop_route_all_default_link_4(self):
        self.placements = Placements()
        self.placement1 = Placement(x=2, y=2, p=2, subvertex=self.subvert1)
        self.placement2 = Placement(x=0, y=0, p=2, subvertex=self.subvert2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        #sort out routing infos
        self.routing_info = RoutingInfo()
        self.subedge_routing_info1 = \
            SubedgeRoutingInfo(key=2 << 11, mask=constants.DEFAULT_MASK,
                               subedge=self.subedge)
        self.routing_info.add_subedge_info(self.subedge_routing_info1)
        #create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(
            machine=self.machine, placements=self.placements,
            partitioned_graph=self.subgraph,
            routing_info_allocation=self.routing_info)

    @unittest.skip("demonstrating skipping")
    def test_router_with_one_hop_route_all_default_link_5(self):
        self.placements = Placements()
        self.placement1 = Placement(x=0, y=2, p=2, subvertex=self.subvert1)
        self.placement2 = Placement(x=0, y=0, p=2, subvertex=self.subvert2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        #sort out routing infos
        self.routing_info = RoutingInfo()
        self.subedge_routing_info1 = \
            SubedgeRoutingInfo(key=2 << 11, mask=constants.DEFAULT_MASK,
                               subedge=self.subedge)
        self.routing_info.add_subedge_info(self.subedge_routing_info1)
        #create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(
            machine=self.machine, placements=self.placements,
            partitioned_graph=self.subgraph,
            routing_info_allocation=self.routing_info)

    @unittest.skip("demonstrating skipping")
    def test_router_with_one_hop_route_not_default(self):
        #sort out placements
        self.placements = Placements()
        self.placement1 = Placement(x=2, y=1, p=2, subvertex=self.subvert1)
        self.placement2 = Placement(x=0, y=0, p=2, subvertex=self.subvert2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        #sort out routing infos
        self.routing_info = RoutingInfo()
        self.subedge_routing_info1 = \
            SubedgeRoutingInfo(key=2 << 11, mask=constants.DEFAULT_MASK,
                               subedge=self.subedge)
        self.routing_info.add_subedge_info(self.subedge_routing_info1)
        #create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(
            machine=self.machine, placements=self.placements,
            partitioned_graph=self.subgraph,
            routing_info_allocation=self.routing_info)

    @unittest.skip("demonstrating skipping")
    def test_router_with_multi_hop_route_across_board(self):
        #sort out placements
        self.placements = Placements()
        self.placement1 = Placement(x=0, y=0, p=2, subvertex=self.subvert1)
        self.placement2 = Placement(x=8, y=7, p=2, subvertex=self.subvert2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        #sort out routing infos
        self.routing_info = RoutingInfo()
        self.subedge_routing_info1 = \
            SubedgeRoutingInfo(key=2 << 11, mask=constants.DEFAULT_MASK,
                               subedge=self.subedge)
        self.routing_info.add_subedge_info(self.subedge_routing_info1)
        #create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(
            machine=self.machine, placements=self.placements,
            partitioned_graph=self.subgraph,
            routing_info_allocation=self.routing_info)

    @unittest.skip("demonstrating skipping")
    def test_new_router(self):
        report_folder = "..\reports"
        self.routing = BasicDijkstraRouting()
        self.assertEqual(self.routing._report_folder, report_folder)
        self.assertEqual(self.routing._graph, None)
        self.assertEqual(self.routing.report_states, None)
        self.assertEqual(self.routing._hostname, None)
        self.assertIsInstance(self.routing._router_algorithm,
                              BasicDijkstraRouting)
        self.assertEqual(self.routing._graph_to_subgraph_mappings, None)

    @unittest.skip("demonstrating skipping")
    def test_new_router_set_non_default_routing_algorithm(self):
        report_folder = "..\reports"
        self.routing = BasicDijkstraRouting()
        self.assertEqual(self.routing._report_folder, report_folder)
        self.assertEqual(self.routing._graph, None)
        self.assertEqual(self.routing.report_states, None)
        self.assertEqual(self.routing._hostname, None)
        self.assertEqual(self.routing._graph_to_subgraph_mappings, None)

    @unittest.skip("demonstrating skipping")
    def test_run_router(self):
        #sort out placements
        self.placements = Placements()
        self.placement1 = Placement(x=0, y=0, p=2, subvertex=self.subvert1)
        self.placement2 = Placement(x=1, y=1, p=2, subvertex=self.subvert2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        #sort out routing infos
        self.routing_info = RoutingInfo()
        self.subedge_routing_info1 = \
            SubedgeRoutingInfo(key=2 << 11, mask=constants.DEFAULT_MASK,
                               subedge=self.subedge)
        self.routing_info.add_subedge_info(self.subedge_routing_info1)
        #create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(
            machine=self.machine, placements=self.placements,
            partitioned_graph=self.subgraph,
            routing_info_allocation=self.routing_info)
    def __call__(self, subgraph, n_keys_map, routing_tables):

        # check that this algorithm supports the constraints
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=subgraph.partitions,
            supported_constraints=[
                KeyAllocatorFixedMaskConstraint,
                KeyAllocatorFixedKeyAndMaskConstraint,
                KeyAllocatorContiguousRangeContraint
            ],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # verify that no edge has more than 1 of a constraint ,and that
        # constraints are compatible
        routing_info_allocator_utilities.\
            check_types_of_edge_constraint(subgraph)

        routing_infos = RoutingInfo()

        # Get the partitioned edges grouped by those that require the same key
        (fixed_key_groups, fixed_mask_groups, fixed_field_groups,
         flexi_field_groups, continuous_groups, none_continuous_groups) = \
            routing_info_allocator_utilities.get_edge_groups(subgraph)

        # Even non-continuous keys will be continuous
        for group in none_continuous_groups:
            continuous_groups.add(group)

        # Go through the groups and allocate keys
        progress_bar = ProgressBar(len(subgraph.partitions),
                                   "Allocating routing keys")

        # allocate the groups that have fixed keys
        for group in fixed_key_groups:  # fixed keys groups

            # Get any fixed keys and masks from the group and attempt to
            # allocate them
            fixed_mask = None
            fixed_key_and_mask_constraint = \
                utility_calls.locate_constraints_of_type(
                    group.constraints,
                    KeyAllocatorFixedKeyAndMaskConstraint)[0]

            # attempt to allocate them
            self._allocate_fixed_keys_and_masks(
                fixed_key_and_mask_constraint.keys_and_masks, fixed_mask)

            # update the pacman data objects
            self._update_routing_objects(
                fixed_key_and_mask_constraint.keys_and_masks, routing_infos,
                group)

            continuous_groups.remove(group)

            progress_bar.update()

        for group in fixed_mask_groups:  # fixed mask groups

            # get mask and fields if need be
            fixed_mask = utility_calls.locate_constraints_of_type(
                group.constraints, KeyAllocatorFixedMaskConstraint)[0].mask

            fields = None
            if group in fixed_field_groups:
                fields = utility_calls.locate_constraints_of_type(
                    group.constraints,
                    KeyAllocatorFixedFieldConstraint)[0].fields
                fixed_field_groups.remove(group)

            # try to allocate
            keys_and_masks = self._allocate_keys_and_masks(
                fixed_mask, fields, n_keys_map.n_keys_for_partition(group))

            # update the pacman data objects
            self._update_routing_objects(keys_and_masks, routing_infos, group)

            continuous_groups.remove(group)

            progress_bar.update()

        for group in fixed_field_groups:
            fields = utility_calls.locate_constraints_of_type(
                group.constraints, KeyAllocatorFixedFieldConstraint)[0].fields

            # try to allocate
            keys_and_masks = self._allocate_keys_and_masks(
                None, fields, n_keys_map.n_keys_for_partition(group))

            # update the pacman data objects
            self._update_routing_objects(keys_and_masks, routing_infos, group)

            continuous_groups.remove(group)

            progress_bar.update()

        if len(flexi_field_groups) != 0:
            raise exceptions.PacmanConfigurationException(
                "MallocBasedRoutingInfoAllocator does not support FlexiField")

        # Sort the rest of the groups, using the routing tables for guidance
        # Group partitions by those which share routes in any table
        partition_groups = OrderedDict()
        routers = reversed(
            sorted(
                routing_tables.get_routers(),
                key=lambda item: len(
                    routing_tables.get_entries_for_router(item[0], item[1]))))
        for x, y in routers:

            # Find all partitions that share a route in this table
            partitions_by_route = defaultdict(OrderedSet)
            routing_table = routing_tables.get_entries_for_router(x, y)
            for partition, entry in routing_table.iteritems():
                if partition in continuous_groups:
                    entry_hash = sum([1 << i for i in entry.out_going_links])
                    entry_hash += sum(
                        [1 << (i + 6) for i in entry.out_going_processors])
                    partitions_by_route[entry_hash].add(partition)

            for entry_hash, partitions in partitions_by_route.iteritems():

                found_groups = list()
                for partition in partitions:
                    if partition in partition_groups:
                        found_groups.append(partition_groups[partition])

                if len(found_groups) == 0:

                    # If no group was found, create a new one
                    for partition in partitions:
                        partition_groups[partition] = partitions

                elif len(found_groups) == 1:

                    # If a single other group was found, merge it
                    for partition in partitions:
                        found_groups[0].add(partition)
                        partition_groups[partition] = found_groups[0]

                else:

                    # Merge the groups
                    new_group = partitions
                    for group in found_groups:
                        for partition in group:
                            new_group.add(partition)
                    for partition in new_group:
                        partition_groups[partition] = new_group

        # Sort partitions by largest group
        continuous_groups = OrderedSet(
            tuple(group) for group in partition_groups.itervalues())
        continuous_groups = reversed(
            sorted([group for group in continuous_groups],
                   key=lambda group: len(group)))

        for group in continuous_groups:
            for partition in group:
                keys_and_masks = self._allocate_keys_and_masks(
                    None, None, n_keys_map.n_keys_for_partition(partition))

                # update the pacman data objects
                self._update_routing_objects(keys_and_masks, routing_infos,
                                             partition)
                progress_bar.update()

        progress_bar.end()
        return {'routing_infos': routing_infos}