sPyNNaker neural_modelling 7.1.1
Loading...
Searching...
No Matches
neuron_impl_external_devices.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017 The University of Manchester
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
19#ifndef _NEURON_IMPL_EXTERNAL_DEVICES_H_
20#define _NEURON_IMPL_EXTERNAL_DEVICES_H_
21
22#include "neuron_impl.h"
23
33
34// Includes for model parts used in this implementation
35
39
42
43// Further includes
44#include <debug.h>
45
46
67
79
87
88// This import depends on variables defined above
90
93
96
99
102
103// Typesafe magic reinterpret cast
104static inline uint _int_bits(int value) {
105 typedef union _int_bits_union {
106 int int_value;
107 uint uint_value;
108 } _int_bits_union;
109
110 _int_bits_union converter;
111 converter.int_value = value;
112 return converter.uint_value;
113}
114
119static inline uint _get_payload(enum send_type type, accum value) {
120 switch (type) {
121 case SEND_TYPE_INT:
122 return _int_bits((int) value);
123 case SEND_TYPE_UINT:
124 return (uint) value;
125 case SEND_TYPE_ACCUM:
126 return _int_bits(bitsk(value));
127 case SEND_TYPE_UACCUM:
128 return bitsuk((unsigned accum) value);
129 case SEND_TYPE_FRACT:
130 return _int_bits(bitslr((long fract) value));
131 case SEND_TYPE_UFRACT:
132 return bitsulr((long unsigned fract) value);
133 default:
134 log_error("Unknown enum value %u", value);
135 rt_error(RTE_SWERR);
136 }
137 return 0;
138}
139
140SOMETIMES_UNUSED // Marked unused as only used sometimes
144static bool neuron_impl_initialise(uint32_t n_neurons) {
145
146 // Allocate DTCM for neuron array
147 log_info("Initialising for %u neurons", n_neurons);
148 neuron_array = spin1_malloc(n_neurons * sizeof(neuron_t));
149 if (neuron_array == NULL) {
150 log_error("Unable to allocate neuron array - Out of DTCM");
151 return false;
152 }
153
154 // Allocate DTCM for packet firing array and copy block of data
156 spin1_malloc(n_neurons * sizeof(packet_firing_data_t));
157 if (packet_firing_array == NULL) {
158 log_error("Unable to allocate packet firing array - Out of DTCM");
159 return false;
160 }
161
162 // Allocate DTCM for synapse shaping parameters
164 spin1_malloc(n_neurons * sizeof(synapse_types_t));
165 if (synapse_types_array == NULL) {
166 log_error("Unable to allocate synapse parameters array"
167 " - Out of DTCM");
168 return false;
169 }
170
171 return true;
172}
173
174SOMETIMES_UNUSED // Marked unused as only used sometimes
180 index_t synapse_type_index, index_t neuron_index,
181 input_t weights_this_timestep) {
182 // simple wrapper to synapse type input function
183 synapse_types_t *parameters = &synapse_types_array[neuron_index];
184 synapse_types_add_neuron_input(synapse_type_index,
185 parameters, weights_this_timestep);
186}
187
191static uint32_t n_words_needed(size_t size) {
192 return (size + (sizeof(uint32_t) - 1)) / sizeof(uint32_t);
193}
194
195SOMETIMES_UNUSED // Marked unused as only used sometimes
196static void neuron_impl_load_neuron_parameters(
197 address_t address, uint32_t next, uint32_t n_neurons,
198 address_t save_initial_state) {
199
200 // Read the number of steps per timestep
201 n_steps_per_timestep = address[next++];
202 if (n_steps_per_timestep > 1) {
203 log_info("Looping over %u steps each timestep", n_steps_per_timestep);
204 } else if (n_steps_per_timestep == 0) {
205 log_error("bad number of steps per timestep: 0");
206 }
207
208 neuron_params_t *neuron_params = (neuron_params_t *) &address[next];
209 for (uint32_t i = 0; i < n_neurons; i++) {
210 neuron_model_initialise(&neuron_array[i], &neuron_params[i], n_steps_per_timestep);
211 }
212 next += n_words_needed(n_neurons * sizeof(neuron_params_t));
213
214 spin1_memcpy(packet_firing_array, &address[next],
217
219 for (uint32_t i = 0; i < n_neurons; i++) {
221 }
223
224 // If we are to save the initial state, copy the whole of the parameters
225 // to the initial state
226 if (save_initial_state) {
227 spin1_memcpy(save_initial_state, address, next * sizeof(uint32_t));
228 }
229
230#if LOG_LEVEL >= LOG_DEBUG
231 for (index_t n = 0; n < n_neurons; n++) {
233 }
234#endif // LOG_LEVEL >= LOG_DEBUG
235}
236
241static bool _test_will_fire(packet_firing_data_t *packet_firing) {
242 if (packet_firing->time_until_next_send == 0) {
243 packet_firing->time_until_next_send =
244 packet_firing->timesteps_between_sending;
245 --packet_firing->time_until_next_send;
246 return true;
247 }
248 --packet_firing->time_until_next_send;
249 return false;
250}
251
252SOMETIMES_UNUSED // Marked unused as only used sometimes
258 UNUSED uint32_t timer_count, UNUSED uint32_t time, uint32_t n_neurons) {
259
260 for (uint32_t neuron_index = 0; neuron_index < n_neurons; neuron_index++) {
261 // Get the neuron itself
262 neuron_t *this_neuron = &neuron_array[neuron_index];
263
264 // Get threshold and additional input parameters for this neuron
265 packet_firing_data_t *the_packet_firing =
266 &packet_firing_array[neuron_index];
267 synapse_types_t *the_synapse_type =
268 &synapse_types_array[neuron_index];
269
270 // Store whether the neuron has spiked
271 bool will_fire = false;
272
273 // Loop however many times requested; do this in reverse for efficiency,
274 // and because the index doesn't actually matter
275 for (uint32_t i = n_steps_per_timestep; i > 0; i--) {
276 // Get the voltage
277 state_t soma_voltage = neuron_model_get_membrane_voltage(this_neuron);
278
279 // Get the exc and inh values from the synapses
281 input_t *exc_input_values =
282 synapse_types_get_excitatory_input(exc_values, the_synapse_type);
284 input_t *inh_input_values =
285 synapse_types_get_inhibitory_input(inh_values, the_synapse_type);
286
287 // Sum g_syn contributions from all receptors for recording
288 REAL total_exc = 0;
289 REAL total_inh = 0;
290
291 for (int i = 0; i < NUM_EXCITATORY_RECEPTORS; i++) {
292 total_exc += exc_input_values[i];
293 }
294 for (int i = 0; i < NUM_INHIBITORY_RECEPTORS; i++) {
295 total_inh += inh_input_values[i];
296 }
297
298 // Do recording if on the first step
299 if (i == n_steps_per_timestep) {
301 V_RECORDING_INDEX, neuron_index, soma_voltage);
303 GSYN_EXC_RECORDING_INDEX, neuron_index, total_exc);
305 GSYN_INH_RECORDING_INDEX, neuron_index, total_inh);
306 }
307
308 // Get any input from an injected current source
309 REAL current_offset = current_source_get_offset(time, neuron_index);
310
311 // update neuron parameters
313 NUM_EXCITATORY_RECEPTORS, exc_input_values,
314 NUM_INHIBITORY_RECEPTORS, inh_input_values,
315 0, current_offset, this_neuron);
316
317 // determine if a packet should fly
318 will_fire = _test_will_fire(the_packet_firing);
319
320 // If spike occurs, communicate to relevant parts of model
321 if (will_fire) {
322 if (the_packet_firing->value_as_payload) {
323 accum value_to_send = result;
324 if (result > the_packet_firing->max_value) {
325 value_to_send = the_packet_firing->max_value;
326 }
327 if (result < the_packet_firing->min_value) {
328 value_to_send = the_packet_firing->min_value;
329 }
330
331 uint payload = _get_payload(
332 the_packet_firing->type,
333 value_to_send * the_packet_firing->value_as_payload);
334
335 send_spike_mc_payload(the_packet_firing->key, payload);
336 } else {
337 send_spike_mc(the_packet_firing->key);
338 }
339 }
340
341 // Shape the existing input according to the included rule
342 synapse_types_shape_input(the_synapse_type);
343 }
344
345 if (will_fire) {
346 // Record the spike
348 }
349
350 #if LOG_LEVEL >= LOG_DEBUG
352 #endif // LOG_LEVEL >= LOG_DEBUG
353 }
354}
355
356SOMETIMES_UNUSED // Marked unused as only used sometimes
362 address_t address, uint32_t next, uint32_t n_neurons) {
363 // Skip over the steps per timestep
364 next += 1;
365
366 neuron_params_t *neuron_params = (neuron_params_t *) &address[next];
367 for (uint32_t i = 0; i < n_neurons; i++) {
368 neuron_model_save_state(&neuron_array[i], &neuron_params[i]);
369 }
370 next += n_words_needed(n_neurons * sizeof(neuron_params_t));
371
372 spin1_memcpy(&address[next], packet_firing_array,
375
377 for (uint32_t i = 0; i < n_neurons; i++) {
379 }
381}
382
383#if LOG_LEVEL >= LOG_DEBUG
384SOMETIMES_UNUSED // Marked unused as only used sometimes
388 bool empty = true;
389 for (index_t i = 0; i < n_neurons; i++) {
393 empty = empty && (0 == bitsk(
396 }
397
398 if (!empty) {
399 for (index_t i = 0; i < n_neurons; i++) {
405 if (bitsk(input) != 0) {
406 log_debug("%3u: %12.6k (= ", i, input);
408 log_debug(")\n");
409 }
410 }
411 }
412}
413
414SOMETIMES_UNUSED // Marked unused as only used sometimes
422
423SOMETIMES_UNUSED // Marked unused as only used sometimes
427const char *neuron_impl_get_synapse_type_char(uint32_t synapse_type) {
428 return synapse_types_get_type_char(synapse_type);
429}
430#endif // LOG_LEVEL >= LOG_DEBUG
431
432#endif // _NEURON_IMPL_EXTERNAL_DEVICES_H_
uint32_t index_t
uint32_t time
The current timer tick value.
Definition c_main.c:94
uint32_t * address_t
General API of a current source implementation.
static REAL current_source_get_offset(uint32_t time, uint32_t neuron_index)
Calculate the current offset from all injected current sources.
Implement all current sources.
void log_error(const char *message,...)
void log_debug(const char *message,...)
void log_info(const char *message,...)
#define NUM_INHIBITORY_RECEPTORS
The number of inhibitory receptors.
Definition input_type.h:37
#define NUM_EXCITATORY_RECEPTORS
The number of excitatory receptors.
Definition input_type.h:28
Input type is standard current-based model.
accum REAL
Type used for "real" numbers.
Definition maths-util.h:89
REAL state_t
The type of a state variable.
REAL input_t
The type of an input.
static uint32_t n_neurons
The number of neurons on the core.
Definition neuron.c:45
General API of a neuron implementation.
bitfield_recording_indices
Indices for recording of bitfields.
@ PACKET_RECORDING_BITFIELD
Spike event recording index.
@ N_BITFIELD_VARS
Number of recorded bitfields.
void neuron_impl_print_synapse_parameters(uint32_t n_neurons)
Print the synapse parameters of the neurons.
static neuron_t * neuron_array
Array of neuron states.
uint32_t key
The key to send to update the value.
const char * neuron_impl_get_synapse_type_char(uint32_t synapse_type)
Get the synapse type character for a synapse type.
static void neuron_impl_do_timestep_update(uint32_t timer_count, uint32_t time, uint32_t n_neurons)
Do the timestep update for the particular implementation.
word_recording_indices
Indices for recording of words.
@ GSYN_INH_RECORDING_INDEX
Gsyn_inh (excitatory synaptic conductance/current) recording index.
@ GSYN_EXC_RECORDING_INDEX
Gsyn_exc (excitatory synaptic conductance/current) recording index.
@ N_RECORDED_VARS
Number of recorded word-sized state variables.
@ V_RECORDING_INDEX
V (somatic potential) recording index.
static uint32_t n_words_needed(size_t size)
The number of words required to hold an object of given size.
send_type
What sort of message payload should we send?
@ SEND_TYPE_ACCUM
Message payload is an accum
@ SEND_TYPE_UFRACT
Message payload is an unsigned fract
@ SEND_TYPE_INT
Message payload is an int32_t
@ SEND_TYPE_UACCUM
Message payload is an unsigned accum
@ SEND_TYPE_UINT
Message payload is an uint32_t
@ SEND_TYPE_FRACT
Message payload is a fract
static void neuron_impl_add_inputs(index_t synapse_type_index, index_t neuron_index, input_t weights_this_timestep)
Add inputs to the neuron.
static packet_firing_data_t * packet_firing_array
Threshold states array.
uint32_t timesteps_between_sending
The time between sending the value.
void neuron_impl_print_inputs(uint32_t n_neurons)
Print the inputs to the neurons.
static bool neuron_impl_initialise(uint32_t n_neurons)
Initialise the particular implementation of the data.
static uint n_steps_per_timestep
The number of steps to run per timestep.
uint32_t time_until_next_send
The time until the next sending of the value (initially 0)
static synapse_types_t * synapse_types_array
The synapse shaping parameters.
static void neuron_impl_store_neuron_parameters(address_t address, uint32_t next, uint32_t n_neurons)
Stores neuron parameters back into SDRAM.
enum send_type type
Send type.
The definition of the threshold.
static void neuron_model_print_state_variables(const neuron_t *neuron)
printout of state variables i.e. those values that might change
static state_t neuron_model_get_membrane_voltage(const neuron_t *neuron)
get the neuron membrane voltage for a given neuron parameter set
static state_t neuron_model_state_update(uint16_t num_excitatory_inputs, const input_t *exc_input, uint16_t num_inhibitory_inputs, const input_t *inh_input, input_t external_bias, REAL current_offset, neuron_t *restrict neuron)
primary function called in timer loop after synaptic updates
static void neuron_model_print_parameters(const neuron_t *neuron)
printout of parameters i.e. those values that don't change
Leaky Integrate and Fire neuron type.
definition of neuron parameters
definition for LIF neuron state
Recording of the state of a neuron (spiking, voltage, etc.)
static void neuron_recording_record_accum(uint32_t var_index, uint32_t neuron_index, accum value)
stores a recording of an accum variable only; this is faster than neuron_recording_record_value for t...
static void neuron_recording_record_bit(uint32_t var_index, uint32_t neuron_index)
stores a recording of a set bit; this is the only way to set a bit in a bitfield; neuron_recording_re...
void rt_error(uint code,...)
#define NULL
void spin1_memcpy(void *dst, void const *src, uint len)
unsigned int uint
static stdp_params params
Configuration parameters.
static void synapse_types_save_state(synapse_types_t *state, synapse_types_params_t *params)
save parameters and state back to SDRAM for reading by host and recovery on restart
static const char * synapse_types_get_type_char(index_t synapse_type_index)
returns a human readable character for the type of synapse.
static input_t * synapse_types_get_excitatory_input(input_t *excitatory_response, synapse_types_t *parameters)
extracts the excitatory input buffers from the buffers available for a given neuron ID
static void synapse_types_initialise(synapse_types_t *state, synapse_types_params_t *params, uint32_t n_steps_per_time_step)
initialise the structure from the parameters
static void synapse_types_add_neuron_input(index_t synapse_type_index, synapse_types_t *parameters, input_t input)
adds the inputs for a give timer period to a given neuron that is being simulated by this model
static void synapse_types_print_input(synapse_types_t *parameters)
prints the input for a neuron ID given the available inputs currently only executed when the models a...
static void synapse_types_print_parameters(synapse_types_t *parameters)
prints the parameters of the synapse type
static void synapse_types_shape_input(synapse_types_t *parameters)
decays the stuff thats sitting in the input buffers as these have not yet been processed and applied ...
static input_t * synapse_types_get_inhibitory_input(input_t *inhibitory_response, synapse_types_t *parameters)
extracts the inhibitory input buffers from the buffers available for a given neuron ID
implementation of synapse_types.h for Exponential shaping
Delta synapses support just a single excitatory and inhibitory input each.
The layout of the synapse parameters region.
Definition synapses.c:257