Source code for spynnaker.pyNN.spynnaker_external_device_plugin_manager

# Copyright (c) 2017 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 spinn_utilities.socket_address import SocketAddress
from pacman.model.graphs.application import ApplicationEdge
from spinn_utilities.config_holder import (get_config_int, get_config_str)
from spinnman.messages.eieio import EIEIOType
from spinn_front_end_common.utility_models import (
    ReverseIpTagMultiCastSource)
from spinn_front_end_common.utilities.utility_objs import (
    LivePacketGatherParameters)
from spynnaker.pyNN.data import SpynnakerDataView
from spynnaker.pyNN.utilities.constants import (
    LIVE_POISSON_CONTROL_PARTITION_ID, SPIKE_PARTITION_ID)
from spynnaker.pyNN.models.populations import Population


[docs] class SpynnakerExternalDevicePluginManager(object): """ User-level interface for the external device plug-in manager. """ __slots__ = []
[docs] @staticmethod def add_database_socket_address( database_notify_host, database_notify_port_num, database_ack_port_num): """ :param database_notify_host: Host to talk to tell that the database (and application) is ready. :type database_notify_host: str or None :param database_notify_port_num: Port to talk to tell that the database (and application) is ready. :type database_notify_port_num: int or None :param database_ack_port_num: Port on which to listen for an acknowledgement that the simulation should start. :type database_ack_port_num: int or None """ # build the database socket address used by the notification interface database_socket = SocketAddress( listen_port=database_ack_port_num, notify_host_name=database_notify_host, notify_port_no=database_notify_port_num) # update socket interface with new demands. SpynnakerDataView.add_database_socket_address(database_socket)
[docs] @staticmethod def activate_live_output_for( population, database_notify_host=None, database_notify_port_num=None, database_ack_port_num=None, port=None, host=None, tag=None, strip_sdp=True, use_prefix=False, key_prefix=None, prefix_type=None, message_type=EIEIOType.KEY_32_BIT, right_shift=0, payload_as_time_stamps=True, notify=True, use_payload_prefix=True, payload_prefix=None, payload_right_shift=0, number_of_packets_sent_per_time_step=0, translate_keys=False): """ Output the spikes from a given population from SpiNNaker as they occur in the simulation. :param ~spynnaker.pyNN.models.populations.Population population: The population to activate the live output for :param str database_notify_host: The hostname for the device which is listening to the database notification. :param int database_ack_port_num: The port number to which a external device will acknowledge that they have finished reading the database and are ready for it to start execution :param int database_notify_port_num: The port number to which a external device will receive the database is ready command :param key_prefix: the prefix to be applied to the key :type key_prefix: int or None :param ~spinnman.messages.eieio.EIEIOPrefix prefix_type: if the prefix type is 32 bit or 16 bit :param ~spinnman.messages.eieio.EIEIOType message_type: If the message is a EIEIO command message, or an EIEIO data message with 16 bit or 32 bit keys. :param bool payload_as_time_stamps: :param int right_shift: :param bool use_payload_prefix: :param bool notify: :param payload_prefix: :type payload_prefix: int or None :param int payload_right_shift: :param int number_of_packets_sent_per_time_step: :param int port: The UDP port to which the live spikes will be sent. If not specified, the port will be taken from the "live_spike_port" parameter in the "Recording" section of the sPyNNaker configuration file. :param str host: The host name or IP address to which the live spikes will be sent. If not specified, the host will be taken from the "live_spike_host" parameter in the "Recording" section of the sPyNNaker configuration file. :param int tag: The IP tag to be used for the spikes. If not specified, one will be automatically assigned :param bool strip_sdp: Determines if the SDP headers will be stripped from the transmitted packet. :param bool use_prefix: Determines if the spike packet will contain a common prefix for the spikes :param str label: The label of the gatherer vertex :param list(str) partition_ids: The names of the partitions to create edges for :param bool translate_keys: Whether the incoming keys from the cores should be translated to global keys rather than core-based keys """ # pylint: disable=too-many-arguments, too-many-locals, protected-access # get default params if none set if port is None: port = get_config_int("Recording", "live_spike_port") if host is None: host = get_config_str("Recording", "live_spike_host") # Use the right-shift to remove the colour from translated keys n_colour_bits = population._vertex.n_colour_bits translated_key_right_shift = n_colour_bits # Use the mask to remove the colour from non-translated keys received_key_mask = 0xFFFFFFFF & ~((2 ** n_colour_bits) - 1) # pylint: disable=too-many-arguments, too-many-locals params = LivePacketGatherParameters( port=port, hostname=host, tag=tag, strip_sdp=strip_sdp, use_prefix=use_prefix, key_prefix=key_prefix, prefix_type=prefix_type, message_type=message_type, right_shift=right_shift, payload_prefix=payload_prefix, payload_as_time_stamps=payload_as_time_stamps, use_payload_prefix=use_payload_prefix, payload_right_shift=payload_right_shift, number_of_packets_sent_per_time_step=( number_of_packets_sent_per_time_step), label="LiveSpikeReceiver", received_key_mask=received_key_mask, translate_keys=translate_keys, translated_key_right_shift=translated_key_right_shift) SpynnakerExternalDevicePluginManager.update_live_packet_gather_tracker( population._vertex, params, [SPIKE_PARTITION_ID]) if notify: SpynnakerExternalDevicePluginManager.add_database_socket_address( database_notify_host, database_notify_port_num, database_ack_port_num)
[docs] @staticmethod def activate_live_output_to( population, device, partition_id=SPIKE_PARTITION_ID): """ Activate the output of spikes from a population to an external device. .. note:: All spikes will be sent to the device. :param ~spynnaker.pyNN.models.populations.Population population: The pyNN population object from which spikes will be sent. :param device: The pyNN population or external device to which the spikes will be sent. :type device: ~spynnaker.pyNN.models.populations.Population or ~pacman.model.graphs.application.ApplicationVertex :param str partition_id: The partition ID to activate live output to. """ device_vertex = device # pylint: disable=protected-access if isinstance(device, Population): device_vertex = device._vertex SpynnakerExternalDevicePluginManager.add_edge( population._vertex, device_vertex, partition_id)
[docs] @staticmethod def update_live_packet_gather_tracker( vertex_to_record_from, params, partition_ids): """ Add an edge from a vertex to the live packet gatherer, builds as needed and has all the parameters for the creation of the live packet gatherer if needed. :param vertex_to_record_from: :type vertex_to_record_from: ~pacman.model.graphs.application.ApplicationVertex or ~pacman.model.graphs.machine.MachineVertex :param params: :type params: ~spinn_front_end_common.utilities.utility_objs.LivePacketGatherParameters :param list(str) partition_ids: :param bool translate_keys: """ # add to the tracker SpynnakerDataView.add_live_packet_gatherer_parameters( params, vertex_to_record_from, partition_ids)
[docs] @staticmethod def add_poisson_live_rate_control( poisson_population, control_label_extension="_control", receive_port=None, database_notify_host=None, database_notify_port_num=None, database_ack_port_num=None, notify=True, reserve_reverse_ip_tag=False): """ Add a live rate controller to a Poisson population. :param poisson_population: The population to control :type poisson_population: ~spynnaker.pyNN.models.populations.Population :param str control_label_extension: An extension to add to the label of the Poisson source. Must match up with the equivalent in the SpynnakerPoissonControlConnection :param int receive_port: The port that the SpiNNaker board should listen on :param str database_notify_host: the hostname for the device which is listening to the database notification. :param int database_ack_port_num: the port number to which a external device will acknowledge that they have finished reading the database and are ready for it to start execution :param int database_notify_port_num: The port number to which an external device will receive the database is ready command :param bool notify: adds to the notification protocol if set. :param bool reserve_reverse_ip_tag: True if a reverse IP tag is to be used, False if SDP is to be used (default) """ # pylint: disable=too-many-arguments, protected-access vertex = poisson_population._vertex control_label = f"{vertex.label}{control_label_extension}" controller = ReverseIpTagMultiCastSource( n_keys=vertex.n_atoms, label=control_label, receive_port=receive_port, reserve_reverse_ip_tag=reserve_reverse_ip_tag, injection_partition_id=LIVE_POISSON_CONTROL_PARTITION_ID) SpynnakerExternalDevicePluginManager.add_application_vertex(controller) edge = SpynnakerExternalDevicePluginManager.add_edge( controller, vertex, LIVE_POISSON_CONTROL_PARTITION_ID) vertex.set_live_poisson_control_edge(edge) if notify: SpynnakerExternalDevicePluginManager.add_database_socket_address( database_notify_host, database_notify_port_num, database_ack_port_num)
[docs] @staticmethod def add_edge(vertex, device_vertex, partition_id): """ Add an edge between two vertices (often a vertex and a external device) on a given partition. :param ~pacman.model.graphs.application.ApplicationVertex vertex: the pre-population vertex to connect the edge from :param device_vertex: the post-population vertex to connect the edge to :type device_vertex: ~pacman.model.graphs.application.ApplicationVertex :param str partition_id: the partition identifier for making nets """ edge = ApplicationEdge(vertex, device_vertex) SpynnakerDataView.add_edge(edge, partition_id) return edge
[docs] @staticmethod def add_application_vertex(vertex): SpynnakerDataView.add_vertex(vertex)