sPyNNaker neural_modelling 7.1.1
Loading...
Searching...
No Matches
synapse_dynamics_stdp_izhikevich_neuromodulation.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016 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 "post_events_with_da.h"
21#include "stdp_typedefs.h"
22
23typedef struct neuromodulation_data_t {
24 uint32_t synapse_type:30;
25 uint32_t is_reward:1;
26 uint32_t is_neuromodulation: 1;
28
30 weight_t weight;
31 plastic_synapse_t eligibility_synapse;
33
34typedef struct nm_update_state_t {
35 accum weight;
36 uint32_t weight_shift;
37 update_state_t eligibility_state;
39
40typedef struct nm_final_state_t {
41 weight_t weight;
42 final_state_t final_state;
44
46 union {
54 neuromodulation_data_t neuromodulation;
55 };
56};
57
58typedef struct nm_params_t {
59
62
65
68
70
71static nm_params_t nm_params;
72
73static int16_lut *tau_c_lookup;
74
75static int16_lut *tau_d_lookup;
76
77static uint32_t *nm_weight_shift;
78
79extern uint32_t skipped_synapses;
80
81#define DECAY_LOOKUP_TAU_C(time) \
82 maths_lut_exponential_decay(time, tau_c_lookup)
83#define DECAY_LOOKUP_TAU_D(time) \
84 maths_lut_exponential_decay(time, tau_d_lookup)
85
86static inline nm_update_state_t get_nm_update_state(
87 neuromodulated_synapse_t synapse, index_t synapse_type) {
88 accum s1615_weight = kbits(synapse.weight << nm_weight_shift[synapse_type]);
89 nm_update_state_t update_state = {
90 .weight=s1615_weight,
91 .weight_shift=nm_weight_shift[synapse_type],
92 .eligibility_state=synapse_structure_get_update_state(
93 synapse.eligibility_synapse, synapse_type)
94 };
95 return update_state;
96}
97
98static inline nm_final_state_t get_nm_final_state(
99 nm_update_state_t update_state) {
100 update_state.weight = kbits(MAX(bitsk(update_state.weight),
101 bitsk(nm_params.min_weight)));
102 update_state.weight = kbits(MIN(bitsk(update_state.weight),
103 bitsk(nm_params.max_weight)));
104 nm_final_state_t final_state = {
105 .weight=(weight_t) (bitsk(update_state.weight) >> update_state.weight_shift),
107 update_state.eligibility_state)
108 };
109 return final_state;
110}
111
112static inline neuromodulated_synapse_t get_nm_final_synaptic_word(
113 nm_final_state_t final_state) {
114 neuromodulated_synapse_t synapse = {
115 .weight=final_state.weight,
117 final_state.final_state)
118 };
119 return synapse;
120}
121
122static inline post_event_window_t get_post_event_window(
124 const uint32_t delayed_pre_time, const uint32_t delayed_last_pre_time,
125 const uint32_t delay_dendritic) {
126 // Get the post-synaptic window of events to be processed
127 const uint32_t window_begin_time =
128 (delayed_last_pre_time >= delay_dendritic)
129 ? (delayed_last_pre_time - delay_dendritic) : 0;
130 const uint32_t window_end_time =
131 (delayed_pre_time >= delay_dendritic)
132 ? (delayed_pre_time - delay_dendritic) : 0;
134 post_event_history, window_begin_time, window_end_time);
135
136 log_debug("\t\tbegin_time:%u, end_time:%u - prev_time:%u (valid %u), num_events:%u",
137 window_begin_time, window_end_time, post_window.prev_time,
138 post_window.prev_time_valid, post_window.num_events);
139
140#if LOG_LEVEL >= LOG_DEBUG
143 window_end_time, delay_dendritic);
144#endif
145 return post_window;
146}
147
148static inline accum get_weight_update(int16_t decay_eligibility_trace,
149 int16_t decay_dopamine_trace, int16_t last_dopamine_trace,
150 accum eligibility_weight) {
151 // (exp(-(t_j - t_c) / tau_C).exp(-(t_j - t_c) / tau_D) - 1)
152 int16_t mul_decay = STDP_FIXED_MUL_16X16(
153 decay_eligibility_trace, decay_dopamine_trace)
155 // C_ij.D_c
156 accum mul_trace = mul_accum_fixed(eligibility_weight, last_dopamine_trace);
157 // C_ij.D_c.(exp(-(t_j - t_c) / tau_C).exp(-(t_j - t_c) / tau_D) - 1)
158 accum mul_trace_decay = mul_accum_fixed(mul_trace, mul_decay);
159 // Constant component = 1 / -((1/tau_C) + (1/tau_D))
160 // const_component.C_ij.D_c.
161 // (exp(-(t_j - t_c) / tau_C).exp(-(t_j - t_c) / tau_D) - 1)
162 accum res = mul_trace_decay * nm_params.weight_update_constant_component;
163 return res;
164}
165
166//---------------------------------------
178 const uint32_t time,
179 const uint32_t last_pre_time, const pre_trace_t last_pre_trace,
180 const pre_trace_t new_pre_trace, const uint32_t delay_dendritic,
181 const uint32_t delay_axonal, nm_update_state_t current_state,
183 log_debug("\tPerforming deferred synapse update at time:%u", time);
184 // Apply axonal delay to time of last presynaptic spike
185 const uint32_t delayed_last_pre_time = last_pre_time + delay_axonal;
186 const uint32_t delayed_pre_time = time + delay_axonal;
187
188 // history <- getHistoryEntries(j, t_old, t)
189 post_event_window_t post_window = get_post_event_window(
190 post_event_history, delayed_pre_time,
191 delayed_last_pre_time, delay_dendritic);
192
193 // t_c = t_old
194 uint32_t prev_corr_time = delayed_last_pre_time;
195
196 // D_c = D_prev.exp(-t_c - t_prev / tau_D)
197 int16_t last_dopamine_trace = 0;
198 if (post_window.prev_time_valid) {
199 last_dopamine_trace = STDP_FIXED_MUL_16X16(
200 post_window.prev_trace.dopamine_trace,
201 DECAY_LOOKUP_TAU_D(delayed_last_pre_time - post_window.prev_time));
202 }
203
204 // Process events in post-synaptic window
205 while (post_window.num_events > 0) {
206 const uint32_t delayed_post_time = *post_window.next_time + delay_dendritic;
207
208 log_debug("\t\tApplying post-synaptic event at delayed time:%u, pre:%u, prev_corr:%u",
209 delayed_post_time, delayed_last_pre_time, prev_corr_time);
210
211 // Calculate EXP components of the weight update equation
212 int16_t decay_eligibility_trace = DECAY_LOOKUP_TAU_C(
213 delayed_post_time - prev_corr_time);
214
215 // No point if dopamine trace is 0 as will just multiply by 0
216 if (last_dopamine_trace != 0) {
217 int16_t decay_dopamine_trace = DECAY_LOOKUP_TAU_D(
218 delayed_post_time - prev_corr_time);
219 accum eligibility_weight = synapse_structure_get_update_weight(
220 current_state.eligibility_state);
221 current_state.weight += get_weight_update(decay_eligibility_trace,
222 decay_dopamine_trace, last_dopamine_trace, eligibility_weight);
223 }
224
225 // C_ij = C_ij.exp(-(t_j-t_c) / tau_C)
226 synapse_structure_decay_weight(&(current_state.eligibility_state),
227 decay_eligibility_trace);
228
229 if (!post_events_next_is_dopamine(post_window)) {
230 current_state.eligibility_state = timing_apply_post_spike(
231 delayed_post_time, post_window.next_trace->post_trace,
232 delayed_last_pre_time, last_pre_trace, post_window.prev_time,
233 post_window.prev_trace.post_trace, current_state.eligibility_state);
234 }
235
236 // Update previous correlation to point to this post-event
237 // D_c = D_j
238 last_dopamine_trace = post_window.next_trace->dopamine_trace;
239 // t_c = t_j
240 prev_corr_time = delayed_post_time;
241
242 // Go onto next event
243 post_window = post_events_next(post_window);
244 }
245
246 // Apply spike to state only if there has been a post spike ever
247 if (post_window.prev_time_valid) {
248 const uint32_t delayed_last_post = post_window.prev_time + delay_dendritic;
249 log_debug("\t\tApplying pre-synaptic event at time:%u last post time:%u, prev_corr=%u",
250 delayed_pre_time, delayed_last_post, prev_corr_time);
251 int32_t decay_eligibility_trace = DECAY_LOOKUP_TAU_C(
252 delayed_pre_time - prev_corr_time);
253
254 if (last_dopamine_trace != 0) {
255 int32_t decay_dopamine_trace = DECAY_LOOKUP_TAU_D(
256 delayed_pre_time - prev_corr_time);
257 accum eligibility_weight = synapse_structure_get_update_weight(
258 current_state.eligibility_state);
259 current_state.weight += get_weight_update(decay_eligibility_trace,
260 decay_dopamine_trace, last_dopamine_trace, eligibility_weight);
261 }
262
263 // C_ij = C_ij.exp(-(t-t_c) / tau_C)
264 synapse_structure_decay_weight(&(current_state.eligibility_state),
265 decay_eligibility_trace);
266
267 current_state.eligibility_state = timing_apply_pre_spike(
268 delayed_pre_time, new_pre_trace, delayed_last_pre_time, last_pre_trace,
269 delayed_last_post, post_window.prev_trace.post_trace,
270 current_state.eligibility_state);
271 }
272
273 return get_nm_final_state(current_state);
274}
275
277 address_t address, uint32_t n_neurons, uint32_t n_synapse_types,
278 uint32_t *ring_buffer_to_input_buffer_left_shifts) {
279
280 if (!synapse_dynamics_stdp_init(&address, &params, n_synapse_types,
281 ring_buffer_to_input_buffer_left_shifts)) {
282 return false;
283 }
284
286 if (post_event_history == NULL) {
287 return false;
288 }
289
290 // Load parameters
291 nm_params_t *sdram_params = (nm_params_t *) address;
292 spin1_memcpy(&nm_params, sdram_params, sizeof(nm_params_t));
293
294 // Read lookup tables
295 address_t lut_address = (void *) &sdram_params[1];
296 tau_c_lookup = maths_copy_int16_lut(&lut_address);
297 tau_d_lookup = maths_copy_int16_lut(&lut_address);
298
299 // Store weight shifts
300 nm_weight_shift = spin1_malloc(sizeof(uint32_t) * n_synapse_types);
301 if (nm_weight_shift == NULL) {
302 log_error("Could not initialise weight region data");
303 return NULL;
304 }
305 for (uint32_t s = 0; s < n_synapse_types; s++) {
306 nm_weight_shift[s] = ring_buffer_to_input_buffer_left_shifts[s];
307 }
308
309 return true;
310}
311
312//---------------------------------------
313// Synaptic row plastic-region implementation
314//---------------------------------------
316 synapse_row_plastic_data_t *plastic_region_data,
317 synapse_row_fixed_part_t *fixed_region,
318 uint32_t *ring_buffer_to_input_buffer_left_shifts) {
319 __use(plastic_region_data);
320 __use(fixed_region);
321 __use(ring_buffer_to_input_buffer_left_shifts);
322
323#if LOG_LEVEL >= LOG_DEBUG
324 // Extract separate arrays of weights (from plastic region),
325 // Control words (from fixed region) and number of plastic synapses
326 const plastic_synapse_t *plastic_words = plastic_region_data->synapses;
327 const control_t *control_words = synapse_row_plastic_controls(fixed_region);
328 size_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region);
329
330 log_debug("Plastic region %u synapses\n", plastic_synapse);
331
332 // Loop through plastic synapses
333 for (uint32_t i = 0; i < plastic_synapse; i++) {
334 // Get next control word (auto incrementing control word)
335 uint32_t control_word = *control_words++;
336 uint32_t synapse_type = synapse_row_sparse_type(
338
339 // Get weight
341 *plastic_words++, synapse_type);
343 update_state);
344 weight_t weight = synapse_structure_get_final_weight(final_state);
345
346 log_debug("%08x [%3d: (w: %5u (=", control_word, i, weight);
348 weight, ring_buffer_to_input_buffer_left_shifts[synapse_type]);
349 log_debug("nA) d: %2u, n = %3u)] - {%08x %08x}\n",
353 }
354#endif // LOG_LEVEL >= LOG_DEBUG
355}
356
357//---------------------------------------
361static inline index_t sparse_axonal_delay(uint32_t x) {
362#if 1
363 // No axonal delay, ever
364 __use(x);
365 return 0;
366#else
367 return (x >> synapse_delay_index_type_bits) & SYNAPSE_AXONAL_DELAY_MASK;
368#endif
369}
370
371//---------------------------------------
373 uint32_t time, index_t neuron_index) {
374 log_debug("Adding post-synaptic event to trace %u at time:%u", neuron_index, time);
375
376 // Add post-event
377 post_event_history_t *history = &post_event_history[neuron_index];
378 const uint32_t last_post_time = history->times[history->count_minus_one];
379 const nm_post_trace_t last_post_trace =
380 history->traces[history->count_minus_one];
381 post_trace_t new_post_trace = timing_add_post_spike(
382 time, last_post_time, last_post_trace.post_trace);
383 int32_t new_dopamine_trace = STDP_FIXED_MUL_16X16(
384 last_post_trace.dopamine_trace,
385 DECAY_LOOKUP_TAU_D(time - last_post_time));
386
387 post_events_add(time, history, new_post_trace, new_dopamine_trace, false);
388}
389
390//---------------------------------------
391static inline neuromodulated_synapse_t process_plastic_synapse(
392 uint32_t control_word, uint32_t last_pre_time, pre_trace_t last_pre_trace,
393 pre_trace_t new_pre_trace, weight_t *ring_buffers, uint32_t time,
394 uint32_t colour_delay, neuromodulated_synapse_t synapse) {
395 fixed_stdp_synapse s = synapse_dynamics_stdp_get_fixed(control_word, time,
396 colour_delay);
397
398 // Create update state from the plastic synaptic word
399 nm_update_state_t current_state = get_nm_update_state(synapse, s.type);
400
401 // Update the synapse state
402 uint32_t post_delay = s.delay_dendritic;
403 if (!params.backprop_delay) {
404 post_delay = 0;
405 }
406 nm_final_state_t final_state =
408 time - colour_delay, last_pre_time, last_pre_trace, new_pre_trace,
409 post_delay, s.delay_axonal, current_state,
410 &post_event_history[s.index]);
411
412 // Add weight to ring-buffer entry, but only if not too late
413 if (s.delay_dendritic + s.delay_axonal > colour_delay) {
414 synapse_dynamics_stdp_update_ring_buffers(ring_buffers, s,
415 final_state.weight);
416 } else {
418 }
419
420 return get_nm_final_synaptic_word(final_state);
421}
422
423static inline void process_neuromodulation(
424 synapse_row_plastic_data_t *plastic_region_address,
425 synapse_row_fixed_part_t *fixed_region, uint32_t time) {
426 bool reward = plastic_region_address->neuromodulation.is_reward;
427 uint32_t n_synapses = synapse_row_num_plastic_controls(fixed_region);
428 const uint32_t *words = (uint32_t *) synapse_row_plastic_controls(fixed_region);
429
430 // Loop through synapses
431 for (; n_synapses > 0; n_synapses--) {
432 // Get next control word (auto incrementing)
433 uint32_t word = *words++;
434 int32_t concentration = (int32_t) synapse_row_sparse_weight(word);
435
436 if (!reward) {
437 concentration = -concentration;
438 }
439
440 uint32_t neuron_index = synapse_row_sparse_index(word, 0xFFFF);
441
442 // Get post event history of this neuron
443 post_event_history_t *history = &post_event_history[neuron_index];
444 const uint32_t last_post_time = history->times[history->count_minus_one];
445 const nm_post_trace_t last_post_trace =
446 history->traces[history->count_minus_one];
447
448 post_trace_t new_post_trace = timing_decay_post(
449 time, last_post_time, last_post_trace.post_trace);
450 int32_t new_dopamine_trace = STDP_FIXED_MUL_16X16(
451 last_post_trace.dopamine_trace,
452 DECAY_LOOKUP_TAU_D(time - last_post_time));
453 new_dopamine_trace += concentration;
454
455 // Add a new history trace into the buffer of post synaptic events
456 post_events_add(time, history, new_post_trace, new_dopamine_trace, true);
457 }
458}
459
461 synapse_row_plastic_data_t *plastic_region_address,
462 synapse_row_fixed_part_t *fixed_region,
463 weight_t *ring_buffers, uint32_t time, uint32_t colour_delay,
464 bool *write_back) {
465
466 // If the flag is set, this is neuromodulation
467 if (plastic_region_address->neuromodulation.is_neuromodulation) {
468 process_neuromodulation(plastic_region_address, fixed_region, time);
469 *write_back = false;
470 return true;
471 }
472
473 // Extract separate arrays of plastic synapses (from plastic region),
474 // Control words (from fixed region) and number of plastic synapses
475 neuromodulated_synapse_t *plastic_words = plastic_region_address->synapses;
476 const control_t *control_words = synapse_row_plastic_controls(fixed_region);
477 size_t n_plastic_synapses = synapse_row_num_plastic_controls(fixed_region);
478
479 num_plastic_pre_synaptic_events += n_plastic_synapses;
480
481 // Get last pre-synaptic event from event history
482 const uint32_t last_pre_time = plastic_region_address->history.prev_time;
483 const pre_trace_t last_pre_trace = plastic_region_address->history.prev_trace;
484
485 // Update pre-synaptic trace
486 log_debug("Adding pre-synaptic event to trace at time:%u", time);
487 plastic_region_address->history.prev_time = time - colour_delay;
488 plastic_region_address->history.prev_trace =
489 timing_add_pre_spike(time - colour_delay, last_pre_time, last_pre_trace);
490
491 // Loop through plastic synapses
492 for (; n_plastic_synapses > 0; n_plastic_synapses--) {
493 // Get next control word (auto incrementing)
494 uint32_t control_word = *control_words++;
495
496 plastic_words[0] = process_plastic_synapse(
497 control_word, last_pre_time, last_pre_trace,
498 plastic_region_address->history.prev_trace, ring_buffers, time,
499 colour_delay, plastic_words[0]);
500 plastic_words++;
501 }
502 *write_back = true;
503 return true;
504}
505
506static inline neuromodulated_synapse_t *get_plastic_synapses(synaptic_row_t row) {
507 synapse_row_plastic_data_t *plastic_data = (void *)
509 return plastic_data->synapses;
510}
511
513 uint32_t id, synaptic_row_t row, weight_t *weight, uint16_t *delay,
514 uint32_t *offset, uint32_t *synapse_type) {
516 const neuromodulated_synapse_t *plastic_words = get_plastic_synapses(row);
517 const control_t *control_words = synapse_row_plastic_controls(fixed_region);
518 const size_t n_plastic_synapses = synapse_row_num_plastic_controls(fixed_region);
519
520 // Loop through plastic synapses
521 for (size_t plastic_synapse = n_plastic_synapses; plastic_synapse > 0;
522 plastic_synapse--, plastic_words++) {
523 // Take the weight anyway as this updates the plastic words
524
525 // Check if index is the one I'm looking for
526 uint32_t control_word = *control_words++;
527 if (synapse_row_sparse_index(control_word, synapse_index_mask) == id) {
529 plastic_words->eligibility_synapse);
530 *offset = n_plastic_synapses - plastic_synapse;
531 *delay = synapse_row_sparse_delay(control_word,
533 *synapse_type = synapse_row_sparse_type(
535 return true;
536 }
537 }
538
539 return false;
540}
541
544 neuromodulated_synapse_t *plastic_words = get_plastic_synapses(row);
545 control_t *control_words = synapse_row_plastic_controls(fixed_region);
546 int32_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region);
547
548 // Delete weight at offset
549 plastic_words[offset] = plastic_words[plastic_synapse - 1];
550
551 // Delete control word at offset
552 control_words[offset] = control_words[plastic_synapse - 1];
553 control_words[plastic_synapse - 1] = 0;
554
555 // Decrement FP
556 fixed_region->num_plastic--;
557 return true;
558}
559
561 weight_t weight, uint32_t delay, uint32_t type) {
563 neuromodulated_synapse_t *plastic_words = get_plastic_synapses(row);
565 control_t new_control = control_conversion(id, delay, type);
566
567 control_t *control_words = synapse_row_plastic_controls(fixed_region);
568 int32_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region);
569
570 // Add weight at offset
571 plastic_words[plastic_synapse] = (neuromodulated_synapse_t) {
572 .eligibility_synapse = new_weight,
573 .weight = weight
574 };
575
576 // Add control word at offset
577 control_words[plastic_synapse] = new_control;
578
579 // Increment FP
580 fixed_region->num_plastic++;
581 return true;
582}
uint32_t index_t
static weight_t * ring_buffers
The ring buffers to be used in the simulation.
Definition c_main.c:118
uint32_t time
The current timer tick value.
Definition c_main.c:94
uint32_t * address_t
void log_error(const char *message,...)
void log_debug(const char *message,...)
uint32_t synapse_delay_mask
The mask to get the synaptic delay from a "synapse".
Definition local_only.c:71
uint32_t synapse_type_index_bits
The number of bits used by the synapse type and post-neuron index.
Definition local_only.c:74
uint32_t synapse_index_bits
The number of bits used by just the post-neuron index.
Definition local_only.c:77
static int16_lut * maths_copy_int16_lut(address_t *address)
Copy a Lookup Table from SDRAM to DTCM, updating the address.
Definition maths.h:57
#define MIN(X, Y)
Minimum. Evaluates arguments twice.
Definition maths.h:34
#define MAX(X, Y)
Maximum. Evaluates arguments twice.
Definition maths.h:39
Lookup Table of 16-bit integers.
Definition maths.h:44
struct synaptic_row * synaptic_row_t
The type of a synaptic row.
static uint32_t n_neurons
The number of neurons on the core.
Definition neuron.c:45
static uint32_t n_synapse_types
The number of synapse types.
Definition neuron.c:51
static post_event_history_t * post_events_init_buffers(uint32_t n_neurons)
Initialise an array of post-synaptic event histories.
Definition post_events.h:83
static void print_event_history(const post_event_history_t *events)
Print a post-synaptic event history.
Definition post_events.h:71
static post_event_window_t post_events_next(post_event_window_t window)
Advance a post-synaptic event window to the next event.
static void post_events_add(uint32_t time, post_event_history_t *events, post_trace_t trace)
Add a post-synaptic event to the history.
static post_event_window_t post_events_get_window_delayed(const post_event_history_t *events, uint32_t begin_time, uint32_t end_time)
Get the post-synaptic event window.
static void print_delayed_window_events(const post_event_history_t *post_event_history, uint32_t begin_time, uint32_t end_time, uint32_t delay_dendritic)
Print the post-synaptic event history.
Post-synaptic events.
uint32_t num_events
The number of events.
Definition post_events.h:59
uint32_t count_minus_one
Number of events stored (minus one)
Definition post_events.h:41
uint32_t times[MAX_POST_SYNAPTIC_EVENTS]
Event times.
Definition post_events.h:43
post_trace_t prev_trace
The previous post-synaptic event trace.
Definition post_events.h:51
const uint32_t * next_time
The next post-synaptic event time.
Definition post_events.h:57
uint32_t prev_time
The previous post-synaptic event time.
Definition post_events.h:53
const post_trace_t * next_trace
The next post-synaptic event trace.
Definition post_events.h:55
uint32_t prev_time_valid
Whether the previous post-synaptic event is valid (based on time)
Definition post_events.h:61
post_trace_t traces[MAX_POST_SYNAPTIC_EVENTS]
Event traces.
Definition post_events.h:45
Trace history of post-synaptic events.
Definition post_events.h:39
Post event window description.
Definition post_events.h:49
#define NULL
void spin1_memcpy(void *dst, void const *src, uint len)
Basic definitions for STDP.
static accum mul_accum_fixed(accum a, int32_t stdp_fixed)
Multiply an accum by an STDP fixed point and return an accum.
#define STDP_FIXED_POINT_ONE
The number 1.0 in the fixed point math used by STDP.
#define STDP_FIXED_MUL_16X16(a, b)
Multiply two STDP fixed point numbers.
STDP core implementation.
uint32_t backprop_delay
The back-propagation delay, in basic simulation timesteps.
static control_t control_conversion(uint32_t id, uint32_t delay, uint32_t type)
packing all of the information into the required plastic control word
static stdp_params params
Configuration parameters.
pre_trace_t prev_trace
The event trace.
static post_event_history_t * post_event_history
The history data of post-events.
static uint32_t num_plastic_pre_synaptic_events
Count of pre-synaptic events relevant to plastic processing.
uint32_t prev_time
The event time.
The type of history data of pre-events.
accum max_weight
Maximum of weight after update.
bool synapse_dynamics_initialise(address_t address, uint32_t n_neurons, uint32_t n_synapse_types, uint32_t *ring_buffer_to_input_buffer_left_shifts)
Initialise the synapse dynamics.
void synapse_dynamics_process_post_synaptic_event(uint32_t time, index_t neuron_index)
Inform the synapses that the neuron fired.
bool synapse_dynamics_find_neuron(uint32_t id, synaptic_row_t row, weight_t *weight, uint16_t *delay, uint32_t *offset, uint32_t *synapse_type)
Search the synaptic row for the the connection with the specified post-synaptic ID.
static index_t sparse_axonal_delay(uint32_t x)
Get the axonal delay.
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_add_neuron(uint32_t id, synaptic_row_t row, weight_t weight, uint32_t delay, uint32_t type)
Add an entry in the synaptic row.
accum weight_update_constant_component
Constant part of weight update.
static nm_final_state_t izhikevich_neuromodulation_plasticity_update_synapse(const uint32_t time, const uint32_t last_pre_time, const pre_trace_t last_pre_trace, const pre_trace_t new_pre_trace, const uint32_t delay_dendritic, const uint32_t delay_axonal, nm_update_state_t current_state, const post_event_history_t *post_event_history)
Synapse update loop core.
bool synapse_dynamics_remove_neuron(uint32_t offset, synaptic_row_t row)
Remove the entry at the specified offset in the synaptic row.
uint32_t skipped_synapses
Definition synapses.c:84
accum min_weight
Minimum of weight after update (must be >= 0)
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.
plastic_synapse_t synapses[]
The per-synapse information.
pre_event_history_t history
The pre-event history.
The format of the plastic data region of a synaptic row.
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 control_t * synapse_row_plastic_controls(synapse_row_fixed_part_t *fixed)
Get the array of plastic controls in the row.
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 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.
size_t num_plastic
The number of plastic controls in data
uint16_t control_t
Define the type of the control data.
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.
static plastic_synapse_t synapse_structure_get_final_synaptic_word(final_state_t final_state)
Get the final plastic synapse data from the final state.
static accum synapse_structure_get_update_weight(update_state_t state)
Get the current synaptic weight stored in the update state.
static void synapse_structure_decay_weight(update_state_t *state, uint32_t decay)
Decay the synaptic weight value stored by multiplication.
static plastic_synapse_t synapse_structure_create_synapse(weight_t weight)
Create the initial plastic synapse data.
static update_state_t synapse_structure_get_update_state(plastic_synapse_t synaptic_word, index_t synapse_type)
Get the update state from the synapse structure.
static weight_t synapse_structure_get_final_weight(final_state_t final_state)
Get the final weight from the final state.
static final_state_t synapse_structure_get_final_state(update_state_t state)
Get the final state from the update state.
static weight_t synapse_structure_get_weight(plastic_synapse_t synaptic_word)
Get the current synaptic weight from the plastic synapse data.
Plastic synapse contains normal 16-bit weight and an accumulator.
uint32_t synapse_index_mask
Mask to pick out the synapse index.
Definition synapses.c:69
uint32_t synapse_type_mask
Mask to pick out the synapse type.
Definition synapses.c:73
static void synapses_print_weight(weight_t weight, uint32_t left_shift)
Print the weight of a synapse.
Definition synapses.h:68
static post_trace_t timing_add_post_spike(uint32_t time, uint32_t last_time, post_trace_t last_trace)
Add a post spike to the post trace.
static post_trace_t timing_decay_post(uint32_t time, uint32_t last_time, post_trace_t last_trace)
Evolve the post trace without adding a spike.
static update_state_t timing_apply_pre_spike(uint32_t time, pre_trace_t trace, uint32_t last_pre_time, pre_trace_t last_pre_trace, uint32_t last_post_time, post_trace_t last_post_trace, update_state_t previous_state)
Apply a pre-spike timing rule state update.
static pre_trace_t timing_add_pre_spike(uint32_t time, uint32_t last_time, pre_trace_t last_trace)
Add a pre spike to the pre trace.
static update_state_t timing_apply_post_spike(uint32_t time, post_trace_t trace, uint32_t last_pre_time, pre_trace_t last_pre_trace, uint32_t last_post_time, post_trace_t last_post_trace, update_state_t previous_state)
Apply a post-spike timing rule state update.
The type of post-spike traces.
The type of pre-spike traces.