示例#1
0
    def __call__(self, transceiver, has_ran, core_subsets,
                 provenance_file_path):
        if not has_ran:
            raise ConfigurationException(
                "The simulation needs to have tried to run before asking for"
                "iobuf. Please fix and try again")

        return self._run_for_core_subsets(core_subsets, transceiver,
                                          provenance_file_path)
示例#2
0
    def __init__(self,
                 n_neurons,
                 spike_times,
                 machine_time_step,
                 spikes_per_second,
                 ring_buffer_sigma,
                 timescale_factor,
                 port=None,
                 tag=None,
                 ip_address=None,
                 board_address=None,
                 max_on_chip_memory_usage_for_spikes_in_bytes=None,
                 space_before_notification=640,
                 constraints=None,
                 label="SpikeSourceArray"):
        if ip_address is None:
            ip_address = config.get("Buffers", "receive_buffer_host")
        if port is None:
            port = config.getint("Buffers", "receive_buffer_port")

        AbstractDataSpecableVertex.__init__(
            self,
            machine_time_step=machine_time_step,
            timescale_factor=timescale_factor)
        AbstractPartitionableVertex.__init__(
            self,
            n_atoms=n_neurons,
            label=label,
            max_atoms_per_core=self._model_based_max_atoms_per_core,
            constraints=constraints)
        AbstractOutgoingEdgeSameContiguousKeysRestrictor.__init__(self)
        self._spike_times = spike_times
        self._max_on_chip_memory_usage_for_spikes = \
            max_on_chip_memory_usage_for_spikes_in_bytes
        self._space_before_notification = space_before_notification

        self.add_constraint(
            TagAllocatorRequireIptagConstraint(ip_address,
                                               port,
                                               strip_sdp=True,
                                               board_address=board_address,
                                               tag_id=tag))

        if self._max_on_chip_memory_usage_for_spikes is None:
            self._max_on_chip_memory_usage_for_spikes = \
                front_end_common_constants.MAX_SIZE_OF_BUFFERED_REGION_ON_CHIP

        # check the values do not conflict with chip memory limit
        if self._max_on_chip_memory_usage_for_spikes < 0:
            raise ConfigurationException(
                "The memory usage on chip is either beyond what is supportable"
                " on the spinnaker board being supported or you have requested"
                " a negative value for a memory usage. Please correct and"
                " try again")

        # Keep track of any previously generated buffers
        self._send_buffers = dict()
    def __call__(self, transceiver, executable_targets, ran_token):
        if not ran_token:
            raise ConfigurationException(
                "The simulation has to have ran before running this system")

        process = ClearIOBUFProcess(transceiver._scamp_connection_selector)
        process.clear_iobuf(executable_targets.all_core_subsets,
                            len(executable_targets.all_core_subsets))
        return True
示例#4
0
def get_max_delay():
    """ The maximum allowed synaptic delay; delays will be clamped to be at\
        most this.

    :return: returns the max delay of the simulation
    """
    if not globals_variables.has_simulator():
        raise ConfigurationException(FAILED_STATE_MSG)
    return __pynn["get_max_delay"]()
示例#5
0
    def get_matrix_data(
            self, label, buffer_manager, region, placements, graph_mapper,
            application_vertex, variable, n_machine_time_steps):
        """ Read a uint32 mapped to time and neuron IDs from the SpiNNaker\
            machine and converts to required data types with scaling if needed.

        :param label: vertex label
        :param buffer_manager: the manager for buffered data
        :param region: the DSG region ID used for this data
        :param placements: the placements object
        :param graph_mapper: \
            the mapping between application and machine vertices
        :param application_vertex:
        :param variable: PyNN name for the variable (V, gsy_inh etc.)
        :type variable: str
        :param n_machine_time_steps:
        :return:
        """
        if variable in self.__bitfield_variables:
            msg = "Variable {} is not supported, use get_spikes".format(
                variable)
            raise ConfigurationException(msg)
        vertices = graph_mapper.get_machine_vertices(application_vertex)
        progress = ProgressBar(
            vertices, "Getting {} for {}".format(variable, label))
        sampling_rate = self.__sampling_rates[variable]
        missing_str = ""
        pop_level_data = None
        sampling_interval = self.get_neuron_sampling_interval(variable)

        indexes = []
        for vertex in progress.over(vertices):
            expected_rows = self.expected_rows_for_a_run_time(
                n_machine_time_steps, sampling_rate)

            placement_data = self._get_placement_matrix_data(
                variable, placements, vertex, sampling_interval, indexes,
                region, graph_mapper, buffer_manager, expected_rows,
                missing_str, sampling_rate, label)

            if placement_data is not None:
                # append to the population data
                if pop_level_data is None:
                    pop_level_data = placement_data
                else:
                    # Add the slice fragment on axis 1
                    # which is IDs/channel_index
                    pop_level_data = numpy.append(
                        pop_level_data, placement_data, axis=1)

        # warn user of missing data
        if len(missing_str) > 0:
            logger.warning(
                "Population {} is missing recorded data in region {} from the"
                " following cores: {}", label, region, missing_str)

        return pop_level_data, indexes, sampling_interval
