Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version and testing for Spin2 #257

Merged
merged 60 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from 58 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
e5294fa
version201
Christian-B Apr 3, 2024
24f702a
split virtual machine tests
Christian-B Apr 3, 2024
757dcce
virtual Spin1 1 Chip machine
Christian-B Apr 3, 2024
695b448
version -1 for when it only matters that there is a version
Christian-B Apr 3, 2024
e36ea3d
version201 json
Christian-B Apr 3, 2024
e79a72e
mock any version
Christian-B Apr 3, 2024
7e7aef2
flake8
Christian-B Apr 3, 2024
bdc332b
flake8
Christian-B Apr 3, 2024
3de2599
pylint
Christian-B Apr 3, 2024
58c11c4
ANY_VERSION
Christian-B Apr 3, 2024
05edc85
multiple flexible versions
Christian-B Apr 3, 2024
2875adf
version sets spinnaker links
Christian-B Apr 3, 2024
ac15619
add str and repr
Christian-B Apr 4, 2024
4869a16
test spinnaker links
Christian-B Apr 4, 2024
cf77e45
flake8
Christian-B Apr 4, 2024
79c5e3c
reinsert check for None
Christian-B Apr 4, 2024
fd88e51
tests taken from master's values
Christian-B Apr 5, 2024
dd4fdd6
more tests based on master
Christian-B Apr 5, 2024
e4cd226
move fpga link creation data to Version using a simple list
Christian-B Apr 5, 2024
f65f828
flake8
Christian-B Apr 5, 2024
434d387
FPGA capitalised in comment
Christian-B Apr 5, 2024
84fea24
Merge branch 'links' into version2
Christian-B Apr 5, 2024
20d0064
add in fpga spinnaker/link tests lost in merge
Christian-B Apr 5, 2024
1de8385
Move monitor core count to Machine level
Christian-B Apr 8, 2024
04b585c
size_from_n_cores
Christian-B Apr 8, 2024
cd4766c
virtual machine by n_cores
Christian-B Apr 8, 2024
24ac4b0
mock machine any version
Christian-B Apr 8, 2024
c420276
fix test to consider scamp core
Christian-B Apr 8, 2024
39d3ac2
flake8
Christian-B Apr 8, 2024
54d9747
correct param order
Christian-B Apr 8, 2024
d83ebc8
typing
Christian-B Apr 8, 2024
b9b6c77
typing assert
Christian-B Apr 9, 2024
7384e71
virtual_machine_by
Christian-B Apr 9, 2024
78b6275
remove hard coded values from tests
Christian-B Apr 9, 2024
340ff52
use virtual_machine_by_boards
Christian-B Apr 9, 2024
a082196
flake8
Christian-B Apr 9, 2024
8b7c92b
merge
Christian-B Apr 9, 2024
b38c33e
flake8
Christian-B Apr 9, 2024
dba7f4e
fix tests
Christian-B Apr 9, 2024
d206dec
fix error message
Christian-B Apr 9, 2024
25f0056
use constants for version(s) being tested
Christian-B Apr 10, 2024
1a0c508
move supports_multiple_boards logic to version
Christian-B Apr 10, 2024
8f48a2d
flake8
Christian-B Apr 10, 2024
803d153
removed special virtual_machine methods from init file
Christian-B Apr 10, 2024
c5327d0
spelling
Christian-B Apr 10, 2024
56baf27
check for None
Christian-B Apr 10, 2024
c1af525
fix spelling
Christian-B Apr 11, 2024
c4bf8de
virtual machine by n chips
Christian-B Apr 11, 2024
c1281e6
flake8
Christian-B Apr 12, 2024
2bf70f4
Merge branch 'n_cores' into version2
Christian-B Apr 12, 2024
f2b414a
test lost in merge
Christian-B Apr 12, 2024
4a17c2a
VersionStrings
Christian-B Apr 12, 2024
e89fa3f
VersionStrings as simple Enum
Christian-B Apr 12, 2024
f4030e7
flake8
Christian-B Apr 12, 2024
7e719aa
multiple values moved to VersionString
Christian-B Apr 12, 2024
fb3666e
merge
Christian-B Apr 16, 2024
04ce1aa
merge
Christian-B Apr 16, 2024
605cc1a
fix merge
Christian-B Apr 16, 2024
cdec110
fix add_monitor_core to all_cores
Christian-B Apr 17, 2024
008acdc
Merge branch 'n_cores' into version2
Christian-B Apr 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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_cores: bool):
Christian-B marked this conversation as resolved.
Show resolved Hide resolved
"""
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_cores:
If True assumes that this Vertex will be placed on all cores
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_cores:
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
8 changes: 8 additions & 0 deletions spinn_machine/link_data_objects/spinnaker_link_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,11 @@ def __hash__(self) -> int:
return hash((self._spinnaker_link_id,
self.connected_chip_x, self.connected_chip_y,
self.connected_link, self.board_address))

def __str__(self):
return (f"id:{self._spinnaker_link_id} x:{self.connected_chip_x} "
f"y:{self.connected_chip_y} link:{self._spinnaker_link_id} "
f"{self.board_address}")

def __repr__(self) -> str:
return self.__str__()
129 changes: 35 additions & 94 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 Expand Up @@ -853,22 +838,18 @@ def add_spinnaker_links(self) -> None:
Add SpiNNaker links that are on a given machine depending on the
version of the board.
"""
if self._width == self._height == 2:
chip_0_0 = self[0, 0]
ip_0_0 = chip_0_0.ip_address
assert ip_0_0 is not None
if not chip_0_0.router.is_link(3):
self._add_spinnaker_link(0, 0, 0, 3, ip_0_0)
chip = self.get_chip_at(1, 0)
if chip is not None and not chip.router.is_link(0):
self._add_spinnaker_link(1, 1, 0, 0, ip_0_0)
elif (self._width == self._height == 8) or \
self.multiple_48_chip_boards():
for chip in self._ethernet_connected_chips:
if not chip.router.is_link(4):
ip = chip.ip_address
assert ip is not None
self._add_spinnaker_link(0, chip.x, chip.y, 4, ip)
version = MachineDataView.get_machine_version()
for ethernet in self._ethernet_connected_chips:
ip = ethernet.ip_address
assert ip is not None
for (s_id, (local_x, local_y, link)) in enumerate(
version.spinnaker_links()):
global_x, global_y = self.get_global_xy(
local_x, local_y, ethernet.x, ethernet.y)
chip = self.get_chip_at(global_x, global_y)
if chip is not None and not chip.router.is_link(link):
self._add_spinnaker_link(
s_id, global_x, global_y, link, ip)

