Source code for spinn_machine.data.machine_data_view

# Copyright (c) 2021-2022 The University of Manchester
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from spinn_utilities.data import UtilsDataView
# pylint: disable=protected-access


class _MachineDataModel(object):
    """
    Singleton data model

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

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

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

    __singleton = None

    __slots__ = [
        # Data values cached
        "_machine",
        "_machine_generator",
        "_user_accessed_machine"
    ]

    def __new__(cls):
        if cls.__singleton:
            return cls.__singleton
        # pylint: disable=protected-access
        obj = object.__new__(cls)
        cls.__singleton = obj
        obj._clear()
        return obj

    def _clear(self):
        """
        Clears out all data
        """
        self._hard_reset()
        self._machine_generator = None

    def _hard_reset(self):
        """
        Clears out all data that should change after a reset and graph change

        This does NOT clear the machine as it may have been asked for before
        """
        self._soft_reset()
        self._machine = None
        self._user_accessed_machine = False

    def _soft_reset(self):
        """
        Clears timing and other data that should changed every reset
        """
        # Holder for any later additions


class MachineDataView(UtilsDataView):
    """
    Adds the extra Methods to the View for Machine level.

    See UtilsDataView for a more detailed description.

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

    __data = _MachineDataModel()
    __slots__ = []

    # machine methods

[docs] @classmethod def has_machine(cls): """ Reports if a machine is currently set or can be mocked :rtype: bool """ return (cls.__data._machine is not None or cls._is_mocked())
[docs] @classmethod def get_machine(cls): """ Returns the Machine if it has been set In Mock mode will create and return a virtual 8 * 8 board :raises ~spinn_utilities.exceptions.SpiNNUtilsException: If the machine is currently unavailable :rtype: ~spinn_machine.Machine """ if cls.is_user_mode(): if cls.is_soft_reset(): cls.__data._machine = None cls.__data._user_accessed_machine = True if cls.__data._machine is None: if cls.__data._machine_generator: # pylint: disable=not-callable cls.__data._machine_generator() return cls.__data._machine raise cls._exception("machine") return cls.__data._machine
[docs] @classmethod def get_chip_at(cls, x, y): """ Gets the chip at x and y Almost Semantic sugar for machine.get_chip_at The method however does not return None but rather raises a KeyError if the chip is not known :param int x: :param int y: :rtype: Chip :raises ~spinn_utilities.exceptions.SpiNNUtilsException: If the machine is currently unavailable :raises KeyError: If the chip does not exist but the machine does """ return cls.get_machine()._chips[(x, y)]
[docs] @classmethod def get_nearest_ethernet(cls, x, y): """ Gets the nearest ethernet x and y for the chip at x, y if it exists If there is no machine or no chip at (x, y) this method, or any other issue will just return x,y .. Note: This method will never request a new machine. Therefore a call to this method will not trigger a hard reset :param int x: :param int y: :return: Chip(x,y)'s nearest_ethernet info or if that is not available just x, and y :rtype: tuple(int, int) """ try: chip = cls.__data._machine._chips[(x, y)] return chip.nearest_ethernet_x, chip.nearest_ethernet_y except Exception: # pylint: disable=broad-except if cls.__data._machine is None: return x, y return x, y
[docs] @classmethod def where_is_xy(cls, x, y): """ Gets a string saying where chip at x and y is if possible Almost Semantic sugar for get_machine.where_is_xy The method does not raise an exception rather returns a String of the exception .. Note: This method will never request a new machine. Therefore a call to this method will not trigger a hard reset :param int x: :param int y: :rtype: str """ try: return cls.__data._machine.where_is_xy(x, y) except Exception as ex: # pylint: disable=broad-except if cls.__data._machine is None: return "No Machine created yet" return str(ex)
[docs] @classmethod def where_is_chip(cls, chip): """ Gets a string saying where chip is if possible Almost Semantic sugar for get_machine.where_is_xy The method does not raise an exception rather returns a String of the exception .. Note: This method will never request a new machine. Therefore a call to this method will not trigger a hard reset :param int x: :param int y: :rtype: str """ try: return cls.__data._machine.where_is_chip(chip) except Exception as ex: # pylint: disable=broad-except if cls.__data._machine is None: return "Chip is from a previous machine" return str(ex)