Example #1
0
    def _create_message_to_send(self, size, vertex, region):
        """ Creates a single message to send with the given boundaries.

        :param size: The number of bytes available for the whole packet
        :type size: int
        :param vertex: The vertex to get the keys from
        :type vertex:\
                    :py:class:`spynnaker.pyNN.models.abstract_models.buffer_models.abstract_sends_buffers_from_host.AbstractSendsBuffersFromHost`
        :param region: The region of the vertex to get keys from
        :type region: int
        :return: A new message, or None if no keys can be added
        :rtype: None or\
                    :py:class:`spinnman.messages.eieio.data_messages.eieio_32bit.eieio_32bit_timed_payload_prefix_data_message.EIEIO32BitTimedPayloadPrefixDataMessage`
        """

        # If there are no more messages to send, return None
        if not vertex.is_next_timestamp(region):
            return None

        # Create a new message
        next_timestamp = vertex.get_next_timestamp(region)
        message = EIEIO32BitTimedPayloadPrefixDataMessage(next_timestamp)

        # If there is no room for the message, return None
        if message.size + _N_BYTES_PER_KEY > size:
            return None

        # Add keys up to the limit
        bytes_to_go = size - message.size
        while (bytes_to_go >= _N_BYTES_PER_KEY
               and vertex.is_next_key(region, next_timestamp)):

            key = vertex.get_next_key(region)
            message.add_key(key)
            bytes_to_go -= _N_BYTES_PER_KEY

            if self._write_reload_files:
                self._reload_buffer_file[(vertex, region)].write(
                    "{}:{}\n".format(next_timestamp, key))
        return message
def _read_32_bit_message(prefix, payload_base, prefix_type, is_time, data,
                         offset, eieio_header):
    """ Return a packet containing 32 bit elements
    """
    if payload_base is None:
        if prefix is None:
            return EIEIO32BitDataMessage(eieio_header.count, data, offset)
        elif prefix_type == EIEIOPrefix.LOWER_HALF_WORD:
            return EIEIO32BitLowerKeyPrefixDataMessage(prefix,
                                                       eieio_header.count,
                                                       data, offset)
        elif prefix_type == EIEIOPrefix.UPPER_HALF_WORD:
            return EIEIO32BitUpperKeyPrefixDataMessage(prefix,
                                                       eieio_header.count,
                                                       data, offset)
    elif payload_base is not None and not is_time:
        if prefix is None:
            return EIEIO32BitPayloadPrefixDataMessage(payload_base,
                                                      eieio_header.count, data,
                                                      offset)
        elif prefix_type == EIEIOPrefix.LOWER_HALF_WORD:
            return EIEIO32BitPayloadPrefixLowerKeyPrefixDataMessage(
                prefix, payload_base, eieio_header.count, data, offset)
        elif prefix_type == EIEIOPrefix.UPPER_HALF_WORD:
            return EIEIO32BitPayloadPrefixUpperKeyPrefixDataMessage(
                prefix, payload_base, eieio_header.count, data, offset)
    elif payload_base is not None and is_time:
        if prefix is None:
            return EIEIO32BitTimedPayloadPrefixDataMessage(
                payload_base, eieio_header.count, data, offset)
        elif prefix_type == EIEIOPrefix.LOWER_HALF_WORD:
            return EIEIO32BitTimedPayloadPrefixLowerKeyPrefixDataMessage(
                prefix, payload_base, eieio_header.count, data, offset)
        elif prefix_type == EIEIOPrefix.UPPER_HALF_WORD:
            return EIEIO32BitTimedPayloadPrefixUpperKeyPrefixDataMessage(
                prefix, payload_base, eieio_header.count, data, offset)
    return EIEIOWithoutPayloadDataMessage(eieio_header, data, offset)
Example #3
0
    def _send_initial_messages(self, vertex, region, progress_bar):
        """ Send the initial set of messages

        :param vertex: The vertex to get the keys from
        :type vertex:\
                    :py:class:`spynnaker.pyNN.models.abstract_models.buffer_models.abstract_sends_buffers_from_host.AbstractSendsBuffersFromHost`
        :param region: The region to get the keys from
        :type region: int
        :return: A list of messages
        :rtype: list of\
                    :py:class:`spinnman.messages.eieio.data_messages.eieio_32bit.eieio_32bit_timed_payload_prefix_data_message.EIEIO32BitTimedPayloadPrefixDataMessage`
        """

        # Get the vertex load details
        # region_base_address = self._locate_region_address(region, vertex)
        region_base_address = \
            helpful_functions.locate_memory_region_for_placement(
                self._placements.get_placement_of_subvertex(vertex), region,
                self._transceiver)
        placement = self._placements.get_placement_of_subvertex(vertex)

        # Add packets until out of space
        sent_message = False
        bytes_to_go = vertex.get_region_buffer_size(region)
        if bytes_to_go % 2 != 0:
            raise exceptions.SpinnFrontEndException(
                "The buffer region of {} must be divisible by 2".format(
                    vertex))
        all_data = ""
        if vertex.is_empty(region):
            sent_message = True
        else:
            min_size_of_packet = \
                EIEIO32BitTimedPayloadPrefixDataMessage.get_min_packet_length()
            while (vertex.is_next_timestamp(region)
                   and bytes_to_go > min_size_of_packet):
                space_available = min(bytes_to_go, 280)
                next_message = self._create_message_to_send(
                    space_available, vertex, region)
                if next_message is None:
                    break

                # Write the message to the memory
                data = next_message.bytestring
                all_data += data
                sent_message = True

                # Update the positions
                bytes_to_go -= len(data)
                progress_bar.update(len(data))

        if not sent_message:
            raise exceptions.BufferableRegionTooSmall(
                "The buffer size {} is too small for any data to be added for"
                " region {} of vertex {}".format(bytes_to_go, region, vertex))

        # If there are no more messages and there is space, add a stop request
        if (not vertex.is_next_timestamp(region)
                and bytes_to_go >= EventStopRequest.get_min_packet_length()):
            data = EventStopRequest().bytestring
            # logger.debug(
            #    "Writing stop message of {} bytes to {} on {}, {}, {}".format(
            #         len(data), hex(region_base_address),
            #         placement.x, placement.y, placement.p))
            all_data += data
            bytes_to_go -= len(data)
            progress_bar.update(len(data))
            self._sent_messages[vertex] = BuffersSentDeque(
                region, sent_stop_message=True)

        # If there is any space left, add padding
        if bytes_to_go > 0:
            padding_packet = PaddingRequest()
            n_packets = bytes_to_go / padding_packet.get_min_packet_length()
            data = padding_packet.bytestring
            data *= n_packets
            all_data += data

        # Do the writing all at once for efficiency
        self._transceiver.write_memory(placement.x, placement.y,
                                       region_base_address, all_data)
