sPyNNaker neural_modelling  development
neuron_impl_standard.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_STANDARD_H_
20 #define _NEURON_IMPL_STANDARD_H_
21 
22 #include "neuron_impl.h"
23 
24 // Includes for model parts used in this implementation
30 
32 
33 // Further includes
34 #include <debug.h>
35 #include <bit_field.h>
36 #include <recording.h>
37 
47  N_RECORDED_VARS = 3
48 };
49 
55  N_BITFIELD_VARS = 1
56 };
57 
58 // This import depends on variables defined above
60 
63 
66 
69 
72 
75 
78 
79 SOMETIMES_UNUSED // Marked unused as only used sometimes
83 static bool neuron_impl_initialise(uint32_t n_neurons) {
84 
85  // Allocate DTCM for neuron array
86  if (sizeof(neuron_t)) {
87  neuron_array = spin1_malloc(n_neurons * sizeof(neuron_t));
88  if (neuron_array == NULL) {
89  log_error("Unable to allocate neuron array - Out of DTCM");
90  return false;
91  }
92  }
93 
94  // Allocate DTCM for input type array and copy block of data
95  if (sizeof(input_type_t)) {
96  input_type_array = spin1_malloc(n_neurons * sizeof(input_type_t));
97  if (input_type_array == NULL) {
98  log_error("Unable to allocate input type array - Out of DTCM");
99  return false;
100  }
101  }
102 
103  // Allocate DTCM for additional input array and copy block of data
104  if (sizeof(additional_input_t)) {
106  spin1_malloc(n_neurons * sizeof(additional_input_t));
107  if (additional_input_array == NULL) {
108  log_error("Unable to allocate additional input array"
109  " - Out of DTCM");
110  return false;
111  }
112  }
113 
114  // Allocate DTCM for threshold type array and copy block of data
115  if (sizeof(threshold_type_t)) {
117  spin1_malloc(n_neurons * sizeof(threshold_type_t));
118  if (threshold_type_array == NULL) {
119  log_error("Unable to allocate threshold type array - Out of DTCM");
120  return false;
121  }
122  }
123 
124  // Allocate DTCM for synapse shaping parameters
125  if (sizeof(synapse_types_t)) {
127  spin1_malloc(n_neurons * sizeof(synapse_types_t));
128  if (synapse_types_array == NULL) {
129  log_error("Unable to allocate synapse types array - Out of DTCM");
130  return false;
131  }
132  }
133 
134  return true;
135 }
136 
137 SOMETIMES_UNUSED // Marked unused as only used sometimes
143  index_t synapse_type_index, index_t neuron_index,
144  input_t weights_this_timestep) {
145  // simple wrapper to synapse type input function
146  synapse_types_t *parameters = &synapse_types_array[neuron_index];
147  synapse_types_add_neuron_input(synapse_type_index,
148  parameters, weights_this_timestep);
149 }
150 
154 static uint32_t n_words_needed(size_t size) {
155  return (size + (sizeof(uint32_t) - 1)) / sizeof(uint32_t);
156 }
157 
158 SOMETIMES_UNUSED // Marked unused as only used sometimes
165  address_t address, uint32_t next, uint32_t n_neurons,
166  address_t save_initial_state) {
167 
168  // Read the number of steps per timestep
169  n_steps_per_timestep = address[next++];
170  if (n_steps_per_timestep == 0) {
171  log_error("bad number of steps per timestep: 0");
172  rt_error(RTE_SWERR);
173  }
174 
175  if (sizeof(neuron_t)) {
176  neuron_params_t *params = (neuron_params_t *) &address[next];
177  for (uint32_t i = 0; i < n_neurons; i++) {
180  }
181  next += n_words_needed(n_neurons * sizeof(neuron_params_t));
182  }
183 
184  if (sizeof(input_type_t)) {
185  input_type_params_t *params = (input_type_params_t *) &address[next];
186  for (uint32_t i = 0; i < n_neurons; i++) {
189  }
190  next += n_words_needed(n_neurons * sizeof(input_type_params_t));
191  }
192 
193  if (sizeof(threshold_type_t)) {
195  for (uint32_t i = 0; i < n_neurons; i++) {
198  }
200  }
201 
202  if (sizeof(synapse_types_t)) {
204  for (uint32_t i = 0; i < n_neurons; i++) {
207  }
209  }
210 
211  if (sizeof(additional_input_t)) {
213  for (uint32_t i = 0; i < n_neurons; i++) {
216  }
218  }
219 
220  // If we are to save the initial state, copy the whole of the parameters
221  // to the initial state
222  if (save_initial_state) {
223  spin1_memcpy(save_initial_state, address, next * sizeof(uint32_t));
224  }
225 
226 #if LOG_LEVEL >= LOG_DEBUG
227  for (index_t n = 0; n < n_neurons; n++) {
230  }
231 #endif // LOG_LEVEL >= LOG_DEBUG
232 }
233 
234 SOMETIMES_UNUSED // Marked unused as only used sometimes
240  uint32_t timer_count, uint32_t time, uint32_t n_neurons) {
241 
242  for (uint32_t neuron_index = 0; neuron_index < n_neurons; neuron_index++) {
243 
244  // Get the neuron itself
245  neuron_t *this_neuron = &neuron_array[neuron_index];
246 
247  // Get the input_type parameters and voltage for this neuron
248  input_type_t *input_types = &input_type_array[neuron_index];
249 
250  // Get threshold and additional input parameters for this neuron
251  threshold_type_t *the_threshold_type = &threshold_type_array[neuron_index];
252  additional_input_t *additional_inputs = &additional_input_array[neuron_index];
253  synapse_types_t *the_synapse_type = &synapse_types_array[neuron_index];
254 
255  // Loop however many times requested; do this in reverse for efficiency,
256  // and because the index doesn't actually matter
257  for (uint32_t i_step = n_steps_per_timestep; i_step > 0; i_step--) {
258  // Get the voltage
259  state_t soma_voltage = neuron_model_get_membrane_voltage(this_neuron);
260 
261  // Get the exc and inh values from the synapses
262  input_t exc_values[NUM_EXCITATORY_RECEPTORS];
263  input_t *exc_syn_values =
264  synapse_types_get_excitatory_input(exc_values, the_synapse_type);
265  input_t inh_values[NUM_INHIBITORY_RECEPTORS];
266  input_t *inh_syn_values =
267  synapse_types_get_inhibitory_input(inh_values, the_synapse_type);
268 
269  // Call functions to obtain exc_input and inh_input
270  input_t *exc_input_values = input_type_get_input_value(
271  exc_syn_values, input_types, NUM_EXCITATORY_RECEPTORS);
272  input_t *inh_input_values = input_type_get_input_value(
273  inh_syn_values, input_types, NUM_INHIBITORY_RECEPTORS);
274 
275  // Sum g_syn contributions from all receptors for recording
276  REAL total_exc = ZERO;
277  REAL total_inh = ZERO;
278 
279  for (int i = 0; i < NUM_EXCITATORY_RECEPTORS; i++) {
280  total_exc += exc_input_values[i];
281  }
282  for (int i = 0; i < NUM_INHIBITORY_RECEPTORS; i++) {
283  total_inh += inh_input_values[i];
284  }
285 
286  // Do recording if on the first step
287  if (i_step == n_steps_per_timestep) {
289  V_RECORDING_INDEX, neuron_index, soma_voltage);
291  GSYN_EXC_RECORDING_INDEX, neuron_index, total_exc);
293  GSYN_INH_RECORDING_INDEX, neuron_index, total_inh);
294  }
295 
296  // Call functions to convert exc_input and inh_input to current
298  exc_input_values, input_types, soma_voltage);
300  inh_input_values, input_types, soma_voltage);
301 
302  // Get any input from an injected current source
303  REAL current_offset = current_source_get_offset(time, neuron_index);
304 
305  // Get any external bias input
307  additional_inputs, soma_voltage);
308 
309  // update neuron parameters
311  NUM_EXCITATORY_RECEPTORS, exc_input_values,
312  NUM_INHIBITORY_RECEPTORS, inh_input_values,
313  external_bias, current_offset, this_neuron);
314 
315  // determine if a spike should occur
316  bool spike_now =
317  threshold_type_is_above_threshold(result, the_threshold_type);
318 
319  // If spike occurs, communicate to relevant parts of model
320  if (spike_now) {
321 
322  // Call relevant model-based functions
323  // Tell the neuron model
324  neuron_model_has_spiked(this_neuron);
325 
326  // Tell the additional input
327  additional_input_has_spiked(additional_inputs);
328 
329  // Record the spike
331 
332  // Send the spike
333  send_spike(timer_count, time, neuron_index);
334  }
335 
336  // Shape the existing input according to the included rule
337  synapse_types_shape_input(the_synapse_type);
338  }
339 
340  #if LOG_LEVEL >= LOG_DEBUG
342  #endif // LOG_LEVEL >= LOG_DEBUG
343  }
344 }
345 
346 SOMETIMES_UNUSED // Marked unused as only used sometimes
352  address_t address, uint32_t next, uint32_t n_neurons) {
353 
354  // Skip over the steps per timestep
355  next += 1;
356 
357  if (sizeof(neuron_t)) {
358  neuron_params_t *params = (neuron_params_t *) &address[next];
359  for (uint32_t i = 0; i < n_neurons; i++) {
361  }
362  next += n_words_needed(n_neurons * sizeof(neuron_params_t));
363  }
364 
365  if (sizeof(input_type_t)) {
366  input_type_params_t *params = (input_type_params_t *) &address[next];
367  for (uint32_t i = 0; i < n_neurons; i++) {
369  }
370  next += n_words_needed(n_neurons * sizeof(input_type_params_t));
371  }
372 
373  if (sizeof(threshold_type_t)) {
375  for (uint32_t i = 0; i < n_neurons; i++) {
377  }
379  }
380 
381  if (sizeof(synapse_types_t)) {
383  for (uint32_t i = 0; i < n_neurons; i++) {
385  }
387  }
388 
389  if (sizeof(additional_input_t)) {
391  for (uint32_t i = 0; i < n_neurons; i++) {
393  }
395  }
396 }
397 
398 #if LOG_LEVEL >= LOG_DEBUG
399 SOMETIMES_UNUSED // Marked unused as only used sometimes
403  bool empty = true;
404  for (index_t i = 0; i < n_neurons; i++) {
406  input_t exc_values[NUM_EXCITATORY_RECEPTORS];
407  input_t inh_values[NUM_INHIBITORY_RECEPTORS];
408  empty = empty && (0 == bitsk(
410  - synapse_types_get_inhibitory_input(inh_values, params)[0]));
411  }
412 
413  if (!empty) {
414  for (index_t i = 0; i < n_neurons; i++) {
416  input_t exc_values[NUM_EXCITATORY_RECEPTORS];
417  input_t inh_values[NUM_INHIBITORY_RECEPTORS];
418  input_t *exc_input = synapse_types_get_excitatory_input(exc_values, params);
419  input_t *inh_input = synapse_types_get_inhibitory_input(inh_values, params);
420  input_t input = exc_input[0] - inh_input[0];
421  if (bitsk(input) != 0) {
422  log_debug("Neuron %3u: input %12.6k (= ", i, input);
424  log_debug(")");
425  }
426  }
427  }
428 }
429 
430 SOMETIMES_UNUSED // Marked unused as only used sometimes
434  for (index_t n = 0; n < n_neurons; n++) {
436  }
437 }
438 
439 SOMETIMES_UNUSED // Marked unused as only used sometimes
443 const char *neuron_impl_get_synapse_type_char(uint32_t synapse_type) {
444  return synapse_types_get_type_char(synapse_type);
445 }
446 #endif // LOG_LEVEL >= LOG_DEBUG
447 
448 #endif // _NEURON_IMPL_STANDARD_H_
API for additional inputs.
static input_t additional_input_get_input_value_as_current(struct additional_input_t *additional_input, state_t membrane_voltage)
Gets the value of current provided by the additional input this timestep.
static void additional_input_initialise(additional_input_t *state, additional_input_params_t *params, uint32_t n_steps_per_timestep)
initialise the structure from the parameters
static void additional_input_save_state(additional_input_t *state, additional_input_params_t *params)
save parameters and state back to SDRAM for reading by host and recovery on restart
static void additional_input_has_spiked(struct additional_input_t *additional_input)
Notifies the additional input type that the neuron has spiked.
The additional input is due to calcium ions.
The additional input is due to calcium ions.
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.
static uint32_t time
Simulation time.
API for synaptic inputs (see also src/neuron/synapse_types)
static void input_type_convert_inhibitory_input_to_current(input_t *restrict inh_input, const input_type_t *input_type, state_t membrane_voltage)
Converts an inhibitory input into an inhibitory current.
static void input_type_initialise(input_type_t *state, input_type_params_t *params, uint32_t n_steps_per_timestep)
initialise the structure from the parameters
#define NUM_INHIBITORY_RECEPTORS
The number of inhibitory receptors.
Definition: input_type.h:37
static input_t * input_type_get_input_value(input_t *restrict value, input_type_t *input_type, uint16_t num_receptors)
Gets the actual input value. This allows any scaling to take place.
#define NUM_EXCITATORY_RECEPTORS
The number of excitatory receptors.
Definition: input_type.h:28
static void input_type_save_state(input_type_t *state, input_type_params_t *params)
save parameters and state back to SDRAM for reading by host and recovery on restart
static void input_type_convert_excitatory_input_to_current(input_t *restrict exc_input, const input_type_t *input_type, state_t membrane_voltage)
Converts an excitatory input into an excitatory current.
Conductance input parameters.
Conductance state.
accum REAL
Type used for "real" numbers.
Definition: maths-util.h:91
#define ZERO
A REAL 0.0.
Definition: maths-util.h:123
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.
word_recording_indices
Indices for recording of words.
@ SPIKE_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.
static input_type_t * input_type_array
Input states array.
static threshold_type_t * threshold_type_array
Threshold states array.
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.
static void neuron_impl_load_neuron_parameters(address_t address, uint32_t next, uint32_t n_neurons, address_t save_initial_state)
Load in the neuron parameters.
@ 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.
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 additional_input_t * additional_input_array
Additional input array.
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.
const char * neuron_impl_get_synapse_type_char(uint32_t synapse_type)
Get the synapse type character for a synapse type.
static uint n_steps_per_timestep
The number of steps to run per timestep.
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.
The API for neuron models themselves.
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_has_spiked(neuron_t *restrict neuron)
Indicates that the neuron has spiked.
static void neuron_model_initialise(neuron_t *state, neuron_params_t *params, uint32_t n_steps_per_timestep)
initialise the structure from the parameters
static void neuron_model_save_state(neuron_t *state, neuron_params_t *params)
save parameters and state back to SDRAM for reading by host and recovery on restart
static void neuron_model_print_parameters(const neuron_t *neuron)
printout of parameters i.e. those values that don't change
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...
static stdp_params params
Configuration parameters.
API for synaptic behaviour types (see also src/neuron/input_types)
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 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 const char * synapse_types_get_type_char(index_t synapse_type_index)
returns a human readable character for the type of synapse.
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 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_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
Delta synapses support just a single excitatory and inhibitory input each.
API for threshold types.
static void threshold_type_initialise(threshold_type_t *state, threshold_type_params_t *params, uint32_t n_steps_per_timestep)
initialise the state from the parameters
static void threshold_type_save_state(threshold_type_t *state, threshold_type_params_t *params)
save parameters and state back to SDRAM for reading by host and recovery on restart
static bool threshold_type_is_above_threshold(state_t value, threshold_type_t *threshold_type)
Determines if the value given is above the threshold value.
Stochastic threshold parameters.
Stochastic threshold configuration.