sPyNNaker neural_modelling 7.1.1
Loading...
Searching...
No Matches
spike_processing_fast.c
1/*
2 * Copyright (c) 2020 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"
22#include "dma_common.h"
23#include <scamp_spin1_sync.h>
24#include <simulation.h>
25#include <recording.h>
26#include <debug.h>
27#include <wfi.h>
28
31typedef struct dma_buffer {
34
38
40 uint32_t n_bytes_transferred;
41
43 uint32_t colour;
44
46 uint32_t colour_mask;
47
51
53#define N_DMA_BUFFERS 2
54
56#define DMA_BUFFER_MOD_MASK 0x1
57
59static dma_buffer dma_buffers[N_DMA_BUFFERS];
60
62static uint32_t next_buffer_to_fill;
63
65static uint32_t next_buffer_to_process;
66
69static uint32_t count_input_buffer_packets_late;
70
72static uint32_t biggest_fill_size_of_input_buffer;
73
76static bool clear_input_buffers_of_late_packets;
77
79static uint32_t clocks_to_transfer = 0;
80
82static uint32_t n_successful_rewires = 0;
83
85static uint32_t dma_complete_count = 0;
86
88static uint32_t spike_processing_count = 0;
89
91static uint32_t max_spikes_received = 0;
92
94static uint32_t spikes_processed_this_time_step = 0;
95
97static uint32_t max_spikes_processed = 0;
98
100static uint32_t transfer_timer_overruns = 0;
101
103static uint32_t max_transfer_timer_overrun = 0;
104
106static uint32_t skipped_time_steps = 0;
107
109static uint32_t latest_spike_received_time = 0xFFFFFFFF;
110
112static uint32_t earliest_spike_received_time = 0;
113
115static uint32_t max_spikes_overflow = 0;
116
118static struct {
119 uint32_t time;
120 uint32_t packets_this_time_step;
121} p_per_ts_struct;
122
124static uint32_t p_per_ts_region;
125
127static struct sdram_config sdram_inputs;
128
130static struct key_config key_config;
131
133static weight_t *ring_buffers;
134
137static inline bool is_end_of_time_step(void) {
138 return tc[T2_COUNT] == 0;
139}
140
142static inline void clear_end_of_time_step(void) {
143 tc[T2_INT_CLR] = 1;
144}
145
149static inline bool wait_for_dma_to_complete_or_end(void) {
150#if LOG_LEVEL >= LOG_DEBUG
151 // Useful for checking when things are going wrong, but shouldn't be
152 // needed in normal code
153 uint32_t n_loops = 0;
154 while (!is_end_of_time_step() && !dma_done() && n_loops < 10000) {
155 n_loops++;
156 }
157 if (!is_end_of_time_step() && !dma_done()) {
158 log_error("Timeout on DMA loop: DMA stat = 0x%08x!", dma[DMA_STAT]);
159 rt_error(RTE_SWERR);
160 }
161#else
162 // This is the normal loop, done without checking
163 while (!dma_done()) {
164 continue;
165 }
166#endif
167 dma[DMA_CTRL] = 0x8;
168
169 return !is_end_of_time_step();
170}
171
175static inline void transfer_buffers(uint32_t time) {
176 uint32_t first_ring_buffer = synapse_row_get_first_ring_buffer_index(
178 log_debug("Writing %d bytes to 0x%08x from ring buffer %d at 0x%08x",
180 &ring_buffers[first_ring_buffer]);
181 do_fast_dma_write(&ring_buffers[first_ring_buffer], sdram_inputs.address,
183}
184
187static inline void process_end_of_time_step(uint32_t time) {
188 // Stop interrupt processing
189 uint32_t cspr = spin1_int_disable();
190
191 cancel_dmas();
192
193 // Start transferring buffer data for next time step
194 transfer_buffers(time);
195 wait_for_dma_to_complete();
196
197 // uint32_t end = tc[T1_COUNT];
198 if (tc[T1_MASK_INT]) {
199 transfer_timer_overruns++;
200 uint32_t diff = tc[T1_LOAD] - tc[T1_COUNT];
201 if (diff > max_transfer_timer_overrun) {
202 max_transfer_timer_overrun = diff;
203 }
204 }
205
206 spin1_mode_restore(cspr);
207}
208
210static inline void read_synaptic_row(spike_t spike, pop_table_lookup_result_t *result) {
212 buffer->sdram_writeback_address = result->row_address;
213 buffer->originating_spike = spike;
214 buffer->n_bytes_transferred = result->n_bytes_to_transfer;
215 buffer->colour = result->colour;
216 buffer->colour_mask = result->colour_mask;
217 do_fast_dma_read(result->row_address, buffer->row, result->n_bytes_to_transfer);
218 next_buffer_to_fill = (next_buffer_to_fill + 1) & DMA_BUFFER_MOD_MASK;
219}
220
225static inline bool get_next_spike(uint32_t time, spike_t *spike) {
226 uint32_t n_spikes = in_spikes_size();
229 }
230 if (!in_spikes_get_next_spike(spike)) {
231 return false;
232 }
233 // Detect a looped back spike
234 if ((*spike & key_config.mask) == key_config.key) {
235 // Process event if not self-connected (if it is, this happens later)
237 synapse_dynamics_process_post_synaptic_event(
238 time, (*spike & key_config.spike_id_mask) >> key_config.colour_shift);
239 }
241 }
242 return true;
243}
244
252static inline bool start_first_dma(uint32_t time, spike_t *spike,
254
255 do {
256 if (population_table_get_first_address(*spike, result)) {
257 read_synaptic_row(*spike, result);
258 return true;
259 }
260 } while (!is_end_of_time_step() && get_next_spike(time, spike));
261
262 return false;
263}
264
270static inline bool get_next_dma(uint32_t time, spike_t *spike,
273 return true;
274 }
275
276 while (!is_end_of_time_step() && get_next_spike(time, spike)) {
277 if (population_table_get_first_address(*spike, result)) {
278 return true;
279 }
280 }
281
282 return false;
283}
284
287static inline void handle_row_error(dma_buffer *buffer) {
288 log_error(
289 "Error processing spike 0x%.8x for address 0x%.8x (local=0x%.8x)",
290 buffer->originating_spike, buffer->sdram_writeback_address, buffer->row);
291
292 // Print out the row for debugging
293 address_t row = (address_t) buffer->row;
294 for (uint32_t i = 0; i < (buffer->n_bytes_transferred >> 2); i++) {
295 log_error(" %u: 0x%08x", i, row[i]);
296 }
297
298 // Print out parsed data for static synapses
300 uint32_t *synaptic_words = synapse_row_fixed_weight_controls(fixed_region);
301 uint32_t fixed_synapse = synapse_row_num_fixed_synapses(fixed_region);
302 if (fixed_synapse > (buffer->n_bytes_transferred >> 2)) {
303 log_error("Too many fixed synapses: %u", fixed_synapse);
304 rt_error(RTE_SWERR);
305 }
306 log_error("\nFixed-Fixed Region (%u synapses):", fixed_synapse);
307 for (; fixed_synapse > 0; fixed_synapse--) {
308 uint32_t synaptic_word = *synaptic_words++;
309
310 uint32_t delay = synapse_row_sparse_delay(
312 uint32_t type = synapse_row_sparse_type(
313 synaptic_word, synapse_index_bits, synapse_type_mask);
314 uint32_t neuron = synapse_row_sparse_index(
315 synaptic_word, synapse_index_mask);
316 log_error(" Delay %u, Synapse Type %u, Neuron %u", delay, type, neuron);
317 }
318 rt_error(RTE_SWERR);
319}
320
324static inline void process_current_row(uint32_t time, bool dma_in_progress) {
325 bool write_back = false;
326 dma_buffer *buffer = &dma_buffers[next_buffer_to_process];
327
328 if (!synapses_process_synaptic_row(time, buffer->colour, buffer->colour_mask,
329 buffer->row, &write_back)) {
330 handle_row_error(buffer);
331 }
332 synaptogenesis_spike_received(time, buffer->originating_spike);
334 if (write_back) {
335 uint32_t n_bytes = synapse_row_plastic_size(buffer->row) * sizeof(uint32_t);
336 void *system_address = synapse_row_plastic_region(
337 buffer->sdram_writeback_address);
338 void *tcm_address = synapse_row_plastic_region(buffer->row);
339 // Make sure an outstanding DMA is completed before starting this one
340 if (dma_in_progress) {
341 wait_for_dma_to_complete();
342 }
343 do_fast_dma_write(tcm_address, system_address, n_bytes);
344 // Only wait for this DMA to complete if there isn't another running,
345 // as otherwise the next wait will fail!
346 if (!dma_in_progress) {
347 wait_for_dma_to_complete();
348 }
349 }
350 next_buffer_to_process = (next_buffer_to_process + 1) & DMA_BUFFER_MOD_MASK;
351 spikes_processed_this_time_step++;
352}
353
356static inline void store_data(uint32_t time) {
357 // Record the number of packets still left
358 uint32_t n_spikes_left = in_spikes_size();
359 count_input_buffer_packets_late += n_spikes_left;
360 if (n_spikes_left > max_spikes_overflow) {
361 max_spikes_overflow = n_spikes_left;
362 }
363
364 // Record the number of packets received last time step
365 p_per_ts_struct.time = time;
367
368 if (p_per_ts_struct.packets_this_time_step > max_spikes_received) {
369 max_spikes_received = p_per_ts_struct.packets_this_time_step;
370 }
371 if (spikes_processed_this_time_step > max_spikes_processed) {
372 max_spikes_processed = spikes_processed_this_time_step;
373 }
374}
375
377static inline void measure_transfer_time(void) {
378 // Measure the time to do an upload to know when to schedule the timer
379 tc[T2_LOAD] = 0xFFFFFFFF;
380 tc[T2_CONTROL] = 0x82;
381 transfer_buffers(0);
382 wait_for_dma_to_complete();
383 clocks_to_transfer = (0xFFFFFFFF - tc[T2_COUNT])
385 tc[T2_CONTROL] = 0;
386 log_info("Transfer of %u bytes to 0x%08x took %u cycles",
387 sdram_inputs.size_in_bytes, sdram_inputs.address, clocks_to_transfer);
388}
389
393static inline bool prepare_timestep(uint32_t time) {
394 uint32_t cspr = spin1_int_disable();
395
396 // Reset these to ensure consistency
398 next_buffer_to_process = 0;
399
400 // We do this here rather than during init, as it should have similar
401 // contention to the expected time of execution
402 if (clocks_to_transfer == 0) {
403 measure_transfer_time();
404 }
405
406 // Start timer2 to tell us when to stop
407 uint32_t timer = tc[T1_COUNT];
408 if (timer < clocks_to_transfer) {
409 return false;
410 }
411 uint32_t time_until_stop = timer - clocks_to_transfer;
412 tc[T2_CONTROL] = 0;
413 tc[T2_LOAD] = time_until_stop;
414 tc[T2_CONTROL] = 0xe3;
415
416 log_debug("Start of time step %d, timer = %d, loading with %d",
417 time, timer, time_until_stop);
418
419 // Store recording data from last time step
420 store_data(time);
421
422 // Clear the buffer if needed
425 }
426 p_per_ts_struct.packets_this_time_step = 0;
427 spikes_processed_this_time_step = 0;
428
430 spin1_mode_restore(cspr);
431 return true;
432}
433
437static inline void do_rewiring(uint32_t time, uint32_t n_rewires) {
438 uint32_t spike;
440 uint32_t current_buffer = 0;
441 uint32_t next_buffer = 0;
442 bool dma_in_progress = false;
443
444 // Start the first transfer
445 uint32_t rewires_to_go = n_rewires;
446 while (rewires_to_go > 0 && !dma_in_progress) {
447 if (synaptogenesis_dynamics_rewire(time, &spike, &result)) {
448 dma_buffers[next_buffer].sdram_writeback_address = result.row_address;
449 dma_buffers[next_buffer].n_bytes_transferred = result.n_bytes_to_transfer;
450 do_fast_dma_read(result.row_address, dma_buffers[next_buffer].row,
451 result.n_bytes_to_transfer);
452 next_buffer = (next_buffer + 1) & DMA_BUFFER_MOD_MASK;
453 dma_in_progress = true;
454 }
455 rewires_to_go--;
456 }
457
458 // Go in a loop until all done
459 while (dma_in_progress) {
460
461 // Start the next DMA if possible
462 dma_in_progress = false;
463 while (rewires_to_go > 0 && !dma_in_progress) {
464 if (synaptogenesis_dynamics_rewire(time, &spike, &result)) {
465 dma_in_progress = true;
466 }
467 rewires_to_go--;
468 }
469
470 // Wait for the last DMA to complete
471 wait_for_dma_to_complete();
472
473 // Start the next DMA read
474 if (dma_in_progress) {
475 dma_buffers[next_buffer].sdram_writeback_address = result.row_address;
476 dma_buffers[next_buffer].n_bytes_transferred = result.n_bytes_to_transfer;
477 do_fast_dma_read(result.row_address, dma_buffers[next_buffer].row,
478 result.n_bytes_to_transfer);
479 next_buffer = (next_buffer + 1) & DMA_BUFFER_MOD_MASK;
480 }
481
482 // If the row has been restructured, transfer back to SDRAM
484 time, dma_buffers[current_buffer].row)) {
486 if (dma_in_progress) {
487 wait_for_dma_to_complete();
488 }
489 do_fast_dma_write(
490 dma_buffers[current_buffer].row,
491 dma_buffers[current_buffer].sdram_writeback_address,
492 dma_buffers[current_buffer].n_bytes_transferred);
493 if (!dma_in_progress) {
494 wait_for_dma_to_complete();
495 }
496 }
497 current_buffer = (current_buffer + 1) & DMA_BUFFER_MOD_MASK;
498 }
499}
500
501void spike_processing_fast_time_step_loop(uint32_t time, uint32_t n_rewires) {
502
503 // Prepare for the start
504 if (!prepare_timestep(time)) {
505 skipped_time_steps++;
506 process_end_of_time_step(time);
507 return;
508 }
509
510 // Do rewiring
511 do_rewiring(time, n_rewires);
512
513 // Loop until the end of a time step is reached
514 while (true) {
515
516 // Wait for a spike, or the timer to expire
517 uint32_t spike;
518 while (!is_end_of_time_step() && !get_next_spike(time, &spike)) {
519 // This doesn't wait for interrupt currently because there isn't
520 // a way to have a T2 interrupt without a callback function, and
521 // a callback function is too slow! This is therefore a busy wait.
522 // wait_for_interrupt();
523 }
524
525 // If the timer has gone off, that takes precedence
526 if (is_end_of_time_step()) {
527 clear_end_of_time_step();
528 process_end_of_time_step(time);
529 return;
530 }
531
532 // There must be a spike! Start a DMA processing loop...
534 bool dma_in_progress = start_first_dma(time, &spike, &result);
535 while (dma_in_progress && !is_end_of_time_step()) {
536
537 // If self-connected looped back spike then process post event here
538 if (((spike & key_config.mask) == key_config.key) &&
540 synapse_dynamics_process_post_synaptic_event(
542 }
543
544 // See if there is another DMA to do
545 dma_in_progress = get_next_dma(time, &spike, &result);
546
547 // Finish the current DMA before starting the next
548 if (!wait_for_dma_to_complete_or_end()) {
550 break;
551 }
553 if (dma_in_progress) {
554 read_synaptic_row(spike, &result);
555 }
556
557 // Process the row we already have while the DMA progresses
558 process_current_row(time, dma_in_progress);
559
560 }
561
562 }
563}
564
565static inline void check_times(void) {
566 uint32_t tc_time = tc[T1_COUNT];
567 if (tc_time > earliest_spike_received_time) {
568 earliest_spike_received_time = tc_time;
569 }
570 if (tc_time < latest_spike_received_time) {
571 latest_spike_received_time = tc_time;
572 }
573}
574
578void multicast_packet_received_callback(uint key, UNUSED uint unused) {
579 log_debug("Received spike %x", key);
580 p_per_ts_struct.packets_this_time_step++;
582 check_times();
583}
584
589 log_debug("Received spike %x with payload %d", key, payload);
590 p_per_ts_struct.packets_this_time_step++;
591
592 // cycle through the packet insertion
593 for (uint count = payload; count > 0; count--) {
595 }
596 check_times();
597}
598
600 uint32_t row_max_n_words, uint32_t spike_buffer_size,
601 bool discard_late_packets, uint32_t pkts_per_ts_rec_region,
602 uint32_t multicast_priority, struct sdram_config sdram_inputs_param,
603 struct key_config key_config_param, weight_t *ring_buffers_param) {
604 // Allocate the DMA buffers
605 for (uint32_t i = 0; i < N_DMA_BUFFERS; i++) {
606 dma_buffers[i].row = spin1_malloc(row_max_n_words * sizeof(uint32_t));
607 if (dma_buffers[i].row == NULL) {
608 log_error("Could not initialise DMA buffers");
609 return false;
610 }
611 log_debug("DMA buffer %u allocated at 0x%08x",
612 i, dma_buffers[i].row);
613 }
615 next_buffer_to_process = 0;
616
617 // Allocate incoming spike buffer
619 return false;
620 }
621
622 // Store parameters and data
623 clear_input_buffers_of_late_packets = discard_late_packets;
624 p_per_ts_region = pkts_per_ts_rec_region;
625 sdram_inputs = sdram_inputs_param;
626 key_config = key_config_param;
627 ring_buffers = ring_buffers_param;
628
629 // Configure for multicast reception
631 multicast_priority);
633 multicast_priority);
634
635 // Wipe the inputs using word writes
636 for (uint32_t i = 0; i < (sdram_inputs.size_in_bytes >> 2); i++) {
637 sdram_inputs.address[i] = 0;
638 }
639
640 return true;
641}
642
651 prov->max_spikes_processed = max_spikes_processed;
653 prov->n_transfer_timer_overruns = transfer_timer_overruns;
654 prov->n_skipped_time_steps = skipped_time_steps;
655 prov->max_transfer_timer_overrun = max_transfer_timer_overrun;
656 prov->earliest_receive = earliest_spike_received_time;
657 prov->latest_receive = latest_spike_received_time;
658 prov->max_spikes_overflow = max_spikes_overflow;
659}
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
static struct sdram_config sdram_inputs
The SDRAM input configuration data.
uint32_t * address_t
void log_error(const char *message,...)
void log_debug(const char *message,...)
void log_info(const char *message,...)
static bool clear_input_buffers_of_late_packets
Whether to clear packets each timestep.
static uint32_t key
Base multicast key for sending messages.
static uint32_t count_input_buffer_packets_late
number of packets late
static bool in_spikes_get_next_spike(spike_t *spike)
Retrieves a spike from the input spike buffer.
Definition in_spikes.h:66
static circular_buffer buffer
Buffer for quickly taking spikes received by a fast interrupt and queueing them for later processing ...
Definition in_spikes.h:28
static bool in_spikes_initialize_spike_buffer(uint32_t size)
This function initialises the input spike buffer.
Definition in_spikes.h:51
static void in_spikes_clear(void)
clears the input spike buffer.
Definition in_spikes.h:126
static uint32_t in_spikes_size(void)
get the size of the input spike buffer
Definition in_spikes.h:121
static counter_t in_spikes_get_n_buffer_overflows(void)
Get the number of times that the input spike buffer overflowed.
Definition in_spikes.h:80
static bool in_spikes_add_spike(spike_t spike)
Adds a spike to the input spike buffer.
Definition in_spikes.h:59
uint32_t n_spikes[2]
Spike buffer counters.
uint32_t synapse_delay_mask
The mask to get the synaptic delay from a "synapse".
Definition local_only.c:71
static uint32_t max_spikes_received
The maximum number of spikes received in any time step.
Definition local_only.c:59
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
uint32_t p_per_ts_region
The region where packets-per-timestep are stored.
Definition local_only.c:80
static struct @8 p_per_ts_struct
The number of packets received this time step for recording.
struct synaptic_row * synaptic_row_t
The type of a synaptic row.
uint32_t spike_t
The type of a spike.
Master pop(ulation) table API.
bool population_table_get_next_address(spike_t *spike, pop_table_lookup_result_t *result)
Get the next row data for a previously given spike. If no spike has been given, return False.
static bool population_table_is_next(void)
Determine if there are more items with the same key.
bool population_table_get_first_address(spike_t spike, pop_table_lookup_result_t *result)
Get the first row data for the given input spike.
A structure to hold a response to a population table lookup.
bool recording_record(channel_index_t channel, void *data, size_t size_bytes)
void rt_error(uint code,...)
#define N_DMA_BUFFERS
The number of DMA Buffers to use.
static uint32_t spike_processing_count
the number of spikes that were processed (used in provenance generation)
static uint32_t n_successful_rewires
The number of successful rewires.
static uint32_t next_buffer_to_fill
The index of the next buffer to be filled by a DMA.
static uint32_t biggest_fill_size_of_input_buffer
tracker of how full the input buffer got.
static void multicast_packet_received_callback(uint key, uint unused)
Called when a multicast packet is received.
static dma_buffer dma_buffers[N_DMA_BUFFERS]
The DTCM buffers for the synapse rows.
static void multicast_packet_pl_received_callback(uint key, uint payload)
Called when a multicast packet is received.
static uint32_t dma_complete_count
the number of DMA completes (used in provenance generation)
Spike processing fast API.
uint32_t spike_id_mask
The mask to get the spike ID.
uint32_t n_packets_dropped_from_lateness
The number of packets that were cleared at the end of timesteps.
uint32_t max_spikes_overflow
The most spikes left at the end of any time step.
uint32_t max_filled_input_buffer_size
The maximum size of the input buffer.
uint32_t mask
The mask.
uint32_t n_dmas_complete
The number of DMAs performed.
void spike_processing_fast_time_step_loop(uint32_t time, uint32_t n_rewires)
The main loop of spike processing to be run once per time step. Note that this function will not retu...
uint32_t n_rewires
The number of rewires performed.
uint32_t self_connected
Is the node self connected.
uint32_t n_skipped_time_steps
The number of times a time step was skipped entirely.
void spike_processing_fast_store_provenance(struct spike_processing_fast_provenance *prov)
Store any provenance data gathered from spike processing.
uint32_t key
The key.
uint32_t n_input_buffer_overflows
A count of the times that the synaptic input circular buffers overflowed.
uint32_t n_transfer_timer_overruns
The number of times the transfer took longer than expected.
uint32_t max_spikes_received
The maximum number of spikes received in a time step.
bool spike_processing_fast_initialise(uint32_t row_max_n_words, uint32_t spike_buffer_size, bool discard_late_packets, uint32_t pkts_per_ts_rec_region, uint32_t multicast_priority, struct sdram_config sdram_inputs_param, struct key_config key_config_param, weight_t *ring_buffers_param)
Set up spike processing.
uint32_t n_spikes_processed
The number of spikes received and processed.
uint32_t max_spikes_processed
The maximum number of spikes processed in a time step.
uint32_t max_transfer_timer_overrun
The maximum additional time taken to transfer.
uint32_t earliest_receive
The earliest received time of a spike.
uint32_t latest_receive
The latest received time of a spike.
uint32_t colour_shift
The colour shift to apply after masking.
Provenance for spike processing.
uint32_t size_in_bytes
The size of the input data to be transferred per core.
uint8_t * address
The start address of the input data to be transferred.
uint32_t time_for_transfer_overhead
The time of the transfer in us.
static struct sdram_config * sdram_inputs
Where synaptic input is to be written.
static uint32_t spike_buffer_size
The size of each spike buffer in bytes.
A region of SDRAM used to transfer synapses.
MCPL_PACKET_RECEIVED
MC_PACKET_RECEIVED
#define NULL
uint spin1_int_disable(void)
void spin1_mode_restore(uint value)
void spin1_callback_on(uint event_id, callback_t cback, int priority)
#define T2_COUNT
#define T1_COUNT
#define T2_CONTROL
#define DMA_CTRL
unsigned int uint
#define T2_LOAD
#define T2_INT_CLR
#define T1_LOAD
spike_t originating_spike
Key of originating spike.
synaptic_row_t row
Row data.
uint32_t n_bytes_transferred
Number of bytes transferred in the read.
synaptic_row_t sdram_writeback_address
Address in SDRAM to write back plastic region to.
uint32_t colour
Spike colour.
uint32_t colour_mask
Spike colour mask.
API for synapse dynamics.
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 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.
The type of the fixed part of the row. The fixed-plastic part follows.
void synapses_flush_ring_buffers(timer_t time)
Reset the ring buffers to 0 at the given time.
Definition synapses.c:337
uint32_t synapse_index_mask
Mask to pick out the synapse index.
Definition synapses.c:69
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
uint32_t synapse_type_mask
Mask to pick out the synapse type.
Definition synapses.c:73
Operations on synapses.
This file contains the main interface for structural plasticity.
bool synaptogenesis_dynamics_rewire(uint32_t time, spike_t *spike, pop_table_lookup_result_t *result)
Trigger the process of synaptic rewiring.
void synaptogenesis_spike_received(uint32_t time, spike_t spike)
Indicates that a spike has been received.
bool synaptogenesis_row_restructure(uint32_t time, synaptic_row_t row)
Perform the actual restructuring of a row.