示例#6
0
def run_until(tstop):
    """ Run until a (simulation) time period has completed.

    :param tstop: the time to stop at (in milliseconds)
    :return: the actual simulation time that the simulation stopped at
    """
    if not globals_variables.has_simulator():
        raise ConfigurationException(FAILED_STATE_MSG)
    return __pynn["run_until"](tstop)
示例#7
0
    def __call__(
            self, hostname, bmp_details, downed_chips, downed_cores,
            downed_links, board_version, auto_detect_bmp, enable_reinjection,
            scamp_connection_data, boot_port_num, reset_machine_on_start_up,
            max_sdram_size=None, max_core_id=None):
        """
        :param hostname: the hostname or ip address of the spinnaker machine
        :param bmp_details: the details of the BMP connections
        :param downed_chips: the chips that are down which SARK thinks are\
                alive
        :param downed_cores: the cores that are down which SARK thinks are\
                alive
        :param board_version: the version of the boards being used within the\
                machine (1, 2, 3, 4 or 5)
        :param auto_detect_bmp: boolean which determines if the BMP should
               be automatically determined
        :param enable_reinjection: True if dropped packet reinjection is to be\
               enabled
        :param boot_port_num: the port num used for the boot connection
        :param scamp_connection_data: the list of scamp connection data or\
               None
        :param max_sdram_size: the maximum SDRAM each chip can say it has
               (mainly used in debugging purposes)
        :type max_sdram_size: int or None
        """

        # if the end user gives you scamp data, use it and don't discover them
        if scamp_connection_data is not None:
            scamp_connection_data = \
                self._sort_out_scamp_connections(scamp_connection_data)

        # sort out BMP connections into list of strings
        bmp_connection_data = self._sort_out_bmp_string(bmp_details)

        txrx = create_transceiver_from_hostname(
            hostname=hostname, bmp_connection_data=bmp_connection_data,
            version=board_version, ignore_chips=downed_chips,
            ignore_cores=downed_cores, ignored_links=downed_links,
            auto_detect_bmp=auto_detect_bmp,
            boot_port_no=boot_port_num,
            scamp_connections=scamp_connection_data,
            max_sdram_size=max_sdram_size, max_core_id=max_core_id)

        if reset_machine_on_start_up:
            txrx.power_off_machine()

        # do auto boot if possible
        if board_version is None:
            raise ConfigurationException(
                "Please set a machine version number in the configuration "
                "file (spynnaker.cfg or pacman.cfg)")
        txrx.ensure_board_is_ready(
            enable_reinjector=enable_reinjection)
        txrx.discover_scamp_connections()
        machine = txrx.get_machine_details()
        return machine, txrx
    def __call__(self, report_default_directory, dsg_targets, transceiver,
                 loaded_app_data_token):
        """ creates a report that states where in sdram each region is
        (read from machine)

        :param report_default_directory: the folder where reports are written
        :param dsg_targets: the map between placement and file writer
        :param transceiver: the spinnMan instance
        :param loaded_app_data_token: flag that app data has been loaded
        :rtype: None
        """

        if not loaded_app_data_token:
            raise ConfigurationException(
                "Needs to have loaded app data for this to work.")

        directory_name = os.path.join(report_default_directory,
                                      MEM_MAP_SUBDIR_NAME)
        if not os.path.exists(directory_name):
            os.makedirs(directory_name)

        progress = ProgressBar(dsg_targets, "Writing memory map reports")
        for (x, y, p) in progress.over(dsg_targets):
            file_name = os.path.join(
                directory_name, "memory_map_from_processor"
                "_{0:d}_{1:d}_{2:d}.txt".format(x, y, p))
            try:
                with open(file_name, "w") as f:
                    f.write("On chip data specification executor\n\n")

                    dsg_app_pointer_table_address_pointer = transceiver.\
                        get_user_0_register_address_from_core(x, y, p)

                    dsg_app_pointer_table_address = \
                        self._get_app_pointer_table(
                            transceiver, x, y,
                            dsg_app_pointer_table_address_pointer)

                    report_bytes = 4 * MAX_MEM_REGIONS

                    mem_map_report_data = buffer(
                        transceiver.read_memory(x, y,
                                                dsg_app_pointer_table_address,
                                                report_bytes))

                    offset = 0
                    for i in xrange(MAX_MEM_REGIONS):
                        region_address = int(
                            struct.unpack_from("<I", mem_map_report_data,
                                               offset)[0])
                        offset += 4
                        f.write("Region {0:d}:\n\t start address: 0x{1:x}\n\t".
                                format(i, region_address))
            except IOError:
                logger.error("Generate_placement_reports: Can't open file"
                             " {} for writing.".format(file_name))
