def add_routing_table(self, routing_table):
        """ Add a routing table

        :param routing_table: a routing table to add
        :type routing_table:\
                    :py:class:`pacman.model.routing_tables.multicast_routing_table.MulticastRoutingTable`
        :return: None
        :rtype: None
        :raise pacman.exceptions.PacmanAlreadyExistsException: If a routing\
                    table already exists for the chip
        """
        if routing_table in self._routing_tables:
            raise PacmanAlreadyExistsException(
                "The Routing table {} has already been added to the collection"
                " before and therefore already exists".format(routing_table),
                str(routing_table))

        if (routing_table.x, routing_table.y) in \
                self._routing_tables_by_chip:
            raise PacmanAlreadyExistsException(
                "The Routing table for chip {}:{} already exists in this "
                "collection and thefore is deemed an error to readd it".format(
                    routing_table.x, routing_table.y), str(routing_table))
        self._routing_tables_by_chip[(routing_table.x, routing_table.y)] = \
            routing_table
        self._routing_tables.add(routing_table)
    def add_multicast_routing_entry(self, multicast_routing_entry):
        """ Adds a routing entry to this table

        :param ~spinn_machine.MulticastRoutingEntry multicast_routing_entry:
            The route to add
        :rtype: None
        :raise PacmanAlreadyExistsException:
            If a routing entry with the same key-mask combination already
            exists
        """
        routing_entry_key = multicast_routing_entry.routing_entry_key
        mask = multicast_routing_entry.mask

        tuple_key = (routing_entry_key, mask)
        if tuple_key in self._entries_by_key_mask:
            raise PacmanAlreadyExistsException("Multicast_routing_entry",
                                               str(multicast_routing_entry))

        self._entries_by_key_mask[tuple_key] =\
            multicast_routing_entry
        self._entries_by_key[routing_entry_key] = multicast_routing_entry
        self._multicast_routing_entries.append(multicast_routing_entry)

        # update default routed counter if required
        if multicast_routing_entry.defaultable:
            self._number_of_defaulted_routing_entries += 1
예제 #3
0
    def add_outgoing_edge_partition(self, edge_partition):
        # verify that this partition is suitable for this graph
        if not isinstance(edge_partition, AbstractMachineEdgePartition):
            raise PacmanInvalidParameterException(
                "outgoing_edge_partition", str(edge_partition.__class__),
                "Partitions of this graph must be an "
                "AbstractMachineEdgePartition")

        # check this partition doesn't already exist
        if edge_partition in self._edge_partitions:
            raise PacmanAlreadyExistsException(
                str(AbstractMachineEdgePartition), edge_partition)

        self._edge_partitions.add(edge_partition)
        edge_partition.register_graph_code(id(self))

        for pre_vertex in edge_partition.pre_vertices:
            key = (pre_vertex, edge_partition.identifier)
            self._outgoing_edge_partitions_by_name[key] = edge_partition
            if isinstance(edge_partition, MulticastEdgePartition):
                self._multicast_edge_partitions_by_pre_vertex[pre_vertex].add(
                    edge_partition)
            elif isinstance(edge_partition, FixedRouteEdgePartition):
                self._fixed_route_edge_partitions_by_pre_vertex[
                    pre_vertex].add(edge_partition)
            elif isinstance(edge_partition, AbstractSDRAMPartition):
                self._sdram_edge_partitions_by_pre_vertex[pre_vertex].add(
                    edge_partition)
            else:
                raise NotImplementedError(
                    "Unexpected edge_partition: {}".format(edge_partition))
        for edge in edge_partition.edges:
            self._register_edge(edge, edge_partition)
 def __add_fixed_route_entry(self, key, link_ids, processor_ids):
     """
     :param tuple(int,int) key:
     :param list(int) link_ids:
     :param list(int) processor_ids:
     :raises PacmanAlreadyExistsException:
     """
     fixed_route_entry = FixedRouteEntry(link_ids=link_ids,
                                         processor_ids=processor_ids)
     if key in self._fixed_route_tables:
         raise PacmanAlreadyExistsException("fixed route entry", str(key))
     self._fixed_route_tables[key] = fixed_route_entry
예제 #5
0
    def add_partition_info(self, partition_info):
        """ Add a partition information item

        :param PartitionRoutingInfo partition_info:\
            The partition information item to add
        :rtype: None
        :raise PacmanAlreadyExistsException:\
            If the partition is already in the set of edges
        """
        p = partition_info.partition

        if p in self._info_by_partition:
            raise PacmanAlreadyExistsException("Partition",
                                               str(partition_info))
        if (p.pre_vertex, p.identifier) in self._info_by_prevertex:
            raise PacmanAlreadyExistsException("Partition",
                                               str(partition_info))

        self._info_by_partition[p] = partition_info
        self._info_by_prevertex[p.pre_vertex, p.identifier] = partition_info

        for edge in p.edges:
            self._info_by_edge[edge] = partition_info
