Exemple #1
0
    def __call__(self, machine_graph, placements, n_keys_map):
        """
        :param MachineGraph machine_graph:
            The machine graph to allocate the routing info for
        :param Placements placements: The placements of the vertices
        :param AbstractMachinePartitionNKeysMap n_keys_map:
            A map between the edges and the number of keys required by the
            edges
        :return: The routing information
        :rtype: PartitionRoutingInfo
        :raise PacmanRouteInfoAllocationException:
            If something goes wrong with the allocation
        """

        # check that this algorithm supports the constraints put onto the
        # partitions
        check_algorithm_can_support_constraints(
            constrained_vertices=machine_graph.outgoing_edge_partitions,
            supported_constraints=[ContiguousKeyRangeContraint],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # take each edge and create keys from its placement
        progress = ProgressBar(machine_graph.n_vertices,
                               "Allocating routing keys")
        routing_infos = RoutingInfo()
        for vertex in progress.over(machine_graph.vertices):
            for partition in machine_graph.\
                    get_multicast_edge_partitions_starting_at_vertex(vertex):
                routing_infos.add_partition_info(
                    self._allocate_key_for_partition(partition, vertex,
                                                     placements, n_keys_map))
        return routing_infos
    def __call__(self, machine_graph, placements, n_keys_map):
        """
        :param MachineGraph machine_graph:
            The graph to allocate the routing info for
        :param Placements placements: The placements of the vertices
        :param AbstractMachinePartitionNKeysMap n_keys_map:
            A map between the edges and the number of keys required by the
            edges
        :return: The routing information
        :rtype: tuple(RoutingInfo, AbstractMulticastRoutingTable)
        :raise PacmanRouteInfoAllocationException:
            If something goes wrong with the allocation
        """

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

        # take each edge and create keys from its placement
        progress = ProgressBar(machine_graph.n_outgoing_edge_partitions,
                               "Allocating routing keys")
        routing_infos = RoutingInfo()
        routing_tables = MulticastRoutingTables()

        for partition in progress.over(machine_graph.outgoing_edge_partitions):
            for edge in partition.edges:
                routing_infos.add_partition_info(
                    self._allocate_partition_route(edge, placements,
                                                   machine_graph, n_keys_map))

        return routing_infos, routing_tables
    def __allocate(self):
        multicast_partitions = self.__machine_graph.multicast_partitions
        progress = ProgressBar(len(multicast_partitions),
                               "Allocating routing keys")
        routing_infos = RoutingInfo()
        app_part_index = 0
        for app_id in progress.over(multicast_partitions):
            while app_part_index in self.__fixed_used:
                app_part_index += 1
            for partition_name, paritition_vertices in \
                    multicast_partitions[app_id].items():
                # convert set to a list and sort by slice
                machine_vertices = list(paritition_vertices)
                machine_vertices.sort(key=lambda x: x.vertex_slice.lo_atom)
                n_bits_atoms = self.__atom_bits_per_app_part[(app_id,
                                                              partition_name)]
                if self.__flexible:
                    n_bits_machine = self.__n_bits_atoms_and_mac - n_bits_atoms
                else:
                    if n_bits_atoms <= self.__n_bits_atoms:
                        # Ok it fits use global sizes
                        n_bits_atoms = self.__n_bits_atoms
                        n_bits_machine = self.__n_bits_machine
                    else:
                        # Nope need more bits! Use the flexible approach here
                        n_bits_machine = \
                            self.__n_bits_atoms_and_mac - n_bits_atoms

                for machine_index, vertex in enumerate(machine_vertices):
                    partition = self.__machine_graph.\
                        get_outgoing_edge_partition_starting_at_vertex(
                            vertex, partition_name)
                    if partition in self.__fixed_partitions:
                        # Ignore zone calculations and just use fixed
                        keys_and_masks = self.__fixed_partitions[partition]
                    else:
                        mask = self.__mask(n_bits_atoms)
                        key = app_part_index
                        key = (key << n_bits_machine) | machine_index
                        key = key << n_bits_atoms
                        keys_and_masks = [
                            BaseKeyAndMask(base_key=key, mask=mask)
                        ]
                    routing_infos.add_partition_info(
                        PartitionRoutingInfo(keys_and_masks, partition))
                app_part_index += 1

        return routing_infos
 def _construct_routing_info(machine_graph, outgoing_partition_key_spaces):
     """ wrap a nengo bit field key space in a NengoBaseKeysAndMasks object. 
     so that it can get the keys when requested
     
     :param machine_graph: the machine graph
     :param outgoing_partition_key_spaces: 
     :return: 
     """
     routing_infos = RoutingInfo()
     for outgoing_partition in machine_graph.outgoing_edge_partitions:
         if outgoing_partition.traffic_type == EdgeTrafficType.MULTICAST:
             keys_and_masks = list([NengoBaseKeysAndMasks(
                 outgoing_partition_key_spaces[outgoing_partition])])
             routing_infos.add_partition_info(
                 PartitionRoutingInfo(keys_and_masks, outgoing_partition))
     return routing_infos
Exemple #5
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, vertex=self.vertex1)
     self.placement2 = Placement(x=0, y=0, p=2, vertex=self.vertex2)
     self.placements.add_placement(self.placement1)
     self.placements.add_placement(self.placement2)
     # sort out routing infos
     self.routing_info = RoutingInfo()
     self.edge_routing_info1 = PartitionRoutingInfo(key=2 << 11,
                                                    mask=DEFAULT_MASK,
                                                    edge=self.edge)
     self.routing_info.add_partition_info(self.edge_routing_info1)
     # create machine
     self.machine = VirtualMachine(10, 10, False)
     self.routing = BasicDijkstraRouting()
     self.routing.route(machine=self.machine,
                        placements=self.placements,
                        machine_graph=self.graph,
                        routing_info_allocation=self.routing_info)