示例#9
0
def initialize(cells, **initial_values):
    """ Sets cells to be initialised to the given values

    :param cells: the cells to change params on
    :param initial_values: the params and there values to change
    :rtype: None
    """
    if not globals_variables.has_simulator():
        raise ConfigurationException(FAILED_STATE_MSG)
    pynn_common.initialize(cells, **initial_values)
示例#10
0
    def _get_variable_unit(self, parameter_name):
        """ Helper method for getting units from a parameter used by the vertex

        :param parameter_name: the parameter name to find the units for
        :return: the units in string form
        """
        if self._vertex_contains_units:
            return self._vertex.get_units(parameter_name)
        raise ConfigurationException(
            "This population does not support describing its units")
    def __call__(
            self, hostname, bmp_details, downed_chips, downed_cores,
            downed_links, board_version, auto_detect_bmp,
            scamp_connection_data, boot_port_num, reset_machine_on_start_up,
            max_sdram_size=None, max_core_id=None):
        """
        :param hostname: the hostname or IP address of the SpiNNaker machine
        :param bmp_details: the details of the BMP connections
        :param downed_chips: \
            the chips that are down which SARK thinks are alive
        :param downed_cores: \
            the cores that are down which SARK thinks are alive
        :param board_version: the version of the boards being used within the\
            machine (1, 2, 3, 4 or 5)
        :param auto_detect_bmp: \
            Whether the BMP should be automatically determined
        :type auto_detect_bmp: bool
        :param boot_port_num: the port num used for the boot connection
        :type boot_port_num: int
        :param scamp_connection_data: \
            the list of SC&MP connection data or None
        :param max_sdram_size: the maximum SDRAM each chip can say it has\
            (mainly used in debugging purposes)
        :type max_sdram_size: int or None
        :type reset_machine_on_start_up: bool
        :return: Connection details and Transceiver
        """
        # pylint: disable=too-many-arguments

        # if the end user gives you scamp data, use it and don't discover them
        if scamp_connection_data is not None:
            scamp_connection_data = [
                self._parse_scamp_connection(piece)
                for piece in scamp_connection_data.split(":")]

        txrx = create_transceiver_from_hostname(
            hostname=hostname,
            bmp_connection_data=self._parse_bmp_details(bmp_details),
            version=board_version, ignore_chips=downed_chips,
            ignore_cores=downed_cores, ignored_links=downed_links,
            auto_detect_bmp=auto_detect_bmp, boot_port_no=boot_port_num,
            scamp_connections=scamp_connection_data,
            max_sdram_size=max_sdram_size, max_core_id=max_core_id)

        if reset_machine_on_start_up:
            txrx.power_off_machine()

        # do auto boot if possible
        if board_version is None:
            raise ConfigurationException(
                "Please set a machine version number in the configuration "
                "file (spynnaker.cfg or pacman.cfg)")
        txrx.ensure_board_is_ready()
        txrx.discover_scamp_connections()
        return txrx.get_machine_details(), txrx