예제 #6
0
    def _do_fixed_routing(
            self, fixed_route_tables, board_version, placements,
            ethernet_chip_x, ethernet_chip_y, destination_class, machine):
        """ Handles this board through the quick routing process, based on a\
            predefined routing table.

        :param fixed_route_tables: fixed routing tables
        :param board_version: the SpiNNaker machine version
        :param placements: the placements object
        :param ethernet_chip_x: chip x of the Ethernet connected chip
        :param ethernet_chip_y: chip y of the Ethernet connected chip
        :param destination_class: \
            the class of the vertex to route to at the Ethernet connected chip
        :param machine: SpiNNMachine instance
        :rtype: None
        """

        joins, paths = self._get_joins_paths(board_version)

        for path_id in paths:
            # create entry for each chip along path
            for (path_chip_x, path_chip_y) in paths[path_id]:
                # figure link IDs (default is [4])
                link_ids = [self.DEFAULT_LINK_ID]
                if (path_chip_x, path_chip_y) in joins:
                    link_ids = [joins[path_chip_x, path_chip_y]]

                # build entry and add to table and add to tables
                fixed_route_entry = FixedRouteEntry(
                    link_ids=link_ids, processor_ids=[])
                chip_x = (
                    path_chip_x + ethernet_chip_x) % (machine.max_chip_x + 1)
                chip_y = (
                    path_chip_y + ethernet_chip_y) % (machine.max_chip_y + 1)
                fixed_route_tables[chip_x, chip_y] = fixed_route_entry

        # locate where to put data
        processor_id = self._locate_destination(
            ethernet_chip_x, ethernet_chip_y, destination_class, placements)

        # create final fixed route entry
        # build entry and add to table and add to tables
        fixed_route_entry = FixedRouteEntry(
            link_ids=[], processor_ids=[processor_id])
        key = (ethernet_chip_x, ethernet_chip_y)
        if key in fixed_route_tables:
            raise PacmanAlreadyExistsException(
                "fixed route entry", str(key))
        fixed_route_tables[key] = fixed_route_entry
예제 #7
0
    def add_routing_table(self, routing_table):
        """ Add a routing table

        :param MulticastRoutingTable routing_table: a routing table to add
        :rtype: None
        :raise PacmanAlreadyExistsException:
            If a routing table already exists for the chip
        """
        if routing_table in self._routing_tables:
            raise PacmanAlreadyExistsException(
                "The Routing table {} has already been added to the collection"
                " before and therefore already exists".format(routing_table),
                str(routing_table))

        if (routing_table.x, routing_table.y) in self._routing_tables_by_chip:
            raise PacmanAlreadyExistsException(
                "The Routing table for chip {}:{} already exists in this "
                "collection and therefore is deemed an error to re-add it".
                format(routing_table.x, routing_table.y), str(routing_table))
        self._routing_tables_by_chip[(routing_table.x, routing_table.y)] = \
            routing_table
        self._routing_tables.add(routing_table)
        self._max_number_of_entries = max(self._max_number_of_entries,
                                          routing_table.number_of_entries)
예제 #8
0
    def remember_machine_vertex(self, machine_vertex):
        """
        Adds the Machine vertex the iterable returned by machine_vertices

        This method will be called by MachineVertex.app_vertex
        No other place should call it.

        :param MachineVertex machine_vertex: A pointer to a machine_vertex.
            This vertex may not be fully initialized but will have a slice
        :raises PacmanValueError: If the slice of the machine_vertex is too big
        """

        machine_vertex.index = len(self._machine_vertices)

        if machine_vertex in self._machine_vertices:
            raise PacmanAlreadyExistsException(str(machine_vertex),
                                               machine_vertex)
        self._machine_vertices.add(machine_vertex)
예제 #9
0
    def other_splitter(self, new_value):
        """ Supports the delayed setting of the other to depend on

        :param new_value: other splitter
        :type new_value: AbstractSplitterCommon or None
        :raise PacmanAlreadyExistsException:
            If there is already a different other set
        :raise PacmanPartitionException:
            If a circular dependency is detected
        """
        if (self._other_splitter is not None and
                self._other_splitter != new_value):
            raise PacmanAlreadyExistsException(
                "other_splitter", self._other_splitter)
        if self.check_circular(new_value):
            raise PacmanPartitionException(
                self.CIRCULAR_ERROR_MESSAGE.format(self, new_value))
        self._other_splitter = new_value
