22#include "dma_common.h"
23#include <scamp_spin1_sync.h>
53#define N_DMA_BUFFERS 2
56#define DMA_BUFFER_MOD_MASK 0x1
62static uint32_t next_buffer_to_fill;
65static uint32_t next_buffer_to_process;
69static uint32_t count_input_buffer_packets_late;
72static uint32_t biggest_fill_size_of_input_buffer;
76static bool clear_input_buffers_of_late_packets;
79static uint32_t clocks_to_transfer = 0;
82static uint32_t n_successful_rewires = 0;
85static uint32_t dma_complete_count = 0;
88static uint32_t spike_processing_count = 0;
91static uint32_t max_spikes_received = 0;
94static uint32_t spikes_processed_this_time_step = 0;
97static uint32_t max_spikes_processed = 0;
100static uint32_t transfer_timer_overruns = 0;
103static uint32_t max_transfer_timer_overrun = 0;
106static uint32_t skipped_time_steps = 0;
109static uint32_t latest_spike_received_time = 0xFFFFFFFF;
112static uint32_t earliest_spike_received_time = 0;
115static uint32_t max_spikes_overflow = 0;
120 uint32_t packets_this_time_step;
137static inline bool is_end_of_time_step(
void) {
142static inline void clear_end_of_time_step(
void) {
149static inline bool wait_for_dma_to_complete_or_end(
void) {
150#if LOG_LEVEL >= LOG_DEBUG
153 uint32_t n_loops = 0;
154 while (!is_end_of_time_step() && !dma_done() && n_loops < 10000) {
157 if (!is_end_of_time_step() && !dma_done()) {
158 log_error(
"Timeout on DMA loop: DMA stat = 0x%08x!", dma[DMA_STAT]);
163 while (!dma_done()) {
169 return !is_end_of_time_step();
175static inline void transfer_buffers(uint32_t time) {
178 log_debug(
"Writing %d bytes to 0x%08x from ring buffer %d at 0x%08x",
187static inline void process_end_of_time_step(uint32_t time) {
194 transfer_buffers(time);
195 wait_for_dma_to_complete();
198 if (tc[T1_MASK_INT]) {
199 transfer_timer_overruns++;
201 if (diff > max_transfer_timer_overrun) {
202 max_transfer_timer_overrun = diff;
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);
225static inline bool get_next_spike(uint32_t time,
spike_t *spike) {
237 synapse_dynamics_process_post_synaptic_event(
252static inline bool start_first_dma(uint32_t time,
spike_t *spike,
257 read_synaptic_row(*spike, result);
260 }
while (!is_end_of_time_step() && get_next_spike(time, spike));
270static inline bool get_next_dma(uint32_t time,
spike_t *spike,
276 while (!is_end_of_time_step() && get_next_spike(time, spike)) {
289 "Error processing spike 0x%.8x for address 0x%.8x (local=0x%.8x)",
294 for (uint32_t i = 0; i < (
buffer->n_bytes_transferred >> 2); i++) {
302 if (fixed_synapse > (
buffer->n_bytes_transferred >> 2)) {
303 log_error(
"Too many fixed synapses: %u", fixed_synapse);
306 log_error(
"\nFixed-Fixed Region (%u synapses):", fixed_synapse);
307 for (; fixed_synapse > 0; fixed_synapse--) {
308 uint32_t synaptic_word = *synaptic_words++;
316 log_error(
" Delay %u, Synapse Type %u, Neuron %u", delay, type, neuron);
324static inline void process_current_row(uint32_t time,
bool dma_in_progress) {
325 bool write_back =
false;
329 buffer->row, &write_back)) {
337 buffer->sdram_writeback_address);
340 if (dma_in_progress) {
341 wait_for_dma_to_complete();
343 do_fast_dma_write(tcm_address, system_address, n_bytes);
346 if (!dma_in_progress) {
347 wait_for_dma_to_complete();
350 next_buffer_to_process = (next_buffer_to_process + 1) & DMA_BUFFER_MOD_MASK;
351 spikes_processed_this_time_step++;
356static inline void store_data(uint32_t time) {
360 if (n_spikes_left > max_spikes_overflow) {
361 max_spikes_overflow = n_spikes_left;
371 if (spikes_processed_this_time_step > max_spikes_processed) {
372 max_spikes_processed = spikes_processed_this_time_step;
377static inline void measure_transfer_time(
void) {
382 wait_for_dma_to_complete();
383 clocks_to_transfer = (0xFFFFFFFF - tc[
T2_COUNT])
386 log_info(
"Transfer of %u bytes to 0x%08x took %u cycles",
393static inline bool prepare_timestep(uint32_t time) {
398 next_buffer_to_process = 0;
402 if (clocks_to_transfer == 0) {
403 measure_transfer_time();
408 if (timer < clocks_to_transfer) {
411 uint32_t time_until_stop = timer - clocks_to_transfer;
416 log_debug(
"Start of time step %d, timer = %d, loading with %d",
417 time, timer, time_until_stop);
427 spikes_processed_this_time_step = 0;
437static inline void do_rewiring(uint32_t time, uint32_t n_rewires) {
440 uint32_t current_buffer = 0;
441 uint32_t next_buffer = 0;
442 bool dma_in_progress =
false;
445 uint32_t rewires_to_go = n_rewires;
446 while (rewires_to_go > 0 && !dma_in_progress) {
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;
459 while (dma_in_progress) {
462 dma_in_progress =
false;
463 while (rewires_to_go > 0 && !dma_in_progress) {
465 dma_in_progress =
true;
471 wait_for_dma_to_complete();
474 if (dma_in_progress) {
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;
486 if (dma_in_progress) {
487 wait_for_dma_to_complete();
491 dma_buffers[current_buffer].sdram_writeback_address,
493 if (!dma_in_progress) {
494 wait_for_dma_to_complete();
497 current_buffer = (current_buffer + 1) & DMA_BUFFER_MOD_MASK;
504 if (!prepare_timestep(
time)) {
505 skipped_time_steps++;
506 process_end_of_time_step(
time);
511 do_rewiring(
time, n_rewires);
518 while (!is_end_of_time_step() && !get_next_spike(
time, &spike)) {
526 if (is_end_of_time_step()) {
527 clear_end_of_time_step();
528 process_end_of_time_step(
time);
534 bool dma_in_progress = start_first_dma(
time, &spike, &result);
535 while (dma_in_progress && !is_end_of_time_step()) {
540 synapse_dynamics_process_post_synaptic_event(
545 dma_in_progress = get_next_dma(
time, &spike, &result);
548 if (!wait_for_dma_to_complete_or_end()) {
553 if (dma_in_progress) {
554 read_synaptic_row(spike, &result);
558 process_current_row(
time, dma_in_progress);
565static inline void check_times(
void) {
567 if (tc_time > earliest_spike_received_time) {
568 earliest_spike_received_time = tc_time;
570 if (tc_time < latest_spike_received_time) {
571 latest_spike_received_time = tc_time;
589 log_debug(
"Received spike %x with payload %d",
key, payload);
593 for (
uint count = payload; count > 0; count--) {
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) {
606 dma_buffers[i].
row = spin1_malloc(row_max_n_words *
sizeof(uint32_t));
608 log_error(
"Could not initialise DMA buffers of %u words",
612 log_debug(
"DMA buffer %u allocated at 0x%08x",
616 next_buffer_to_process = 0;
static weight_t * ring_buffers
The ring buffers to be used in the simulation.
uint32_t time
The current timer tick value.
static struct sdram_config sdram_inputs
The SDRAM input configuration data.
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.
static circular_buffer buffer
Buffer for quickly taking spikes received by a fast interrupt and queueing them for later processing ...
static bool in_spikes_initialize_spike_buffer(uint32_t size)
This function initialises the input spike buffer.
static void in_spikes_clear(void)
clears the input spike buffer.
static uint32_t in_spikes_size(void)
get the size of the input spike buffer
static counter_t in_spikes_get_n_buffer_overflows(void)
Get the number of times that the input spike buffer overflowed.
static bool in_spikes_add_spike(spike_t spike)
Adds a spike to the input spike buffer.
uint32_t n_spikes[2]
Spike buffer counters.
uint32_t synapse_delay_mask
The mask to get the synaptic delay from a "synapse".
static uint32_t max_spikes_received
The maximum number of spikes received in any time step.
uint32_t synapse_type_index_bits
The number of bits used by the synapse type and post-neuron index.
uint32_t synapse_index_bits
The number of bits used by just the post-neuron index.
uint32_t p_per_ts_region
The region where packets-per-timestep are stored.
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 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 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.
uint spin1_int_disable(void)
void spin1_mode_restore(uint value)
void spin1_callback_on(uint event_id, callback_t cback, int priority)
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.
uint32_t synapse_index_mask
Mask to pick out the synapse index.
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
uint32_t synapse_type_mask
Mask to pick out the synapse type.
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.