示例#12
0
    def __init__(self,
                 key,
                 payload=None,
                 time=None,
                 repeat=0,
                 delay_between_repeats=0):
        """

        :param key: The key of the command
        :type key: int
        :param payload: The payload of the command
        :type payload: int
        :param time: The time within the simulation at which to send the\
                    command, or None if this is not a timed command
        :type time: int
        :param repeat: The number of times that the command should be\
                    repeated after sending it once.  This could be used to\
                    ensure that the command is sent despite lost packets.\
                    Must be between 0 and 65535
        :type repeat: int
        :param delay_between_repeats: The amount of time in micro seconds to\
                    wait between sending repeats of the same command.\
                    Must be between 0 and 65535, and must be 0 if repeat is 0
        :type delay_between_repeats: int
        :raise SpynnakerException: If the repeat or delay are out of range
        """

        if repeat < 0 or repeat > 0xFFFF:
            raise ConfigurationException("repeat must be between 0 and 65535")
        if delay_between_repeats < 0 or delay_between_repeats > 0xFFFF:
            raise ConfigurationException(
                "delay_between_repeats must be between 0 and 65535")
        if delay_between_repeats > 0 and repeat == 0:
            raise ConfigurationException(
                "If repeat is 0, delay_betweeen_repeats must be 0")

        self._time = time
        self._key = key

        self._payload = payload
        self._repeat = repeat
        self._delay_between_repeats = delay_between_repeats
示例#13
0
def rank():
    """ The MPI rank of the current node.

    .. note::
        Always 0 on SpiNNaker, whcih doesn't use MPI.

    :return: MPI rank
    """
    if not globals_variables.has_simulator():
        raise ConfigurationException(FAILED_STATE_MSG)
    return __pynn["rank"]()
示例#14
0
def num_processes():
    """ The number of MPI processes.

    .. note::
        Always 1 on SpiNNaker, which doesn't use MPI.

    :return: the number of MPI processes
    """
    if not globals_variables.has_simulator():
        raise ConfigurationException(FAILED_STATE_MSG)
    return __pynn["num_processes"]()
示例#15
0
def create(cellclass, cellparams=None, n=1):
    """ Builds a population with certain params

    :param cellclass: population class
    :param cellparams: population params.
    :param n: n neurons
    :rtype: None
    """
    if not globals_variables.has_simulator():
        raise ConfigurationException(FAILED_STATE_MSG)
    __pynn["create"](cellclass, cellparams, n)
示例#16
0
def run(simtime, callbacks=None):
    """ The run() function advances the simulation for a given number of \
        milliseconds, e.g.:

    :param simtime: time to run for (in milliseconds)
    :param callbacks: callbacks to run
    :return: the actual simulation time that the simulation stopped at
    """
    if not globals_variables.has_simulator():
        raise ConfigurationException(FAILED_STATE_MSG)
    return __pynn["run"](simtime, callbacks=callbacks)
 def create_vertex(self, n_neurons, label, constraints, spikes_per_second,
                   ring_buffer_sigma, incoming_spike_buffer_size):
     if n_neurons != len(self._devices):
         raise ConfigurationException(
             "Number of neurons does not match number of devices in {}".
             format(label))
     max_atoms = self.get_max_atoms_per_core()
     return ExternalDeviceLifControlVertex(
         self._devices, self._create_edges, max_atoms, self._model, self,
         self._translator, spikes_per_second, label, ring_buffer_sigma,
         incoming_spike_buffer_size, constraints)
示例#18
0
 def is_recording(self, variable):
     """
     :param str variable:
     :rtype: bool
     """
     try:
         return self.__sampling_rates[variable] > 0
     except KeyError as e:
         msg = "Variable {} is not supported. Supported variables are {}" \
               "".format(variable, self.get_recordable_variables())
         raise_from(ConfigurationException(msg), e)
