sPyNNaker neural_modelling  7.4.2
current_source.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 
21 #ifndef _CURRENT_SOURCE_H_
22 #define _CURRENT_SOURCE_H_
23 
24 #include <common/neuron-typedefs.h>
25 
26 // Struct for current source id type and current source index of that type
27 typedef struct cs_id_index_t {
28  uint32_t cs_id;
29  uint32_t cs_index;
31 
32 // Global struct for each neuron's current source IDs and indices
33 typedef struct neuron_current_source_t {
34  uint32_t n_current_sources; // the number of current sources for this neuron
35  cs_id_index_t cs_id_index_list[]; // the list of CS type ID and index in that type
37 
38 // Global values for the total number of current sources and number of each type
39 static uint32_t n_current_sources;
40 static uint32_t n_dc_sources;
41 static uint32_t n_ac_sources;
42 static uint32_t n_step_sources;
43 static uint32_t n_noisy_sources;
44 
45 static uint32_t n_neurons_on_core;
46 
47 static neuron_current_source_t **neuron_current_source;
48 
49 #ifndef SOMETIMES_UNUSED
50 #define SOMETIMES_UNUSED __attribute__((unused))
51 #endif // !SOMETIMES_UNUSED
52 
53 SOMETIMES_UNUSED // Marked unused as only used sometimes
58 static bool current_source_initialise(address_t cs_address, uint32_t n_neurons) {
59  // Avoid the loops if no current sources
60  #if !defined(_CURRENT_SOURCE_DC_H_) && !defined(_CURRENT_SOURCE_AC_H) && \
61  !defined(_CURRENT_SOURCE_STEP_H_) && !defined(_CURRENT_SOURCE_NOISY_H_)
62  return true;
63  #else
64 
65  n_neurons_on_core = n_neurons;
66 
67  // Read from cs_address; the first value is the number of current sources
68  n_current_sources = cs_address[0];
69 
70  // Don't initialise if no current sources
71  if (n_current_sources != 0) {
72 
73  neuron_current_source = spin1_malloc(n_neurons * sizeof(uint32_t*));
74 
75  // Loop over neurons and read in the current IDs and indices
76  uint32_t next = 1;
77  for (uint32_t n=0; n < n_neurons; n++) {
78  uint32_t n_sources = (uint32_t) cs_address[next];
79  uint32_t struct_size = (1 + (2 * n_sources)) * sizeof(uint32_t);
80  neuron_current_source[n] = spin1_malloc(struct_size);
81  spin1_memcpy(neuron_current_source[n], &cs_address[next], struct_size);
82 
83  next += 1 + (n_sources * 2);
84 
85  }
86 
87  // Read number of each type of current source
88  n_dc_sources = (uint32_t) cs_address[next++];
89  n_ac_sources = (uint32_t) cs_address[next++];
90  n_step_sources = (uint32_t) cs_address[next++];
91  n_noisy_sources = (uint32_t) cs_address[next++];
92 
93  // Now initialise separate sources
94 #ifdef _CURRENT_SOURCE_DC_H_
95  if (!current_source_dc_init(n_dc_sources, &next)) {
96  return false;
97  }
98 #else
99  if (n_dc_sources > 0) {
100  log_error("DC current source is not supported for this build");
101  return false;
102  }
103 #endif
104 
105 #ifdef _CURRENT_SOURCE_AC_H_
106  if (!current_source_ac_init(n_ac_sources, &next)) {
107  return false;
108  }
109 #else
110  if (n_ac_sources > 0) {
111  log_error("AC current source is not supported for this build");
112  return false;
113  }
114 #endif
115 
116 #ifdef _CURRENT_SOURCE_STEP_H_
117  if (!current_source_step_init(cs_address, n_step_sources, &next)) {
118  return false;
119  }
120 #else
121  if (n_step_sources > 0) {
122  log_error("Step current source is not supported for this build");
123  return false;
124  }
125 #endif
126 
127 #ifdef _CURRENT_SOURCE_NOISY_H_
128  if (!current_source_noisy_init(n_noisy_sources, &next)) {
129  return false;
130  }
131 #else
132  if (n_noisy_sources > 0) {
133  log_error("Noisy current source is not supported for this build");
134  return false;
135  }
136 #endif
137 
138  }
139 
140  return true;
141 
142  #endif
143 }
144 
145 SOMETIMES_UNUSED // Marked unused as only used sometimes
149 static bool current_source_load_parameters(address_t cs_address) {
150  // Avoid the loops if no current sources
151  #if !defined(_CURRENT_SOURCE_DC_H_) && !defined(_CURRENT_SOURCE_AC_H) && \
152  !defined(_CURRENT_SOURCE_STEP_H_) && !defined(_CURRENT_SOURCE_NOISY_H_)
153  io_printf(IO_BUF, "no current sources defined \n");
154  return true;
155  #else
156 
157  // Read the number of current sources
158  n_current_sources = cs_address[0];
159 
160  // Don't load if no current sources
161  if (n_current_sources != 0) {
162  uint32_t next = 1;
163 
164  // Copy data into neuron_current_source array
165  for (uint32_t n=0; n < n_neurons_on_core; n++) {
166  uint32_t n_sources = (uint32_t) cs_address[next];
167  uint32_t struct_size = (1 + (2 * n_sources)) * sizeof(uint32_t);
168  neuron_current_source[n] = spin1_malloc(struct_size);
169  spin1_memcpy(neuron_current_source[n], &cs_address[next], struct_size);
170 
171  next += 1 + (n_sources * 2);
172  }
173 
174  // Read number of each type of current source
175  n_dc_sources = (uint32_t) cs_address[next++];
176  n_ac_sources = (uint32_t) cs_address[next++];
177  n_step_sources = (uint32_t) cs_address[next++];
178  n_noisy_sources = (uint32_t) cs_address[next++];
179 
180  // Copy into individual source arrays
181 #ifdef _CURRENT_SOURCE_DC_H_
182  current_source_dc_load_parameters(cs_address, n_dc_sources, &next);
183 #endif
184 #ifdef _CURRENT_SOURCE_AC_H_
185  current_source_ac_load_parameters(cs_address, n_ac_sources, &next);
186 #endif
187 #ifdef _CURRENT_SOURCE_STEP_H_
188  current_source_step_load_parameters(cs_address, n_step_sources, &next);
189 #endif
190 #ifdef _CURRENT_SOURCE_NOISY_H_
191  current_source_noisy_load_parameters(cs_address, n_noisy_sources, &next);
192 #endif
193 
194  }
195 
196  return true;
197 
198  #endif
199 }
200 
201 
202 SOMETIMES_UNUSED // Marked unused as only used sometimes
207 static inline REAL current_source_get_offset(uint32_t time, uint32_t neuron_index) {
208  // Avoid the loops if no current sources defined
209  #if !defined(_CURRENT_SOURCE_DC_H_) && !defined(_CURRENT_SOURCE_AC_H) && \
210  !defined(_CURRENT_SOURCE_STEP_H_) && !defined(_CURRENT_SOURCE_NOISY_H_)
211  return ZERO;
212  #else
213 
214  REAL current_offset = ZERO;
215 
216  // Also avoid the loop if no current sources set by user
217  if (n_current_sources != 0) {
218  uint32_t n_current_sources_neuron =
219  neuron_current_source[neuron_index]->n_current_sources;
220  if (n_current_sources_neuron > 0) {
221  for (uint32_t n_cs=0; n_cs < n_current_sources_neuron; n_cs++) {
222  uint32_t cs_id =
223  neuron_current_source[neuron_index]->cs_id_index_list[n_cs].cs_id;
224  uint32_t cs_index =
225  neuron_current_source[neuron_index]->cs_id_index_list[n_cs].cs_index;
226  // Now do the appropriate calculation based on the ID value
227  #ifdef _CURRENT_SOURCE_DC_H_
228  if (cs_id == 1) { // DCSource
229  current_offset += current_source_dc_get_offset(cs_index, time);
230  }
231  #endif
232  #ifdef _CURRENT_SOURCE_AC_H_
233  if (cs_id == 2) { // ACSource
234  current_offset += current_source_ac_get_offset(cs_index, time);
235  }
236  #endif
237  #ifdef _CURRENT_SOURCE_STEP_H_
238  if (cs_id == 3) { // StepCurrentSource
239  current_offset += current_source_step_get_offset(cs_index, time);
240  }
241  #endif
242  #ifdef _CURRENT_SOURCE_NOISY_H_
243  if (cs_id == 4) { // NoisyCurrentSource
244  current_offset += current_source_noisy_get_offset(cs_index, time);
245  }
246  #endif
247  }
248 
249  }
250  }
251 
252  return current_offset;
253 
254  #endif
255 }
256 
257 #endif // _CURRENT_SOURCE_H_
static bool current_source_initialise(address_t cs_address, uint32_t n_neurons)
Initialise the particular implementation of the data.
static REAL current_source_get_offset(uint32_t time, uint32_t neuron_index)
Calculate the current offset from all injected current sources.
static bool current_source_load_parameters(address_t cs_address)
Load the data into the allocated array structures.
static uint32_t time
Simulation time.
accum REAL
Type used for "real" numbers.
Definition: maths-util.h:91
#define ZERO
A REAL 0.0.
Definition: maths-util.h:123
Data type definitions for SpiNNaker Neuron-modelling.
static uint32_t n_neurons
The number of neurons on the core.
Definition: neuron.c:45