def _add_spinnaker_link(
self, spinnaker_link_id: int, x: int, y: int, link: int,
Expand All @@ -883,72 +864,32 @@ def add_fpga_links(self) -> None:
Add FPGA links that are on a given machine depending on the
version of the board.
"""
if self._width == self._height == 8 or self.multiple_48_chip_boards():

for ethernet_connected_chip in self._ethernet_connected_chips:

# the sides of the hexagonal shape of the board are as follows
#
#
# Top
# ####
# #####
# Top Left ###### Right
# #######
# ########
# #######
# Left ###### Bottom Right
# #####
# Bottom
#

# handle the first chip
(ex, ey) = ethernet_connected_chip
ip = ethernet_connected_chip.ip_address
assert ip is not None

# List of start x, start y, first link, second link,
# change in x to next, change in y to next
chip_links = [(7, 3, 0, 5, -1, -1), # Bottom Right
(4, 0, 4, 5, -1, 0), # Bottom
(0, 0, 4, 3, 0, 1), # Left
(0, 3, 2, 3, 1, 1), # Top Left
(4, 7, 2, 1, 1, 0), # Top
(7, 7, 0, 1, 0, -1)] # Right

f = 0
lk = 0
for i, (x, y, l1, l2, dx, dy) in enumerate(chip_links):
for _ in range(4):
fx = (x + ex) % (self._width)
fy = (y + ey) % (self._height)
self._add_fpga_link(f, lk, fx, fy, l1, ip, ex, ey)
f, lk = self._next_fpga_link(f, lk)
if i % 2 == 1:
x += dx
y += dy
fx = (x + ex) % (self._width)
fy = (y + ey) % (self._height)
self._add_fpga_link(f, lk, fx, fy, l2, ip, ex, ey)
f, lk = self._next_fpga_link(f, lk)
if i % 2 == 0:
x += dx
y += dy
version = MachineDataView.get_machine_version()
for ethernet in self._ethernet_connected_chips:
ip = ethernet.ip_address
assert ip is not None
for (local_x, local_y, link, fpga_id, fpga_link) in \
version.fpga_links():
global_x, global_y = self.get_global_xy(
local_x, local_y, ethernet.x, ethernet.y)
chip = self.get_chip_at(global_x, global_y)
if chip is not None:
self._add_fpga_link(fpga_id, fpga_link, chip.x, chip.y,
link, ip, ethernet.x, ethernet.y)

def _add_fpga_link(
self, fpga_id: int, fpga_link: int, x: int, y: int, link: int,
board_address: str, ex: int, ey: int):
# pylint: disable=too-many-arguments
if self.is_chip_at(x, y):
link_data = FPGALinkData(
fpga_link_id=fpga_link, fpga_id=fpga_id,
connected_chip_x=x, connected_chip_y=y,
connected_link=link, board_address=board_address)
self._fpga_links[board_address, fpga_id, fpga_link] = link_data
# Add for the exact chip coordinates
self._fpga_links[(x, y), fpga_id, fpga_link] = link_data
# Add for the Ethernet chip coordinates to allow this to work too
self._fpga_links[(ex, ey), fpga_id, fpga_link] = link_data
link_data = FPGALinkData(
fpga_link_id=fpga_link, fpga_id=fpga_id,
connected_chip_x=x, connected_chip_y=y,
connected_link=link, board_address=board_address)
self._fpga_links[board_address, fpga_id, fpga_link] = link_data
# Add for the exact chip coordinates
self._fpga_links[(x, y), fpga_id, fpga_link] = link_data
# Add for the Ethernet chip coordinates to allow this to work too
self._fpga_links[(ex, ey), fpga_id, fpga_link] = link_data

@staticmethod
def _next_fpga_link(fpga_id: int, fpga_link: int) -> Tuple[int, int]:
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"]
Loading
Loading