Source code for spynnaker.pyNN.models.utility_models.delays.delay_extension_vertex

# Copyright (c) 2014 The University of Manchester
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# 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 __future__ import annotations
from typing import List, Sequence, Tuple, TYPE_CHECKING, cast
from spinn_utilities.overrides import overrides
from spinn_utilities.config_holder import get_config_bool
from pacman.model.graphs.application import (
    ApplicationEdgePartition, ApplicationVertex)
from spinn_front_end_common.utilities.constants import BYTES_PER_WORD

from spynnaker.pyNN.models.abstract_models import ColouredApplicationVertex
from spynnaker.pyNN.exceptions import DelayExtensionException
from spynnaker.pyNN.models.abstract_models import AbstractHasDelayStages
from spynnaker.pyNN.utilities.constants import POP_TABLE_MAX_ROW_LENGTH
from spynnaker.pyNN.models.neural_projections import DelayedApplicationEdge
if TYPE_CHECKING:
    from spynnaker.pyNN.extra_algorithms.splitter_components import (
        SplitterDelayVertexSlice)

_DELAY_PARAM_HEADER_WORDS = 9


class DelayExtensionVertex(ColouredApplicationVertex, AbstractHasDelayStages):
    """
    Provide delays to incoming spikes in multiples of the maximum delays
    of a neuron (typically 16 or 32).
    """
    __slots__ = (
        # The partition this Delay is supporting
        "__partition",
        "__delay_per_stage",
        "__n_delay_stages",
        "__drop_late_spikes",
        "__outgoing_edges",
        "__n_colour_bits")

    # this maps to what master assumes
    MAX_SLOTS = 8
    SAFETY_FACTOR = 5000
    MAX_DTCM_AVAILABLE = 59756 - SAFETY_FACTOR

    def __init__(
            self, partition: ApplicationEdgePartition, delay_per_stage: int,
            n_delay_stages: int, n_colour_bits: int,
            label: str = "DelayExtension"):
        """
        :param partition: The partition that this delay is supporting
        :type partition:
            ~pacman.model.graphs.application.ApplicationEdgePartition
        :param int delay_per_stage: the delay per stage
        :param int n_delay_stages: the (initial) number of delay stages needed
        :param int n_colour_bits: the number of bits for event colouring
        :param str label: the vertex label
        """
        # pylint: disable=too-many-arguments
        super().__init__(
            label, POP_TABLE_MAX_ROW_LENGTH, splitter=None)

        self.__partition = partition
        self.__n_delay_stages = n_delay_stages
        self.__delay_per_stage = delay_per_stage

        self.__drop_late_spikes = get_config_bool(
            "Simulation", "drop_late_spikes") or False

        self.__outgoing_edges: List[DelayedApplicationEdge] = list()

        self.__n_colour_bits = n_colour_bits

    @property
    def n_atoms(self) -> int:
        """
        The number of atoms in this vertex.

        :rtype: int
        """
        return self.__partition.pre_vertex.n_atoms

    @property
    @overrides(ColouredApplicationVertex.atoms_shape)
    def atoms_shape(self) -> Tuple[int, ...]:
        return self.__partition.pre_vertex.atoms_shape

    @property
    def _delay_splitter(self) -> SplitterDelayVertexSlice:
        if TYPE_CHECKING:
            return cast(SplitterDelayVertexSlice, self._splitter)
        else:
            return self._splitter

    @property
    def drop_late_spikes(self) -> bool:
        """
        Whether to drop late spikes.
        """
        return self.__drop_late_spikes

[docs] @staticmethod def get_max_delay_ticks_supported(delay_ticks_at_post_vertex: int) -> int: """ Get the max ticks the combination of delay and post vertex can handle. :param int delay_ticks_at_post_vertex: :rtype: int """ return DelayExtensionVertex.MAX_SLOTS * delay_ticks_at_post_vertex
@property @overrides(AbstractHasDelayStages.n_delay_stages) def n_delay_stages(self) -> int: return self.__n_delay_stages
[docs] def set_new_n_delay_stages_and_delay_per_stage( self, n_delay_stages: int, delay_per_stage: int) -> None: """ Sets the delays per stages. Verifies delay per stage is unchanged. :param int n_delay_stages: :param int delay_per_stage: """ if delay_per_stage != self.__delay_per_stage: raise DelayExtensionException( "The delay per stage is already set to " f"{self.__delay_per_stage}, and therefore {delay_per_stage} " "is not yet feasible. " "Please report it to Spinnaker user mail list.") if n_delay_stages > self.__n_delay_stages: self.__n_delay_stages = n_delay_stages
@property def delay_per_stage(self) -> int: """ The delay per stage, in timesteps. """ return self.__delay_per_stage @property def source_vertex(self) -> ApplicationVertex: """ The pre vertex of the delayed partition. :rtype: ApplicationVertex """ return self.__partition.pre_vertex
[docs] def delay_params_size(self) -> int: """ The size of the delay parameters. """ return BYTES_PER_WORD * _DELAY_PARAM_HEADER_WORDS
@property def partition(self) -> ApplicationEdgePartition: """ The partition that this delay is supporting. """ return self.__partition
[docs] def add_outgoing_edge(self, edge: DelayedApplicationEdge) -> None: """ Add an outgoing edge to the delay extension. :param DelayedApplicationEdge edge: The edge to add """ self.__outgoing_edges.append(edge)
@property def outgoing_edges(self) -> Sequence[DelayedApplicationEdge]: """ The outgoing edges from this vertex. """ return self.__outgoing_edges @property @overrides(ColouredApplicationVertex.n_colour_bits) def n_colour_bits(self) -> int: return self.__n_colour_bits