示例#19
0
def reset(annotations=None):
    """ Resets the simulation to t = 0

    :param annotations: the annotations to the data objects
    :rtype: None
    """
    if annotations is None:
        annotations = {}
    if not globals_variables.has_simulator():
        raise ConfigurationException(FAILED_STATE_MSG)
    __pynn["reset"](annotations)
    def _check_time_window_size(self, number_of_cpu_cycles_per_receive,
                                machine_time_step, time_scale_factor,
                                n_packets_per_time_window, max_in_edges,
                                safety_factor,
                                other_cpu_demands_in_cpu_cycles):
        """ Calculates the CPU cycles per window, and therefore verifies if\
            there is enough time to do so with a end user safety margin

        :param number_of_cpu_cycles_per_receive:\
            how long the packet reception callback takes in CPU cycles
        :param machine_time_step: the timer tick in microseconds
        :param time_scale_factor:\
            the multiplicative factor on the machine time step.
        :param n_packets_per_time_window:\
            how many packets are to be sent per time window
        :param max_in_edges:\
            the max number of edges going into any vertex in the machine graph
        :param safety_factor: the end user safely factor
        :param other_cpu_demands_in_cpu_cycles:\
            extra costs (e.g. timer tick callback etc.)
        :return: CPU cycles available per window.
        :rtype: float
        :raises ConfigurationException:\
            if the overall time is below what is possible to receive packets\
            with
        """
        # pylint: disable=too-many-arguments

        # figure out if its feasible for window to work
        total_cycles_available = \
            machine_time_step * time_scale_factor * \
            _CONVERSION_BETWEEN_MICRO_TO_CPU_CYCLES

        cpu_cycles_needed_per_window = math.ceil(
            (number_of_cpu_cycles_per_receive +
             _CPU_CYCLES_PER_INTERRUPT_TO_CALLBACK) *
            (n_packets_per_time_window + safety_factor))

        time_needed_per_epoch = \
            (cpu_cycles_needed_per_window * max_in_edges) + \
            other_cpu_demands_in_cpu_cycles

        if total_cycles_available < time_needed_per_epoch:
            raise ConfigurationException(
                "Cannot create a window for this simulation with its "
                "combined machine_time_step, time_scale_factor, and time "
                "needed per packet receive and the number of edges going to "
                "a core. Recommend reducing the graph connectivity, "
                "or increasing the machine time step or the time scale "
                "factor.\n\n"
                "Assuming same connectivity, the best current available "
                "would be {} machine_time_steps with a timescale factor of "
                "1".format(time_needed_per_epoch))
        return cpu_cycles_needed_per_window
    def __call__(self,
                 machine_graph=None,
                 application_graph=None,
                 graph_mapper=None):

        if machine_graph is None:
            raise ConfigurationException(
                "A machine graph is required for this mapper. "
                "Please choose and try again")
        if (application_graph is None) != (graph_mapper is None):
            raise ConfigurationException(
                "Can only do one graph. semantically doing 2 graphs makes no "
                "sense. Please choose and try again")

        if application_graph is not None:
            # generate progress bar
            progress = ProgressBar(
                machine_graph.n_vertices,
                "Getting constraints for application graph")

            # iterate over each partition in the graph
            for vertex in progress.over(machine_graph.vertices):
                partitions = machine_graph.\
                    get_outgoing_edge_partitions_starting_at_vertex(
                        vertex)
                for partition in partitions:
                    if partition.traffic_type == EdgeTrafficType.MULTICAST:
                        self._process_application_partition(
                            partition, graph_mapper)
        else:
            # generate progress bar
            progress = ProgressBar(machine_graph.n_vertices,
                                   "Getting constraints for machine graph")

            for vertex in progress.over(machine_graph.vertices):
                partitions = machine_graph.\
                    get_outgoing_edge_partitions_starting_at_vertex(
                        vertex)
                for partition in partitions:
                    if partition.traffic_type == EdgeTrafficType.MULTICAST:
                        self._process_machine_partition(partition)