Example #4
0
from spinn_front_end_common.interface.buffer_management.storage_objects.\
    end_buffering_state import EndBufferingState

# general imports
import struct
import threading
import logging
import traceback
import os
import re

logger = logging.getLogger(__name__)

# The minimum size of any message - this is the headers plus one entry
_MIN_MESSAGE_SIZE = (
    EIEIO32BitTimedPayloadPrefixDataMessage.get_min_packet_length())

# The number of bytes in each key to be sent
_N_BYTES_PER_KEY = EIEIOType.KEY_32_BIT.key_bytes  # @UndefinedVariable


class BufferManager(object):
    """ Manager of send buffers
    """
    def __init__(self, placements, tags, transceiver, write_reload_files,
                 application_folder_path):
        """

        :param placements: The placements of the vertices
        :type placements:\
                    :py:class:`pacman.model.placements.placements.Placements`
    def _send_initial_messages(self, vertex, region, progress_bar):
        """ Send the initial set of messages

        :param vertex: The vertex to get the keys from
        :type vertex:\
                    :py:class:`spynnaker.pyNN.models.abstract_models.buffer_models.abstract_sends_buffers_from_host_partitioned_vertex.AbstractSendsBuffersFromHostPartitionedVertex`
        :param region: The region to get the keys from
        :type region: int
        :return: A list of messages
        :rtype: list of\
                    :py:class:`spinnman.messages.eieio.data_messages.eieio_32bit.eieio_32bit_timed_payload_prefix_data_message.EIEIO32BitTimedPayloadPrefixDataMessage`
        """

        # Get the vertex load details
        region_base_address = self._locate_region_address(region, vertex)
        placement = self._placements.get_placement_of_subvertex(vertex)

        # Add packets until out of space
        sent_message = False
        bytes_to_go = vertex.get_region_buffer_size(region)
        if bytes_to_go % 2 != 0:
            raise exceptions.SpinnFrontEndException(
                "The buffer region of {} must be divisible by 2".format(
                    vertex))
        all_data = ""
        if vertex.is_empty(region):
            sent_message = True
        else:
            min_size_of_packet = \
                EIEIO32BitTimedPayloadPrefixDataMessage.get_min_packet_length()
            while (vertex.is_next_timestamp(region) and
                    bytes_to_go > min_size_of_packet):
                space_available = min(bytes_to_go, 280)
                next_message = self._create_message_to_send(
                    space_available, vertex, region)
                if next_message is None:
                    break

                # Write the message to the memory
                data = next_message.bytestring
                all_data += data
                sent_message = True

                # Update the positions
                bytes_to_go -= len(data)
                progress_bar.update(len(data))

        if not sent_message:
            raise exceptions.BufferableRegionTooSmall(
                "The buffer size {} is too small for any data to be added for"
                " region {} of vertex {}".format(bytes_to_go, region, vertex))

        # If there are no more messages and there is space, add a stop request
        if (not vertex.is_next_timestamp(region) and
                bytes_to_go >= EventStopRequest.get_min_packet_length()):
            data = EventStopRequest().bytestring
            # logger.debug(
            #    "Writing stop message of {} bytes to {} on {}, {}, {}".format(
            #         len(data), hex(region_base_address),
            #         placement.x, placement.y, placement.p))
            all_data += data
            bytes_to_go -= len(data)
            progress_bar.update(len(data))
            self._sent_messages[vertex] = BuffersSentDeque(
                region, sent_stop_message=True)

        # If there is any space left, add padding
        if bytes_to_go > 0:
            padding_packet = PaddingRequest()
            n_packets = bytes_to_go / padding_packet.get_min_packet_length()
            data = padding_packet.bytestring
            data *= n_packets
            all_data += data

        # Do the writing all at once for efficiency
        self._transceiver.write_memory(
            placement.x, placement.y, region_base_address, all_data)