Skip to content

Commit

Permalink
merged in master
Browse files Browse the repository at this point in the history
  • Loading branch information
Christian-B committed Apr 19, 2024
2 parents 259b9cc + 3c53f25 commit c6e6a97
Show file tree
Hide file tree
Showing 31 changed files with 2,033 additions and 706 deletions.
1 change: 0 additions & 1 deletion spinn_machine/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@
from .spinnaker_triad_geometry import SpiNNakerTriadGeometry
from .virtual_machine import virtual_machine


__all__ = ["Chip", "CoreSubset", "CoreSubsets",
"FrozenCoreSubsets", "Link", "Machine", "MulticastRoutingEntry",
"Router", "RoutingEntry", "SpiNNakerTriadGeometry",
Expand Down
33 changes: 33 additions & 0 deletions spinn_machine/data/machine_data_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class _MachineDataModel(object):

__slots__ = [
# Data values cached
"_all_monitor_cores",
"_ethernet_monitor_cores",
"_machine",
"_machine_generator",
"_machine_version",
Expand Down Expand Up @@ -73,6 +75,8 @@ def _hard_reset(self) -> None:
This does NOT clear the machine as it may have been asked for before
"""
self._soft_reset()
self._all_monitor_cores: int = 0
self._ethernet_monitor_cores: int = 0
self._machine: Optional[Machine] = None
self._user_accessed_machine = False

Expand Down Expand Up @@ -263,3 +267,32 @@ def get_machine_version(cls) -> AbstractVersion:
if cls.__data._machine_version is None:
cls.__data._machine_version = version_factory()
return cls.__data._machine_version

@classmethod
def get_all_monitor_cores(cls) -> int:
"""
The number of cores on every chip reported to be used by \
monitor vertices.
Ethernet-enabled chips may have more.
Does not include the system core reserved by the machine/ scamp.
:rtype: int
"""
return cls.__data._all_monitor_cores

@classmethod
def get_ethernet_monitor_cores(cls) -> int:
"""
The number of cores on every Ethernet chip reported to be used by \
monitor vertices.
This includes the one returned by get_all_monitor_cores unless for
some reason these are not on Ethernet chips.
Does not include the system core reserved by the machine/ scamp.
:rtype: int
"""
return cls.__data._ethernet_monitor_cores
29 changes: 22 additions & 7 deletions spinn_machine/data/machine_data_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
from spinn_utilities.data.utils_data_writer import UtilsDataWriter
from spinn_utilities.overrides import overrides
from spinn_utilities.log import FormatAdapter
from spinn_machine import Machine, virtual_machine
from spinn_machine import Machine
from spinn_machine.virtual_machine import virtual_machine_by_boards
from .machine_data_view import MachineDataView, _MachineDataModel
logger = FormatAdapter(logging.getLogger(__name__))
__temp_dir = None
Expand Down Expand Up @@ -46,12 +47,7 @@ def _mock_machine(self) -> None:
"""
Method to create a virtual machine in mock mode.
"""
if self.get_machine_version().number == 3:
self.set_machine(virtual_machine(width=2, height=2))
elif self.get_machine_version().number == 5:
self.set_machine(virtual_machine(width=8, height=8))
else:
raise NotImplementedError("Please set machine version")
self.set_machine(virtual_machine_by_boards(1))

@overrides(UtilsDataWriter._setup)
def _setup(self) -> None:
Expand Down Expand Up @@ -109,3 +105,22 @@ def set_machine_generator(self, machine_generator: Callable[[], None]):
if not callable(machine_generator):
raise TypeError("machine_generator must be callable")
self.__data._machine_generator = machine_generator

def add_monitor_core(self, all_chips: bool):
"""
Accepts a simple of the monitor cores to be added.
Called by PacmanDataWriter add_sample_monitor_vertex.
Only affect is to change the numbers reported by the
get_all/ethernet_monitor methods.
:param bool all_chips:
If True assumes that this Vertex will be placed on all chips
including Ethernet ones.
If False assumes that this Vertex type will only be placed on
Ethernet Vertices
"""
self.__data._ethernet_monitor_cores += 1
if all_chips:
self.__data._all_monitor_cores += 1
4 changes: 0 additions & 4 deletions spinn_machine/full_wrap_machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ class FullWrapMachine(Machine):
This class provides the more complex maths to deal with wraps.
"""
@overrides(Machine.multiple_48_chip_boards)
def multiple_48_chip_boards(self) -> bool:
return self._width % 12 == 0 and self._height % 12 == 0

@overrides(Machine.get_xys_by_ethernet)
def get_xys_by_ethernet(
self, ethernet_x: int, ethernet_y: int) -> Iterable[XY]:
Expand Down
4 changes: 0 additions & 4 deletions spinn_machine/horizontal_wrap_machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ class HorizontalWrapMachine(Machine):
This class provides the more complex maths to deal with wraps.
"""

@overrides(Machine.multiple_48_chip_boards)
def multiple_48_chip_boards(self) -> bool:
return self._width % 12 == 0 and (self._height - 4) % 12 == 0

@overrides(Machine.get_xys_by_ethernet)
def get_xys_by_ethernet(
self, ethernet_x: int, ethernet_y: int) -> Iterable[XY]:
Expand Down
32 changes: 17 additions & 15 deletions spinn_machine/json_machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,21 +236,7 @@ def to_json() -> JsonObject:
:rtype: dict
"""
machine = MachineDataView.get_machine()
# Find the standard values for any non-Ethernet chip to use by default
std = None
for chip in machine.chips:
if chip.ip_address is None:
std = _Desc(
monitors=chip.n_processors - chip.n_placable_processors,
router_entries=_int_value(
chip.router.n_available_multicast_entries),
sdram=chip.sdram,
tags=list(chip.tag_ids))
break
else:
raise ValueError("could not compute standard resources")

# find the nth values to use for Ethernet chips
# find the standard values to use for Ethernet chips
chip = machine.boot_chip
eth = _Desc(
monitors=chip.n_processors - chip.n_placable_processors,
Expand All @@ -259,6 +245,22 @@ def to_json() -> JsonObject:
sdram=chip.sdram,
tags=list(chip.tag_ids))

# Find the standard values for any non-Ethernet chip to use by default
if machine.n_chips > 1:
for chip in machine.chips:
if chip.ip_address is None:
std = _Desc(
monitors=chip.n_processors - chip.n_placable_processors,
router_entries=_int_value(
chip.router.n_available_multicast_entries),
sdram=chip.sdram,
tags=list(chip.tag_ids))
break
else:
raise ValueError("could not compute standard resources")
else:
std = eth

# write basic stuff
return {
"height": machine.height,
Expand Down
19 changes: 2 additions & 17 deletions spinn_machine/machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,21 +119,6 @@ def __init__(self, width: int, height: int, chip_core_map: Dict[XY, int],
self._n_router_entries_counter: Counter[int] = Counter()
self._sdram_counter: Counter[int] = Counter()

@abstractmethod
def multiple_48_chip_boards(self) -> bool:
"""
Checks that the width and height correspond to the expected size for a
multi-board machine made up of more than one 48 chip board.
The assumption is that any size machine can be supported but that
only ones with an expected 48 chip board size can have more than one
Ethernet-enabled chip.
:return: True if this machine can have multiple 48 chip boards
:rtype: bool
"""
raise NotImplementedError

@abstractmethod
def get_xys_by_ethernet(
self, ethernet_x: int, ethernet_y: int) -> Iterable[XY]:
Expand Down Expand Up @@ -501,15 +486,15 @@ def validate(self) -> None:
if self._boot_ethernet_address is None:
raise SpinnMachineException(
"no ethernet chip at 0, 0 found")
version = MachineDataView.get_machine_version()
if len(self._ethernet_connected_chips) > 1:
if not self.multiple_48_chip_boards():
if not version.supports_multiple_boards:
raise SpinnMachineException(
f"A {self.wrap} machine of size {self._width}, "
f"{self._height} can not handle multiple ethernet chips")
# The fact that self._boot_ethernet_address is set means there is an
# Ethernet chip and it is at 0,0 so no need to check that

version = MachineDataView.get_machine_version()
for chip in self.chips:
if chip.x < 0:
raise SpinnMachineException(
Expand Down
4 changes: 0 additions & 4 deletions spinn_machine/no_wrap_machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ class NoWrapMachine(Machine):
This class provides the simpler maths that do not deal with wraps.
"""

@overrides(Machine.multiple_48_chip_boards)
def multiple_48_chip_boards(self) -> bool:
return (self._width - 4) % 12 == 0 and (self._height - 4) % 12 == 0

@overrides(Machine.get_xys_by_ethernet)
def get_xys_by_ethernet(
self, ethernet_x: int, ethernet_y: int) -> Iterable[XY]:
Expand Down
2 changes: 2 additions & 0 deletions spinn_machine/spinn_machine.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

[Machine]
version = None
# Used Instead of version if multiple versions should be tested!
versions = None
width = None
height = None
# Note: if json_path is set all other configs for virtual boards are ignored
Expand Down
4 changes: 4 additions & 0 deletions spinn_machine/version/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@
# 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 .version_factory import FIVE, SPIN2_1CHIP, THREE, version_factory

__all__ = ["FIVE", "SPIN2_1CHIP", "THREE", "version_factory"]
69 changes: 67 additions & 2 deletions spinn_machine/version/abstract_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from spinn_utilities.log import FormatAdapter
from spinn_utilities.config_holder import get_config_int_or_none
from spinn_utilities.typing.coords import XY
from spinn_machine.data import MachineDataView
from spinn_machine.exceptions import SpinnMachineException
if TYPE_CHECKING:
from spinn_machine.machine import Machine
Expand Down Expand Up @@ -214,9 +215,9 @@ def chip_core_map(self) -> Mapping[XY, int]:

@property
@abstractmethod
def clock_speed_hz(self) -> int:
def clock_speeds_hz(self) -> List[int]:
"""
The processor clock speed in Hz
The processor clock speeds in Hz this processor can run at
:rtype: int
"""
Expand Down Expand Up @@ -352,6 +353,70 @@ def illegal_ethernet_message(self, x: int, y: int) -> Optional[str]:
"""
raise NotImplementedError

def size_from_n_cores(self, n_cores: int) -> Tuple[int, int]:
"""
Returns the size needed to support this many cores.
Takes into consideration scamp and monitor cores.
Designed for use with virtual boards.
Does not include a safety factor for blacklisted cores or chips.
For real machines a slightly bigger Machine may be needed.
:param int n_cores: Number of None Scamp and monitor cores needed
:rtype: (int, int)
"""
cores_per_board = sum(self.chip_core_map.values())
cores_per_board -= MachineDataView.get_ethernet_monitor_cores()
cores_per_board -= (
(MachineDataView.get_all_monitor_cores() + self.n_scamp_cores)
* self.n_chips_per_board)
# Double minus to round up
return self.size_from_n_boards(-(-n_cores // cores_per_board))

def size_from_n_chips(self, n_chips: int) -> Tuple[int, int]:
"""
Returns the size needed to support this many chips.
Designed for use with virtual boards.
Does not include a safety factor for blacklisted Chips.
For real machines a slightly bigger Machine may be needed.
:param int n_boards:
:rtype: (int, int)
:raises SpinnMachineException:
If multiple boards are needed but not supported
"""
# Double minus to round up
return self.size_from_n_boards(-(-n_chips // self.n_chips_per_board))

def size_from_n_boards(self, n_boards: int) -> Tuple[int, int]:
"""
Returns the size needed to support this many boards.
:param int n_boards:
:rtype: (int, int)
:raises SpinnMachineException:
If multiple boards are needed but not supported
"""
# Override for versions that support multiple boards
if n_boards == 1:
return self.board_shape
if self.supports_multiple_boards:
raise NotImplementedError
raise SpinnMachineException(
f"Version {self} does not support multiple boards")

@property
@abstractmethod
def supports_multiple_boards(self) -> bool:
"""
Specifies if this version allows machines of more than one board
:return:
"""
raise NotImplementedError

def spinnaker_links(self) -> List[Tuple[int, int, int]]:
"""
The list of Local X, Y and link Id to add spinnaker links to
Expand Down
Loading

0 comments on commit c6e6a97

Please sign in to comment.