示例#22
0
    def _install_virtual_key(self, n_keys):
        # check that virtual key is valid
        if self._virtual_key < 0:
            raise ConfigurationException("Virtual keys must be positive")

        # Get a mask and maximum number of keys for the number of keys
        # requested
        self._mask = self._calculate_mask(n_keys)

        if self._prefix is not None:
            # Check that the prefix doesn't change the virtual key in the
            # masked area
            masked_key = (self._virtual_key | self._prefix) & self._mask
            if self._virtual_key != masked_key:
                raise ConfigurationException(
                    "The number of keys, virtual key and key prefix settings "
                    "don't work together")
        else:
            # If no prefix was generated, generate one
            self._prefix_type = EIEIOPrefix.UPPER_HALF_WORD
            self._prefix = self._virtual_key
    def _check_constraints_equal(constraints, stored_constraints):
        """

        :param constraints:
        :param stored_constraints:
        :rtype: None
        """
        for constraint in constraints:
            if constraint not in stored_constraints:
                raise ConfigurationException(
                    "Two edges within the same partition have different "
                    "constraints")
    def __call__(self,
                 transceiver,
                 machine,
                 router_tables,
                 has_ran,
                 provenance_data_objects=None):
        """
        :param transceiver: the SpiNNMan interface object
        :param machine: the python representation of the spinnaker machine
        :param router_tables: the router tables that have been generated
        :param has_ran: token that states that the simulation has ran
        """

        if not has_ran:
            raise ConfigurationException(
                "This function has been called before the simulation has ran."
                " This is deemed an error, please rectify and try again")

        self._total_sent_packets = 0
        self._total_new_packets = 0
        self._total_dropped_packets = 0
        self._total_missed_dropped_packets = 0
        self._total_lost_dropped_packets = 0

        if provenance_data_objects is not None:
            prov_items = provenance_data_objects
        else:
            prov_items = list()

        prov_items.extend(
            self._write_router_provenance_data(router_tables, machine,
                                               transceiver))

        prov_items.append(
            ProvenanceDataItem(
                ["router_provenance", "total_multi_cast_sent_packets"],
                self._total_sent_packets))
        prov_items.append(
            ProvenanceDataItem(["router_provenance", "total_created_packets"],
                               self._total_new_packets))
        prov_items.append(
            ProvenanceDataItem(["router_provenance", "total_dropped_packets"],
                               self._total_dropped_packets))
        prov_items.append(
            ProvenanceDataItem(
                ["router_provenance", "total_missed_dropped_packets"],
                self._total_missed_dropped_packets))
        prov_items.append(
            ProvenanceDataItem(
                ["router_provenance", "total_lost_dropped_packets"],
                self._total_lost_dropped_packets))

        return prov_items
示例#25
0
    def set_constraint(self, constraint):
        """ Apply a constraint to a population that restricts the processor\
            onto which its atoms will be placed.
        """
        globals_variables.get_simulator().verify_not_running()
        if not isinstance(constraint, AbstractConstraint):
            raise ConfigurationException(
                "the constraint entered is not a recognised constraint")

        self._vertex.add_constraint(constraint)
        # state that something has changed in the population,
        self._change_requires_mapping = True
    def __init__(self,
                 devices,
                 create_edges,
                 max_atoms_per_core,
                 neuron_impl,
                 pynn_model,
                 translator=None,
                 spikes_per_second=None,
                 label=None,
                 ring_buffer_sigma=None,
                 incoming_spike_buffer_size=None,
                 constraints=None):
        """
        :param n_neurons: The number of neurons in the population
        :param devices:\
            The AbstractMulticastControllableDevice instances to be controlled\
            by the population
        :param create_edges:\
            True if edges to the devices should be added by this dev (set\
            to False if using the dev over Ethernet using a translator)
        :param translator:\
            Translator to be used when used for Ethernet communication.  Must\
            be provided if the dev is to be controlled over Ethernet.
        """
        # pylint: disable=too-many-arguments, too-many-locals

        if not devices:
            raise ConfigurationException("No devices specified")

        # Create a partition to key map
        self.__partition_id_to_key = OrderedDict(
            (str(dev.device_control_partition_id), dev.device_control_key)
            for dev in devices)

        # Create a partition to atom map
        self.__partition_id_to_atom = {
            partition: i
            for (i, partition) in enumerate(self.__partition_id_to_key.keys())
        }

        self.__devices = devices
        self.__message_translator = translator

        # Add the edges to the devices if required
        self.__dependent_vertices = list()
        if create_edges:
            self.__dependent_vertices = devices

        super(ExternalDeviceLifControlVertex,
              self).__init__(len(devices), label, constraints,
                             max_atoms_per_core, spikes_per_second,
                             ring_buffer_sigma, incoming_spike_buffer_size,
                             neuron_impl, pynn_model)
