sPyNNaker neural_modelling 7.1.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
218 for (; fixed_synapse > 0; fixed_synapse--) {
219 // Get the next 32 bit word from the synaptic_row
220 // (should auto increment pointer in single instruction)
221 uint32_t synaptic_word = *synaptic_words++;
222
223 // If the (shifted) delay is non zero and too small, skip
224 if (((synaptic_word & synapse_delay_mask_shifted) != 0) &&
225 ((synaptic_word & synapse_delay_mask_shifted) <= colour_delay_shifted)) {
227 continue;
228 }
229
230 // The ring buffer index can be found by adding on the time to the delay
231 // in the synaptic word directly, and then masking off the whole index.
232 // The addition of the masked time to the delay even with the mask might
233 // overflow into the weight at worst but can't affect the lower bits.
234 uint32_t ring_buffer_index = (synaptic_word + masked_time) & ring_buffer_mask;
235 uint32_t weight = synapse_row_sparse_weight(synaptic_word);
236
237 // Add weight to current ring buffer value
238 uint32_t accumulation = ring_buffers[ring_buffer_index] + weight;
239
240 // If 17th bit is set, saturate accumulator at UINT16_MAX (0xFFFF)
241 // **NOTE** 0x10000 can be expressed as an ARM literal,
242 // but 0xFFFF cannot. Therefore, we use (0x10000 - 1)
243 // to obtain this value
244 uint32_t sat_test = accumulation & 0x10000;
245 if (sat_test) {
246 accumulation = sat_test - 1;
248 }
249
250 // Store saturated value back in ring-buffer
251 ring_buffers[ring_buffer_index] = accumulation;
252 }
253 return true;
254}
255
258 uint32_t n_neurons;
259 uint32_t n_synapse_types;
260 uint32_t log_n_neurons;
261 uint32_t log_n_synapse_types;
262 uint32_t log_max_delay;
263 uint32_t drop_late_packets;
264 uint32_t incoming_spike_buffer_size;
265 uint32_t ring_buffer_shifts[];
266};
267
268/* INTERFACE FUNCTIONS */
270 address_t synapse_params_address,
271 uint32_t *n_neurons_out, uint32_t *n_synapse_types_out,
272 weight_t **ring_buffers_out,
273 uint32_t **ring_buffer_to_input_buffer_left_shifts,
274 bool* clear_input_buffers_of_late_packets_init,
275 uint32_t *incoming_spike_buffer_size) {
276 struct synapse_params *params = (struct synapse_params *) synapse_params_address;
277 *clear_input_buffers_of_late_packets_init = params->drop_late_packets;
278 *incoming_spike_buffer_size = params->incoming_spike_buffer_size;
279 n_neurons = params->n_neurons;
280 *n_neurons_out = n_neurons;
281 n_synapse_types = params->n_synapse_types;
282 *n_synapse_types_out = n_synapse_types;
283
284 uint32_t log_n_neurons = params->log_n_neurons;
285 uint32_t log_n_synapse_types = params->log_n_synapse_types;
286 uint32_t log_max_delay = params->log_max_delay;
287
288 // Set up ring buffer left shifts
290 spin1_malloc(n_synapse_types * sizeof(uint32_t));
292 log_error("Not enough memory to allocate ring buffer");
293 return false;
294 }
295
296 // read in ring buffer to input left shifts
298 ring_buffer_to_input_left_shifts, params->ring_buffer_shifts,
299 n_synapse_types * sizeof(uint32_t));
300 *ring_buffer_to_input_buffer_left_shifts =
302
303 synapse_type_index_bits = log_n_neurons + log_n_synapse_types;
305 synapse_index_bits = log_n_neurons;
307 synapse_type_bits = log_n_synapse_types;
308 synapse_type_mask = (1 << log_n_synapse_types) - 1;
309 synapse_delay_bits = log_max_delay;
312
313 n_neurons_peak = 1 << log_n_neurons;
314
315 uint32_t n_ring_buffer_bits =
316 log_n_neurons + log_n_synapse_types + synapse_delay_bits;
317 ring_buffer_size = 1 << (n_ring_buffer_bits);
319
320 ring_buffers = spin1_malloc(ring_buffer_size * sizeof(weight_t));
321 if (ring_buffers == NULL) {
322 log_error("Could not allocate %u entries for ring buffers; Biggest space %u",
324 return false;
325 }
326 for (uint32_t i = 0; i < ring_buffer_size; i++) {
327 ring_buffers[i] = 0;
328 }
329 *ring_buffers_out = ring_buffers;
330
331 log_info("Ready to process synapses for %u neurons with %u synapse types",
333
334 return true;
335}
336
338 uint32_t synapse_index = 0;
339 uint32_t ring_buffer_index = synapse_row_get_first_ring_buffer_index(
341 for (uint32_t s_i = n_synapse_types; s_i > 0; s_i--) {
342 uint32_t neuron_index = 0;
343 for (uint32_t n_i = n_neurons_peak; n_i > 0; n_i--) {
344 ring_buffers[ring_buffer_index] = 0;
345 ring_buffer_index++;
346 neuron_index++;
347 }
348 synapse_index++;
349 }
350}
351
353 uint32_t time, uint32_t spike_colour, uint32_t colour_mask,
354 synaptic_row_t row, bool *write_back) {
355
356 // Work out how much delay takes off or adds on to the actual delay because
357 // of a delayed spike arrival time, or delayed change of time step in the
358 // current core. Spikes can be as late as the bits in colour_mask dictates.
359 // Masked difference is used to calculate this, which will always be
360 // positive because the mask removes the negative bit.
361 // Example: time colour 8, spike colour 13, colour mask 0xF means time
362 // colour has gone up to 15 and then wrapped since spike was sent.
363 // 8 - 13 = -5; -5 & 0xF = 11, so spike was sent 11 steps ago.
364 uint32_t time_colour = time & colour_mask;
365 int32_t colour_diff = time_colour - spike_colour;
366 uint32_t colour_delay = colour_diff & colour_mask;
367
368 late_spikes += colour_delay & 0x1;
369 if (colour_delay > max_late_spike) {
370 max_late_spike = colour_delay;
371 }
372
373 // By default don't write back
374 *write_back = false;
375
376 // Get address of non-plastic region from row
378
379 // **TODO** multiple optimised synaptic row formats
380 //if (plastic_tag(row) == 0) {
381 // If this row has a plastic region
382 if (synapse_row_plastic_size(row) > 0) {
383 // Get region's address
384 synapse_row_plastic_data_t *plastic_data =
386
387 // Process any plastic synapses
388 profiler_write_entry_disable_fiq(
389 PROFILER_ENTER | PROFILER_PROCESS_PLASTIC_SYNAPSES);
391 fixed_region, ring_buffers, time, colour_delay, write_back)) {
392 return false;
393 }
394 profiler_write_entry_disable_fiq(
395 PROFILER_EXIT | PROFILER_PROCESS_PLASTIC_SYNAPSES);
396 }
397
398 // Process any fixed synapses
399 // **NOTE** this is done after initiating DMA in an attempt
400 // to hide cost of DMA behind this loop to improve the chance
401 // that the DMA controller is ready to read next synaptic row afterwards
402 return process_fixed_synapses(fixed_region, time, colour_delay);
403 //}
404}
405
410
412 // If the time has been reset to zero then the ring buffers need to be
413 // flushed in case there is a delayed spike left over from a previous run
414 if (time == 0) {
415 for (uint32_t i = 0; i < ring_buffer_size; i++) {
416 ring_buffers[i] = 0;
417 }
418 }
419}
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.
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.
The format of the plastic data region of a synaptic row.
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:337
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:411
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:406
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:269
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:352
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:257
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