sPyNNaker neural_modelling 7.3.1
Loading...
Searching...
No Matches
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
37static uint32_t n_neurons;
38
40static uint32_t n_synapse_types;
41
43static weight_t *ring_buffers;
44
46static uint32_t ring_buffer_size;
47
49static uint32_t ring_buffer_mask;
50
53
78
81
84uint32_t skipped_synapses = 0;
85
87uint32_t late_spikes = 0;
88
90uint32_t max_late_spike = 0;
91
93static uint32_t n_neurons_peak;
94
96static uint32_t synapse_delay_mask_shifted = 0;
97
98
99/* PRIVATE FUNCTIONS */
100
101#if LOG_LEVEL >= LOG_DEBUG
105static 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
114static 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);
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));
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
165static 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
206static 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));
291 log_error("Not enough memory to allocate ring buffer");
292 return false;
293 }
294
295 // read in ring buffer to input left shifts
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",
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
409
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}
uint32_t time
The current timer tick value.
Definition c_main.c:94
uint32_t timer_t
uint32_t * address_t
void log_error(const char *message,...)
void log_debug(const char *message,...)
void log_info(const char *message,...)
static uint32_t colour_mask
The mask to apply to get the colour from the current timestep or key.
struct synaptic_row * synaptic_row_t
The type of a synaptic row.
@ PROFILER_PROCESS_PLASTIC_SYNAPSES
plastic synapse processing
const char * neuron_get_synapse_type_char(uint32_t synapse_type)
Get the synapse type description character.
Definition neuron.c:238
interface for neurons
void io_printf(char *stream, char *format,...)
heap_t * heap
sark_data_t sark
uint sark_heap_max(heap_t *heap, uint flag)
#define IO_BUF
Spike processing API.
#define NULL
void spin1_memcpy(void *dst, void const *src, uint len)
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.
static size_t synapse_row_num_plastic_controls(const synapse_row_fixed_part_t *fixed)
Get the number of plastic controls in the row.
static synapse_row_fixed_part_t * synapse_row_fixed_region(synaptic_row_t row)
Get the address of the non-plastic (or fixed) region.
static index_t synapse_row_sparse_type(uint32_t x, uint32_t synapse_index_bits, uint32_t synapse_type_mask)
Get the type code.
static size_t synapse_row_num_fixed_synapses(const synapse_row_fixed_part_t *fixed)
Get the number of fixed synapses in the row.
static index_t synapse_row_sparse_index(uint32_t x, uint32_t synapse_index_mask)
Get the index.
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.
static synapse_row_plastic_data_t * synapse_row_plastic_region(synaptic_row_t row)
Get the address of the plastic region.
static size_t synapse_row_plastic_size(const synaptic_row_t row)
Get the size of the plastic region.
static uint32_t * synapse_row_fixed_weight_controls(synapse_row_fixed_part_t *fixed)
The array of fixed weights in the row.
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.
static weight_t synapse_row_sparse_weight(uint32_t x)
Get the weight from an encoded synapse descriptor.
The type of the fixed part of the row. The fixed-plastic part follows.
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 const char * get_type_char(uint32_t synapse_type)
get the synapse type character
Definition synapses.c:105
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 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