示例#27
0
    def _compute_rate(self, sampling_interval):
        """ Convert a sampling interval into a rate. \
            Remember, machine time step is in nanoseconds

        :param sampling_interval: interval between samples in microseconds
        :return: rate
        """
        if sampling_interval is None:
            return 1

        step = globals_variables.get_simulator().machine_time_step / 1000
        rate = int(sampling_interval / step)
        if sampling_interval != rate * step:
            msg = "sampling_interval {} is not an an integer multiple of the "\
                  "simulation timestep {}".format(sampling_interval, step)
            raise ConfigurationException(msg)
        if rate > self.MAX_RATE:
            msg = "sampling_interval {} higher than max allowed which is {}" \
                  "".format(sampling_interval, step * self.MAX_RATE)
            raise ConfigurationException(msg)
        return rate
    def __init__(self,
                 p_connect,
                 allow_self_connections=True,
                 safe=True,
                 verbose=False):
        super(FixedProbabilityConnector, self).__init__(safe, verbose)
        self._p_connect = p_connect
        self._allow_self_connections = allow_self_connections

        if not 0 <= self._p_connect <= 1:
            raise ConfigurationException(
                "The probability must be between 0 and 1 (inclusive)")
    def __init__(
            self,
            devices,
            create_edges,
            translator=None,

            # default params for the neuron model type
            tau_m=20.0,
            cm=1.0,
            v_rest=0.0,
            v_reset=0.0,
            tau_syn_E=5.0,
            tau_syn_I=5.0,
            tau_refrac=0.1,
            i_offset=0.0,
            v=0.0,
            isyn_inh=0.0,
            isyn_exc=0.0):
        """
        :param devices:\
            The AbstractMulticastControllableDevice instances to be controlled\
            by the population
        :param create_edges:\
            True if edges to the devices should be added by this device (set\
            to False if using the device over Ethernet using a translator)
        :param translator:\
            Translator to be used when used for Ethernet communication.  Must\
            be provided if the device is to be controlled over Ethernet.
        """
        # pylint: disable=too-many-arguments, too-many-locals

        if not devices:
            raise ConfigurationException("No devices specified")

        neuron_model = NeuronModelLeakyIntegrateAndFire(
            v, v_rest, tau_m, cm, i_offset, v_reset, tau_refrac)
        synapse_type = SynapseTypeExponential(tau_syn_E, tau_syn_I, isyn_inh,
                                              isyn_exc)
        input_type = InputTypeCurrent()
        threshold_type = ThresholdTypeMulticastDeviceControl(devices)

        self._devices = devices
        self._translator = translator
        self._create_edges = create_edges

        super(ExternalDeviceLifControl,
              self).__init__(model_name="ExternalDeviceLifControl",
                             binary="external_device_lif_control.aplx",
                             neuron_model=neuron_model,
                             input_type=input_type,
                             synapse_type=synapse_type,
                             threshold_type=threshold_type)
    def __generate_data_spec_for_vertices(self, pl, vertex, targets,
                                          data_n_timesteps):
        """
        :param ~.Placement pl: placement of machine graph to cores
        :param ~.AbstractVertex vertex: the specific vertex to write DSG for.
        :param DataSpecificationTargets targets:
        :return: True if the vertex was data spec-able, False otherwise
        :rtype: bool
        :raises ConfigurationException: if things don't fit
        """
        # if the vertex can generate a DSG, call it
        if not isinstance(vertex, AbstractGeneratesDataSpecification):
            return False

        with targets.create_data_spec(pl.x, pl.y, pl.p) as data_writer:
            report_writer = get_report_writer(pl.x, pl.y, pl.p, self._hostname,
                                              self._report_dir,
                                              self._write_text)
            spec = DataSpecificationGenerator(data_writer, report_writer)

            # generate the DSG file
            vertex.generate_data_specification(spec, pl)

            # Check the memory usage
            self._region_sizes[pl.x, pl.y, pl.p] = (APP_PTR_TABLE_BYTE_SIZE +
                                                    sum(spec.region_sizes))

            # extracts the int from the numpy data type generated
            if not isinstance(self._region_sizes[pl.x, pl.y, pl.p], int):
                self._region_sizes[pl.x, pl.y, pl.p] =\
                    self._region_sizes[pl.x, pl.y, pl.p].item()

            self._vertices_by_chip[pl.x, pl.y].append(pl.vertex)
            self._sdram_usage[pl.x, pl.y] += sum(spec.region_sizes)
            if (self._sdram_usage[pl.x, pl.y] <= self._machine.get_chip_at(
                    pl.x, pl.y).sdram.size):
                return True

        # creating the error message which contains the memory usage of
        #  what each core within the chip uses and its original
        # estimate.
        memory_usage = "\n".join(("    {}: {} (total={}, estimated={})".format(
            vert, self._region_sizes[pl.x, pl.y, pl.p],
            sum(self._region_sizes[pl.x, pl.y, pl.p]),
            vert.resources_required.sdram.get_total_sdram(data_n_timesteps))
                                  for vert in self._vertices_by_chip[pl.x,
                                                                     pl.y]))

        raise ConfigurationException(
            "Too much SDRAM has been used on {}, {}.  Vertices and"
            " their usage on that chip is as follows:\n{}".format(
                pl.x, pl.y, memory_usage))