sPyNNaker neural_modelling  7.4.2
synapses.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 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 #include "synapses.h"
20 #include "spike_processing.h"
21 #include "neuron.h"
23 #include <profiler.h>
24 #include <debug.h>
25 #include <spin1_api.h>
26 #include <utils.h>
27 
29 #ifdef PROFILER_ENABLED
30 #include "profile_tags.h"
31 #endif //PROFILER_ENABLED
32 
35 
37 static uint32_t n_neurons;
38 
40 static uint32_t n_synapse_types;
41 
43 static weight_t *ring_buffers;
44 
46 static uint32_t ring_buffer_size;
47 
49 static uint32_t ring_buffer_mask;
50 
53 
78 
81 
84 uint32_t skipped_synapses = 0;
85 
87 uint32_t late_spikes = 0;
88 
90 uint32_t max_late_spike = 0;
91 
93 static uint32_t n_neurons_peak;
94 
96 static uint32_t synapse_delay_mask_shifted = 0;
97 
98 
99 /* PRIVATE FUNCTIONS */
100 
101 #if LOG_LEVEL >= LOG_DEBUG
105 static inline const char *get_type_char(uint32_t synapse_type) {
106  return neuron_get_synapse_type_char(synapse_type);
107 }
108 #endif // LOG_LEVEL >= LOG_DEBUG
109 
114 static inline void print_synaptic_row(synaptic_row_t synaptic_row) {
115  log_debug("Synaptic row, at address %08x, Num plastic words:%u",
116  (uint32_t) synaptic_row, synapse_row_plastic_size(synaptic_row));
117  if (synaptic_row == NULL) {
118  return;
119  }
120 #if LOG_LEVEL >= LOG_DEBUG
121  io_printf(IO_BUF, "----------------------------------------\n");
122 
123  // Get details of fixed region
124  synapse_row_fixed_part_t *fixed_region =
125  synapse_row_fixed_region(synaptic_row);
126  address_t fixed_synapses = synapse_row_fixed_weight_controls(fixed_region);
127  size_t n_fixed_synapses = synapse_row_num_fixed_synapses(fixed_region);
128  io_printf(IO_BUF,
129  "Fixed region %u fixed synapses (%u plastic control words):\n",
130  n_fixed_synapses, synapse_row_num_plastic_controls(fixed_region));
131 
132  for (uint32_t i = 0; i < n_fixed_synapses; i++) {
133  uint32_t synapse = fixed_synapses[i];
134  uint32_t synapse_type = synapse_row_sparse_type(
136 
137  io_printf(IO_BUF, "%08x [%3d: (w: %5u (=",
138  synapse, i, synapse_row_sparse_weight(synapse));
140  ring_buffer_to_input_left_shifts[synapse_type]);
141  io_printf(IO_BUF, "nA) d: %2u, %d, n = %3u)] - {%08x %08x}\n",
144  synapse_type,
147  }
148 
149  // If there's a plastic region
150  if (synapse_row_plastic_size(synaptic_row) > 0) {
151  io_printf(IO_BUF, "----------------------------------------\n");
152  synapse_row_plastic_data_t *plastic_data =
153  synapse_row_plastic_region(synaptic_row);
155  plastic_data, fixed_region, ring_buffer_to_input_left_shifts);
156  }
157 
158  io_printf(IO_BUF, "----------------------------------------\n");
159 #endif // LOG_LEVEL >= LOG_DEBUG
160 }
161 
165 static inline void print_ring_buffers(uint32_t time) {
166  log_debug("Ring Buffer at %u", time);
167 #if LOG_LEVEL >= LOG_DEBUG
168  io_printf(IO_BUF, "----------------------------------------\n");
169  uint32_t n_delay_bits = (1 << synapse_delay_bits);
170  for (uint32_t n = 0; n < n_neurons; n++) {
171  for (uint32_t t = 0; t < n_synapse_types; t++) {
172  // Determine if this row can be omitted
173  for (uint32_t d = 0; d < n_delay_bits; d++) {
175  d + time, t, n, synapse_type_index_bits,
177  goto doPrint;
178  }
179  }
180  continue;
181  doPrint:
182  // Have to print the row
183  io_printf(IO_BUF, "%3d(%s):", n, get_type_char(t));
184  for (uint32_t d = 0; d < n_delay_bits; d++) {
185  io_printf(IO_BUF, " ");
186  uint32_t ring_buffer_index = synapse_row_get_ring_buffer_index(
187  d + time, t, n, synapse_type_index_bits,
189  synapses_print_weight(ring_buffers[ring_buffer_index],
191  }
192  io_printf(IO_BUF, "\n");
193  }
194  }
195  io_printf(IO_BUF, "----------------------------------------\n");
196 #endif // LOG_LEVEL >= LOG_DEBUG
197 }
198 
199 
206 static inline bool process_fixed_synapses(
207  synapse_row_fixed_part_t *fixed_region, uint32_t time,
208  uint32_t colour_delay) {
209  uint32_t *synaptic_words = synapse_row_fixed_weight_controls(fixed_region);
210  uint32_t fixed_synapse = synapse_row_num_fixed_synapses(fixed_region);
211 
212  num_fixed_pre_synaptic_events += fixed_synapse;
213 
214  // Pre-mask the time and account for colour delay
215  uint32_t colour_delay_shifted = colour_delay << synapse_type_index_bits;
216  uint32_t masked_time = ((time - colour_delay) & synapse_delay_mask) << synapse_type_index_bits;
217  uint32_t sat_flag = 0xFFFF0000;
218  uint32_t sat_value = 0xFFFF;
219 
220  for (; fixed_synapse > 0; fixed_synapse--) {
221  // Get the next 32 bit word from the synaptic_row
222  // (should auto increment pointer in single instruction)
223  uint32_t synaptic_word = *synaptic_words++;
224 
225  // If the (shifted) delay is non zero and too small, skip
226  if (((synaptic_word & synapse_delay_mask_shifted) != 0) &&
227  ((synaptic_word & synapse_delay_mask_shifted) <= colour_delay_shifted)) {
229  continue;
230  }
231 
232  // The ring buffer index can be found by adding on the time to the delay
233  // in the synaptic word directly, and then masking off the whole index.
234  // The addition of the masked time to the delay even with the mask might
235  // overflow into the weight at worst but can't affect the lower bits.
236  uint32_t ring_buffer_index = (synaptic_word + masked_time) & ring_buffer_mask;
237  uint32_t weight = synapse_row_sparse_weight(synaptic_word);
238 
239  // Add weight to current ring buffer value
240  uint32_t accumulation = ring_buffers[ring_buffer_index] + weight;
241 
242  // If any of bits 31-17 are set, saturate accumulator at UINT16_MAX (0xFFFF)
243  uint32_t sat_test = accumulation & sat_flag;
244  if (sat_test) {
245  accumulation = sat_value;
247  }
248 
249  // Store saturated value back in ring-buffer
250  ring_buffers[ring_buffer_index] = accumulation;
251  }
252  return true;
253 }
254 
257  uint32_t n_neurons;
258  uint32_t n_synapse_types;
259  uint32_t log_n_neurons;
260  uint32_t log_n_synapse_types;
261  uint32_t log_max_delay;
262  uint32_t drop_late_packets;
263  uint32_t incoming_spike_buffer_size;
264  uint32_t ring_buffer_shifts[];
265 };
266 
267 /* INTERFACE FUNCTIONS */
269  address_t synapse_params_address,
270  uint32_t *n_neurons_out, uint32_t *n_synapse_types_out,
271  weight_t **ring_buffers_out,
272  uint32_t **ring_buffer_to_input_buffer_left_shifts,
273  bool* clear_input_buffers_of_late_packets_init,
274  uint32_t *incoming_spike_buffer_size) {
275  struct synapse_params *params = (struct synapse_params *) synapse_params_address;
276  *clear_input_buffers_of_late_packets_init = params->drop_late_packets;
277  *incoming_spike_buffer_size = params->incoming_spike_buffer_size;
278  n_neurons = params->n_neurons;
279  *n_neurons_out = n_neurons;
280  n_synapse_types = params->n_synapse_types;
281  *n_synapse_types_out = n_synapse_types;
282 
283  uint32_t log_n_neurons = params->log_n_neurons;
284  uint32_t log_n_synapse_types = params->log_n_synapse_types;
285  uint32_t log_max_delay = params->log_max_delay;
286 
287  // Set up ring buffer left shifts
289  spin1_malloc(n_synapse_types * sizeof(uint32_t));
290  if (ring_buffer_to_input_left_shifts == NULL) {
291  log_error("Not enough memory to allocate ring buffer");
292  return false;
293  }
294 
295  // read in ring buffer to input left shifts
296  spin1_memcpy(
297  ring_buffer_to_input_left_shifts, params->ring_buffer_shifts,
298  n_synapse_types * sizeof(uint32_t));
299  *ring_buffer_to_input_buffer_left_shifts =
301 
302  synapse_type_index_bits = log_n_neurons + log_n_synapse_types;
304  synapse_index_bits = log_n_neurons;
306  synapse_type_bits = log_n_synapse_types;
307  synapse_type_mask = (1 << log_n_synapse_types) - 1;
308  synapse_delay_bits = log_max_delay;
311 
312  n_neurons_peak = 1 << log_n_neurons;
313 
314  uint32_t n_ring_buffer_bits =
315  log_n_neurons + log_n_synapse_types + synapse_delay_bits;
316  ring_buffer_size = 1 << (n_ring_buffer_bits);
318 
319  ring_buffers = spin1_malloc(ring_buffer_size * sizeof(weight_t));
320  if (ring_buffers == NULL) {
321  log_error("Could not allocate %u entries for ring buffers; Biggest space %u",
322  ring_buffer_size, sark_heap_max(sark.heap, 0));
323  return false;
324  }
325  for (uint32_t i = 0; i < ring_buffer_size; i++) {
326  ring_buffers[i] = 0;
327  }
328  *ring_buffers_out = ring_buffers;
329 
330  log_info("Ready to process synapses for %u neurons with %u synapse types",
332 
333  return true;
334 }
335 
337  uint32_t synapse_index = 0;
338  uint32_t ring_buffer_index = synapse_row_get_first_ring_buffer_index(
340  for (uint32_t s_i = n_synapse_types; s_i > 0; s_i--) {
341  uint32_t neuron_index = 0;
342  for (uint32_t n_i = n_neurons_peak; n_i > 0; n_i--) {
343  ring_buffers[ring_buffer_index] = 0;
344  ring_buffer_index++;
345  neuron_index++;
346  }
347  synapse_index++;
348  }
349 }
350 
352  uint32_t time, uint32_t spike_colour, uint32_t colour_mask,
353  synaptic_row_t row, bool *write_back) {
354 
355  // Work out how much delay takes off or adds on to the actual delay because
356  // of a delayed spike arrival time, or delayed change of time step in the
357  // current core. Spikes can be as late as the bits in colour_mask dictates.
358  // Masked difference is used to calculate this, which will always be
359  // positive because the mask removes the negative bit.
360  // Example: time colour 8, spike colour 13, colour mask 0xF means time
361  // colour has gone up to 15 and then wrapped since spike was sent.
362  // 8 - 13 = -5; -5 & 0xF = 11, so spike was sent 11 steps ago.
363  uint32_t time_colour = time & colour_mask;
364  int32_t colour_diff = time_colour - spike_colour;
365  uint32_t colour_delay = colour_diff & colour_mask;
366 
367  late_spikes += colour_delay & 0x1;
368  if (colour_delay > max_late_spike) {
369  max_late_spike = colour_delay;
370  }
371 
372  // By default don't write back
373  *write_back = false;
374 
375  // Get address of non-plastic region from row
377 
378  // **TODO** multiple optimised synaptic row formats
379  //if (plastic_tag(row) == 0) {
380  // If this row has a plastic region
381  if (synapse_row_plastic_size(row) > 0) {
382  // Get region's address
383  synapse_row_plastic_data_t *plastic_data =
385 
386  // Process any plastic synapses
387  profiler_write_entry_disable_fiq(
388  PROFILER_ENTER | PROFILER_PROCESS_PLASTIC_SYNAPSES);
390  fixed_region, ring_buffers, time, colour_delay, write_back)) {
391  return false;
392  }
393  profiler_write_entry_disable_fiq(
394  PROFILER_EXIT | PROFILER_PROCESS_PLASTIC_SYNAPSES);
395  }
396 
397  // Process any fixed synapses
398  // **NOTE** this is done after initiating DMA in an attempt
399  // to hide cost of DMA behind this loop to improve the chance
400  // that the DMA controller is ready to read next synaptic row afterwards
401  return process_fixed_synapses(fixed_region, time, colour_delay);
402  //}
403 }
404 
408 }
409 
410 void synapses_resume(timer_t time) {
411  // If the time has been reset to zero then the ring buffers need to be
412  // flushed in case there is a delayed spike left over from a previous run
413  if (time == 0) {
414  for (uint32_t i = 0; i < ring_buffer_size; i++) {
415  ring_buffers[i] = 0;
416  }
417  }
418 }
static uint32_t colour_mask
The mask to apply to get the colour from the current timestep or key.
static uint32_t time
Simulation time.
struct synaptic_row * synaptic_row_t
The type of a synaptic row.
@ PROFILER_PROCESS_PLASTIC_SYNAPSES
plastic synapse processing
Definition: profile_tags.h:27
const char * neuron_get_synapse_type_char(uint32_t synapse_type)
Get the synapse type description character.
Definition: neuron.c:238
interface for neurons
Spike processing API.
API for synapse dynamics.
The format of the plastic data region of a synaptic row.
static stdp_params params
Configuration parameters.
uint32_t synapse_dynamics_get_plastic_pre_synaptic_events(void)
Get the counters for plastic pre synaptic events based on (if the model was compiled with SYNAPSE_BEN...
void synapse_dynamics_print_plastic_synapses(synapse_row_plastic_data_t *plastic_region_data, synapse_row_fixed_part_t *fixed_region, uint32_t *ring_buffer_to_input_buffer_left_shifts)
Print the synapse dynamics.
bool synapse_dynamics_process_plastic_synapses(synapse_row_plastic_data_t *plastic_region_address, synapse_row_fixed_part_t *fixed_region, weight_t *ring_buffers, uint32_t time, uint32_t colour_delay, bool *write_back)
Process the dynamics of the synapses.
static index_t synapse_row_get_first_ring_buffer_index(uint32_t simulation_timestep, uint32_t synapse_type_index_bits, int32_t synapse_delay_mask)
Get the index of the first ring buffer for a given timestep.
Definition: synapse_row.h:285
static size_t synapse_row_num_plastic_controls(const synapse_row_fixed_part_t *fixed)
Get the number of plastic controls in the row.
Definition: synapse_row.h:164
static uint32_t * synapse_row_fixed_weight_controls(synapse_row_fixed_part_t *fixed)
The array of fixed weights in the row.
Definition: synapse_row.h:180
static synapse_row_fixed_part_t * synapse_row_fixed_region(synaptic_row_t row)
Get the address of the non-plastic (or fixed) region.
Definition: synapse_row.h:147
static index_t synapse_row_sparse_type(uint32_t x, uint32_t synapse_index_bits, uint32_t synapse_type_mask)
Get the type code.
Definition: synapse_row.h:201
static size_t synapse_row_num_fixed_synapses(const synapse_row_fixed_part_t *fixed)
Get the number of fixed synapses in the row.
Definition: synapse_row.h:156
static index_t synapse_row_sparse_index(uint32_t x, uint32_t synapse_index_mask)
Get the index.
Definition: synapse_row.h:190
static index_t synapse_row_sparse_delay(uint32_t x, uint32_t synapse_type_index_bits, uint32_t synapse_delay_mask)
Get the delay from an encoded synapse descriptor.
Definition: synapse_row.h:222
static synapse_row_plastic_data_t * synapse_row_plastic_region(synaptic_row_t row)
Get the address of the plastic region.
Definition: synapse_row.h:138
static size_t synapse_row_plastic_size(const synaptic_row_t row)
Get the size of the plastic region.
Definition: synapse_row.h:129
static index_t synapse_row_get_ring_buffer_index(uint32_t simulation_timestep, uint32_t synapse_type_index, uint32_t neuron_index, uint32_t synapse_type_index_bits, uint32_t synapse_index_bits, uint32_t synapse_delay_mask)
Get the index of the ring buffer for a given timestep, synapse type and neuron index.
Definition: synapse_row.h:259
static weight_t synapse_row_sparse_weight(uint32_t x)
Get the weight from an encoded synapse descriptor.
Definition: synapse_row.h:230
The type of the fixed part of the row. The fixed-plastic part follows.
Definition: synapse_row.h:118
uint32_t max_late_spike
The maximum lateness of a spike.
Definition: synapses.c:90
void synapses_flush_ring_buffers(timer_t time)
Reset the ring buffers to 0 at the given time.
Definition: synapses.c:336
static bool process_fixed_synapses(synapse_row_fixed_part_t *fixed_region, uint32_t time, uint32_t colour_delay)
The "inner loop" of the neural simulation.
Definition: synapses.c:206
uint32_t synapse_delay_mask
Mask to pick out the delay.
Definition: synapses.c:77
uint32_t synapse_type_index_bits
Number of bits needed for the synapse type and index.
Definition: synapses.c:59
static const char * get_type_char(uint32_t synapse_type)
get the synapse type character
Definition: synapses.c:105
static uint32_t n_neurons_peak
Number of neurons.
Definition: synapses.c:93
static void print_synaptic_row(synaptic_row_t synaptic_row)
Print a synaptic row.
Definition: synapses.c:114
static uint32_t n_neurons
The number of neurons.
Definition: synapses.c:37
uint32_t synapse_index_bits
Number of bits in the synapse index.
Definition: synapses.c:67
uint32_t synapse_index_mask
Mask to pick out the synapse index.
Definition: synapses.c:69
uint32_t synapses_saturation_count
Count of the number of times the ring buffers have saturated.
Definition: synapses.c:80
void synapses_resume(timer_t time)
Resume processing of synapses after a pause.
Definition: synapses.c:410
static uint32_t ring_buffer_size
Ring buffer size.
Definition: synapses.c:46
static weight_t * ring_buffers
Ring buffers to handle delays between synapses and neurons.
Definition: synapses.c:43
uint32_t synapses_get_pre_synaptic_events(void)
returns the counters for plastic and fixed pre synaptic events based on (if the model was compiled wi...
Definition: synapses.c:405
uint32_t synapse_delay_bits
Number of bits in the delay.
Definition: synapses.c:75
bool synapses_initialise(address_t synapse_params_address, uint32_t *n_neurons_out, uint32_t *n_synapse_types_out, weight_t **ring_buffers_out, uint32_t **ring_buffer_to_input_buffer_left_shifts, bool *clear_input_buffers_of_late_packets_init, uint32_t *incoming_spike_buffer_size)
Initialise the synapse processing.
Definition: synapses.c:268
static void print_ring_buffers(uint32_t time)
Print the contents of the ring buffers.
Definition: synapses.c:165
uint32_t synapse_type_index_mask
Mask to pick out the synapse type and index.
Definition: synapses.c:65
static uint32_t synapse_delay_mask_shifted
The mask of the delay shifted into position i.e. pre-shift.
Definition: synapses.c:96
uint32_t late_spikes
Count of the spikes that are received late.
Definition: synapses.c:87
static uint32_t ring_buffer_mask
Ring buffer mask.
Definition: synapses.c:49
uint32_t num_fixed_pre_synaptic_events
if using profiler import profiler tags
Definition: synapses.c:34
bool synapses_process_synaptic_row(uint32_t time, uint32_t spike_colour, uint32_t colour_mask, synaptic_row_t row, bool *write_back)
process a synaptic row
Definition: synapses.c:351
static uint32_t * ring_buffer_to_input_left_shifts
Amount to left shift the ring buffer by to make it an input.
Definition: synapses.c:52
static uint32_t n_synapse_types
The number of synapse types.
Definition: synapses.c:40
uint32_t synapse_type_bits
Number of bits in the synapse type.
Definition: synapses.c:71
uint32_t skipped_synapses
Definition: synapses.c:84
uint32_t synapse_type_mask
Mask to pick out the synapse type.
Definition: synapses.c:73
The layout of the synapse parameters region.
Definition: synapses.c:256
Operations on synapses.
static void synapses_print_weight(weight_t weight, uint32_t left_shift)
Print the weight of a synapse.
Definition: synapses.h:68