Exemple #6
0
    def __call__(self, machine_graph, placements, n_keys_map):
        """
        :param machine_graph: The graph to allocate the routing info for
        :type machine_graph:\
            :py:class:`pacman.model.graphs.machine.MachineGraph`
        :param placements: The placements of the vertices
        :type placements:\
            :py:class:`pacman.model.placements.Placements`
        :param n_keys_map: A map between the edges and the number of keys\
            required by the edges
        :type n_keys_map:\
            :py:class:`pacman.model.routing_info.AbstractMachinePartitionNKeysMap`
        :return: The routing information
        :rtype: \
            :py:class:`pacman.model.routing_info.RoutingInfo`, \
            :py:class:`pacman.model.routing_tables.MulticastRoutingTable
        :raise pacman.exceptions.PacmanRouteInfoAllocationException: \
            If something goes wrong with the allocation
        """

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

        # take each edge and create keys from its placement
        progress = ProgressBar(machine_graph.n_outgoing_edge_partitions,
                               "Allocating routing keys")
        routing_infos = RoutingInfo()
        routing_tables = MulticastRoutingTables()

        for partition in progress.over(machine_graph.outgoing_edge_partitions):
            for edge in partition.edges:
                routing_infos.add_partition_info(
                    self._allocate_partition_route(edge, placements,
                                                   machine_graph, n_keys_map))

        return routing_infos, routing_tables
    def __call__(self, machine_graph, n_keys_map):
        """
        :param MachineGraph machine_graph:
        :param AbstractMachinePartitionNKeysMap n_keys_map:
        :rtype: RoutingInfo
        :raises PacmanRouteInfoAllocationException:
        """
        self._n_keys_map = n_keys_map
        # check that this algorithm supports the constraints
        check_algorithm_can_support_constraints(
            constrained_vertices=machine_graph.outgoing_edge_partitions,
            supported_constraints=[
                FixedMaskConstraint, FixedKeyAndMaskConstraint,
                ContiguousKeyRangeContraint, ShareKeyConstraint
            ],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

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

        # final keys allocations
        routing_infos = RoutingInfo()

        # Get the edges grouped by those that require the same key
        (fixed_keys, shared_keys, fixed_masks, fixed_fields, continuous,
         noncontinuous) = get_mulitcast_edge_groups(machine_graph)

        # Go through the groups and allocate keys
        progress = ProgressBar(machine_graph.n_outgoing_edge_partitions,
                               "Allocating routing keys")

        # allocate the groups that have fixed keys
        for group in progress.over(fixed_keys, False):
            self._allocate_fixed_keys(group, routing_infos)

        for group in progress.over(fixed_masks, False):
            self._allocate_fixed_masks(group, routing_infos)

        for group in progress.over(fixed_fields, False):
            self._allocate_fixed_fields(group, routing_infos)

        for group in progress.over(shared_keys, False):
            self._allocate_share_key(group, routing_infos)

        for group in continuous:
            self._allocate_other_groups(group, routing_infos, True)

        for group in noncontinuous:
            self._allocate_other_groups(group, routing_infos, False)

        progress.end()
        return routing_infos
    def __call__(self, machine_graph, n_keys_map, graph_mapper=None):
        # check that this algorithm supports the constraints
        check_algorithm_can_support_constraints(
            constrained_vertices=machine_graph.outgoing_edge_partitions,
            supported_constraints=[
                FixedMaskConstraint, FixedKeyAndMaskConstraint,
                ContiguousKeyRangeContraint, ShareKeyConstraint
            ],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

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

        # final keys allocations
        routing_infos = RoutingInfo()

        # Get the edges grouped by those that require the same key
        (fixed_keys, shared_keys, fixed_masks, fixed_fields, flexi_fields,
         continuous,
         noncontinuous) = utilities.get_edge_groups(machine_graph,
                                                    EdgeTrafficType.MULTICAST)

        # Even non-continuous keys will be continuous
        for group in noncontinuous:
            continuous.append(group)

        # Go through the groups and allocate keys
        progress = ProgressBar(machine_graph.n_outgoing_edge_partitions,
                               "Allocating routing keys")

        # allocate the groups that have fixed keys
        for group in progress.over(fixed_keys, False):
            self._allocate_fixed_keys(group, routing_infos)

        for group in progress.over(fixed_masks, False):
            self._allocate_fixed_masks(group, n_keys_map, routing_infos)

        for group in progress.over(fixed_fields, False):
            self._allocate_fixed_fields(group, n_keys_map, routing_infos)

        if flexi_fields:
            raise PacmanConfigurationException(
                "MallocBasedRoutingInfoAllocator does not support FlexiField")

        for group in progress.over(shared_keys, False):
            self._allocate_share_key(group, routing_infos, n_keys_map)

        for group in continuous:
            self._allocate_continuous_groups(group, routing_infos, n_keys_map)

        progress.end()
        return routing_infos
    def __call__(self, machine_graph, placements, n_keys_map):
        """
        :param machine_graph:\
            The machine graph to allocate the routing info for
        :type machine_graph:\
            :py:class:`pacman.model.graphs.machine.MachineGraph`
        :param placements: The placements of the vertices
        :type placements:\
            :py:class:`pacman.model.placements.placements.Placements`
        :param n_keys_map:\
            A map between the edges and the number of keys required by the\
            edges
        :type n_keys_map:\
            :py:class:`pacman.model.routing_info.AbstractMachinePartitionNKeysMap`
        :return: The routing information
        :rtype:\
            :py:class:`pacman.model.routing_info.PartitionRoutingInfo`
        :raise pacman.exceptions.PacmanRouteInfoAllocationException: \
            If something goes wrong with the allocation
        """

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

        # take each edge and create keys from its placement
        progress = ProgressBar(machine_graph.n_vertices,
                               "Allocating routing keys")
        routing_infos = RoutingInfo()
        for vertex in progress.over(machine_graph.vertices):
            for partition in machine_graph.\
                    get_outgoing_edge_partitions_starting_at_vertex(vertex):
                routing_infos.add_partition_info(
                    self._allocate_key_for_partition(partition, vertex,
                                                     placements, n_keys_map))
        return routing_infos
    def __call__(self, machine_graph, placements, n_keys_map):
        """
        :param machine_graph: The graph to allocate the routing info for
        :type machine_graph:\
            :py:class:`pacman.model.graphs.machine.MachineGraph`
        :param placements: The placements of the vertices
        :type placements:\
            :py:class:`pacman.model.placements.Placements`
        :param n_keys_map: A map between the edges and the number of keys\
            required by the edges
        :type n_keys_map:\
            :py:class:`pacman.model.routing_info.AbstractMachinePartitionNKeysMap`
        :return: The routing information
        :rtype: \
            :py:class:`pacman.model.routing_info.RoutingInfo`, \
            :py:class:`pacman.model.routing_tables.MulticastRoutingTable
        :raise pacman.exceptions.PacmanRouteInfoAllocationException: \
            If something goes wrong with the allocation
        """

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

        # take each edge and create keys from its placement
        progress = ProgressBar(machine_graph.n_outgoing_edge_partitions,
                               "Allocating routing keys")
        routing_infos = RoutingInfo()
        routing_tables = MulticastRoutingTables()

        for partition in progress.over(machine_graph.outgoing_edge_partitions):
            for edge in partition.edges:
                routing_infos.add_partition_info(
                    self._allocate_partition_route(
                        edge, placements, machine_graph, n_keys_map))

        return routing_infos, routing_tables
    def __call__(self, machine_graph, placements, n_keys_map):
        """
        :param machine_graph:\
            The machine graph to allocate the routing info for
        :type machine_graph:\
            :py:class:`pacman.model.graphs.machine.MachineGraph`
        :param placements: The placements of the vertices
        :type placements:\
            :py:class:`pacman.model.placements.placements.Placements`
        :param n_keys_map:\
            A map between the edges and the number of keys required by the\
            edges
        :type n_keys_map:\
            :py:class:`pacman.model.routing_info.AbstractMachinePartitionNKeysMap`
        :return: The routing information
        :rtype:\
            :py:class:`pacman.model.routing_info.PartitionRoutingInfo`
        :raise pacman.exceptions.PacmanRouteInfoAllocationException: \
            If something goes wrong with the allocation
        """

        # check that this algorithm supports the constraints put onto the
        # partitions
        check_algorithm_can_support_constraints(
            constrained_vertices=machine_graph.outgoing_edge_partitions,
            supported_constraints=[ContiguousKeyRangeContraint],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # take each edge and create keys from its placement
        progress = ProgressBar(
            machine_graph.n_vertices, "Allocating routing keys")
        routing_infos = RoutingInfo()
        for vertex in progress.over(machine_graph.vertices):
            for partition in machine_graph.\
                    get_outgoing_edge_partitions_starting_at_vertex(vertex):
                routing_infos.add_partition_info(
                    self._allocate_key_for_partition(
                        partition, vertex, placements, n_keys_map))
        return routing_infos
    def test_routing_info(self):
        partition = MachineOutgoingEdgePartition("Test")
        pre_vertex = SimpleMachineVertex(resources=ResourceContainer())
        post_vertex = SimpleMachineVertex(resources=ResourceContainer())
        edge = MachineEdge(pre_vertex, post_vertex)
        key = 12345
        partition_info = PartitionRoutingInfo(
            [BaseKeyAndMask(key, _32_BITS)], partition)
        partition.add_edge(edge)
        routing_info = RoutingInfo([partition_info])

        with self.assertRaises(PacmanAlreadyExistsException):
            routing_info.add_partition_info(partition_info)

        assert routing_info.get_first_key_from_partition(partition) == key
        assert routing_info.get_first_key_from_partition(None) is None

        assert routing_info.get_routing_info_from_partition(partition) == \
            partition_info
        assert routing_info.get_routing_info_from_partition(None) is None

        assert routing_info.get_routing_info_from_pre_vertex(
            pre_vertex, "Test") == partition_info
        assert routing_info.get_routing_info_from_pre_vertex(
            post_vertex, "Test") is None
        assert routing_info.get_routing_info_from_pre_vertex(
            pre_vertex, "None") is None

        assert routing_info.get_first_key_from_pre_vertex(
            pre_vertex, "Test") == key
        assert routing_info.get_first_key_from_pre_vertex(
            post_vertex, "Test") is None
        assert routing_info.get_first_key_from_pre_vertex(
            pre_vertex, "None") is None

        assert routing_info.get_routing_info_for_edge(edge) == partition_info
        assert routing_info.get_routing_info_for_edge(None) is None

        assert routing_info.get_first_key_for_edge(edge) == key
        assert routing_info.get_first_key_for_edge(None) is None

        assert next(iter(routing_info)) == partition_info

        partition2 = MachineOutgoingEdgePartition("Test")
        partition2.add_edge(MachineEdge(pre_vertex, post_vertex))

        with self.assertRaises(PacmanAlreadyExistsException):
            routing_info.add_partition_info(PartitionRoutingInfo(
                [BaseKeyAndMask(key, _32_BITS)], partition2))
        assert partition != partition2

        partition3 = MachineOutgoingEdgePartition("Test2")
        partition3.add_edge(MachineEdge(pre_vertex, post_vertex))
        routing_info.add_partition_info(PartitionRoutingInfo(
            [BaseKeyAndMask(key, _32_BITS)], partition3))

        assert routing_info.get_routing_info_from_partition(partition) != \
            routing_info.get_routing_info_from_partition(partition3)
        assert partition != partition3
        assert routing_info.get_routing_info_from_partition(
            partition3).get_keys().tolist() == [key]

        partition3 = MachineOutgoingEdgePartition("Test3")
        partition3.add_edge(MachineEdge(pre_vertex, post_vertex))
        routing_info.add_partition_info(PartitionRoutingInfo(
            [BaseKeyAndMask(key, _32_BITS),
             BaseKeyAndMask(key*2, _32_BITS)], partition3))

        assert routing_info.get_routing_info_from_partition(
            partition3).get_keys().tolist() == [key, key*2]
Exemple #13
0
    def test_write_synaptic_matrix_and_master_population_table(self):
        MockSimulator.setup()
        # Add an sdram so max SDRAM is high enough
        SDRAM(10000)

        # UGLY but the mock transceiver NEED generate_on_machine to be False
        AbstractGenerateConnectorOnMachine.generate_on_machine = self.say_false
        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_slice = Slice(0, 9)
        pre_vertex = pre_app_vertex.create_machine_vertex(
            pre_vertex_slice, None)
        post_app_vertex = SimpleApplicationVertex(10)
        post_vertex_slice = Slice(0, 9)
        post_vertex = post_app_vertex.create_machine_vertex(
            post_vertex_slice, None)
        post_slice_index = 0

        one_to_one_connector_1 = OneToOneConnector(None)
        direct_synapse_information_1 = SynapseInformation(
            one_to_one_connector_1, pre_app_vertex, post_app_vertex, False,
            False, None, SynapseDynamicsStatic(), 0, 1.5, 1.0)
        one_to_one_connector_1.set_projection_information(
            machine_time_step, direct_synapse_information_1)
        one_to_one_connector_2 = OneToOneConnector(None)
        direct_synapse_information_2 = SynapseInformation(
            one_to_one_connector_2, pre_app_vertex, post_app_vertex, False,
            False, None, SynapseDynamicsStatic(), 1, 2.5, 2.0)
        one_to_one_connector_2.set_projection_information(
            machine_time_step, direct_synapse_information_2)
        all_to_all_connector = AllToAllConnector(None)
        all_to_all_synapse_information = SynapseInformation(
            all_to_all_connector, pre_app_vertex, post_app_vertex, False,
            False, None, SynapseDynamicsStatic(), 0, 4.5, 4.0)
        all_to_all_connector.set_projection_information(
            machine_time_step, all_to_all_synapse_information)

        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 = app_edge.create_machine_edge(pre_vertex,
                                                    post_vertex,
                                                    label=None)
        partition_name = "TestPartition"

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

        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
        all_syn_block_sz = 2000
        master_pop_region = 0
        synapse_region = 1
        direct_region = 2
        spec.reserve_memory_region(master_pop_region, master_pop_sz)
        spec.reserve_memory_region(synapse_region, all_syn_block_sz)

        synaptic_manager = SynapticManager(n_synapse_types=2,
                                           ring_buffer_sigma=5.0,
                                           spikes_per_second=100.0,
                                           config=config)
        # Poke in our testing region IDs
        synaptic_manager._pop_table_region = master_pop_region
        synaptic_manager._synaptic_matrix_region = synapse_region
        synaptic_manager._direct_matrix_region = direct_region

        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, routing_info,
            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)
        direct_matrix = executor.get_region(2)

        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])
        all_data.extend(
            direct_matrix.region_data[:direct_matrix.max_write_pointer])
        master_pop_table_address = 0
        synaptic_matrix_address = master_pop_table.max_write_pointer
        direct_synapses_address = (synaptic_matrix_address +
                                   synaptic_matrix.max_write_pointer)
        direct_synapses_address += 4
        indirect_synapses_address = synaptic_matrix_address
        placement = Placement(None, 0, 0, 1)
        transceiver = MockTransceiverRawData(all_data)

        # Get the master population table details
        items = synaptic_manager._extract_synaptic_matrix_data_location(
            key, master_pop_table_address, transceiver, placement)

        # 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
        assert items[0][2]
        assert not items[1][2]
        assert not items[2][2]

        data_1, row_len_1 = synaptic_manager._retrieve_synaptic_block(
            txrx=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_monitors=False)
        connections_1 = synaptic_manager._read_synapses(
            direct_synapse_information_1, pre_vertex_slice, post_vertex_slice,
            row_len_1, 0, weight_scales, data_1, None, 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(
            txrx=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_monitors=False)
        connections_2 = synaptic_manager._read_synapses(
            direct_synapse_information_2, pre_vertex_slice, post_vertex_slice,
            row_len_2, 0, weight_scales, data_2, None, 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(
            txrx=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_monitors=False)
        connections_3 = synaptic_manager._read_synapses(
            all_to_all_synapse_information, pre_vertex_slice,
            post_vertex_slice, row_len_3, 0, weight_scales, data_3, None,
            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])
    def test_routing_info(self):
        # mock to avoid having to create a graph for this test
        graph_code = 123
        pre_vertex = SimpleMachineVertex(resources=ResourceContainer())
        partition = MulticastEdgePartition(pre_vertex, "Test")
        partition.register_graph_code(graph_code)  # This is a hack
        post_vertex = SimpleMachineVertex(resources=ResourceContainer())
        edge = MachineEdge(pre_vertex, post_vertex)
        key = 12345
        partition_info = PartitionRoutingInfo([BaseKeyAndMask(key, FULL_MASK)],
                                              partition)
        partition.add_edge(edge, graph_code)
        routing_info = RoutingInfo([partition_info])

        with self.assertRaises(PacmanAlreadyExistsException):
            routing_info.add_partition_info(partition_info)

        assert routing_info.get_first_key_from_partition(partition) == key
        assert routing_info.get_first_key_from_partition(None) is None

        assert routing_info.get_routing_info_from_partition(partition) == \
            partition_info
        assert routing_info.get_routing_info_from_partition(None) is None

        assert routing_info.get_routing_info_from_pre_vertex(
            pre_vertex, "Test") == partition_info
        assert routing_info.get_routing_info_from_pre_vertex(
            post_vertex, "Test") is None
        assert routing_info.get_routing_info_from_pre_vertex(
            pre_vertex, "None") is None

        assert routing_info.get_first_key_from_pre_vertex(pre_vertex,
                                                          "Test") == key
        assert routing_info.get_first_key_from_pre_vertex(post_vertex,
                                                          "Test") is None
        assert routing_info.get_first_key_from_pre_vertex(pre_vertex,
                                                          "None") is None

        assert routing_info.get_routing_info_for_edge(edge) == partition_info
        assert routing_info.get_routing_info_for_edge(None) is None

        assert routing_info.get_first_key_for_edge(edge) == key
        assert routing_info.get_first_key_for_edge(None) is None

        assert next(iter(routing_info)) == partition_info

        partition2 = MulticastEdgePartition(pre_vertex, "Test")
        partition2.register_graph_code(graph_code)  # This is a hack
        partition2.add_edge(MachineEdge(pre_vertex, post_vertex), graph_code)

        with self.assertRaises(PacmanAlreadyExistsException):
            routing_info.add_partition_info(
                PartitionRoutingInfo([BaseKeyAndMask(key, FULL_MASK)],
                                     partition2))
        assert partition != partition2

        partition3 = MulticastEdgePartition(pre_vertex, "Test2")
        partition3.register_graph_code(graph_code)  # This is a hack
        partition3.add_edge(MachineEdge(pre_vertex, post_vertex), graph_code)
        routing_info.add_partition_info(
            PartitionRoutingInfo([BaseKeyAndMask(key, FULL_MASK)], partition3))

        assert routing_info.get_routing_info_from_partition(partition) != \
            routing_info.get_routing_info_from_partition(partition3)
        assert partition != partition3
        assert routing_info.get_routing_info_from_partition(
            partition3).get_keys().tolist() == [key]

        partition4 = MulticastEdgePartition(pre_vertex, "Test4")
        partition4.register_graph_code(graph_code)  # This is a hack
        partition4.add_edge(MachineEdge(pre_vertex, post_vertex), graph_code)
        routing_info.add_partition_info(
            PartitionRoutingInfo([
                BaseKeyAndMask(key, FULL_MASK),
                BaseKeyAndMask(key * 2, FULL_MASK)
            ], partition4))

        assert routing_info.get_routing_info_from_partition(
            partition4).get_keys().tolist() == [key, key * 2]
    def test_write_synaptic_matrix_and_master_population_table(self):
        MockSimulator.setup()
        # Add an sdram so maxsdram is high enough
        SDRAM(10000)

        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_2 = OneToOneConnector(None)
        one_to_one_connector_2.set_projection_information(
            pre_app_vertex, post_app_vertex, None, machine_time_step)
        all_to_all_connector = AllToAllConnector(None)
        all_to_all_connector.set_projection_information(
            pre_app_vertex, post_app_vertex, None, machine_time_step)
        direct_synapse_information_1 = SynapseInformation(
            one_to_one_connector_1, SynapseDynamicsStatic(), 0, 1.5, 1.0)
        direct_synapse_information_2 = SynapseInformation(
            one_to_one_connector_2, SynapseDynamicsStatic(), 1, 2.5, 2.0)
        all_to_all_synapse_information = SynapseInformation(
            all_to_all_connector, SynapseDynamicsStatic(), 0, 4.5, 4.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
        direct_region = 2
        spec.reserve_memory_region(master_pop_region, master_pop_sz)
        spec.reserve_memory_region(synapse_region, all_syn_block_sz)

        synaptic_manager = SynapticManager(
            n_synapse_types=2, ring_buffer_sigma=5.0,
            spikes_per_second=100.0, config=config)
        # UGLY but the mock transceiver NEED generate_on_machine be False
        abstract_generate_connector_on_machine.IS_PYNN_8 = False
        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, direct_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)
        direct_matrix = executor.get_region(2)

        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])
        all_data.extend(direct_matrix.region_data[
            :direct_matrix.max_write_pointer])
        master_pop_table_address = 0
        synaptic_matrix_address = master_pop_table.max_write_pointer
        direct_synapses_address = (
            synaptic_matrix_address + synaptic_matrix.max_write_pointer)
        direct_synapses_address += 4
        indirect_synapses_address = synaptic_matrix_address
        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
        assert 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])
