• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SpiNNakerManchester / SpiNNMachine / 6557632050

18 Oct 2023 07:28AM UTC coverage: 92.803% (-0.7%) from 93.483%
6557632050

push

github

web-flow
Merge pull request #225 from SpiNNakerManchester/roc_part

Typing and minor Changes

743 of 842 branches covered (0.0%)

Branch coverage included in aggregate %.

671 of 671 new or added lines in 34 files covered. (100.0%)

2171 of 2298 relevant lines covered (94.47%)

0.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.77
/spinn_machine/data/machine_data_view.py
1
# Copyright (c) 2021 The University of Manchester
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
6
#
7
#     https://www.apache.org/licenses/LICENSE-2.0
8
#
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
14
from __future__ import annotations
1✔
15
from typing import Callable, Optional, TYPE_CHECKING
1✔
16
from spinn_utilities.typing.coords import XY
1✔
17
from spinn_utilities.data import UtilsDataView
1✔
18
from spinn_machine.exceptions import SpinnMachineException
1✔
19
from spinn_machine.version.version_factory import version_factory
1✔
20
if TYPE_CHECKING:
21
    from spinn_machine.chip import Chip
22
    from spinn_machine.machine import Machine
23
    from spinn_machine.version.abstract_version import AbstractVersion
24
# pylint: disable=protected-access
25

26

27
class _MachineDataModel(object):
1✔
28
    """
29
    Singleton data model.
30

31
    This class should not be accessed directly please use the DataView and
32
    DataWriter classes.
33
    Accessing or editing the data held here directly is NOT SUPPORTED
34

35
    There may be other DataModel classes which sit next to this one and hold
36
    additional data. The DataView and DataWriter classes will combine these
37
    as needed.
38

39
    What data is held where and how can change without notice.
40
    """
41

42
    __singleton: Optional['_MachineDataModel'] = None
1✔
43

44
    __slots__ = [
1✔
45
        # Data values cached
46
        "_machine",
47
        "_machine_generator",
48
        "_machine_version",
49
        "_user_accessed_machine"
50
    ]
51

52
    def __new__(cls) -> '_MachineDataModel':
1✔
53
        if cls.__singleton is not None:
1✔
54
            return cls.__singleton
1✔
55
        # pylint: disable=protected-access
56
        obj = object.__new__(cls)
1✔
57
        cls.__singleton = obj
1✔
58
        obj._clear()
1✔
59
        return obj
1✔
60

61
    def _clear(self) -> None:
1✔
62
        """
63
        Clears out all data
64
        """
65
        self._hard_reset()
1✔
66
        self._machine_generator: Optional[Callable[[], None]] = None
1✔
67
        self._machine_version: Optional[AbstractVersion] = None
1✔
68

69
    def _hard_reset(self) -> None:
1✔
70
        """
71
        Clears out all data that should change after a reset and graph change
72

73
        This does NOT clear the machine as it may have been asked for before
74
        """
75
        self._soft_reset()
1✔
76
        self._machine: Optional[Machine] = None
1✔
77
        self._user_accessed_machine = False
1✔
78

79
    def _soft_reset(self) -> None:
1✔
80
        """
81
        Clears timing and other data that should changed every reset
82
        """
83
        # Holder for any later additions
84

85

86
class MachineDataView(UtilsDataView):
1✔
87
    """
88
    Adds the extra Methods to the View for Machine level.
89

90
    See :py:class:`~spinn_utilities.data.UtilsDataView` for a more detailed
91
    description.
92

93
    This class is designed to only be used directly within the SpiNNMachine
94
    repository as all methods are available to subclasses
95
    """
96

97
    __data = _MachineDataModel()
1✔
98
    __slots__ = ()
1✔
99

100
    # machine methods
101

102
    @classmethod
1✔
103
    def has_machine(cls) -> bool:
1✔
104
        """
105
        Reports if a machine is currently set or can be mocked.
106

107
        Unlike has_existing_machine for unit tests this will return True even
108
        if a Machine has not yet been created
109

110
        :rtype: bool
111
        """
112
        return (cls.__data._machine is not None or cls._is_mocked())
1✔
113

114
    @classmethod
1✔
115
    def has_existing_machine(cls) -> bool:
1✔
116
        """
117
        Reports if a machine is currently already created.
118

119
        Unlike has_machine this method returns false if a machine could be
120
        mocked
121

122
        :rtype: bool
123
        """
124
        return cls.__data._machine is not None
×
125

126
    @classmethod
1✔
127
    def get_machine(cls) -> Machine:
1✔
128
        """
129
        Returns the Machine if it has been set.
130

131
        In Mock mode will create and return a virtual 8 * 8 board
132

133
        :raises ~spinn_utilities.exceptions.SpiNNUtilsException:
134
            If the machine is currently unavailable
135
        :rtype: ~spinn_machine.Machine
136
        """
