From ae1ced835c0c6e57b41dda32cf929916e9273e56 Mon Sep 17 00:00:00 2001 From: "Christian Y. Brenninkmeijer" Date: Wed, 27 Mar 2024 07:16:52 +0000 Subject: [PATCH 01/10] replace FixedRoueEntry with Shared RoutingEntry class --- .../fixed_route_router/fixed_route_router.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pacman/operations/fixed_route_router/fixed_route_router.py b/pacman/operations/fixed_route_router/fixed_route_router.py index 41160dd7c..c21a9c96d 100644 --- a/pacman/operations/fixed_route_router/fixed_route_router.py +++ b/pacman/operations/fixed_route_router/fixed_route_router.py @@ -14,7 +14,7 @@ from typing import Dict, List, Tuple, Type from spinn_utilities.progress_bar import ProgressBar -from spinn_machine import Chip, FixedRouteEntry +from spinn_machine import Chip, RoutingEntry from pacman.data import PacmanDataView from pacman.exceptions import ( PacmanAlreadyExistsException, PacmanConfigurationException, @@ -22,14 +22,14 @@ def fixed_route_router( - destination_class: Type) -> Dict[Tuple[int, int], FixedRouteEntry]: + destination_class: Type) -> Dict[Tuple[int, int], RoutingEntry]: """ Runs the fixed route generator for all boards on machine. :param destination_class: the destination class to route packets to :type destination_class: type :return: router tables for fixed route paths - :rtype: dict((int, int)), ~spinn_machine.FixedRouteEntry) + :rtype: dict((int, int)), ~spinn_machine.RoutingEntry) :raises PacmanConfigurationException: if no placement processor found :raises PacmanRoutingException: :raises PacmanAlreadyExistsException: @@ -56,15 +56,15 @@ def __init__(self, destination_class: Type): """ self._machine = PacmanDataView.get_machine() self._destination_class = destination_class - self._fixed_route_tables: Dict[Tuple[int, int], FixedRouteEntry] = \ + self._fixed_route_tables: Dict[Tuple[int, int], RoutingEntry] = \ dict() - def build_fixed_routes(self) -> Dict[Tuple[int, int], FixedRouteEntry]: + def build_fixed_routes(self) -> Dict[Tuple[int, int], RoutingEntry]: """ Runs the fixed route generator for all boards on machine. :return: router tables for fixed route paths - :rtype: dict((int, int), ~spinn_machine.FixedRouteEntry) + :rtype: dict((int, int), ~spinn_machine.RoutingEntry) :raises PacmanConfigurationException: if no placement processor found :raises PacmanRoutingException: :raises PacmanAlreadyExistsException: @@ -136,7 +136,7 @@ def __add_fixed_route_entry(self, key: Tuple[int, int], if key in self._fixed_route_tables: raise PacmanAlreadyExistsException( "fixed route entry", str(key)) - self._fixed_route_tables[key] = FixedRouteEntry( + self._fixed_route_tables[key] = RoutingEntry( link_ids=link_ids, processor_ids=processor_ids) def __locate_destination(self, chip: Chip) -> int: From 29e7b9b047c99855e09e1cb616d830a1b94ca3c6 Mon Sep 17 00:00:00 2001 From: "Christian Y. Brenninkmeijer" Date: Wed, 27 Mar 2024 17:24:58 +0000 Subject: [PATCH 02/10] replace MulticastRoutingTableByPartitionEntry with RoutingEntry --- .../routing_info/app_vertex_routing_info.py | 9 +- .../routing_table_by_partition/__init__.py | 5 +- .../multicast_routing_table_by_partition.py | 22 +- ...ticast_routing_table_by_partition_entry.py | 283 ------------------ .../router_algorithms/application_router.py | 27 +- .../basic_routing_table_generator.py | 8 +- .../merged_routing_table_generator.py | 18 +- .../test_routing_tables_model.py | 64 ++-- .../test_merged.py | 4 +- 9 files changed, 67 insertions(+), 373 deletions(-) delete mode 100644 pacman/model/routing_table_by_partition/multicast_routing_table_by_partition_entry.py diff --git a/pacman/model/routing_info/app_vertex_routing_info.py b/pacman/model/routing_info/app_vertex_routing_info.py index 6b2a8f814..94310b89b 100644 --- a/pacman/model/routing_info/app_vertex_routing_info.py +++ b/pacman/model/routing_info/app_vertex_routing_info.py @@ -16,13 +16,11 @@ import math from typing import Iterable, List, Tuple, TYPE_CHECKING from spinn_utilities.overrides import overrides -from spinn_machine.multicast_routing_entry import MulticastRoutingEntry +from spinn_machine import MulticastRoutingEntry, RoutingEntry from .vertex_routing_info import VertexRoutingInfo if TYPE_CHECKING: from pacman.model.graphs.application import ApplicationVertex from pacman.model.routing_info import BaseKeyAndMask - from pacman.model.routing_table_by_partition import ( - MulticastRoutingTableByPartitionEntry) from .machine_vertex_routing_info import MachineVertexRoutingInfo logger = logging.getLogger(__name__) @@ -58,7 +56,7 @@ def __init__( self.__max_machine_index = max_machine_index def merge_machine_entries(self, entries: List[Tuple[ - MulticastRoutingTableByPartitionEntry, + RoutingEntry, MachineVertexRoutingInfo]]) -> Iterable[MulticastRoutingEntry]: """ Merge the machine entries. @@ -66,8 +64,7 @@ def merge_machine_entries(self, entries: List[Tuple[ :param entries: The entries to merge :type entries: - list(tuple( - MulticastRoutingTableByPartitionEntry, VertexRoutingInfo)) + list(tuple(RoutingEntry, VertexRoutingInfo)) :rtype: iterable(~spinn_machine.MulticastRoutingEntry) """ n_entries = len(entries) diff --git a/pacman/model/routing_table_by_partition/__init__.py b/pacman/model/routing_table_by_partition/__init__.py index 44badd1f2..99c3d20e4 100644 --- a/pacman/model/routing_table_by_partition/__init__.py +++ b/pacman/model/routing_table_by_partition/__init__.py @@ -14,8 +14,5 @@ from .multicast_routing_table_by_partition import ( MulticastRoutingTableByPartition) -from .multicast_routing_table_by_partition_entry import ( - MulticastRoutingTableByPartitionEntry) -__all__ = ["MulticastRoutingTableByPartition", - "MulticastRoutingTableByPartitionEntry"] +__all__ = ["MulticastRoutingTableByPartition"] diff --git a/pacman/model/routing_table_by_partition/multicast_routing_table_by_partition.py b/pacman/model/routing_table_by_partition/multicast_routing_table_by_partition.py index c26de4608..c49e6044e 100644 --- a/pacman/model/routing_table_by_partition/multicast_routing_table_by_partition.py +++ b/pacman/model/routing_table_by_partition/multicast_routing_table_by_partition.py @@ -15,13 +15,12 @@ import logging from typing import Dict, Iterator, Optional, Tuple, TYPE_CHECKING from spinn_utilities.typing.coords import XY +from spinn_machine import RoutingEntry from pacman.model.graphs.application import ApplicationVertex from pacman.exceptions import PacmanInvalidParameterException from pacman.model.graphs.machine import MachineVertex if TYPE_CHECKING: from pacman.model.graphs import AbstractVertex - from .multicast_routing_table_by_partition_entry import ( - MulticastRoutingTableByPartitionEntry) log = logging.getLogger(__name__) @@ -38,17 +37,16 @@ class MulticastRoutingTableByPartition(object): def __init__(self) -> None: self._router_to_entries_map: Dict[XY, Dict[ - Tuple[AbstractVertex, str], - MulticastRoutingTableByPartitionEntry]] = dict() + Tuple[AbstractVertex, str], RoutingEntry]] = dict() def add_path_entry( - self, entry: MulticastRoutingTableByPartitionEntry, + self, entry: RoutingEntry, router_x: int, router_y: int, source_vertex: AbstractVertex, partition_id: str): """ Adds a multicast routing path entry. - :param MulticastRoutingTableByPartitionEntry entry: the entry to add + :param RoutingEntry entry: the entry to add :param int router_x: the X coordinate of the router :param int router_y: the Y coordinate of the router :param source_vertex: The source that will send via this entry @@ -82,7 +80,7 @@ def add_path_entry( entries[source_key] = entry else: try: - entries[source_key] = entry.merge_entry(entries[source_key]) + entries[source_key] = entry.merge(entries[source_key]) except PacmanInvalidParameterException as e: log.error( "Error merging entries on %s for %s", key, source_key) @@ -106,8 +104,7 @@ def n_routers(self) -> int: return len(self._router_to_entries_map) def get_entries_for_router(self, router_x: int, router_y: int) -> Optional[ - Dict[Tuple[AbstractVertex, str], - MulticastRoutingTableByPartitionEntry]]: + Dict[Tuple[AbstractVertex, str], RoutingEntry]]: """ Get the set of multicast path entries assigned to this router. @@ -115,15 +112,14 @@ def get_entries_for_router(self, router_x: int, router_y: int) -> Optional[ :param int router_y: the Y coordinate of the router :return: all router_path_entries for the router. :rtype: dict(tuple((ApplicationVertex or MachineVertex), str), - MulticastRoutingTableByPartitionEntry) + RoutingEntry) """ key = (router_x, router_y) return self._router_to_entries_map.get(key) def get_entry_on_coords_for_edge( self, source_vertex: AbstractVertex, partition_id: str, - router_x: int, router_y: int) -> Optional[ - MulticastRoutingTableByPartitionEntry]: + router_x: int, router_y: int) -> Optional[RoutingEntry]: """ Get an entry from a specific coordinate. @@ -132,7 +128,7 @@ def get_entry_on_coords_for_edge( :param str partition_id: :param int router_x: the X coordinate of the router :param int router_y: the Y coordinate of the router - :rtype: MulticastRoutingTableByPartitionEntry or None + :rtype: RoutingEntry or None """ entries = self.get_entries_for_router(router_x, router_y) if entries is None: diff --git a/pacman/model/routing_table_by_partition/multicast_routing_table_by_partition_entry.py b/pacman/model/routing_table_by_partition/multicast_routing_table_by_partition_entry.py deleted file mode 100644 index be20bd791..000000000 --- a/pacman/model/routing_table_by_partition/multicast_routing_table_by_partition_entry.py +++ /dev/null @@ -1,283 +0,0 @@ -# Copyright (c) 2015 The University of Manchester -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -from __future__ import annotations -import logging -from typing import FrozenSet, Iterable, Optional, Union -from spinn_utilities.log import FormatAdapter -from pacman.exceptions import ( - PacmanConfigurationException, PacmanInvalidParameterException) - -log = FormatAdapter(logging.getLogger(__name__)) - -_INCOMING_LINK_MASK = 0x07000000 -_INCOMING_LINK_SHIFT = 24 -_INCOMING_PROC_MASK = 0xF8000000 -_INCOMING_PROC_SHIFT = 27 -_OUTGOING_LINKS_MASK = 0x0000003F -_OUTGOING_LINK_1 = 0x00000001 -_OUTGOING_PROCS_MASK = 0x00FFFFC0 -_OUTGOING_PROC_1 = 0x00000040 -_SPINNAKER_ROUTE_MASK = _OUTGOING_LINKS_MASK | _OUTGOING_PROCS_MASK -_COMPARE_MASK = _INCOMING_LINK_MASK | _SPINNAKER_ROUTE_MASK -_N_PROCS = 18 -_N_LINKS = 6 - - -class MulticastRoutingTableByPartitionEntry(object): - """ - An entry in a path of a multicast route. - """ - - __slots__ = ( - # pylint: disable=wrong-spelling-in-comment - # Entry made up of bits as follows: - # | IL = 6 bits | IP = 1 bit | OL = 6 bits | OP = 18 bits | - # IL = incoming link id - # IP = whether the source is a processor or not - # OL = outgoing links - # OP = outgoing processors - "_links_and_procs", ) - - def __init__(self, out_going_links: Union[int, Iterable[int], None], - outgoing_processors: Union[int, Iterable[int], None], - incoming_processor: Optional[int] = None, - incoming_link: Optional[int] = None): - """ - :param out_going_links: - the edges this path entry goes down, each of which is between - 0 and 5 - :type out_going_links: int or iterable(int) or None - :param outgoing_processors: - the processors this path entry goes to, each of which is between - 0 and 17 - :type outgoing_processors: int or iterable(int) or None - :param int incoming_processor: - the direction this entry came from (between 0 and 17) - :param int incoming_link: - the direction this entry came from in link (between 0 and 5) - :raises PacmanInvalidParameterException: - """ - self._links_and_procs = 0 - if isinstance(out_going_links, int): - self.__set_outgoing_links([out_going_links]) - elif out_going_links is not None: - self.__set_outgoing_links(out_going_links) - - if isinstance(outgoing_processors, int): - self.__set_outgoing_procs([outgoing_processors]) - elif outgoing_processors is not None: - self.__set_outgoing_procs(outgoing_processors) - - if incoming_link is not None and incoming_processor is not None: - raise PacmanInvalidParameterException( - "The incoming direction for a path can only be from either " - "one link or one processors, not both", - str(incoming_link), str(incoming_processor)) - if incoming_processor is not None: - self.__set_incoming_proc(incoming_processor) - elif incoming_link is not None: - self.__set_incoming_link(incoming_link) - - def __set_incoming_link(self, link: int): - if link > _N_LINKS: - raise ValueError(f"Link {link} > {_N_LINKS}") - # Add one so that 0 means not set - self._links_and_procs |= (link + 1) << _INCOMING_LINK_SHIFT - - def __set_incoming_proc(self, proc: int): - if proc > _N_PROCS: - raise ValueError(f"Processor {proc} > {_N_PROCS}") - # Add one so that 0 means not set - self._links_and_procs |= (proc + 1) << _INCOMING_PROC_SHIFT - - def __set_outgoing_links(self, links: Iterable[int]): - for link in links: - if link > _N_LINKS: - raise ValueError(f"Link {link} > {_N_LINKS}") - self._links_and_procs |= _OUTGOING_LINK_1 << link - - def __set_outgoing_procs(self, procs: Iterable[int]): - for proc in procs: - if proc > _N_PROCS: - raise ValueError(f"Processor {proc} > {_N_PROCS}") - self._links_and_procs |= _OUTGOING_PROC_1 << proc - - @property - def processor_ids(self) -> FrozenSet[int]: - """ - The destination processors of the entry. - - :rtype: frozenset(int) - """ - return frozenset(i for i in range(_N_PROCS) - if self._links_and_procs & (_OUTGOING_PROC_1 << i)) - - @property - def link_ids(self) -> FrozenSet[int]: - """ - The destination links of the entry. - - :rtype: frozenset(int) - """ - return frozenset(i for i in range(_N_LINKS) - if self._links_and_procs & (_OUTGOING_LINK_1 << i)) - - @property - def incoming_link(self) -> Optional[int]: - """ - The source link for this path entry. - - :rtype: int or None - """ - link = ((self._links_and_procs & _INCOMING_LINK_MASK) >> - _INCOMING_LINK_SHIFT) - if link == 0: - return None - # Subtract 1 as 0 means not set - return link - 1 - - @incoming_link.setter - def incoming_link(self, incoming_link: int): - if self.incoming_processor is not None: - raise PacmanConfigurationException( - f"Entry already has an incoming processor " - f"{self.incoming_processor}") - self_link = self.incoming_link - if self_link is not None and self_link != incoming_link: - raise PacmanConfigurationException( - f"Entry already has an incoming link {self_link}") - self.__set_incoming_link(incoming_link) - - @property - def incoming_processor(self) -> Optional[int]: - """ - The source processor. - - :rtype: int or None - """ - proc = ((self._links_and_procs & _INCOMING_PROC_MASK) >> - _INCOMING_PROC_SHIFT) - if proc == 0: - return None - # Subtract 1 as 0 means not set - return proc - 1 - - @incoming_processor.setter - def incoming_processor(self, incoming_processor: int): - if self.incoming_link is not None: - raise PacmanConfigurationException( - f"Entry already has an incoming link {self.incoming_link}") - self_proc = self.incoming_processor - if self_proc is not None and self_proc != incoming_processor: - raise PacmanConfigurationException( - f"Entry already has an incoming processor {self_proc}") - self.__set_incoming_proc(incoming_processor) - - @property - def defaultable(self) -> bool: - """ - The defaultable status of the entry. - - :rtype: bool - """ - if self.incoming_processor is not None: - return False - in_link = self.incoming_link - if in_link is None: - return False - out_links = self.link_ids - if len(out_links) != 1: - return False - if self.processor_ids: - return False - out_link = next(iter(out_links)) - return ((in_link + 3) % 6) == out_link - - @staticmethod - def __merge_none_or_equal(p1, p2, name): - if p1 is None: - return p2 - if p2 is None or p2 == p1: - return p1 - raise PacmanInvalidParameterException( - name, "invalid merge", - "The two MulticastRoutingTableByPartitionEntry have " - "different " + name + "s, and so can't be merged") - - def merge_entry(self, other: MulticastRoutingTableByPartitionEntry) -> \ - MulticastRoutingTableByPartitionEntry: - """ - Merges the another entry with this one and returns a new - MulticastRoutingTableByPartitionEntry - - :param MulticastRoutingTableByPartitionEntry other: - the entry to merge into this one - :return: a merged MulticastRoutingTableByPartitionEntry - :raises PacmanInvalidParameterException: - """ - # pylint:disable=protected-access - if not isinstance(other, MulticastRoutingTableByPartitionEntry): - raise PacmanInvalidParameterException( - "other", "type error", - "The other parameter is not an instance of " - "MulticastRoutingTableByPartitionEntry, and therefore cannot " - "be merged.") - - # validate incoming - try: - in_proc = self.__merge_none_or_equal( - self.incoming_processor, other.incoming_processor, - "incoming_processor") - in_link = self.__merge_none_or_equal( - self.incoming_link, other.incoming_link, "incoming_link") - if in_proc is not None and in_link is not None: - raise PacmanInvalidParameterException( - "other", "merge error", - f"Cannot merge {other} and {self}: both incoming processor" - " and link are set") - except PacmanInvalidParameterException as e: - log.error("Error merging entry {} into {}", other, self) - raise e - - # Set the value directly as faster - entry = MulticastRoutingTableByPartitionEntry(None, None) - entry._links_and_procs = self._links_and_procs | other._links_and_procs - return entry - - def __repr__(self) -> str: - return (f"{self.incoming_link}:{self.incoming_processor}:" - f"{self.defaultable}:" - f"{{{', '.join(map(str, self.link_ids))}}}:" - f"{{{', '.join(map(str, self.processor_ids))}}}") - - def has_same_route( - self, entry: MulticastRoutingTableByPartitionEntry) -> bool: - """ - Checks if the two Entries have the same routes after applying mask - - :param MulticastRoutingTableByPartitionEntry entry: - :rtype: bool - """ - # pylint:disable=protected-access - return ((self._links_and_procs & _COMPARE_MASK) == - (entry._links_and_procs & _COMPARE_MASK)) - - @property - def spinnaker_route(self) -> int: - """ - The masked routes - - :rtype: int - """ - return self._links_and_procs & _SPINNAKER_ROUTE_MASK diff --git a/pacman/operations/router_algorithms/application_router.py b/pacman/operations/router_algorithms/application_router.py index 984cca167..bda9ea43b 100644 --- a/pacman/operations/router_algorithms/application_router.py +++ b/pacman/operations/router_algorithms/application_router.py @@ -18,11 +18,11 @@ from typing_extensions import TypeAlias from spinn_utilities.progress_bar import ProgressBar from spinn_utilities.typing.coords import XY -from spinn_machine import Machine +from spinn_machine import Machine, RoutingEntry from pacman.data import PacmanDataView from pacman.exceptions import PacmanRoutingException from pacman.model.routing_table_by_partition import ( - MulticastRoutingTableByPartition, MulticastRoutingTableByPartitionEntry) + MulticastRoutingTableByPartition) from pacman.utilities.algorithm_utilities.routing_algorithm_utilities import ( longest_dimension_first, get_app_partitions, vertex_xy, vertex_xy_and_route) @@ -984,9 +984,11 @@ def _convert_a_route( app_vertex_source = True else: machine_vertex_sources.add(source) - entry = MulticastRoutingTableByPartitionEntry( - link_ids + add_links, processor_ids + add_cores, - incoming_processor, incoming_link) + entry = RoutingEntry( + link_ids=link_ids + add_links, + processor_ids=processor_ids + add_cores, + incoming_processor=incoming_processor, + incoming_link=incoming_link) _add_routing_entry( first_route, routing_tables, entry, x, y, source, partition_id) @@ -997,15 +999,18 @@ def _convert_a_route( for m_vert in source_vertex.splitter.get_out_going_vertices( partition_id): if m_vert not in machine_vertex_sources: - entry = MulticastRoutingTableByPartitionEntry( - link_ids, processor_ids, incoming_processor, - incoming_link) + entry = RoutingEntry( + link_ids=link_ids, processor_ids=processor_ids, + incoming_processor=incoming_processor, + incoming_link=incoming_link) _add_routing_entry( first_route, routing_tables, entry, x, y, m_vert, partition_id) else: - entry = MulticastRoutingTableByPartitionEntry( - link_ids, processor_ids, incoming_processor, incoming_link) + entry = RoutingEntry( + link_ids=link_ids, processor_ids=processor_ids, + incoming_processor=incoming_processor, + incoming_link=incoming_link) _add_routing_entry( first_route, routing_tables, entry, x, y, source_vertex, partition_id) @@ -1014,7 +1019,7 @@ def _convert_a_route( def _add_routing_entry( first_route: RoutingTree, routing_tables: MulticastRoutingTableByPartition, - entry: MulticastRoutingTableByPartitionEntry, + entry: RoutingEntry, x: int, y: int, source: _AnyVertex, partition_id: str): try: routing_tables.add_path_entry(entry, x, y, source, partition_id) diff --git a/pacman/operations/routing_table_generators/basic_routing_table_generator.py b/pacman/operations/routing_table_generators/basic_routing_table_generator.py index 267aa6beb..5064a2599 100644 --- a/pacman/operations/routing_table_generators/basic_routing_table_generator.py +++ b/pacman/operations/routing_table_generators/basic_routing_table_generator.py @@ -13,13 +13,11 @@ # limitations under the License. from typing import Dict, Tuple from spinn_utilities.progress_bar import ProgressBar -from spinn_machine import MulticastRoutingEntry +from spinn_machine import MulticastRoutingEntry, RoutingEntry from pacman.data import PacmanDataView from pacman.model.routing_tables import ( UnCompressedMulticastRoutingTable, MulticastRoutingTables) from pacman.model.graphs import AbstractVertex -from pacman.model.routing_table_by_partition import ( - MulticastRoutingTableByPartitionEntry) from pacman.model.routing_info import RoutingInfo @@ -48,7 +46,7 @@ def basic_routing_table_generator() -> MulticastRoutingTables: def __create_routing_table( x: int, y: int, partitions_in_table: Dict[ - Tuple[AbstractVertex, str], MulticastRoutingTableByPartitionEntry], + Tuple[AbstractVertex, str], RoutingEntry], routing_infos: RoutingInfo): """ :param int x: @@ -56,7 +54,7 @@ def __create_routing_table( :param partitions_in_table: :type partitions_in_table: dict(((ApplicationVertex or MachineVertex), str), - MulticastRoutingTableByPartitionEntry) + RoutingEntry) :param RoutingInfo routing_infos: :rtype: MulticastRoutingTable """ diff --git a/pacman/operations/routing_table_generators/merged_routing_table_generator.py b/pacman/operations/routing_table_generators/merged_routing_table_generator.py index d7aca7b44..6712b0dfd 100644 --- a/pacman/operations/routing_table_generators/merged_routing_table_generator.py +++ b/pacman/operations/routing_table_generators/merged_routing_table_generator.py @@ -14,7 +14,7 @@ from typing import ( Dict, Iterable, List, Optional, Tuple, TypeVar, Generic) from spinn_utilities.progress_bar import ProgressBar -from spinn_machine import MulticastRoutingEntry +from spinn_machine import MulticastRoutingEntry, RoutingEntry from pacman.data import PacmanDataView from pacman.exceptions import PacmanRoutingException from pacman.model.routing_tables import ( @@ -23,8 +23,6 @@ from pacman.model.routing_info import ( RoutingInfo, AppVertexRoutingInfo, MachineVertexRoutingInfo) from pacman.model.graphs import AbstractVertex -from pacman.model.routing_table_by_partition import ( - MulticastRoutingTableByPartitionEntry) from pacman.model.graphs.machine.machine_vertex import MachineVertex @@ -54,15 +52,14 @@ def merged_routing_table_generator() -> MulticastRoutingTables: def __create_routing_table( x: int, y: int, partitions_in_table: Dict[Tuple[AbstractVertex, str], - MulticastRoutingTableByPartitionEntry], + RoutingEntry], routing_info: RoutingInfo) -> UnCompressedMulticastRoutingTable: """ :param int x: :param int y: :param partitions_in_table: :type partitions_in_table: - dict(((ApplicationVertex or MachineVertex), str), - MulticastRoutingTableByPartitionEntry) + dict(((ApplicationVertex or MachineVertex), str), RoutingEntry) :param RoutingInfo routing_infos: :rtype: MulticastRoutingTable """ @@ -101,8 +98,7 @@ def __create_routing_table( # Get the entries to merge entries: List[Tuple[ - MulticastRoutingTableByPartitionEntry, - MachineVertexRoutingInfo]] = [(entry, r_info)] + RoutingEntry, MachineVertexRoutingInfo]] = [(entry, r_info)] while __match(iterator, vertex, part_id, r_info, entry, routing_info, app_r_info): (vertex, part_id), entry = iterator.pop() @@ -142,7 +138,8 @@ def __match( return False app_src = vertex.app_vertex next_app_src = next_vertex.app_vertex - return next_app_src == app_src and entry.has_same_route(next_entry) + return (next_app_src == app_src and + entry.spinnaker_route == next_entry.spinnaker_route) def __mask_has_holes(mask: int) -> bool: @@ -161,8 +158,7 @@ def __mask_has_holes(mask: int) -> bool: def __merged_keys_and_masks( app_r_info: AppVertexRoutingInfo, - entries: List[Tuple[ - MulticastRoutingTableByPartitionEntry, + entries: List[Tuple[RoutingEntry, MachineVertexRoutingInfo]]) -> Iterable[MulticastRoutingEntry]: if not entries: return diff --git a/unittests/model_tests/routing_table_tests/test_routing_tables_model.py b/unittests/model_tests/routing_table_tests/test_routing_tables_model.py index f4936cd57..0d4ba39c2 100644 --- a/unittests/model_tests/routing_table_tests/test_routing_tables_model.py +++ b/unittests/model_tests/routing_table_tests/test_routing_tables_model.py @@ -14,13 +14,14 @@ import unittest from pacman.config_setup import unittest_setup -from spinn_machine import MulticastRoutingEntry +from spinn_machine import MulticastRoutingEntry, RoutingEntry +from spinn_machine.exceptions import SpinnMachineInvalidParameterException from pacman.model.routing_tables import ( UnCompressedMulticastRoutingTable, MulticastRoutingTables) from pacman.model.routing_tables.multicast_routing_tables import ( to_json, from_json) from pacman.model.routing_table_by_partition import ( - MulticastRoutingTableByPartition, MulticastRoutingTableByPartitionEntry) + MulticastRoutingTableByPartition) from pacman.exceptions import ( PacmanAlreadyExistsException, PacmanInvalidParameterException) from pacman.utilities import file_format_schemas @@ -192,12 +193,11 @@ def test_multicast_routing_table_by_partition(self): mrt = MulticastRoutingTableByPartition() partition_id = "foo" source_vertex = SimpleMachineVertex(sdram=None) - entry = MulticastRoutingTableByPartitionEntry(range(2), range(4)) + entry = RoutingEntry(link_ids=range(2), processor_ids=range(4)) mrt.add_path_entry(entry, 0, 0, source_vertex, partition_id) - entry = MulticastRoutingTableByPartitionEntry(range(2, 4), range(4, 8)) + entry = RoutingEntry(link_ids=range(2, 4), processor_ids=range(4, 8)) mrt.add_path_entry(entry, 0, 0, source_vertex, partition_id) - entry = MulticastRoutingTableByPartitionEntry( - range(4, 6), range(8, 12)) + entry = RoutingEntry(link_ids=range(4, 6), processor_ids=range(8, 12)) mrt.add_path_entry(entry, 0, 0, source_vertex, partition_id) assert list(mrt.get_routers()) == [(0, 0)] assert len(mrt.get_entries_for_router(0, 0)) == 1 @@ -205,43 +205,31 @@ def test_multicast_routing_table_by_partition(self): source_vertex, partition_id) mre = mrt.get_entries_for_router(0, 0)[source_vertex, partition_id] assert str(mre) == ( - "None:None:False:" - "{0, 1, 2, 3, 4, 5}:{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}") + "{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}:{0, 1, 2, 3, 4, 5}") assert mre == mrt.get_entry_on_coords_for_edge( source_vertex, partition_id, 0, 0) def test_multicast_routing_table_by_partition_entry(self): - with self.assertRaises(PacmanInvalidParameterException): - MulticastRoutingTableByPartitionEntry(range(6), range(18), 4, 3) - with self.assertRaises(ValueError): - MulticastRoutingTableByPartitionEntry(7, 18) - with self.assertRaises(ValueError): - MulticastRoutingTableByPartitionEntry(6, 19) - e1 = MulticastRoutingTableByPartitionEntry(range(6), range(18)) - e2 = MulticastRoutingTableByPartitionEntry( - range(2), range(4), incoming_processor=4) - e3 = MulticastRoutingTableByPartitionEntry( - range(3, 5), range(12, 16), incoming_link=3) - e4 = MulticastRoutingTableByPartitionEntry(2, 16) - e5 = MulticastRoutingTableByPartitionEntry(None, None) - assert str(e2) == "None:4:False:{0, 1}:{0, 1, 2, 3}" - assert str(e3) == "3:None:False:{3, 4}:{12, 13, 14, 15}" - with self.assertRaises(PacmanInvalidParameterException): - e2.merge_entry(e3) - e6 = e2.merge_entry(MulticastRoutingTableByPartitionEntry( - range(3, 5), range(12, 16))) - assert str(e2) == "None:4:False:{0, 1}:{0, 1, 2, 3}" + with self.assertRaises(SpinnMachineInvalidParameterException): + RoutingEntry(link_ids=range(6), processor_ids=range(18), + incoming_processor=4, incoming_link=3) + e1 = RoutingEntry(link_ids=range(6), processor_ids=range(18)) + e2 = RoutingEntry(link_ids=range(2), processor_ids=range(4), + incoming_processor=4) + e3 = RoutingEntry(link_ids=range(3, 5), processor_ids=range(12, 16), + incoming_link=3) + e4 = RoutingEntry(link_ids=2, processor_ids=16) + assert str(e2) == "{0, 1, 2, 3}:{0, 1}" + assert str(e3) == "{12, 13, 14, 15}:{3, 4}" + e6 = e2.merge( + RoutingEntry(link_ids=range(3, 5), processor_ids=range(12, 16))) + assert str(e2) == "{0, 1, 2, 3}:{0, 1}" assert str(e6) == ( - "None:4:False:{0, 1, 3, 4}:{0, 1, 2, 3, 12, 13, 14, 15}") - e6 = e3.merge_entry(MulticastRoutingTableByPartitionEntry( - range(2), range(4))) - assert str(e3) == "3:None:False:{3, 4}:{12, 13, 14, 15}" - assert str(e6) == ( - "3:None:False:{0, 1, 3, 4}:{0, 1, 2, 3, 12, 13, 14, 15}") - assert str(e4.merge_entry(e5)) == "None:None:False:{2}:{16}" - assert str(e1) == str(e5.merge_entry(e1)) - # NB: Have true object identity; we have setters! - assert e5 != MulticastRoutingTableByPartitionEntry(None, None) + "{0, 1, 2, 3, 12, 13, 14, 15}:{0, 1, 3, 4}") + e6 = e3.merge(RoutingEntry( + link_ids=range(2), processor_ids=range(4))) + assert str(e3) == "{12, 13, 14, 15}:{3, 4}" + assert str(e6) == ("{0, 1, 2, 3, 12, 13, 14, 15}:{0, 1, 3, 4}") if __name__ == '__main__': diff --git a/unittests/operations_tests/routing_table_generator_tests/test_merged.py b/unittests/operations_tests/routing_table_generator_tests/test_merged.py index d57ac6821..302f99d88 100644 --- a/unittests/operations_tests/routing_table_generator_tests/test_merged.py +++ b/unittests/operations_tests/routing_table_generator_tests/test_merged.py @@ -114,7 +114,7 @@ def test_graph2(self): self.create_graphs3(writer) self.make_infos(writer) data = merged_routing_table_generator() - self.assertEqual(7, data.get_max_number_of_entries()) + self.assertEqual(6, data.get_max_number_of_entries()) self.assertEqual(5, len(list(data.routing_tables))) def test_graph3_with_system(self): @@ -125,7 +125,7 @@ def test_graph3_with_system(self): system_plaements.add_placement(Placement(mv, 1, 2, 3)) self.make_infos(writer, system_plaements) data = merged_routing_table_generator() - self.assertEqual(7, data.get_max_number_of_entries()) + self.assertEqual(6, data.get_max_number_of_entries()) self.assertEqual(5, len(list(data.routing_tables))) def test_bad_infos(self): From 8c58fc3aefda39ba1603a467a9865abf81ef351e Mon Sep 17 00:00:00 2001 From: "Christian Y. Brenninkmeijer" Date: Thu, 28 Mar 2024 07:41:07 +0000 Subject: [PATCH 03/10] MulticastRoutingEntry wraps a RoutingEntry --- .../routing_info/app_vertex_routing_info.py | 9 +--- .../multicast_routing_tables.py | 8 ++-- .../uncompressed_multicast_routing_table.py | 8 ++-- .../router_compressors/ranged_compressor.py | 6 ++- .../routing_compression_checker.py | 4 +- .../operations/router_compressors/rt_entry.py | 10 ++--- .../basic_routing_table_generator.py | 3 +- .../merged_routing_table_generator.py | 11 ++--- .../test_routing_tables_model.py | 39 +++++++++-------- .../test_compressors.py | 42 ++++++++----------- 10 files changed, 64 insertions(+), 76 deletions(-) diff --git a/pacman/model/routing_info/app_vertex_routing_info.py b/pacman/model/routing_info/app_vertex_routing_info.py index 94310b89b..aecce1e27 100644 --- a/pacman/model/routing_info/app_vertex_routing_info.py +++ b/pacman/model/routing_info/app_vertex_routing_info.py @@ -79,9 +79,7 @@ def merge_machine_entries(self, entries: List[Tuple[ # If that is OK, we can just use them if next_entries <= (n_entries - i) or is_last: mask = self.__group_mask(next_entries) - yield MulticastRoutingEntry( - r_info.key, mask, defaultable=entry.defaultable, - spinnaker_route=entry.spinnaker_route) + yield MulticastRoutingEntry(r_info.key, mask, entry) i += next_entries # Otherwise, we have to break down into powers of two @@ -91,10 +89,7 @@ def merge_machine_entries(self, entries: List[Tuple[ next_entries = 2 ** int(math.log2(entries_to_go)) mask = self.__group_mask(next_entries) (entry, r_info) = entries[i] - yield MulticastRoutingEntry( - r_info.key, mask, - defaultable=entry.defaultable, - spinnaker_route=entry.spinnaker_route) + yield MulticastRoutingEntry(r_info.key, mask, entry) entries_to_go -= next_entries i += next_entries diff --git a/pacman/model/routing_tables/multicast_routing_tables.py b/pacman/model/routing_tables/multicast_routing_tables.py index 6a17bd20b..d42bcd529 100644 --- a/pacman/model/routing_tables/multicast_routing_tables.py +++ b/pacman/model/routing_tables/multicast_routing_tables.py @@ -19,7 +19,7 @@ from spinn_utilities.typing.coords import XY from spinn_utilities.typing.json import JsonObjectArray -from spinn_machine import MulticastRoutingEntry +from spinn_machine import MulticastRoutingEntry, RoutingEntry from pacman.exceptions import PacmanAlreadyExistsException @@ -182,8 +182,8 @@ def from_json(j_router: Union[str, JsonObjectArray]) -> MulticastRoutingTables: table = UnCompressedMulticastRoutingTable(x, y) tables.add_routing_table(table) for j_entry in cast(JsonObjectArray, j_table["entries"]): + entry = RoutingEntry(defaultable=cast(bool, j_entry["defaultable"]), + spinnaker_route=cast(int, j_entry["spinnaker_route"])) table.add_multicast_routing_entry(MulticastRoutingEntry( - cast(int, j_entry["key"]), cast(int, j_entry["mask"]), - defaultable=cast(bool, j_entry["defaultable"]), - spinnaker_route=cast(int, j_entry["spinnaker_route"]))) + cast(int, j_entry["key"]), cast(int, j_entry["mask"]), entry)) return tables diff --git a/pacman/model/routing_tables/uncompressed_multicast_routing_table.py b/pacman/model/routing_tables/uncompressed_multicast_routing_table.py index 7f36d23c9..a737f37cc 100644 --- a/pacman/model/routing_tables/uncompressed_multicast_routing_table.py +++ b/pacman/model/routing_tables/uncompressed_multicast_routing_table.py @@ -19,7 +19,7 @@ from spinn_utilities.log import FormatAdapter from spinn_utilities.overrides import overrides -from spinn_machine import MulticastRoutingEntry +from spinn_machine import MulticastRoutingEntry, RoutingEntry from pacman.exceptions import PacmanAlreadyExistsException from pacman.model.routing_tables import AbstractMulticastRoutingTable @@ -139,14 +139,16 @@ def _from_csv_file( key = int(row[0], base=16) mask = int(row[1], base=16) route = int(row[2], base=16) + entry = RoutingEntry(spinnaker_route=route) table.add_multicast_routing_entry( - MulticastRoutingEntry(key, mask, spinnaker_route=route)) + MulticastRoutingEntry(key, mask, entry)) elif len(row) == 6: key = int(row[1], base=16) mask = int(row[2], base=16) route = int(row[3], base=16) + entry = RoutingEntry(spinnaker_route=route) table.add_multicast_routing_entry( - MulticastRoutingEntry(key, mask, spinnaker_route=route)) + MulticastRoutingEntry(key, mask, entry)) except ValueError as ex: logger.warning(f"csv read error {ex}") return table diff --git a/pacman/operations/router_compressors/ranged_compressor.py b/pacman/operations/router_compressors/ranged_compressor.py index 8f620afd0..e875eac92 100644 --- a/pacman/operations/router_compressors/ranged_compressor.py +++ b/pacman/operations/router_compressors/ranged_compressor.py @@ -18,7 +18,7 @@ from spinn_utilities.config_holder import get_config_bool from spinn_utilities.log import FormatAdapter from spinn_utilities.progress_bar import ProgressBar -from spinn_machine import MulticastRoutingEntry +from spinn_machine import MulticastRoutingEntry, RoutingEntry from pacman.data import PacmanDataView from pacman.model.routing_tables import ( CompressedMulticastRoutingTable, MulticastRoutingTables, @@ -201,8 +201,10 @@ def _merge_range(self, first: int, last: int): # make the new router entry new_mask = 2 ** 32 - power route = self._entries[first].spinnaker_route + + entry = RoutingEntry(spinnaker_route=route) self._compressed.add_multicast_routing_entry(MulticastRoutingEntry( - low_cut, new_mask, spinnaker_route=route)) + low_cut, new_mask, entry)) # Check if we're done if full_last == last: diff --git a/pacman/operations/router_compressors/routing_compression_checker.py b/pacman/operations/router_compressors/routing_compression_checker.py index e3b16a79c..d3bb521eb 100644 --- a/pacman/operations/router_compressors/routing_compression_checker.py +++ b/pacman/operations/router_compressors/routing_compression_checker.py @@ -131,11 +131,11 @@ def compare_route( c_route = compressed_dict[c_code] if f is not None: f.write(f"\t\t{format_route(c_route)}\n") - if o_route.processor_ids != c_route.processor_ids: + if o_route.entry.processor_ids != c_route.entry.processor_ids: raise PacmanRoutingException( f"Compressed route {c_route} covers original route " f"{o_route} but has a different processor_ids.") - if o_route.link_ids != c_route.link_ids: + if o_route.entry.link_ids != c_route.entry.link_ids: raise PacmanRoutingException( f"Compressed route {c_route} covers original route " f"{o_route} but has a different link_ids.") diff --git a/pacman/operations/router_compressors/rt_entry.py b/pacman/operations/router_compressors/rt_entry.py index d821c9784..bb009b5e1 100644 --- a/pacman/operations/router_compressors/rt_entry.py +++ b/pacman/operations/router_compressors/rt_entry.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. from __future__ import annotations -from spinn_machine import MulticastRoutingEntry +from spinn_machine import MulticastRoutingEntry, RoutingEntry class RTEntry(object): @@ -66,13 +66,13 @@ def from_multicast_routing_entry(source: MulticastRoutingEntry) -> RTEntry: # Yes I know using _params is ugly but this is for speed # pylint:disable=protected-access return RTEntry( - source._routing_entry_key, source._mask, source._defaultable, - source._spinnaker_route) + source._routing_entry_key, source._mask, source.defaultable, + source.spinnaker_route) def to_multicast_routing_entry(self) -> MulticastRoutingEntry: """ :rtype: ~spinn_machine.MulticastRoutingEntry """ return MulticastRoutingEntry( - self.key, self.mask, defaultable=self.defaultable, - spinnaker_route=self.spinnaker_route) + self.key, self.mask, + RoutingEntry(spinnaker_route=self.spinnaker_route)) diff --git a/pacman/operations/routing_table_generators/basic_routing_table_generator.py b/pacman/operations/routing_table_generators/basic_routing_table_generator.py index 5064a2599..2a4c8f4ea 100644 --- a/pacman/operations/routing_table_generators/basic_routing_table_generator.py +++ b/pacman/operations/routing_table_generators/basic_routing_table_generator.py @@ -68,7 +68,6 @@ def __create_routing_table( entry = partitions_in_table[source_vertex, partition_id] table.add_multicast_routing_entry(MulticastRoutingEntry( routing_entry_key=r_info.key_and_mask.key_combo, - defaultable=entry.defaultable, mask=r_info.key_and_mask.mask, - link_ids=entry.link_ids, processor_ids=entry.processor_ids)) + mask=r_info.key_and_mask.mask, routing_entry=entry)) return table diff --git a/pacman/operations/routing_table_generators/merged_routing_table_generator.py b/pacman/operations/routing_table_generators/merged_routing_table_generator.py index 6712b0dfd..97414f890 100644 --- a/pacman/operations/routing_table_generators/merged_routing_table_generator.py +++ b/pacman/operations/routing_table_generators/merged_routing_table_generator.py @@ -76,8 +76,7 @@ def __create_routing_table( if isinstance(vertex, ApplicationVertex): table.add_multicast_routing_entry( MulticastRoutingEntry( - r_info.key, r_info.mask, defaultable=entry.defaultable, - spinnaker_route=entry.spinnaker_route)) + r_info.key, r_info.mask, entry)) continue # Otherwise it has to be a machine vertex... assert isinstance(vertex, MachineVertex) @@ -86,9 +85,7 @@ def __create_routing_table( # If there is no application vertex, just add the entry if vertex.app_vertex is None: table.add_multicast_routing_entry( - MulticastRoutingEntry( - r_info.key, r_info.mask, defaultable=entry.defaultable, - spinnaker_route=entry.spinnaker_route)) + MulticastRoutingEntry(r_info.key, r_info.mask, entry)) continue # This has to be AppVertexRoutingInfo! @@ -164,9 +161,7 @@ def __merged_keys_and_masks( return (entry, r_info) = entries[0] if len(entries) == 1: - yield MulticastRoutingEntry( - r_info.key, r_info.mask, defaultable=entry.defaultable, - spinnaker_route=entry.spinnaker_route) + yield MulticastRoutingEntry(r_info.key, r_info.mask, entry) else: yield from app_r_info.merge_machine_entries(entries) diff --git a/unittests/model_tests/routing_table_tests/test_routing_tables_model.py b/unittests/model_tests/routing_table_tests/test_routing_tables_model.py index 0d4ba39c2..f7a519a54 100644 --- a/unittests/model_tests/routing_table_tests/test_routing_tables_model.py +++ b/unittests/model_tests/routing_table_tests/test_routing_tables_model.py @@ -45,9 +45,8 @@ def test_new_multicast_routing_table_entry(self): mask = 0xff00 proc_ids = range(18) link_ids = range(6) - MulticastRoutingEntry(key_combo, mask, - processor_ids=proc_ids, link_ids=link_ids, - defaultable=True) + MulticastRoutingEntry(key_combo, mask, RoutingEntry( + processor_ids=proc_ids, link_ids=link_ids, defaultable=True)) def test_new_multicast_routing_table(self): """ @@ -66,7 +65,8 @@ def test_new_multicast_routing_table(self): for i in range(5): multicast_entries.append(MulticastRoutingEntry( key_combo + i, mask + i, - processor_ids=proc_ids, link_ids=link_ids, defaultable=True)) + RoutingEntry(processor_ids=proc_ids, link_ids=link_ids, + defaultable=True))) mrt = UnCompressedMulticastRoutingTable(0, 0, multicast_entries) self.assertEqual(mrt.x, 0) self.assertEqual(mrt.y, 0) @@ -97,14 +97,16 @@ def test_new_multicast_routing_table_duplicate_entry(self): multicast_entries = list() for i in range(5): multicast_entries.append(MulticastRoutingEntry( - key_combo + i, mask + i, processor_ids=proc_ids, - link_ids=link_ids, defaultable=True)) + key_combo + i, mask + i, + RoutingEntry(processor_ids=proc_ids, link_ids=link_ids, + defaultable=True))) mrt = UnCompressedMulticastRoutingTable(0, 0, multicast_entries) # We can't add an entry with the same key but different route with self.assertRaises(PacmanAlreadyExistsException): mrt.add_multicast_routing_entry(MulticastRoutingEntry( - key_combo, mask, processor_ids=[], link_ids=link_ids, - defaultable=True)) + key_combo, mask, + RoutingEntry(processor_ids=[], link_ids=link_ids, + defaultable=True))) def test_new_multicast_routing_table_duplicate_key_combo(self): @@ -119,8 +121,9 @@ def test_new_multicast_routing_table_duplicate_key_combo(self): multicast_entries = list() for i in range(5): multicast_entries.append(MulticastRoutingEntry( - key_combo, mask, processor_ids=proc_ids, link_ids=link_ids, - defaultable=True)) + key_combo, mask, RoutingEntry( + processor_ids=proc_ids, link_ids=link_ids, + defaultable=True))) # We can add entries that are exactly the same UnCompressedMulticastRoutingTable(0, 0, multicast_entries) @@ -134,11 +137,11 @@ def test_new_multicast_routing_tables(self): for i in range(6): link_ids.append(i) multicast_entries1 = MulticastRoutingEntry( - key_combo, mask, processor_ids=proc_ids, link_ids=link_ids, - defaultable=True) + key_combo, mask, RoutingEntry( + processor_ids=proc_ids, link_ids=link_ids, defaultable=True)) multicast_entries2 = MulticastRoutingEntry( - key_combo - 1, mask - 1, processor_ids=proc_ids, link_ids=link_ids, - defaultable=True) + key_combo - 1, mask - 1, RoutingEntry( + processor_ids=proc_ids, link_ids=link_ids, defaultable=True)) mrt = list() t1 = UnCompressedMulticastRoutingTable(0, 0, [multicast_entries1]) @@ -175,12 +178,12 @@ def test_add_routing_table_for_duplicate_chip(self): for i in range(6): link_ids.append(i) multicast_entries1 = MulticastRoutingEntry( - key_combo, mask, processor_ids=proc_ids, link_ids=link_ids, - defaultable=True) + key_combo, mask, RoutingEntry( + processor_ids=proc_ids, link_ids=link_ids, defaultable=True)) multicast_entries2 = MulticastRoutingEntry( - key_combo - 1, mask, processor_ids=proc_ids, link_ids=link_ids, - defaultable=True) + key_combo - 1, mask, RoutingEntry( + processor_ids=proc_ids, link_ids=link_ids, defaultable=True)) mrt = list() mrt.append( UnCompressedMulticastRoutingTable(3, 0, [multicast_entries1])) diff --git a/unittests/operations_tests/router_compressor_tests/test_compressors.py b/unittests/operations_tests/router_compressor_tests/test_compressors.py index d477196ae..00dd9fdc3 100644 --- a/unittests/operations_tests/router_compressor_tests/test_compressors.py +++ b/unittests/operations_tests/router_compressor_tests/test_compressors.py @@ -14,7 +14,7 @@ import unittest from spinn_utilities.config_holder import set_config -from spinn_machine import MulticastRoutingEntry +from spinn_machine import MulticastRoutingEntry, RoutingEntry from pacman.config_setup import unittest_setup from pacman.data import PacmanDataView from pacman.data.pacman_data_writer import PacmanDataWriter @@ -34,37 +34,29 @@ def setUp(self): original_tables = MulticastRoutingTables() original_table = UnCompressedMulticastRoutingTable(x=0, y=0) original_table.add_multicast_routing_entry( - MulticastRoutingEntry( - 0b0000, 0b1111, - processor_ids=[1, 2], link_ids=[], defaultable=False)) + MulticastRoutingEntry(0b0000, 0b1111, RoutingEntry( + processor_ids=[1, 2], link_ids=[], defaultable=False))) original_table.add_multicast_routing_entry( - MulticastRoutingEntry( - 0b0001, 0b1111, - processor_ids=[0], link_ids=[], defaultable=False)) + MulticastRoutingEntry(0b0001, 0b1111, RoutingEntry( + processor_ids=[0], link_ids=[], defaultable=False))) original_table.add_multicast_routing_entry( - MulticastRoutingEntry( - 0b0101, 0b1111, - processor_ids=[4], link_ids=[], defaultable=False)) + MulticastRoutingEntry(0b0101, 0b1111, RoutingEntry( + processor_ids=[4], link_ids=[], defaultable=False))) original_table.add_multicast_routing_entry( - MulticastRoutingEntry( - 0b1000, 0b1111, - processor_ids=[1, 2], link_ids=[], defaultable=False)) + MulticastRoutingEntry(0b1000, 0b1111, RoutingEntry( + processor_ids=[1, 2], link_ids=[], defaultable=False))) original_table.add_multicast_routing_entry( - MulticastRoutingEntry( - 0b1001, 0b1111, - processor_ids=[0], link_ids=[], defaultable=False)) + MulticastRoutingEntry(0b1001, 0b1111, RoutingEntry( + processor_ids=[0], link_ids=[], defaultable=False))) original_table.add_multicast_routing_entry( - MulticastRoutingEntry( - 0b1110, 0b1111, - processor_ids=[4], link_ids=[], defaultable=False)) + MulticastRoutingEntry(0b1110, 0b1111, RoutingEntry( + processor_ids=[4], link_ids=[], defaultable=False))) original_table.add_multicast_routing_entry( - MulticastRoutingEntry( - 0b1100, 0b1111, - processor_ids=[1, 2], link_ids=[], defaultable=False)) + MulticastRoutingEntry(0b1100, 0b1111, RoutingEntry( + processor_ids=[1, 2], link_ids=[], defaultable=False))) original_table.add_multicast_routing_entry( - MulticastRoutingEntry( - 0b0010, 0b1011, - processor_ids=[4, 5], link_ids=[], defaultable=False)) + MulticastRoutingEntry(0b0010, 0b1011, RoutingEntry( + processor_ids=[4, 5], link_ids=[], defaultable=False))) original_tables.add_routing_table(original_table) unittest_setup() set_config( From ac61c54cfd1c0104afaa7001b1631557dd7340e1 Mon Sep 17 00:00:00 2001 From: "Christian Y. Brenninkmeijer" Date: Thu, 28 Mar 2024 10:51:19 +0000 Subject: [PATCH 04/10] use MulticastRoutingEntry instead of RTEntry --- .../multicast_routing_tables.py | 2 +- .../uncompressed_multicast_routing_table.py | 2 +- .../valid_routes_checker.py | 4 +- .../operations/router_compressors/__init__.py | 3 +- .../router_compressors/abstract_compressor.py | 9 +-- .../ordered_covering.py | 62 ++++++++------- .../utils.py | 11 +-- .../router_compressors/pair_compressor.py | 33 ++++---- .../router_compressors/ranged_compressor.py | 6 +- .../routing_compression_checker.py | 2 +- .../operations/router_compressors/rt_entry.py | 78 ------------------- .../basic_routing_table_generator.py | 2 +- .../algorithm_utilities/routes_format.py | 2 +- 13 files changed, 73 insertions(+), 143 deletions(-) delete mode 100644 pacman/operations/router_compressors/rt_entry.py diff --git a/pacman/model/routing_tables/multicast_routing_tables.py b/pacman/model/routing_tables/multicast_routing_tables.py index d42bcd529..0f612150b 100644 --- a/pacman/model/routing_tables/multicast_routing_tables.py +++ b/pacman/model/routing_tables/multicast_routing_tables.py @@ -149,7 +149,7 @@ def to_json(router_table: MulticastRoutingTables) -> JsonObjectArray: "y": routing_table.y, "entries": [ { - "key": entry.routing_entry_key, + "key": entry.key, "mask": entry.mask, "defaultable": entry.defaultable, "spinnaker_route": entry.spinnaker_route diff --git a/pacman/model/routing_tables/uncompressed_multicast_routing_table.py b/pacman/model/routing_tables/uncompressed_multicast_routing_table.py index a737f37cc..219dffd53 100644 --- a/pacman/model/routing_tables/uncompressed_multicast_routing_table.py +++ b/pacman/model/routing_tables/uncompressed_multicast_routing_table.py @@ -71,7 +71,7 @@ def __init__( @overrides(AbstractMulticastRoutingTable.add_multicast_routing_entry) def add_multicast_routing_entry( self, multicast_routing_entry: MulticastRoutingEntry): - routing_entry_key = multicast_routing_entry.routing_entry_key + routing_entry_key = multicast_routing_entry.key mask = multicast_routing_entry.mask tuple_key = (routing_entry_key, mask) diff --git a/pacman/operations/multi_cast_router_check_functionality/valid_routes_checker.py b/pacman/operations/multi_cast_router_check_functionality/valid_routes_checker.py index 87cf44f1b..97d0d3e30 100644 --- a/pacman/operations/multi_cast_router_check_functionality/valid_routes_checker.py +++ b/pacman/operations/multi_cast_router_check_functionality/valid_routes_checker.py @@ -262,7 +262,7 @@ def _check_all_keys_hit_entry( bad_entries = list() for atom_id in range(0, n_atoms): key = base_key + atom_id - if entry.mask & key != entry.routing_entry_key: + if entry.mask & key != entry.key: bad_entries.append(key) return bad_entries @@ -398,7 +398,7 @@ def _locate_routing_entry( found_entry = None for entry in current_router.multicast_routing_entries: key_combo = entry.mask & key - e_key = entry.routing_entry_key + e_key = entry.key if key_combo == e_key: if found_entry is None: found_entry = entry diff --git a/pacman/operations/router_compressors/__init__.py b/pacman/operations/router_compressors/__init__.py index 5cc26f93a..115db569a 100644 --- a/pacman/operations/router_compressors/__init__.py +++ b/pacman/operations/router_compressors/__init__.py @@ -13,9 +13,8 @@ # limitations under the License. from .abstract_compressor import AbstractCompressor -from .rt_entry import RTEntry from .pair_compressor import pair_compressor from .ranged_compressor import range_compressor, RangeCompressor -__all__ = ['AbstractCompressor', 'RTEntry', 'pair_compressor', +__all__ = ['AbstractCompressor', 'pair_compressor', 'RangeCompressor', 'range_compressor'] diff --git a/pacman/operations/router_compressors/abstract_compressor.py b/pacman/operations/router_compressors/abstract_compressor.py index c568b2ee8..001416ff2 100644 --- a/pacman/operations/router_compressors/abstract_compressor.py +++ b/pacman/operations/router_compressors/abstract_compressor.py @@ -22,12 +22,12 @@ from spinn_utilities.config_holder import get_config_bool from spinn_utilities.log import FormatAdapter from spinn_utilities.progress_bar import ProgressBar +from spinn_machine import MulticastRoutingEntry from pacman.data import PacmanDataView from pacman.model.routing_tables import ( CompressedMulticastRoutingTable, MulticastRoutingTables) from pacman.exceptions import MinimisationFailedError from pacman.model.routing_tables import UnCompressedMulticastRoutingTable -from .rt_entry import RTEntry logger = FormatAdapter(logging.getLogger(__name__)) @@ -69,12 +69,12 @@ def compress_all_tables(self) -> MulticastRoutingTables: @abstractmethod def compress_table( self, router_table: UnCompressedMulticastRoutingTable) -> List[ - RTEntry]: + MulticastRoutingEntry]: """ :param UnCompressedMulticastRoutingTable router_table: Original routing table for a single chip :return: Raw compressed routing table entries for the same chip - :rtype: list(RTEntry) + :rtype: list(MulticastRoutingEntry) """ raise NotImplementedError @@ -108,8 +108,7 @@ def compress_tables( new_table = CompressedMulticastRoutingTable(table.x, table.y) for entry in compressed_table: - new_table.add_multicast_routing_entry( - entry.to_multicast_routing_entry()) + new_table.add_multicast_routing_entry(entry) if new_table.number_of_entries > target: self._problems += ( f"(x:{new_table.x},y:{new_table.y})=" diff --git a/pacman/operations/router_compressors/ordered_covering_router_compressor/ordered_covering.py b/pacman/operations/router_compressors/ordered_covering_router_compressor/ordered_covering.py index 8e0a5618e..f6788c469 100644 --- a/pacman/operations/router_compressors/ordered_covering_router_compressor/ordered_covering.py +++ b/pacman/operations/router_compressors/ordered_covering_router_compressor/ordered_covering.py @@ -22,10 +22,12 @@ from spinn_utilities.config_holder import get_config_bool from spinn_utilities.timer import Timer +from spinn_machine import MulticastRoutingEntry, RoutingEntry + from pacman.exceptions import MinimisationFailedError from pacman.utilities.constants import FULL_MASK from pacman.model.routing_tables import UnCompressedMulticastRoutingTable -from pacman.operations.router_compressors import (AbstractCompressor, RTEntry) +from pacman.operations.router_compressors import AbstractCompressor from pacman.model.routing_tables import MulticastRoutingTables from pacman.data.pacman_data_view import PacmanDataView @@ -63,7 +65,7 @@ def __init__(self) -> None: def compress_table( self, router_table: UnCompressedMulticastRoutingTable - ) -> List[RTEntry]: + ) -> List[MulticastRoutingEntry]: """ Reduce the size of a routing table by merging together entries where possible and by removing any remaining default routes. @@ -74,7 +76,7 @@ def compress_table( Routing table to be merged. :return: The compressed table entries - :rtype: list(RTEntry) + :rtype: list(MulticastRoutingEntry) :raises MinimisationFailedError: If the smallest table that can be produced is larger than the space usually available in a hardware router table. @@ -86,23 +88,21 @@ def compress_table( else: chip = PacmanDataView.get_chip_at(router_table.x, router_table.y) target_length = chip.router.n_available_multicast_entries - # Convert into a list of entries - routing_table = list(map( - RTEntry.from_multicast_routing_entry, - router_table.multicast_routing_entries)) # Compress the router entries table, _ = ordered_covering( - routing_table=routing_table, target_length=target_length, + routing_table=router_table.multicast_routing_entries, + target_length=target_length, aliases={}, no_raise=True, time_to_run_for=None) # Strip the defaultable routes return remove_default_routes(table, target_length) def ordered_covering( - routing_table: List[RTEntry], target_length: Optional[int], + routing_table: List[MulticastRoutingEntry], + target_length: Optional[int], aliases: _Aliases, *, no_raise: bool = False, time_to_run_for: Optional[float] = None - ) -> Tuple[List[RTEntry], _Aliases]: + ) -> Tuple[List[MulticastRoutingEntry], _Aliases]: """ Reduce the size of a routing table by merging together entries where possible. @@ -121,7 +121,7 @@ def ordered_covering( at least orthogonal (i.e., there are no two entries which would match the same key) and reorderable. - :param list(RTEntry) routing_table: + :param list(MulticastRoutingEntry) routing_table: Routing entries to be merged. :param target_length: Target length of the routing table; the minimisation procedure will @@ -146,7 +146,8 @@ def ordered_covering( If supplied, a maximum number of seconds to run for before giving an error. May only be obeyed approximately. :return: new routing table, A new _aliases dictionary. - :rtype: tuple(list(RTEntry), dict(tuple(int,int), set(tuple(int,int)))) + :rtype: tuple(list(MulticastRoutingEntry), + dict(tuple(int,int), set(tuple(int,int)))) :raises MinimisationFailedError: If the smallest table that can be produced is larger than ``target_length``. @@ -217,7 +218,7 @@ def get_generality(key: int, mask: int) -> int: return bin(xs).count("1") -def _get_entry_generality(entry: Union[RTEntry, _Merge]) -> int: +def _get_entry_generality(entry: Union[MulticastRoutingEntry, _Merge]) -> int: """ Actually useful-in-this-file form of get_generality. """ @@ -225,12 +226,14 @@ def _get_entry_generality(entry: Union[RTEntry, _Merge]) -> int: def _get_best_merge( - routing_table: List[RTEntry], aliases: _ROAliases) -> '_Merge': + routing_table: List[MulticastRoutingEntry], + aliases: _ROAliases) -> '_Merge': """ Inspect all possible merges for the routing table and return the merge which would combine the greatest number of entries. - :param RTEntry routing_table: Routing entries to be merged. + :param MulticastRoutingEntry routing_table: + Routing entries to be merged. :param aliases: Dictionary of which keys and masks in the routing table are combinations of other (now removed) keys and masks; this allows us to @@ -268,11 +271,13 @@ def _get_best_merge( return best_merge -def _get_all_merges(routing_table: List[RTEntry]) -> Iterable['_Merge']: +def _get_all_merges(routing_table: List[MulticastRoutingEntry] + ) -> Iterable['_Merge']: """ Get possible sets of entries to merge. - :param list(RTEntry) routing_table: Routing entries to be merged. + :param list(MulticastRoutingEntry) routing_table: + Routing entries to be merged. :rtype: iterable(_Merge) """ # Memorise entries that have been considered as part of a merge @@ -322,10 +327,10 @@ class _Merge(object): # Whether this merge is defaultable "defaultable"] - def __init__(self, routing_table: List[RTEntry], + def __init__(self, routing_table: List[MulticastRoutingEntry], entries: Collection[int] = frozenset()): """ - :param list(RTEntry) routing_table: + :param list(MulticastRoutingEntry) routing_table: :param set(int) entries: """ # Generate the new key, mask and sources @@ -346,7 +351,7 @@ def __init__(self, routing_table: List[RTEntry], # Compute the goodness of the merge self.goodness: int = len(entries) - 1 - self.routing_table: List[RTEntry] = routing_table + self.routing_table: List[MulticastRoutingEntry] = routing_table self.entries: FrozenSet[int] = frozenset(entries) # Compute the new mask, key and generality @@ -390,7 +395,7 @@ def _get_insertion_index(self) -> int: return pos - def apply(self, aliases: _Aliases) -> List[RTEntry]: + def apply(self, aliases: _Aliases) -> List[MulticastRoutingEntry]: """ Apply the merge to the routing table it is defined against and get a new routing table. @@ -405,17 +410,20 @@ def apply(self, aliases: _Aliases) -> List[RTEntry]: *This dictionary will be updated by this method.* :type aliases: dict(tuple(int, int), set(tuple(int, int)) :return: new routing table - :rtype: list(RTEntry) + :rtype: list(MulticastRoutingEntry) """ # Create a new routing table of the correct size new_size = len(self.routing_table) - len(self.entries) + 1 - new_table: List[Optional[RTEntry]] = [None for _ in range(new_size)] + new_table: List[Optional[MulticastRoutingEntry]] = [ + None for _ in range(new_size)] # Get the new entry - new_entry = RTEntry( + routing_entry = RoutingEntry( spinnaker_route=self.routing_table[ next(iter(self.entries))].spinnaker_route, - key=self.key, mask=self.mask, defaultable=self.defaultable) + defaultable=self.defaultable) + new_entry = MulticastRoutingEntry( + key=self.key, mask=self.mask, routing_entry=routing_entry) our_aliases: Set[_KeyMask] = set() # Iterate through the old table copying entries across @@ -446,7 +454,7 @@ def apply(self, aliases: _Aliases) -> List[RTEntry]: new_table[insert] = new_entry # All entries in new_table are now not None; cast is safe - return cast(List[RTEntry], new_table) + return cast(List[MulticastRoutingEntry], new_table) def _refine_merge( @@ -761,7 +769,7 @@ def _get_covered_keys_and_masks( # and masks would overlap with the key and mask of the merged entry. covered: List[_KeyMask] = list() for entry in merge.routing_table[merge.insertion_index:]: - km = entry.key_mask + km = (entry.key, entry.mask) for key_mask in aliases.get(km, {km}): key, mask = key_mask if intersect(merge.key, merge.mask, key, mask): diff --git a/pacman/operations/router_compressors/ordered_covering_router_compressor/utils.py b/pacman/operations/router_compressors/ordered_covering_router_compressor/utils.py index 49db0bef5..777b6a057 100644 --- a/pacman/operations/router_compressors/ordered_covering_router_compressor/utils.py +++ b/pacman/operations/router_compressors/ordered_covering_router_compressor/utils.py @@ -19,7 +19,7 @@ """ from typing import List, Optional -from pacman.operations.router_compressors import RTEntry +from spinn_machine import MulticastRoutingEntry from pacman.exceptions import MinimisationFailedError @@ -51,13 +51,14 @@ def intersect(key_a: int, mask_a: int, key_b: int, mask_b: int) -> bool: def remove_default_routes( - table: List[RTEntry], target_length: Optional[int], - check_for_aliases: bool = True) -> List[RTEntry]: + table: List[MulticastRoutingEntry], target_length: Optional[int], + check_for_aliases: bool = True) -> List[MulticastRoutingEntry]: """ Remove from the routing table any entries which could be replaced by default routing. - :param list(RTEntry) table: Routing entries to be merged. + :param list(router_table.multicast_routing_entries) table: + Routing entries to be merged. :param target_length: Target length of the routing table; the minimisation procedure will halt once either this target is reached or no further minimisation is @@ -73,7 +74,7 @@ def remove_default_routes( If ``False``, the alias-check is skipped resulting in O(N) runtime. This option should only be used if the supplied table is guaranteed not to contain any aliased entries. - :rtype: list(RTEntry) + :rtype: list(MulticastRoutingEntry) :raises MinimisationFailedError: If the smallest table that can be produced is larger than ``target_length``. diff --git a/pacman/operations/router_compressors/pair_compressor.py b/pacman/operations/router_compressors/pair_compressor.py index d9ef4dcea..a9c463a94 100644 --- a/pacman/operations/router_compressors/pair_compressor.py +++ b/pacman/operations/router_compressors/pair_compressor.py @@ -14,13 +14,12 @@ import functools from typing import List, Tuple, cast -from spinn_machine import MulticastRoutingEntry +from spinn_machine import MulticastRoutingEntry, RoutingEntry from pacman.data import PacmanDataView from pacman.exceptions import PacmanElementAllocationException from pacman.model.routing_tables import ( MulticastRoutingTables, AbstractMulticastRoutingTable) from .abstract_compressor import AbstractCompressor -from .rt_entry import RTEntry def pair_compressor( @@ -171,7 +170,7 @@ class _PairCompressor(AbstractCompressor): def __init__(self, ordered: bool = True, accept_overflow: bool = False, c_sort: bool = False): super().__init__(ordered, accept_overflow) - self._all_entries: List[RTEntry] = [] + self._all_entries: List[MulticastRoutingEntry] = [] self._c_sort = c_sort self._write_index = 0 self._max_index = 0 @@ -182,7 +181,8 @@ def __init__(self, ordered: bool = True, accept_overflow: bool = False, self._routes_count = 0 def _compare_entries( - self, route_a_entry: RTEntry, route_b_entry: RTEntry) -> int: + self, route_a_entry: MulticastRoutingEntry, + route_b_entry: MulticastRoutingEntry) -> int: """ Compares two entries for sorting based on the frequency of each entry's SpiNNaker route. @@ -195,8 +195,8 @@ def _compare_entries( For two different routes but with the same frequency order is based on the (currently arbitrary) order they are in the self._routes table - :param RTEntry route_a_entry: - :param RTEntry route_b_entry: + :param MulticastRoutingEntry route_a_entry: + :param MulticastRoutingEntry route_b_entry: :return: ordering value (-1, 0, 1) :rtype: int """ @@ -353,9 +353,10 @@ def _find_merge(self, left: int, index: int) -> bool: self._all_entries[check].mask, m_key, m_mask): return False - self._all_entries[left] = RTEntry( - m_key, m_mask, defaultable, - self._all_entries[left].spinnaker_route) + self._all_entries[left] = MulticastRoutingEntry( + m_key, m_mask, RoutingEntry( + defaultable=defaultable, + spinnaker_route=self._all_entries[left].spinnaker_route)) return True def _compress_by_route(self, left: int, right: int): @@ -403,7 +404,7 @@ def _update_frequency(self, entry: MulticastRoutingEntry): def compress_table( self, router_table: AbstractMulticastRoutingTable - ) -> List[RTEntry]: + ) -> List[MulticastRoutingEntry]: """ Compresses all the entries for a single table. @@ -417,7 +418,7 @@ def compress_table( :param UnCompressedMulticastRoutingTable router_table: Original Routing table for a single chip :return: Compressed routing table for the same chip - :rtype: list(RTEntry) + :rtype: list(MulticastRoutingEntry) """ # Split the entries into buckets based on spinnaker_route self._all_entries = [] @@ -429,8 +430,7 @@ def compress_table( self._routes_frequency = n_routes * [0] for entry in router_table.multicast_routing_entries: - self._all_entries.append( - RTEntry.from_multicast_routing_entry(entry)) + self._all_entries.append(entry) self._update_frequency(entry) if self._c_sort: @@ -493,15 +493,16 @@ def intersect(key_a: int, mask_a: int, key_b: int, mask_b: int) -> bool: """ return (key_a & mask_b) == (key_b & mask_a) - def merge(self, entry1: RTEntry, entry2: RTEntry) -> Tuple[int, int, bool]: + def merge(self, entry1: MulticastRoutingEntry, + entry2: MulticastRoutingEntry) -> Tuple[int, int, bool]: """ Merges two entries/triples into one that covers both. The assumption is that they both have the same known spinnaker_route - :param ~pacman.operations.router_compressors.RTEntry entry1: + :param MulticastRoutingEntry entry1: Key, Mask, defaultable from the first entry - :param ~pacman.operations.router_compressors.RTEntry entry2: + :param MulticastRoutingEntry entry2: Key, Mask, defaultable from the second entry :return: Key, Mask, defaultable from merged entry :rtype: tuple(int, int, bool) diff --git a/pacman/operations/router_compressors/ranged_compressor.py b/pacman/operations/router_compressors/ranged_compressor.py index e875eac92..0171f290c 100644 --- a/pacman/operations/router_compressors/ranged_compressor.py +++ b/pacman/operations/router_compressors/ranged_compressor.py @@ -96,7 +96,7 @@ def compress_table( # Step 1 get the entries and make sure they are sorted by key self._entries = list(uncompressed.multicast_routing_entries) - self._entries.sort(key=lambda x: x.routing_entry_key) + self._entries.sort(key=lambda x: x.key) if not self._validate(): return uncompressed @@ -141,7 +141,7 @@ def _get_key(self, index: int) -> int: if index == len(self._entries): return sys.maxsize entry = self._entries[index] - return entry.routing_entry_key & entry.mask + return entry.key & entry.mask def _get_endpoint(self, index: int) -> int: """ @@ -155,7 +155,7 @@ def _get_endpoint(self, index: int) -> int: return 0 entry = self._entries[index] # return the key plus the mask flipping ones and zeros - return (entry.routing_entry_key | ~entry.mask) & 0xFFFFFFFF + return (entry.key | ~entry.mask) & 0xFFFFFFFF def _merge_range(self, first: int, last: int): while True: diff --git a/pacman/operations/router_compressors/routing_compression_checker.py b/pacman/operations/router_compressors/routing_compression_checker.py index d3bb521eb..bca42cb34 100644 --- a/pacman/operations/router_compressors/routing_compression_checker.py +++ b/pacman/operations/router_compressors/routing_compression_checker.py @@ -40,7 +40,7 @@ def codify(route: MulticastRoutingEntry, length: int = 32) -> str: :rtype: str """ mask = route.mask - key = route.routing_entry_key + key = route.key # Check for validity: key 1 with mask 0 is an error bad = key & ~mask if bad: diff --git a/pacman/operations/router_compressors/rt_entry.py b/pacman/operations/router_compressors/rt_entry.py deleted file mode 100644 index bb009b5e1..000000000 --- a/pacman/operations/router_compressors/rt_entry.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (c) 2017 The University of Manchester -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -from __future__ import annotations -from spinn_machine import MulticastRoutingEntry, RoutingEntry - - -class RTEntry(object): - """ - The internal representation of router table entries used by the router - table compressors. Essentially a tuple and compacted version of - :py:class:`~spinn_machine.MulticastRoutingEntry`. - - :param key: The key - :type key: int - :param mask: The mask - :type mask: int - :param defaultable: Whether the route may be handled by default routing - :type defaultable: bool - :param spinnaker_route: The route - :type spinnaker_route: int - :param key_mask: The key,mask pair - :type key_mask: tuple(int,int) - """ - __slots__ = ("key", "mask", "defaultable", "spinnaker_route", "key_mask") - - def __init__(self, key: int, mask: int, defaultable: bool, - spinnaker_route: int): - """ - :param int key: - :param int mask: - :param bool defaultable: - :param int spinnaker_route: - """ - self.key = key - self.mask = mask - self.defaultable = defaultable - self.spinnaker_route = spinnaker_route - self.key_mask = (key, mask) - - def __str__(self): - return f"{self.key} {self.mask} {self.spinnaker_route}" - - def __eq__(self, other): - if not isinstance(other, RTEntry): - return False - return (self.key == other.key and self.mask == other.mask and - self.spinnaker_route == other.spinnaker_route) - - @staticmethod - def from_multicast_routing_entry(source: MulticastRoutingEntry) -> RTEntry: - """ - :param ~spinn_machine.MulticastRoutingEntry source: - :rtype: RTEntry - """ - # Yes I know using _params is ugly but this is for speed - # pylint:disable=protected-access - return RTEntry( - source._routing_entry_key, source._mask, source.defaultable, - source.spinnaker_route) - - def to_multicast_routing_entry(self) -> MulticastRoutingEntry: - """ - :rtype: ~spinn_machine.MulticastRoutingEntry - """ - return MulticastRoutingEntry( - self.key, self.mask, - RoutingEntry(spinnaker_route=self.spinnaker_route)) diff --git a/pacman/operations/routing_table_generators/basic_routing_table_generator.py b/pacman/operations/routing_table_generators/basic_routing_table_generator.py index 2a4c8f4ea..dc125f799 100644 --- a/pacman/operations/routing_table_generators/basic_routing_table_generator.py +++ b/pacman/operations/routing_table_generators/basic_routing_table_generator.py @@ -67,7 +67,7 @@ def __create_routing_table( continue entry = partitions_in_table[source_vertex, partition_id] table.add_multicast_routing_entry(MulticastRoutingEntry( - routing_entry_key=r_info.key_and_mask.key_combo, + key=r_info.key_and_mask.key_combo, mask=r_info.key_and_mask.mask, routing_entry=entry)) return table diff --git a/pacman/utilities/algorithm_utilities/routes_format.py b/pacman/utilities/algorithm_utilities/routes_format.py index c5c36b423..85d09ed4c 100644 --- a/pacman/utilities/algorithm_utilities/routes_format.py +++ b/pacman/utilities/algorithm_utilities/routes_format.py @@ -63,7 +63,7 @@ def format_route(entry: MulticastRoutingEntry) -> str: :param ~spinn_machine.MulticastRoutingEntry entry: :rtype: str """ - key = entry.routing_entry_key + key = entry.key mask = entry.mask route = _reduce_route_value(entry.processor_ids, entry.link_ids) return (f"0x{key:08X} 0x{mask:08X} 0x{route:08X} {entry.defaultable:<7} " From f7b0158c0b3b9709420bc08e4e88aa6f0beb2e37 Mon Sep 17 00:00:00 2001 From: "Christian Y. Brenninkmeijer" Date: Thu, 28 Mar 2024 11:23:29 +0000 Subject: [PATCH 05/10] expose processor and link ids --- .../router_compressors/routing_compression_checker.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pacman/operations/router_compressors/routing_compression_checker.py b/pacman/operations/router_compressors/routing_compression_checker.py index bca42cb34..cf3afd530 100644 --- a/pacman/operations/router_compressors/routing_compression_checker.py +++ b/pacman/operations/router_compressors/routing_compression_checker.py @@ -131,11 +131,11 @@ def compare_route( c_route = compressed_dict[c_code] if f is not None: f.write(f"\t\t{format_route(c_route)}\n") - if o_route.entry.processor_ids != c_route.entry.processor_ids: + if o_route.processor_ids != c_route.processor_ids: raise PacmanRoutingException( f"Compressed route {c_route} covers original route " f"{o_route} but has a different processor_ids.") - if o_route.entry.link_ids != c_route.entry.link_ids: + if o_route.link_ids != c_route.link_ids: raise PacmanRoutingException( f"Compressed route {c_route} covers original route " f"{o_route} but has a different link_ids.") From d6b30ef8a21ae1bc4dca9cb5c74667f6b7cee4f2 Mon Sep 17 00:00:00 2001 From: "Christian Y. Brenninkmeijer" Date: Thu, 28 Mar 2024 16:02:06 +0000 Subject: [PATCH 06/10] when given links autodetect defaultable. --- .../test_routing_tables_model.py | 22 ++++++++----------- .../test_compressors.py | 16 +++++++------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/unittests/model_tests/routing_table_tests/test_routing_tables_model.py b/unittests/model_tests/routing_table_tests/test_routing_tables_model.py index f7a519a54..b7b4413e8 100644 --- a/unittests/model_tests/routing_table_tests/test_routing_tables_model.py +++ b/unittests/model_tests/routing_table_tests/test_routing_tables_model.py @@ -46,7 +46,7 @@ def test_new_multicast_routing_table_entry(self): proc_ids = range(18) link_ids = range(6) MulticastRoutingEntry(key_combo, mask, RoutingEntry( - processor_ids=proc_ids, link_ids=link_ids, defaultable=True)) + processor_ids=proc_ids, link_ids=link_ids)) def test_new_multicast_routing_table(self): """ @@ -65,8 +65,7 @@ def test_new_multicast_routing_table(self): for i in range(5): multicast_entries.append(MulticastRoutingEntry( key_combo + i, mask + i, - RoutingEntry(processor_ids=proc_ids, link_ids=link_ids, - defaultable=True))) + RoutingEntry(processor_ids=proc_ids, link_ids=link_ids))) mrt = UnCompressedMulticastRoutingTable(0, 0, multicast_entries) self.assertEqual(mrt.x, 0) self.assertEqual(mrt.y, 0) @@ -98,15 +97,13 @@ def test_new_multicast_routing_table_duplicate_entry(self): for i in range(5): multicast_entries.append(MulticastRoutingEntry( key_combo + i, mask + i, - RoutingEntry(processor_ids=proc_ids, link_ids=link_ids, - defaultable=True))) + RoutingEntry(processor_ids=proc_ids, link_ids=link_ids))) mrt = UnCompressedMulticastRoutingTable(0, 0, multicast_entries) # We can't add an entry with the same key but different route with self.assertRaises(PacmanAlreadyExistsException): mrt.add_multicast_routing_entry(MulticastRoutingEntry( key_combo, mask, - RoutingEntry(processor_ids=[], link_ids=link_ids, - defaultable=True))) + RoutingEntry(processor_ids=[], link_ids=link_ids))) def test_new_multicast_routing_table_duplicate_key_combo(self): @@ -122,8 +119,7 @@ def test_new_multicast_routing_table_duplicate_key_combo(self): for i in range(5): multicast_entries.append(MulticastRoutingEntry( key_combo, mask, RoutingEntry( - processor_ids=proc_ids, link_ids=link_ids, - defaultable=True))) + processor_ids=proc_ids, link_ids=link_ids))) # We can add entries that are exactly the same UnCompressedMulticastRoutingTable(0, 0, multicast_entries) @@ -138,10 +134,10 @@ def test_new_multicast_routing_tables(self): link_ids.append(i) multicast_entries1 = MulticastRoutingEntry( key_combo, mask, RoutingEntry( - processor_ids=proc_ids, link_ids=link_ids, defaultable=True)) + processor_ids=proc_ids, link_ids=link_ids)) multicast_entries2 = MulticastRoutingEntry( key_combo - 1, mask - 1, RoutingEntry( - processor_ids=proc_ids, link_ids=link_ids, defaultable=True)) + processor_ids=proc_ids, link_ids=link_ids)) mrt = list() t1 = UnCompressedMulticastRoutingTable(0, 0, [multicast_entries1]) @@ -179,11 +175,11 @@ def test_add_routing_table_for_duplicate_chip(self): link_ids.append(i) multicast_entries1 = MulticastRoutingEntry( key_combo, mask, RoutingEntry( - processor_ids=proc_ids, link_ids=link_ids, defaultable=True)) + processor_ids=proc_ids, link_ids=link_ids)) multicast_entries2 = MulticastRoutingEntry( key_combo - 1, mask, RoutingEntry( - processor_ids=proc_ids, link_ids=link_ids, defaultable=True)) + processor_ids=proc_ids, link_ids=link_ids)) mrt = list() mrt.append( UnCompressedMulticastRoutingTable(3, 0, [multicast_entries1])) diff --git a/unittests/operations_tests/router_compressor_tests/test_compressors.py b/unittests/operations_tests/router_compressor_tests/test_compressors.py index 00dd9fdc3..36cc57365 100644 --- a/unittests/operations_tests/router_compressor_tests/test_compressors.py +++ b/unittests/operations_tests/router_compressor_tests/test_compressors.py @@ -35,28 +35,28 @@ def setUp(self): original_table = UnCompressedMulticastRoutingTable(x=0, y=0) original_table.add_multicast_routing_entry( MulticastRoutingEntry(0b0000, 0b1111, RoutingEntry( - processor_ids=[1, 2], link_ids=[], defaultable=False))) + processor_ids=[1, 2], link_ids=[]))) original_table.add_multicast_routing_entry( MulticastRoutingEntry(0b0001, 0b1111, RoutingEntry( - processor_ids=[0], link_ids=[], defaultable=False))) + processor_ids=[0], link_ids=[]))) original_table.add_multicast_routing_entry( MulticastRoutingEntry(0b0101, 0b1111, RoutingEntry( - processor_ids=[4], link_ids=[], defaultable=False))) + processor_ids=[4], link_ids=[]))) original_table.add_multicast_routing_entry( MulticastRoutingEntry(0b1000, 0b1111, RoutingEntry( - processor_ids=[1, 2], link_ids=[], defaultable=False))) + processor_ids=[1, 2], link_ids=[]))) original_table.add_multicast_routing_entry( MulticastRoutingEntry(0b1001, 0b1111, RoutingEntry( - processor_ids=[0], link_ids=[], defaultable=False))) + processor_ids=[0], link_ids=[]))) original_table.add_multicast_routing_entry( MulticastRoutingEntry(0b1110, 0b1111, RoutingEntry( - processor_ids=[4], link_ids=[], defaultable=False))) + processor_ids=[4], link_ids=[]))) original_table.add_multicast_routing_entry( MulticastRoutingEntry(0b1100, 0b1111, RoutingEntry( - processor_ids=[1, 2], link_ids=[], defaultable=False))) + processor_ids=[1, 2], link_ids=[]))) original_table.add_multicast_routing_entry( MulticastRoutingEntry(0b0010, 0b1011, RoutingEntry( - processor_ids=[4, 5], link_ids=[], defaultable=False))) + processor_ids=[4, 5], link_ids=[]))) original_tables.add_routing_table(original_table) unittest_setup() set_config( From b1e263371972d0176006984bd0baf69095ac1bb8 Mon Sep 17 00:00:00 2001 From: "Christian Y. Brenninkmeijer" Date: Thu, 28 Mar 2024 16:33:30 +0000 Subject: [PATCH 07/10] flake8 --- pacman/model/routing_tables/multicast_routing_tables.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pacman/model/routing_tables/multicast_routing_tables.py b/pacman/model/routing_tables/multicast_routing_tables.py index 0f612150b..f9e1305c0 100644 --- a/pacman/model/routing_tables/multicast_routing_tables.py +++ b/pacman/model/routing_tables/multicast_routing_tables.py @@ -182,7 +182,8 @@ def from_json(j_router: Union[str, JsonObjectArray]) -> MulticastRoutingTables: table = UnCompressedMulticastRoutingTable(x, y) tables.add_routing_table(table) for j_entry in cast(JsonObjectArray, j_table["entries"]): - entry = RoutingEntry(defaultable=cast(bool, j_entry["defaultable"]), + entry = RoutingEntry( + defaultable=cast(bool, j_entry["defaultable"]), spinnaker_route=cast(int, j_entry["spinnaker_route"])) table.add_multicast_routing_entry(MulticastRoutingEntry( cast(int, j_entry["key"]), cast(int, j_entry["mask"]), entry)) From a23dc45c5948e16cfabf92847c4b5b17ce41ecb7 Mon Sep 17 00:00:00 2001 From: "Christian Y. Brenninkmeijer" Date: Tue, 2 Apr 2024 07:09:46 +0100 Subject: [PATCH 08/10] flake8 --- .../routing_table_tests/test_routing_tables_model.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/unittests/model_tests/routing_table_tests/test_routing_tables_model.py b/unittests/model_tests/routing_table_tests/test_routing_tables_model.py index b7b4413e8..d3bf597ef 100644 --- a/unittests/model_tests/routing_table_tests/test_routing_tables_model.py +++ b/unittests/model_tests/routing_table_tests/test_routing_tables_model.py @@ -22,8 +22,7 @@ to_json, from_json) from pacman.model.routing_table_by_partition import ( MulticastRoutingTableByPartition) -from pacman.exceptions import ( - PacmanAlreadyExistsException, PacmanInvalidParameterException) +from pacman.exceptions import PacmanAlreadyExistsException from pacman.utilities import file_format_schemas from pacman.model.graphs.machine import SimpleMachineVertex @@ -212,12 +211,10 @@ def test_multicast_routing_table_by_partition_entry(self): with self.assertRaises(SpinnMachineInvalidParameterException): RoutingEntry(link_ids=range(6), processor_ids=range(18), incoming_processor=4, incoming_link=3) - e1 = RoutingEntry(link_ids=range(6), processor_ids=range(18)) e2 = RoutingEntry(link_ids=range(2), processor_ids=range(4), incoming_processor=4) e3 = RoutingEntry(link_ids=range(3, 5), processor_ids=range(12, 16), incoming_link=3) - e4 = RoutingEntry(link_ids=2, processor_ids=16) assert str(e2) == "{0, 1, 2, 3}:{0, 1}" assert str(e3) == "{12, 13, 14, 15}:{3, 4}" e6 = e2.merge( From 07fd15af4ef058100e7a7e61742a90f30aca8a6c Mon Sep 17 00:00:00 2001 From: "Christian Y. Brenninkmeijer" Date: Tue, 2 Apr 2024 07:10:03 +0100 Subject: [PATCH 09/10] flake8 --- .../merged_routing_table_generator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pacman/operations/routing_table_generators/merged_routing_table_generator.py b/pacman/operations/routing_table_generators/merged_routing_table_generator.py index 97414f890..e7aa56f81 100644 --- a/pacman/operations/routing_table_generators/merged_routing_table_generator.py +++ b/pacman/operations/routing_table_generators/merged_routing_table_generator.py @@ -155,8 +155,8 @@ def __mask_has_holes(mask: int) -> bool: def __merged_keys_and_masks( app_r_info: AppVertexRoutingInfo, - entries: List[Tuple[RoutingEntry, - MachineVertexRoutingInfo]]) -> Iterable[MulticastRoutingEntry]: + entries: List[Tuple[RoutingEntry, MachineVertexRoutingInfo]] + ) -> Iterable[MulticastRoutingEntry]: if not entries: return (entry, r_info) = entries[0] From 6e2d0849d8aa8aa9c5ae0978553e0df1421a6287 Mon Sep 17 00:00:00 2001 From: "Christian Y. Brenninkmeijer" Date: Tue, 2 Apr 2024 07:34:29 +0100 Subject: [PATCH 10/10] typing fixes --- .../ordered_covering_router_compressor/ordered_covering.py | 4 ++-- pacman/utilities/algorithm_utilities/routing_tree.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pacman/operations/router_compressors/ordered_covering_router_compressor/ordered_covering.py b/pacman/operations/router_compressors/ordered_covering_router_compressor/ordered_covering.py index f6788c469..383bf3bee 100644 --- a/pacman/operations/router_compressors/ordered_covering_router_compressor/ordered_covering.py +++ b/pacman/operations/router_compressors/ordered_covering_router_compressor/ordered_covering.py @@ -98,7 +98,7 @@ def compress_table( def ordered_covering( - routing_table: List[MulticastRoutingEntry], + routing_table: Iterable[MulticastRoutingEntry], target_length: Optional[int], aliases: _Aliases, *, no_raise: bool = False, time_to_run_for: Optional[float] = None @@ -121,7 +121,7 @@ def ordered_covering( at least orthogonal (i.e., there are no two entries which would match the same key) and reorderable. - :param list(MulticastRoutingEntry) routing_table: + :param iterable(MulticastRoutingEntry) routing_table: Routing entries to be merged. :param target_length: Target length of the routing table; the minimisation procedure will diff --git a/pacman/utilities/algorithm_utilities/routing_tree.py b/pacman/utilities/algorithm_utilities/routing_tree.py index 849aea8a2..b4dd25585 100644 --- a/pacman/utilities/algorithm_utilities/routing_tree.py +++ b/pacman/utilities/algorithm_utilities/routing_tree.py @@ -17,7 +17,7 @@ This representation of a route explicitly describes a tree-structure and the complete path taken by a route. This is used during place and route in -preference to a set of RoutingTableEntry tuples since it is more easily +preference to a set of RoutingEntry tuples since it is more easily verified and more accurately represents the problem at hand. Based on