Exemple #16
0
    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])
    def __call__(self, machine_graph, n_keys_map, routing_tables):
        """
        :param MachineGraph machine_graph:
        :param AbstractMachinePartitionNKeysMap n_keys_map:
        :param MulticastRoutingTableByPartition routing_tables:
        :rtype: RoutingInfo
        """
        # check that this algorithm supports the constraints
        check_algorithm_can_support_constraints(
            constrained_vertices=machine_graph.outgoing_edge_partitions,
            supported_constraints=[
                FixedMaskConstraint, FixedKeyAndMaskConstraint,
                ContiguousKeyRangeContraint
            ],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

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

        routing_infos = RoutingInfo()

        # Get the edges grouped by those that require the same key
        (fixed_keys, _shared_keys, fixed_masks, fixed_fields, continuous,
         noncontinuous) = get_mulitcast_edge_groups(machine_graph)

        # Even non-continuous keys will be continuous
        continuous.extend(noncontinuous)

        # Go through the groups and allocate keys
        progress = ProgressBar(machine_graph.n_outgoing_edge_partitions,
                               "Allocating routing keys")

        # allocate the groups that have fixed keys
        for group in progress.over(fixed_keys, False):
            # Get any fixed keys and masks from the group and attempt to
            # allocate them
            fixed_mask = None
            fixed_key_and_mask_constraint = locate_constraints_of_type(
                group.constraints, FixedKeyAndMaskConstraint)[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.remove(group)

        for group in progress.over(fixed_masks, False):
            # get mask and fields if need be
            fixed_mask = locate_constraints_of_type(
                group.constraints, FixedMaskConstraint)[0].mask

            fields = None
            if group in fixed_fields:
                fields = locate_constraints_of_type(
                    group.constraints, FixedKeyFieldConstraint)[0].fields
                fixed_fields.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.remove(group)

        for group in progress.over(fixed_fields, False):
            fields = locate_constraints_of_type(
                group.constraints, FixedKeyFieldConstraint)[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.remove(group)

        # 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 iteritems(routing_table):
                if partition in continuous:
                    entry_hash = sum(1 << i for i in entry.link_ids)
                    entry_hash += sum(1 << (i + 6)
                                      for i in entry.processor_ids)
                    partitions_by_route[entry_hash].add(partition)

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

                if not found_groups:
                    # 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 = list(
            OrderedSet(tuple(group) for group in itervalues(partition_groups)))

        for group in reversed(sorted(continuous, key=len)):
            for partition in progress.over(group, False):
                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.end()
        return routing_infos
    def __call__(self, application_graph, graph_mapper, machine_graph,
                 n_keys_map):
        """
        :param application_graph: The application graph
        :param graph_mapper: the mapping between graphs
        :param machine_graph: the machine graph
        :param n_keys_map: the mapping between edges and n keys
        :return: routing information objects
        """
        progress_bar = ProgressBar(
            machine_graph.n_outgoing_edge_partitions * 3,
            "Allocating routing keys")

        # ensure groups are stable and correct
        self._determine_groups(
            machine_graph, graph_mapper, application_graph, n_keys_map,
            progress_bar)

        # define the key space
        bit_field_space = BitField(32)
        field_positions = set()

        # locate however many types of constraints there are
        seen_fields = deduce_types(machine_graph)
        progress_bar.update(machine_graph.n_outgoing_edge_partitions)

        if len(seen_fields) > 1:
            self._adds_application_field_to_the_fields(seen_fields)

        # handle the application space
        self._create_application_space_in_the_bit_field_space(
            bit_field_space, seen_fields, field_positions)

        # assign fields to positions in the space
        bit_field_space.assign_fields()

        # get positions of the flexible fields:
        self._assign_flexi_field_positions(
            bit_field_space, seen_fields, field_positions)

        # create routing_info_allocator
        routing_info = RoutingInfo()
        seen_mask_instances = 0

        # extract keys and masks for each edge from the bitfield
        for partition in machine_graph.outgoing_edge_partitions:
            # get keys and masks
            keys_and_masks, seen_mask_instances = \
                self._extract_keys_and_masks_from_bit_field(
                    partition, bit_field_space, n_keys_map,
                    seen_mask_instances)

            # update routing info for each edge in the partition
            partition_info = PartitionRoutingInfo(keys_and_masks, partition)
            routing_info.add_partition_info(partition_info)

            # update the progress bar again
            progress_bar.update()
        progress_bar.end()

        return routing_info, field_positions
    def test_routing_info(self):
        partition = MachineOutgoingEdgePartition("Test")
        pre_vertex = SimpleMachineVertex(resources=ResourceContainer())
        post_vertex = SimpleMachineVertex(resources=ResourceContainer())
        edge = MachineEdge(pre_vertex, post_vertex)
        key = 12345
        partition_info = PartitionRoutingInfo([BaseKeyAndMask(key, _32_BITS)],
                                              partition)
        partition.add_edge(edge)
        routing_info = RoutingInfo([partition_info])

        with self.assertRaises(PacmanAlreadyExistsException):
            routing_info.add_partition_info(partition_info)

        assert routing_info.get_first_key_from_partition(partition) == key
        assert routing_info.get_first_key_from_partition(None) is None

        assert routing_info.get_routing_info_from_partition(partition) == \
            partition_info
        assert routing_info.get_routing_info_from_partition(None) is None

        assert routing_info.get_routing_info_from_pre_vertex(
            pre_vertex, "Test") == partition_info
        assert routing_info.get_routing_info_from_pre_vertex(
            post_vertex, "Test") is None
        assert routing_info.get_routing_info_from_pre_vertex(
            pre_vertex, "None") is None

        assert routing_info.get_first_key_from_pre_vertex(pre_vertex,
                                                          "Test") == key
        assert routing_info.get_first_key_from_pre_vertex(post_vertex,
                                                          "Test") is None
        assert routing_info.get_first_key_from_pre_vertex(pre_vertex,
                                                          "None") is None

        assert routing_info.get_routing_info_for_edge(edge) == partition_info
        assert routing_info.get_routing_info_for_edge(None) is None

        assert routing_info.get_first_key_for_edge(edge) == key
        assert routing_info.get_first_key_for_edge(None) is None

        assert next(iter(routing_info)) == partition_info

        partition2 = MachineOutgoingEdgePartition("Test")
        partition2.add_edge(MachineEdge(pre_vertex, post_vertex))

        with self.assertRaises(PacmanAlreadyExistsException):
            routing_info.add_partition_info(
                PartitionRoutingInfo([BaseKeyAndMask(key, _32_BITS)],
                                     partition2))
        assert partition != partition2

        partition3 = MachineOutgoingEdgePartition("Test2")
        partition3.add_edge(MachineEdge(pre_vertex, post_vertex))
        routing_info.add_partition_info(
            PartitionRoutingInfo([BaseKeyAndMask(key, _32_BITS)], partition3))

        assert routing_info.get_routing_info_from_partition(partition) != \
            routing_info.get_routing_info_from_partition(partition3)
        assert partition != partition3
        assert routing_info.get_routing_info_from_partition(
            partition3).get_keys().tolist() == [key]

        partition3 = MachineOutgoingEdgePartition("Test3")
        partition3.add_edge(MachineEdge(pre_vertex, post_vertex))
        routing_info.add_partition_info(
            PartitionRoutingInfo([
                BaseKeyAndMask(key, _32_BITS),
                BaseKeyAndMask(key * 2, _32_BITS)
            ], partition3))

        assert routing_info.get_routing_info_from_partition(
            partition3).get_keys().tolist() == [key, key * 2]
Exemple #20
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 = ApplicationEdge(self.vert1, self.vert2, "First edge")
        self.verts = [self.vert1, self.vert2]
        self.edges = [self.edge1]
        self.graph = ApplicationGraph("Graph", self.verts, self.edges)
        # sort out graph
        self.graph = MachineGraph()
        self.vertex1 = SimpleMachineVertex(
            0, 10, self.vert1.get_resources_used_by_atoms(0, 10, []))
        self.vertex2 = SimpleMachineVertex(
            0, 5, self.vert2.get_resources_used_by_atoms(0, 10, []))
        self.edge = MachineEdge(self.vertex1, self.vertex2)
        self.graph.add_vertex(self.vertex1)
        self.graph.add_vertex(self.vertex2)
        self.graph.add_edge(self.edge, "TEST")

    @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, vertex=self.vertex1)
        self.placement2 = Placement(x=0, y=0, p=3, vertex=self.vertex2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        # sort out routing infos
        self.routing_info = RoutingInfo()
        self.edge_routing_info1 = PartitionRoutingInfo(key=2 << 11,
                                                       mask=DEFAULT_MASK,
                                                       edge=self.edge)
        self.routing_info.add_partition_info(self.edge_routing_info1)
        # create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(machine=self.machine,
                           placements=self.placements,
                           machine_graph=self.graph,
                           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, vertex=self.vertex1)
        self.placement2 = Placement(x=1, y=1, p=2, vertex=self.vertex2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        # sort out routing infos
        self.routing_info = RoutingInfo()
        self.edge_routing_info1 = PartitionRoutingInfo(key=2 << 11,
                                                       mask=DEFAULT_MASK,
                                                       edge=self.edge)
        self.routing_info.add_partition_info(self.edge_routing_info1)
        # create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(machine=self.machine,
                           placements=self.placements,
                           machine_graph=self.graph,
                           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, vertex=self.vertex1)
        self.placement2 = Placement(x=2, y=0, p=2, vertex=self.vertex2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        # sort out routing infos
        self.routing_info = RoutingInfo()
        self.edge_routing_info1 = PartitionRoutingInfo(key=2 << 11,
                                                       mask=DEFAULT_MASK,
                                                       edge=self.edge)
        self.routing_info.add_partition_info(self.edge_routing_info1)
        # create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(machine=self.machine,
                           placements=self.placements,
                           machine_graph=self.graph,
                           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, vertex=self.vertex1)
        self.placement2 = Placement(x=2, y=2, p=2, vertex=self.vertex2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        # sort out routing infos
        self.routing_info = RoutingInfo()
        self.edge_routing_info1 = PartitionRoutingInfo(key=2 << 11,
                                                       mask=DEFAULT_MASK,
                                                       edge=self.edge)
        self.routing_info.add_partition_info(self.edge_routing_info1)
        # create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(machine=self.machine,
                           placements=self.placements,
                           machine_graph=self.graph,
                           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, vertex=self.vertex1)
        self.placement2 = Placement(x=0, y=2, p=2, vertex=self.vertex2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        # sort out routing infos
        self.routing_info = RoutingInfo()
        self.edge_routing_info1 = PartitionRoutingInfo(key=2 << 11,
                                                       mask=DEFAULT_MASK,
                                                       edge=self.edge)
        self.routing_info.add_partition_info(self.edge_routing_info1)
        # create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(machine=self.machine,
                           placements=self.placements,
                           machine_graph=self.graph,
                           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, vertex=self.vertex1)
        self.placement2 = Placement(x=0, y=0, p=2, vertex=self.vertex2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        # sort out routing infos
        self.routing_info = RoutingInfo()
        self.edge_routing_info1 = PartitionRoutingInfo(key=2 << 11,
                                                       mask=DEFAULT_MASK,
                                                       edge=self.edge)
        self.routing_info.add_partition_info(self.edge_routing_info1)
        # create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(machine=self.machine,
                           placements=self.placements,
                           machine_graph=self.graph,
                           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, vertex=self.vertex1)
        self.placement2 = Placement(x=0, y=0, p=2, vertex=self.vertex2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        # sort out routing infos
        self.routing_info = RoutingInfo()
        self.edge_routing_info1 = PartitionRoutingInfo(key=2 << 11,
                                                       mask=DEFAULT_MASK,
                                                       edge=self.edge)
        self.routing_info.add_partition_info(self.edge_routing_info1)
        # create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(machine=self.machine,
                           placements=self.placements,
                           machine_graph=self.graph,
                           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, vertex=self.vertex1)
        self.placement2 = Placement(x=0, y=0, p=2, vertex=self.vertex2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        # sort out routing infos
        self.routing_info = RoutingInfo()
        self.edge_routing_info1 = PartitionRoutingInfo(key=2 << 11,
                                                       mask=DEFAULT_MASK,
                                                       edge=self.edge)
        self.routing_info.add_partition_info(self.edge_routing_info1)
        # create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(machine=self.machine,
                           placements=self.placements,
                           machine_graph=self.graph,
                           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, vertex=self.vertex1)
        self.placement2 = Placement(x=0, y=0, p=2, vertex=self.vertex2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        # sort out routing infos
        self.routing_info = RoutingInfo()
        self.edge_routing_info1 = PartitionRoutingInfo(key=2 << 11,
                                                       mask=DEFAULT_MASK,
                                                       edge=self.edge)
        self.routing_info.add_partition_info(self.edge_routing_info1)
        # create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(machine=self.machine,
                           placements=self.placements,
                           machine_graph=self.graph,
                           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, vertex=self.vertex1)
        self.placement2 = Placement(x=8, y=7, p=2, vertex=self.vertex2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        # sort out routing infos
        self.routing_info = RoutingInfo()
        self.edge_routing_info1 = PartitionRoutingInfo(key=2 << 11,
                                                       mask=DEFAULT_MASK,
                                                       edge=self.edge)
        self.routing_info.add_partition_info(self.edge_routing_info1)
        # create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(machine=self.machine,
                           placements=self.placements,
                           machine_graph=self.graph,
                           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_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_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, vertex=self.vertex1)
        self.placement2 = Placement(x=1, y=1, p=2, vertex=self.vertex2)
        self.placements.add_placement(self.placement1)
        self.placements.add_placement(self.placement2)
        # sort out routing infos
        self.routing_info = RoutingInfo()
        self.edge_routing_info1 = PartitionRoutingInfo(key=2 << 11,
                                                       mask=DEFAULT_MASK,
                                                       edge=self.edge)
        self.routing_info.add_partition_info(self.edge_routing_info1)
        # create machine
        self.machine = VirtualMachine(10, 10, False)
        self.routing = BasicDijkstraRouting()
        self.routing.route(machine=self.machine,
                           placements=self.placements,
                           machine_graph=self.graph,
                           routing_info_allocation=self.routing_info)