Skip to content

Commit

Permalink
Merge pull request #261 from SpiNNakerManchester/down_cores
Browse files Browse the repository at this point in the history
more supports for spin2 qx qy and qp
  • Loading branch information
rowleya authored May 13, 2024
2 parents ad45f79 + 3afcc58 commit 03de404
Show file tree
Hide file tree
Showing 7 changed files with 261 additions and 86 deletions.
27 changes: 6 additions & 21 deletions spinn_machine/ignores/ignore_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,16 @@
# 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.
import re
from typing import Any, Iterable, List, Optional, Set, Union
from typing import Any, List, Optional, Set, Union
from typing_extensions import TypeAlias
from spinn_machine.data import MachineDataView

_Intable: TypeAlias = Union[int, str]

TYPICAL_PHYSICAL_VIRTUAL_MAP = {
0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10, 10: 0, 11: 12,
12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18}

CORE_RANGE = re.compile(r"(\d+)-(\d+)")


class IgnoreCore(object):
"""
Expand Down Expand Up @@ -69,21 +68,6 @@ def virtual_p(self) -> int:
else:
return TYPICAL_PHYSICAL_VIRTUAL_MAP[0-self.p]

@staticmethod
def parse_cores(core_string: str) -> Iterable[int]:
"""
Parses the "core" part of a string, which might be a single core,
or otherwise is a range of cores
:param str: A string to parse
:return: A list of cores, which might be just one
:rtype: list(int)
"""
result = CORE_RANGE.fullmatch(core_string)
if result is not None:
return range(int(result.group(1)), int(result.group(2)) + 1)
return (int(core_string),)

@staticmethod
def parse_single_string(downed_core: str) -> List['IgnoreCore']:
"""
Expand Down Expand Up @@ -113,14 +97,15 @@ def parse_single_string(downed_core: str) -> List['IgnoreCore']:
:return: A list of IgnoreCore objects
:rtype: list(IgnoreCore)
"""
version = MachineDataView.get_machine_version()
parts = downed_core.split(",")

if len(parts) == 3:
return [IgnoreCore(parts[0], parts[1], core)
for core in IgnoreCore.parse_cores(parts[2])]
for core in version.parse_cores_string(parts[2])]
elif len(parts) == 4:
return [IgnoreCore(parts[0], parts[1], core, parts[3])
for core in IgnoreCore.parse_cores(parts[2])]
for core in version.parse_cores_string(parts[2])]
else:
raise ValueError(f"Unexpected downed_core: {downed_core}")

Expand Down
81 changes: 80 additions & 1 deletion spinn_machine/version/abstract_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
# limitations under the License.
from __future__ import annotations
import logging
from typing import Dict, List, Optional, Sequence, Tuple, TYPE_CHECKING
import re
from typing import (Dict, Iterable, List, Optional, Sequence, Tuple,
TYPE_CHECKING)

from spinn_utilities.abstract_base import AbstractBase, abstractmethod
from spinn_utilities.log import FormatAdapter
from spinn_utilities.config_holder import get_config_int_or_none
Expand All @@ -25,6 +28,9 @@

logger = FormatAdapter(logging.getLogger(__name__))

CORE_RANGE = re.compile(r"(\d+)-(\d+)")
CORE_SINGLE = re.compile(r"(-*)(\d+)")


class AbstractVersion(object, metaclass=AbstractBase):
"""
Expand Down Expand Up @@ -417,6 +423,7 @@ def supports_multiple_boards(self) -> bool:
"""
raise NotImplementedError

@abstractmethod
def spinnaker_links(self) -> List[Tuple[int, int, int]]:
"""
The list of Local X, Y and link Id to add spinnaker links to
Expand All @@ -428,6 +435,7 @@ def spinnaker_links(self) -> List[Tuple[int, int, int]]:
"""
raise NotImplementedError

@abstractmethod
def fpga_links(self) -> List[Tuple[int, int, int, int, int]]:
"""
The list of Local X, Y, link, fpga_link_id and fpga_id
Expand All @@ -439,6 +447,7 @@ def fpga_links(self) -> List[Tuple[int, int, int, int, int]]:
"""
raise NotImplementedError

@abstractmethod
def quads_maps(self) -> Optional[Dict[int, Tuple[int, int, int]]]:
"""
If applicable returns a map of virtual id to quad qx, qy, qp
Expand All @@ -448,3 +457,73 @@ def quads_maps(self) -> Optional[Dict[int, Tuple[int, int, int]]]:
:rtype: None or dict(int, (int, int, int)
"""
raise NotImplementedError

@abstractmethod
def qx_qy_qp_to_id(self, qx: int, qy: int, qp: int) -> int:
"""
Converts quad coordinates to the core id
:param int qx: quad x coordinate of the core
:param int qy: quad y coordinate of the core
:param int qp: quad p coordinate of the core
:rtype: int
:raises NotImplementedError:
If called on a version that does not support quads
"""
raise NotImplementedError

@abstractmethod
def id_to_qx_qy_qp(self, core_id: int) -> Tuple[int, int, int]:
"""
Converts core id to quad coordinates
:param int core_id: id of the core
:return: (qx, qy, qp)
:rtype: (int, int, int)
:raises NotImplementedError:
If called on a version that does not support quads
"""
raise NotImplementedError

def parse_cores_string(self, core_string: str) -> Iterable[int]:
"""
Parses a string representation of a core or cores
The main usage of this method is to support the cfg down_cores.
This may be a single positive int
which will be taken as the virtual core id
This may be a single negative int
which will be taken as the physical core id
This may be two int values separated by a minus
which will be taken as a range of one of the above
Other formats are version specific.
See version_parse_cores_string
:param str: A string to parse
:return: A list of cores, which might be just one
:rtype: list(int)
"""
result = CORE_SINGLE.fullmatch(core_string)
if result is not None:
return (int(core_string),)

result = CORE_RANGE.fullmatch(core_string)
if result is not None:
return range(int(result.group(1)), int(result.group(2)) + 1)

return self.version_parse_cores_string(core_string)

@abstractmethod
def version_parse_cores_string(self, core_string: str) -> Iterable[int]:
"""
A version specific parsing of the core string
:param str core_string:
:return: A list of cores, which might be just one
:rtype: list(int)
"""
raise NotImplementedError
19 changes: 18 additions & 1 deletion spinn_machine/version/version_spin1.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import List
from typing import List, Iterable, Tuple
from spinn_utilities.abstract_base import AbstractBase
from spinn_utilities.exceptions import ConfigException
from spinn_utilities.overrides import overrides

from spinn_machine.exceptions import SpinnMachineException
from .abstract_version import AbstractVersion


Expand Down Expand Up @@ -54,5 +57,19 @@ def clock_speeds_hz(self) -> List[int]:
def dtcm_bytes(self) -> int:
return 2 ** 16

@overrides(AbstractVersion.quads_maps)
def quads_maps(self) -> None:
return None

@overrides(AbstractVersion.qx_qy_qp_to_id)
def qx_qy_qp_to_id(self, qx: int, qy: int, qp: int) -> int:
raise SpinnMachineException("Not supported in Version 1")

@overrides(AbstractVersion.id_to_qx_qy_qp)
def id_to_qx_qy_qp(self, core_id: int) -> Tuple[int, int, int]:
raise SpinnMachineException("Not supported in Version 1")

@overrides(AbstractVersion.version_parse_cores_string)
def version_parse_cores_string(self, core_string: str) -> Iterable[int]:
raise ConfigException(
f"{core_string} does not represent cores for Version 1 boards")
110 changes: 68 additions & 42 deletions spinn_machine/version/version_spin2.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,56 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Dict, Final, List, Tuple
import re
from typing import Dict, Final, List, Iterable, Tuple

from spinn_utilities.abstract_base import AbstractBase
from spinn_utilities.exceptions import ConfigException
from spinn_utilities.overrides import overrides

from .abstract_version import AbstractVersion

CHIPS_PER_BOARD: Final = {(0, 0): 152}
CORE_QX_QY_QP = re.compile(r"(\d)\.(\d)\.(\d)")
QUAD_MAP = (
{0: (0, 0, 0), 1: (7, 6, 0), 2: (7, 6, 1), 3: (7, 6, 2), 4: (7, 6, 3),
5: (7, 5, 0), 6: (7, 5, 1), 7: (7, 5, 2), 8: (7, 5, 3),
9: (6, 6, 0), 10: (6, 6, 1), 11: (6, 6, 2), 12: (6, 6, 3),
13: (6, 5, 0), 14: (6, 5, 1), 15: (6, 5, 2), 16: (6, 5, 3),
17: (6, 4, 0), 18: (6, 4, 1), 19: (6, 4, 2), 20: (6, 4, 3),
21: (5, 4, 0), 22: (5, 4, 1), 23: (5, 4, 2), 24: (5, 4, 3),
25: (5, 6, 0), 26: (5, 6, 1), 27: (5, 6, 2), 28: (5, 6, 3),
29: (3, 6, 0), 30: (3, 6, 1), 31: (3, 6, 2), 32: (3, 6, 3),
33: (4, 6, 0), 34: (4, 6, 1), 35: (4, 6, 2), 36: (4, 6, 3),
37: (5, 5, 0), 38: (5, 5, 1), 39: (5, 5, 2), 40: (5, 5, 3),
41: (3, 5, 0), 42: (3, 5, 1), 43: (3, 5, 2), 44: (3, 5, 3),
45: (4, 5, 0), 46: (4, 5, 1), 47: (4, 5, 2), 48: (4, 5, 3),
49: (1, 6, 0), 50: (1, 6, 1), 51: (1, 6, 2), 52: (1, 6, 3),
53: (2, 6, 0), 54: (2, 6, 1), 55: (2, 6, 2), 56: (2, 6, 3),
57: (1, 5, 0), 58: (1, 5, 1), 59: (1, 5, 2), 60: (1, 5, 3),
61: (2, 5, 0), 62: (2, 5, 1), 63: (2, 5, 2), 64: (2, 5, 3),
65: (1, 4, 0), 66: (1, 4, 1), 67: (1, 4, 2), 68: (1, 4, 3),
69: (2, 4, 0), 70: (2, 4, 1), 71: (2, 4, 2), 72: (2, 4, 3),
73: (3, 4, 0), 74: (3, 4, 1), 75: (3, 4, 2), 76: (3, 4, 3),
77: (1, 1, 0), 78: (1, 1, 1), 79: (1, 1, 2), 80: (1, 1, 3),
81: (2, 1, 0), 82: (2, 1, 1), 83: (2, 1, 2), 84: (2, 1, 3),
85: (1, 2, 0), 86: (1, 2, 1), 87: (1, 2, 2), 88: (1, 2, 3),
89: (2, 2, 0), 90: (2, 2, 1), 91: (2, 2, 2), 92: (2, 2, 3),
93: (1, 3, 0), 94: (1, 3, 1), 95: (1, 3, 2), 96: (1, 3, 3),
97: (2, 3, 0), 98: (2, 3, 1), 99: (2, 3, 2), 100: (2, 3, 3),
101: (3, 3, 0), 102: (3, 3, 1), 103: (3, 3, 2), 104: (3, 3, 3),
105: (5, 1, 0), 106: (5, 1, 1), 107: (5, 1, 2), 108: (5, 1, 3),
109: (3, 1, 0), 110: (3, 1, 1), 111: (3, 1, 2), 112: (3, 1, 3),
113: (4, 1, 0), 114: (4, 1, 1), 115: (4, 1, 2), 116: (4, 1, 3),
117: (5, 2, 0), 118: (5, 2, 1), 119: (5, 2, 2), 120: (5, 2, 3),
121: (3, 2, 0), 122: (3, 2, 1), 123: (3, 2, 2), 124: (3, 2, 3),
125: (4, 2, 0), 126: (4, 2, 1), 127: (4, 2, 2), 128: (4, 2, 3),
129: (7, 1, 0), 130: (7, 1, 1), 131: (7, 1, 2), 132: (7, 1, 3),
133: (6, 1, 0), 134: (6, 1, 1), 135: (6, 1, 2), 136: (6, 1, 3),
137: (7, 2, 0), 138: (7, 2, 1), 139: (7, 2, 2), 140: (7, 2, 3),
141: (6, 2, 0), 142: (6, 2, 1), 143: (6, 2, 2), 144: (6, 2, 3),
145: (6, 3, 0), 146: (6, 3, 1), 147: (6, 3, 2), 148: (6, 3, 3),
149: (5, 3, 0), 150: (5, 3, 1), 151: (5, 3, 2), 152: (5, 3, 3)})


class VersionSpin2(AbstractVersion, metaclass=AbstractBase):
Expand All @@ -28,11 +70,13 @@ class VersionSpin2(AbstractVersion, metaclass=AbstractBase):
Code for the 1 Chip test Spin2 board versions
"""

__slots__ = ()
__slots__ = ["_reverse_quad_map"]

def __init__(self) -> None:
super().__init__(max_cores_per_chip=153,
max_sdram_per_chip=1073741824)
self._reverse_quad_map: Dict[Tuple[int, int, int], int] = (
dict((v, k) for k, v in QUAD_MAP.items()))

@property
@overrides(AbstractVersion.n_scamp_cores)
Expand All @@ -59,44 +103,26 @@ def clock_speeds_hz(self) -> List[int]:
def dtcm_bytes(self) -> int:
raise NotImplementedError

@overrides(AbstractVersion.quads_maps)
def quads_maps(self) -> Dict[int, Tuple[int, int, int]]:
return (
{0: (0, 0, 0),
1: (7, 6, 0), 2: (7, 6, 1), 3: (7, 6, 2), 4: (7, 6, 3),
5: (7, 5, 0), 6: (7, 5, 1), 7: (7, 5, 2), 8: (7, 5, 3),
9: (6, 6, 0), 10: (6, 6, 1), 11: (6, 6, 2), 12: (6, 6, 3),
13: (6, 5, 0), 14: (6, 5, 1), 15: (6, 5, 2), 16: (6, 5, 3),
17: (6, 4, 0), 18: (6, 4, 1), 19: (6, 4, 2), 20: (6, 4, 3),
21: (5, 4, 0), 22: (5, 4, 1), 23: (5, 4, 2), 24: (5, 4, 3),
25: (5, 6, 0), 26: (5, 6, 1), 27: (5, 6, 2), 28: (5, 6, 3),
29: (3, 6, 0), 30: (3, 6, 1), 31: (3, 6, 2), 32: (3, 6, 3),
33: (4, 6, 0), 34: (4, 6, 1), 35: (4, 6, 2), 36: (4, 6, 3),
37: (5, 5, 0), 38: (5, 5, 1), 39: (5, 5, 2), 40: (5, 5, 3),
41: (3, 5, 0), 42: (3, 5, 1), 43: (3, 5, 2), 44: (3, 5, 3),
45: (4, 5, 0), 46: (4, 5, 1), 47: (4, 5, 2), 48: (4, 5, 3),
49: (1, 6, 0), 50: (1, 6, 1), 51: (1, 6, 2), 52: (1, 6, 3),
53: (2, 6, 0), 54: (2, 6, 1), 55: (2, 6, 2), 56: (2, 6, 3),
57: (1, 5, 0), 58: (1, 5, 1), 59: (1, 5, 2), 60: (1, 5, 3),
61: (2, 5, 0), 62: (2, 5, 1), 63: (2, 5, 2), 64: (2, 5, 3),
65: (1, 4, 0), 66: (1, 4, 1), 67: (1, 4, 2), 68: (1, 4, 3),
69: (2, 4, 0), 70: (2, 4, 1), 71: (2, 4, 2), 72: (2, 4, 3),
73: (3, 4, 0), 74: (3, 4, 1), 75: (3, 4, 2), 76: (3, 4, 3),
77: (1, 1, 0), 78: (1, 1, 1), 79: (1, 1, 2), 80: (1, 1, 3),
81: (2, 1, 0), 82: (2, 1, 1), 83: (2, 1, 2), 84: (2, 1, 3),
85: (1, 2, 0), 86: (1, 2, 1), 87: (1, 2, 2), 88: (1, 2, 3),
89: (2, 2, 0), 90: (2, 2, 1), 91: (2, 2, 2), 92: (2, 2, 3),
93: (1, 3, 0), 94: (1, 3, 1), 95: (1, 3, 2), 96: (1, 3, 3),
97: (2, 3, 0), 98: (2, 3, 1), 99: (2, 3, 2), 100: (2, 3, 3),
101: (3, 3, 0), 102: (3, 3, 1), 103: (3, 3, 2), 104: (3, 3, 3),
105: (5, 1, 0), 106: (5, 1, 1), 107: (5, 1, 2), 108: (5, 1, 3),
109: (3, 1, 0), 110: (3, 1, 1), 111: (3, 1, 2), 112: (3, 1, 3),
113: (4, 1, 0), 114: (4, 1, 1), 115: (4, 1, 2), 116: (4, 1, 3),
117: (5, 2, 0), 118: (5, 2, 1), 119: (5, 2, 2), 120: (5, 2, 3),
121: (3, 2, 0), 122: (3, 2, 1), 123: (3, 2, 2), 124: (3, 2, 3),
125: (4, 2, 0), 126: (4, 2, 1), 127: (4, 2, 2), 128: (4, 2, 3),
129: (7, 1, 0), 130: (7, 1, 1), 131: (7, 1, 2), 132: (7, 1, 3),
133: (6, 1, 0), 134: (6, 1, 1), 135: (6, 1, 2), 136: (6, 1, 3),
137: (7, 2, 0), 138: (7, 2, 1), 139: (7, 2, 2), 140: (7, 2, 3),
141: (6, 2, 0), 142: (6, 2, 1), 143: (6, 2, 2), 144: (6, 2, 3),
145: (6, 3, 0), 146: (6, 3, 1), 147: (6, 3, 2), 148: (6, 3, 3),
149: (5, 3, 0), 150: (5, 3, 1), 151: (5, 3, 2), 152: (5, 3, 3)})
return QUAD_MAP

@overrides(AbstractVersion.qx_qy_qp_to_id)
def qx_qy_qp_to_id(self, qx: int, qy: int, qp: int) -> int:
return self._reverse_quad_map[(qx, qy, qp)]

@overrides(AbstractVersion.id_to_qx_qy_qp)
def id_to_qx_qy_qp(self, core_id: int) -> Tuple[int, int, int]:
return QUAD_MAP[core_id]

@overrides(AbstractVersion.version_parse_cores_string)
def version_parse_cores_string(self, core_string: str) -> Iterable[int]:
result = CORE_QX_QY_QP.fullmatch(core_string)
if result is not None:
qx = int(result.group(1))
qy = int(result.group(2))
qp = int(result.group(3))
return (self.qx_qy_qp_to_id(qx, qy, qp),)

raise ConfigException(
f"{core_string} does not represent cores for Version 2 boards")
Loading

0 comments on commit 03de404

Please sign in to comment.