예제 #10
0
    def add_outgoing_edge_partition(self, edge_partition):
        # verify that this partition is suitable for this graph
        if not isinstance(edge_partition, ApplicationEdgePartition):
            raise PacmanInvalidParameterException(
                "outgoing_edge_partition", edge_partition.__class__,
                "Partitions of this graph must be an ApplicationEdgePartition")

        # check this partition doesn't already exist
        key = (edge_partition.pre_vertex, edge_partition.identifier)
        if key in self._outgoing_edge_partitions_by_name:
            raise PacmanAlreadyExistsException(str(ApplicationEdgePartition),
                                               key)

        edge_partition.register_graph_code(id(self))

        self._outgoing_edge_partitions_by_pre_vertex[
            edge_partition.pre_vertex].add(edge_partition)
        self._outgoing_edge_partitions_by_name[key] = edge_partition
        for edge in edge_partition.edges:
            self._register_edge(edge, edge_partition)
예제 #11
0
    def add_vertex(self, vertex):
        """ Add a vertex to the graph.

        :param AbstractVertex vertex: The vertex to add
        :raises PacmanInvalidParameterException:
            If the vertex is not of a valid type
        :raises PacmanConfigurationException:
            If there is an attempt to add the same vertex more than once
        """
        if not isinstance(vertex, self._allowed_vertex_types):
            raise PacmanInvalidParameterException(
                "vertex", str(vertex.__class__),
                "Vertices of this graph must be one of the following types:"
                " {}".format(self._allowed_vertex_types))
        if not vertex.label:
            vertex.set_label(vertex.__class__.__name__ + "_" +
                             self._label_postfix())
        elif vertex.label in self._vertex_by_label:
            if self._vertex_by_label[vertex.label] == vertex:
                raise PacmanAlreadyExistsException("vertex", vertex.label)
            vertex.set_label(vertex.label + self._label_postfix())
        vertex.addedToGraph()
        self._vertices.append(vertex)
        self._vertex_by_label[vertex.label] = vertex
예제 #12
0
    def _register_edge(self, edge, partition):
        """ Add an edge to the graph.

        :param AbstractEdge edge: The edge to add
        :param AbstractEdgePartition partition:
            The name of the edge partition to add the edge to; each edge
            partition is the partition of edges that start at the same vertex
        :raises PacmanInvalidParameterException:
            If the edge is not of a valid type or if edges have already been
            added to this partition that start at a different vertex to this
            one
        """
        # verify that the edge is one suitable for this graph
        if not isinstance(edge, self._allowed_edge_types):
            raise PacmanInvalidParameterException(
                "edge", edge.__class__,
                "Edges of this graph must be one of the following types:"
                " {}".format(self._allowed_edge_types))

        if edge.pre_vertex.label not in self._vertex_by_label:
            raise PacmanInvalidParameterException(
                "Edge", str(edge.pre_vertex),
                "Pre-vertex must be known in graph")
        if edge.post_vertex.label not in self._vertex_by_label:
            raise PacmanInvalidParameterException(
                "Edge", str(edge.post_vertex),
                "Post-vertex must be known in graph")

        # Add the edge to the indices
        self._outgoing_edges[edge.pre_vertex].add(edge)
        self._incoming_edges_by_partition_name[
            edge.post_vertex, partition.identifier].append(edge)
        self._incoming_edges[edge.post_vertex].add(edge)
        if edge in self._outgoing_edge_partition_by_edge:
            raise PacmanAlreadyExistsException("edge", edge)
        self._outgoing_edge_partition_by_edge[edge] = partition
예제 #13
0
    def add_outgoing_edge_partition(self, outgoing_edge_partition):

        # verify that this partition is suitable for this graph
        if not isinstance(
                outgoing_edge_partition, self._allowed_partition_types):
            raise PacmanInvalidParameterException(
                "outgoing_edge_partition", outgoing_edge_partition.__class__,
                "Partitions of this graph must be one of the following types:"
                " {}".format(self._allowed_partition_types))

        # check this partition doesn't already exist
        if ((outgoing_edge_partition.pre_vertex,
                outgoing_edge_partition.identifier) in
                self._outgoing_edge_partitions_by_name):
            raise PacmanAlreadyExistsException(
                "{}".format(OutgoingEdgePartition.__class__),
                (outgoing_edge_partition.pre_vertex,
                 outgoing_edge_partition.identifier))

        self._outgoing_edge_partitions_by_pre_vertex[
            outgoing_edge_partition.pre_vertex].add(outgoing_edge_partition)
        self._outgoing_edge_partitions_by_name[
            outgoing_edge_partition.pre_vertex,
            outgoing_edge_partition.identifier] = outgoing_edge_partition
예제 #14
0
    def _do_dynamic_routing(
            self, fixed_route_tables, placements, ethernet_connected_chip,
            destination_class, machine, board_version):
        """ Uses a router to route fixed routes

        :param fixed_route_tables: fixed route tables entry holder
        :param placements: placements
        :param ethernet_connected_chip: the chip to consider for this routing
        :param destination_class: the class at the Ethernet connected chip\
            for receiving all these routes.
        :param machine: SpiNNMachine instance
        :param board_version: The version of the machine
        :rtype: None
        """
        graph = MachineGraph(label="routing graph")
        fake_placements = Placements()

        # build fake setup for the routing
        eth_x = ethernet_connected_chip.x
        eth_y = ethernet_connected_chip.y
        down_links = set()
        for (chip_x, chip_y) in machine.get_chips_on_board(
                ethernet_connected_chip):
            vertex = RoutingMachineVertex()
            graph.add_vertex(vertex)
            rel_x = chip_x - eth_x
            if rel_x < 0:
                rel_x += machine.max_chip_x + 1
            rel_y = chip_y - eth_y
            if rel_y < 0:
                rel_y += machine.max_chip_y + 1

            free_processor = 0
            while ((free_processor < machine.MAX_CORES_PER_CHIP) and
                   fake_placements.is_processor_occupied(
                       self.FAKE_ETHERNET_CHIP_X,
                       y=self.FAKE_ETHERNET_CHIP_Y,
                       p=free_processor)):
                free_processor += 1

            fake_placements.add_placement(Placement(
                x=rel_x, y=rel_y, p=free_processor, vertex=vertex))
            down_links.update({
                (rel_x, rel_y, link) for link in range(
                    Router.MAX_LINKS_PER_ROUTER)
                if not machine.is_link_at(chip_x, chip_y, link)})

        # Create a fake machine consisting of only the one board that
        # the routes should go over
        fake_machine = machine
        if (board_version in machine.BOARD_VERSION_FOR_48_CHIPS and
                (machine.max_chip_x > machine.MAX_CHIP_X_ID_ON_ONE_BOARD or
                 machine.max_chip_y > machine.MAX_CHIP_Y_ID_ON_ONE_BOARD)):
            down_chips = {
                (x, y) for x, y in zip(
                    range(machine.SIZE_X_OF_ONE_BOARD),
                    range(machine.SIZE_Y_OF_ONE_BOARD))
                if not machine.is_chip_at(
                    (x + eth_x) % (machine.max_chip_x + 1),
                    (y + eth_y) % (machine.max_chip_y + 1))}

            # build a fake machine which is just one board but with the missing
            # bits of the real board
            fake_machine = VirtualMachine(
                machine.SIZE_X_OF_ONE_BOARD, machine.SIZE_Y_OF_ONE_BOARD,
                False, down_chips=down_chips, down_links=down_links)

        # build destination
        verts = graph.vertices
        vertex_dest = RoutingMachineVertex()
        graph.add_vertex(vertex_dest)
        destination_processor = self._locate_destination(
            ethernet_chip_x=ethernet_connected_chip.x,
            ethernet_chip_y=ethernet_connected_chip.y,
            destination_class=destination_class,
            placements=placements)
        fake_placements.add_placement(Placement(
            x=self.FAKE_ETHERNET_CHIP_X, y=self.FAKE_ETHERNET_CHIP_Y,
            p=destination_processor, vertex=vertex_dest))

        # deal with edges
        for vertex in verts:
            graph.add_edge(
                MachineEdge(pre_vertex=vertex, post_vertex=vertex_dest),
                self.FAKE_ROUTING_PARTITION)

        # route as if using multicast
        router = BasicDijkstraRouting()
        routing_tables_by_partition = router(
            placements=fake_placements, machine=fake_machine,
            machine_graph=graph, use_progress_bar=False)

        # convert to fixed route entries
        for (chip_x, chip_y) in routing_tables_by_partition.get_routers():
            mc_entries = routing_tables_by_partition.get_entries_for_router(
                chip_x, chip_y)
            # only want the first entry, as that will all be the same.
            mc_entry = next(itervalues(mc_entries))
            fixed_route_entry = FixedRouteEntry(
                link_ids=mc_entry.out_going_links,
                processor_ids=mc_entry.out_going_processors)
            x = (chip_x + eth_x) % (machine.max_chip_x + 1)
            y = (chip_y + eth_y) % (machine.max_chip_y + 1)
            key = (x, y)
            if key in fixed_route_tables:
                raise PacmanAlreadyExistsException(
                    "fixed route entry", str(key))
            fixed_route_tables[key] = fixed_route_entry