137
        if cls.is_user_mode():
1✔
138
            if cls.is_soft_reset():
1!
139
                cls.__data._machine = None
×
140
            cls.__data._user_accessed_machine = True
1✔
141
        if cls.__data._machine is None:
1✔
142
            if cls.__data._machine_generator is not None:
1✔
143
                # pylint: disable=not-callable
144
                cls.__data._machine_generator()
1✔
145
                if cls.__data._machine is None:
1!
146
                    raise SpinnMachineException(
×
147
                        "machine generator did not generate machine")
148
                return cls.__data._machine
1✔
149
            raise cls._exception("machine")
1✔
150
        return cls.__data._machine
1✔
151

152
    @classmethod
1✔
153
    def get_chip_at(cls, x: int, y: int) -> Chip:
1✔
154
        """
155
        Gets the chip at (`x`, `y`).
156

157
        Almost Semantic sugar for `get_machine()[x, y]`
158

159
        The method however does not return `None` but rather raises a KeyError
160
        if the chip is not known
161

162
        :param int x:
163
        :param int y:
164
        :rtype: Chip
165
        :raises ~spinn_utilities.exceptions.SpiNNUtilsException:
166
            If the machine is currently unavailable
167
        :raises KeyError: If the chip does not exist but the machine does
168
        """
169
        return cls.get_machine()._chips[x, y]
1✔
170

171
    @classmethod
1✔
172
    def get_nearest_ethernet(cls, x: int, y: int) -> XY:
1✔
173
        """
174
        Gets the nearest Ethernet-enabled chip (`x`, `y`) for the chip at
175
        (`x`, `y`) if it exists.
176

177
        If there is no machine or no chip at (`x`, `y`) this method,
178
        or any other issue will just return (`x`, `y`)
179

180
        .. note::
181
            This method will never request a new machine.
182
            Therefore a call to this method will not trigger a hard reset
183

184
        :param int x: Chip X coordinate
185
        :param int y: Chip Y coordinate
186
        :return: Chip (`x`,`y`)'s nearest_ethernet info
187
            or if that is not available just (`x`, `y`)
188
        :rtype: tuple(int, int)
189
        """
190
        try:
×
191
            m = cls.__data._machine
×
192
            if m is not None:
×
193
                chip = m._chips[(x, y)]
×
194
                return chip.nearest_ethernet_x, chip.nearest_ethernet_y
×
195
        except Exception:  # pylint: disable=broad-except
×
196
            pass
×
197
        return x, y
×
198

199
    @classmethod
1✔
200
    def where_is_xy(cls, x: int, y: int) -> str:
1✔
201
        """
202
        Gets a string saying where chip at x and y is if possible.
203

204
        Almost Semantic sugar for `get_machine().where_is_xy()`
205

206
        The method does not raise an exception rather returns a String of the
207
        exception
208

209
        .. note::
210
            This method will never request a new machine.
211
            Therefore a call to this method will not trigger a hard reset
212

213
        :param int x:
214
        :param int y:
215
        :rtype: str
216
        """
217
        try:
1✔
218
            m = cls.__data._machine
1✔
219
            if m is not None:
1✔
220
                return m.where_is_xy(x, y)
1✔
221
            return "No Machine created yet"
1✔
222
        except Exception as ex:  # pylint: disable=broad-except
×
223
            if cls.__data._machine is None:
×
224
                return "No Machine created yet"
×
225
            return str(ex)
×
226

227
    @classmethod
1✔
228
    def where_is_chip(cls, chip: Chip) -> str:
1✔
229
        """
230
        Gets a string saying where chip is if possible.
231

232
        Almost Semantic sugar for `get_machine().where_is_chip()`
233

234
        The method does not raise an exception rather returns a String of the
235
        exception
236

237
        .. note::
238
            This method will never request a new machine.
239
            Therefore a call to this method will not trigger a hard reset
240

241
        :param Chip chip:
242
        :rtype: str
243
        """
244
        try:
1✔
245
            m = cls.__data._machine
1✔
246
            if m is not None:
1!
247
                return m.where_is_chip(chip)
1✔
248
        except Exception as ex:  # pylint: disable=broad-except
×
249
            if cls.__data._machine is not None:
×
250
                return str(ex)
×
251
        return "Chip is from a previous machine"
×
252

253
    @classmethod
1✔
254
    def get_machine_version(cls) -> AbstractVersion:
1✔
255
        """
256
        Returns the Machine Version if it has or can be set.
257

258
`       May call version_factory to create the version
259

260
        :return: A superclass of AbstractVersion
261
        :raises SpinnMachineException: If the cfg version is not set correctly
262
        """
263
        if cls.__data._machine_version is None:
1✔
264
            cls.__data._machine_version = version_factory()
1✔
265
        return cls.__data._machine_version
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc