def read_parameters_from_machine( self, transceiver, placement, vertex_slice): # locate SDRAM address to where the neuron parameters are stored neuron_region_sdram_address = \ helpful_functions.locate_memory_region_for_placement( placement, constants.POPULATION_BASED_REGIONS.NEURON_PARAMS.value, transceiver) # shift past the extra stuff before neuron parameters that we don't # need to read neuron_parameters_sdram_address = ( neuron_region_sdram_address + self.BYTES_TILL_START_OF_GLOBAL_PARAMETERS) # get size of neuron params size_of_region = self._get_sdram_usage_for_neuron_params(vertex_slice) size_of_region -= self.BYTES_TILL_START_OF_GLOBAL_PARAMETERS # get data from the machine byte_array = transceiver.read_memory( placement.x, placement.y, neuron_parameters_sdram_address, size_of_region) # Skip the recorder globals as these are not change on machine # Just written out in case data is changed and written back offset = self._neuron_recorder.get_sdram_usage_in_bytes( vertex_slice) # update python neuron parameters with the data self._neuron_impl.read_data( byte_array, offset, vertex_slice, self._parameters, self._state_variables)
def read_parameters_from_machine( self, transceiver, placement, vertex_slice): # locate sdram address to where the neuron parameters are stored poisson_parameter_region_sdram_address = \ helpful_functions.locate_memory_region_for_placement( placement, _REGIONS.POISSON_PARAMS_REGION.value, transceiver) # shift past the extra stuff before neuron parameters that we don't # need to read poisson_parameter_parameters_sdram_address = \ poisson_parameter_region_sdram_address + \ START_OF_POISSON_GENERATOR_PARAMETERS # get size of poisson params size_of_region = self.get_params_bytes(vertex_slice) size_of_region -= START_OF_POISSON_GENERATOR_PARAMETERS # get data from the machine byte_array = transceiver.read_memory( placement.x, placement.y, poisson_parameter_parameters_sdram_address, size_of_region) # Convert the data to parameter values (start, end, is_fast_source, exp_minus_lambda, isi, time_to_next_spike) = _PoissonStruct.read_data( byte_array, 0, vertex_slice.n_atoms) # Convert start values as timesteps into milliseconds self._start[vertex_slice.as_slice] = self._convert_n_timesteps_to_ms( start, self._machine_time_step) # Convert end values as timesteps to durations in milliseconds self._duration[vertex_slice.as_slice] = ( self._convert_n_timesteps_to_ms(end, self._machine_time_step) - self._start[vertex_slice.as_slice]) # Work out the spikes per tick depending on if the source is slow # or fast is_fast_source = is_fast_source == 1.0 spikes_per_tick = numpy.zeros(len(is_fast_source), dtype="float") spikes_per_tick[is_fast_source] = numpy.log( exp_minus_lambda[is_fast_source]) * -1.0 slow_elements = isi > 0 spikes_per_tick[slow_elements] = 1.0 / isi[slow_elements] # Convert spikes per tick to rates self._rate[vertex_slice.as_slice] = ( spikes_per_tick * (MICROSECONDS_PER_SECOND / float(self._machine_time_step))) # Store the updated time until next spike so that it can be # rewritten when the parameters are loaded self._time_to_spike[vertex_slice.as_slice] = time_to_next_spike
def get_data(transceiver, placement, region, region_size): """ Get the recorded data from a region """ region_base_address = locate_memory_region_for_placement( placement, region, transceiver) number_of_bytes_written = _RECORDING_COUNT.unpack_from( transceiver.read_memory( placement.x, placement.y, region_base_address, _RECORDING_COUNT.size))[0] # Subtract 4 for the word representing the size itself expected_size = region_size - _RECORDING_COUNT.size if number_of_bytes_written > expected_size: raise MemReadException( "Expected {} bytes but read {}".format( expected_size, number_of_bytes_written)) return ( transceiver.read_memory( placement.x, placement.y, region_base_address + 4, number_of_bytes_written), number_of_bytes_written)
def get_recording_region_base_address(self, txrx, placement): return locate_memory_region_for_placement( placement, self.CHIP_POWER_MONITOR_REGIONS.RECORDING.value, txrx)
def _send_initial_messages(self, vertex, region, progress): """ 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.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.EIEIODataMessage` """ # Get the vertex load details # region_base_address = self._locate_region_address(region, vertex) region_base_address = funs.locate_memory_region_for_placement( self._placements.get_placement_of_vertex(vertex), region, self._transceiver) placement = self._placements.get_placement_of_vertex(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 = _MIN_MESSAGE_SIZE 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.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.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)
def get_connections_from_machine( self, transceiver, placement, subedge, graph_mapper, routing_infos, synapse_info, partitioned_graph): edge = graph_mapper.get_partitionable_edge_from_partitioned_edge( subedge) if not isinstance(edge, ProjectionPartitionableEdge): return None # Get details for extraction pre_vertex_slice = graph_mapper.get_subvertex_slice( subedge.pre_subvertex) post_vertex_slice = graph_mapper.get_subvertex_slice( subedge.post_subvertex) n_synapse_types = self._synapse_type.get_n_synapse_types() # Get the key for the pre_subvertex partition = partitioned_graph.get_partition_of_subedge(subedge) key = routing_infos.get_keys_and_masks_from_partition( partition)[0].key # Get the key for the delayed pre_subvertex delayed_key = None if edge.delay_edge is not None: delayed_key = self._delay_key_index[ (edge.pre_vertex, pre_vertex_slice.lo_atom, pre_vertex_slice.hi_atom)][0].key # Get the block for the connections from the pre_subvertex master_pop_table_address = \ helpful_functions.locate_memory_region_for_placement( placement, constants.POPULATION_BASED_REGIONS.POPULATION_TABLE.value, transceiver) synaptic_matrix_address = \ helpful_functions.locate_memory_region_for_placement( placement, constants.POPULATION_BASED_REGIONS.SYNAPTIC_MATRIX.value, transceiver) direct_synapses_address = ( self._get_static_synaptic_matrix_sdram_requirements() + synaptic_matrix_address + struct.unpack_from( "<I", transceiver.read_memory( placement.x, placement.y, synaptic_matrix_address, 4))[0]) indirect_synapses_address = synaptic_matrix_address + 4 data, max_row_length = self._retrieve_synaptic_block( transceiver, placement, master_pop_table_address, indirect_synapses_address, direct_synapses_address, key, pre_vertex_slice.n_atoms, synapse_info.index) # Get the block for the connections from the delayed pre_subvertex delayed_data = None delayed_max_row_length = 0 if delayed_key is not None: delayed_data, delayed_max_row_length = \ self._retrieve_synaptic_block( transceiver, placement, master_pop_table_address, indirect_synapses_address, direct_synapses_address, delayed_key, pre_vertex_slice.n_atoms * edge.n_delay_stages, synapse_info.index) # Convert the blocks into connections return self._synapse_io.read_synapses( synapse_info, pre_vertex_slice, post_vertex_slice, max_row_length, delayed_max_row_length, n_synapse_types, self._weight_scales[placement], data, delayed_data, edge.n_delay_stages)
def read_parameters_from_machine(self, transceiver, placement, vertex_slice): # locate SDRAM address to where the neuron parameters are stored neuron_region_sdram_address = \ helpful_functions.locate_memory_region_for_placement( placement, constants.POPULATION_BASED_REGIONS.NEURON_PARAMS.value, transceiver) # shift past the extra stuff before neuron parameters that we don't # need to read neuron_parameters_sdram_address = ( neuron_region_sdram_address + self.BYTES_TILL_START_OF_GLOBAL_PARAMETERS) # get size of neuron params size_of_region = self._get_sdram_usage_for_neuron_params(vertex_slice) size_of_region -= self.BYTES_TILL_START_OF_GLOBAL_PARAMETERS # get data from the machine byte_array = transceiver.read_memory(placement.x, placement.y, neuron_parameters_sdram_address, size_of_region) # Skip the recorder globals as these are not change on machione # Just written out in case data is changed and written back offset = self._neuron_recorder.get_size_of_global_parameters( vertex_slice) # update python neuron parameters with the data # handle global params (only once, so given a slice of 0 to 0) global_params, offset = utility_calls.translate_parameters( self._neuron_model.get_global_parameter_types(), byte_array, offset, Slice(0, 0)) self._neuron_model.set_global_parameters(global_params) # handle state params for a neuron neuron_params, offset = utility_calls.translate_parameters( self._neuron_model.get_neural_parameter_types(), byte_array, offset, vertex_slice) self._neuron_model.set_neural_parameters(neuron_params, vertex_slice) # handle input params input_params, offset = utility_calls.translate_parameters( self._input_type.get_input_type_parameter_types(), byte_array, offset, vertex_slice) self._input_type.set_input_type_parameters(input_params, vertex_slice) # handle additional input params, if they exist if self._additional_input is not None: additional_params, offset = utility_calls.translate_parameters( self._additional_input.get_parameter_types(), byte_array, offset, vertex_slice) self._additional_input.set_parameters(additional_params, vertex_slice) # handle threshold type params threshold_params, offset = utility_calls.translate_parameters( self._threshold_type.get_threshold_parameter_types(), byte_array, offset, vertex_slice) self._threshold_type.set_threshold_parameters(threshold_params, vertex_slice) # Read synapse parameters self._synapse_manager.read_parameters_from_machine( transceiver, placement, vertex_slice)
def read_parameters_from_machine(self, transceiver, placement, vertex_slice): # locate SDRAM address where parameters are stored poisson_params = \ helpful_functions.locate_memory_region_for_placement( placement, _REGIONS.POISSON_PARAMS_REGION.value, transceiver) seed_array = transceiver.read_memory( placement.x, placement.y, poisson_params + SEED_OFFSET_BYTES, SEED_SIZE_BYTES) self.__kiss_seed[vertex_slice] = struct.unpack_from("<4I", seed_array) # locate SDRAM address where the rates are stored poisson_rate_region_sdram_address = \ helpful_functions.locate_memory_region_for_placement( placement, _REGIONS.RATES_REGION.value, transceiver) # get size of poisson params size_of_region = self.get_rates_bytes(vertex_slice) # get data from the machine byte_array = transceiver.read_memory( placement.x, placement.y, poisson_rate_region_sdram_address, size_of_region) # For each atom, read the number of rates and the rate parameters offset = 0 for i in range(vertex_slice.lo_atom, vertex_slice.hi_atom + 1): n_values = struct.unpack_from("<I", byte_array, offset)[0] offset += 4 # Skip reading the index, as it will be recalculated on data write offset += 4 (_start, _end, _next, is_fast_source, exp_minus_lambda, sqrt_lambda, isi, time_to_next_spike) = _PoissonStruct.read_data( byte_array, offset, n_values) offset += _PoissonStruct.get_size_in_whole_words(n_values) * 4 # Work out the spikes per tick depending on if the source is # slow (isi), fast (exp) or faster (sqrt) is_fast_source = is_fast_source == 1.0 spikes_per_tick = numpy.zeros(len(is_fast_source), dtype="float") spikes_per_tick[is_fast_source] = numpy.log( exp_minus_lambda[is_fast_source]) * -1.0 is_faster_source = sqrt_lambda > 0 # pylint: disable=assignment-from-no-return spikes_per_tick[is_faster_source] = numpy.square( sqrt_lambda[is_faster_source]) slow_elements = isi > 0 spikes_per_tick[slow_elements] = 1.0 / isi[slow_elements] # Convert spikes per tick to rates self.__data["rates"].set_value_by_id( i, spikes_per_tick * (MICRO_TO_SECOND_CONVERSION / float(self.__machine_time_step))) # Store the updated time until next spike so that it can be # rewritten when the parameters are loaded self.__data["time_to_spike"].set_value_by_id(i, time_to_next_spike)
def poisson_rate_region_address(self, placement, transceiver): return helpful_functions.locate_memory_region_for_placement( placement, self.POISSON_SPIKE_SOURCE_REGIONS.RATES_REGION.value, transceiver)
def get_recording_region_base_address(self, txrx, placement): return locate_memory_region_for_placement( placement, self._REGIONS.RECORDING, txrx)
def bit_field_base_address(self, transceiver, placement): return locate_memory_region_for_placement( placement=placement, transceiver=transceiver, region=POPULATION_BASED_REGIONS.BIT_FIELD_FILTER.value)
def key_to_atom_map_region_base_address(self, transceiver, placement): return locate_memory_region_for_placement( placement=placement, transceiver=transceiver, region=POPULATION_BASED_REGIONS.BIT_FIELD_KEY_MAP.value)
def bit_field_builder_region(self, transceiver, placement): return locate_memory_region_for_placement( placement=placement, transceiver=transceiver, region=self._synapse_regions.bitfield_builder)
def get_connections_from_machine(self, transceiver, placement, machine_edge, graph_mapper, routing_infos, synapse_info, machine_time_step): application_edge = graph_mapper.get_application_edge(machine_edge) if not isinstance(application_edge, ProjectionApplicationEdge): return None # Get details for extraction pre_vertex_slice = graph_mapper.get_slice(machine_edge.pre_vertex) post_vertex_slice = graph_mapper.get_slice(machine_edge.post_vertex) n_synapse_types = self._synapse_type.get_n_synapse_types() # Get the key for the pre_vertex key = routing_infos.get_first_key_for_edge(machine_edge) # Get the key for the delayed pre_vertex delayed_key = None if application_edge.delay_edge is not None: delayed_key = self._delay_key_index[( application_edge.pre_vertex, pre_vertex_slice.lo_atom, pre_vertex_slice.hi_atom)].first_key # Get the block for the connections from the pre_vertex master_pop_table_address = \ helpful_functions.locate_memory_region_for_placement( placement, constants.POPULATION_BASED_REGIONS.POPULATION_TABLE.value, transceiver) synaptic_matrix_address = \ helpful_functions.locate_memory_region_for_placement( placement, constants.POPULATION_BASED_REGIONS.SYNAPTIC_MATRIX.value, transceiver) direct_synapses_address = ( self._get_static_synaptic_matrix_sdram_requirements() + synaptic_matrix_address + struct.unpack_from( "<I", str( transceiver.read_memory(placement.x, placement.y, synaptic_matrix_address, 4)))[0]) indirect_synapses_address = synaptic_matrix_address + 4 data, max_row_length = self._retrieve_synaptic_block( transceiver, placement, master_pop_table_address, indirect_synapses_address, direct_synapses_address, key, pre_vertex_slice.n_atoms, synapse_info.index) # Get the block for the connections from the delayed pre_vertex delayed_data = None delayed_max_row_length = 0 if delayed_key is not None: delayed_data, delayed_max_row_length = \ self._retrieve_synaptic_block( transceiver, placement, master_pop_table_address, indirect_synapses_address, direct_synapses_address, delayed_key, pre_vertex_slice.n_atoms * application_edge.n_delay_stages, synapse_info.index) # Convert the blocks into connections return self._synapse_io.read_synapses( synapse_info, pre_vertex_slice, post_vertex_slice, max_row_length, delayed_max_row_length, n_synapse_types, self._weight_scales[placement], data, delayed_data, application_edge.n_delay_stages, machine_time_step)
def key_to_atom_map_region_base_address(self, transceiver, placement): return locate_memory_region_for_placement( placement=placement, transceiver=transceiver, region=self._synapse_regions.bitfield_key_map)
def bit_field_base_address(self, transceiver, placement): return locate_memory_region_for_placement( placement=placement, transceiver=transceiver, region=self._synapse_regions.bitfield_filter)
def get_recording_region_base_address(self, txrx, placement): return locate_memory_region_for_placement(placement, self.__regions.recording, txrx)
def get_recording_region_base_address(self, txrx, placement): return helpful_functions.locate_memory_region_for_placement( placement, self.DATA_REGIONS.OUTPUT_DATA.value, txrx)
def bit_field_builder_region(self, transceiver, placement): return locate_memory_region_for_placement( placement=placement, transceiver=transceiver, region=POPULATION_BASED_REGIONS.BIT_FIELD_BUILDER.value)
def get_recording_region_base_address(self, txrx, placement): return locate_memory_region_for_placement( placement, self.POISSON_SPIKE_SOURCE_REGIONS.SPIKE_HISTORY_REGION.value, txrx)
def get_recording_region_base_address(self, txrx, placement): return locate_memory_region_for_placement( placement, self.CHIP_POWER_MONITOR_REGIONS.RECORDING.value, txrx)
def get_recording_region_base_address(self, txrx, placement): return locate_memory_region_for_placement( placement, self.DATA_REGIONS.STRING_DATA.value, txrx)
def get_recording_region_base_address(self, txrx, placement): return locate_memory_region_for_placement( placement, POPULATION_BASED_REGIONS.RECORDING.value, txrx)
def get_recording_region_base_address(self, txrx, placement): return helpful_functions.locate_memory_region_for_placement( placement, self._RECALL_REGIONS.RECORDING.value, txrx)
def get_recording_region_base_address(self, txrx, placement): return locate_memory_region_for_placement( placement, POPULATION_BASED_REGIONS.RECORDING.value, txrx)
def get_recording_region_base_address(self, txrx, placement): return locate_memory_region_for_placement( placement, DataRegions.RESULTS, txrx)
def get_recording_region_base_address(self, txrx, placement): return fec_helpful_functions.locate_memory_region_for_placement( placement=placement, transceiver=txrx, region=self.DATA_REGIONS.RECORDING.value)
def get_recording_region_base_address(self, txrx, placement): return locate_memory_region_for_placement(placement, MLPRegions.REC_INFO.value, txrx)
def get_recording_region_base_address(self, txrx, placement): return helpful_functions.locate_memory_region_for_placement( placement, constants.POPULATION_BASED_REGIONS.RECORDING.value, txrx)