sPyNNaker neural_modelling 7.3.1
Loading...
Searching...
No Matches
delay_extension.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
20#include "delay_extension.h"
21
23#include <common/in_spikes.h>
24#include <bit_field.h>
25#include <data_specification.h>
26#include <debug.h>
27#include <simulation.h>
28#include <spin1_api.h>
29#include <common/send_mc.h>
30
32#define IN_BUFFER_SIZE 256
33
35#define COUNTER_SATURATION_VALUE 255
36
46
74
75// Globals
77static bool has_key;
79static uint32_t key = 0;
81static uint32_t incoming_key = 0;
83static uint32_t incoming_mask = 0;
86static uint32_t incoming_neuron_mask = 0;
87
89static uint32_t num_neurons = 0;
90
92static uint32_t max_keys = 0;
93
96
98static uint32_t time = UINT32_MAX;
100static uint32_t simulation_ticks = 0;
102static uint32_t infinite_run;
103
111static uint8_t **spike_counters = NULL;
113static uint32_t num_delay_stages = 0;
115static uint32_t n_delay_in_a_stage = 0;
117static uint32_t num_delay_slots = 0;
119static uint32_t num_delay_slots_mask = 0;
121static uint32_t neuron_bit_field_words = 0;
122
124static uint32_t n_in_spikes = 0;
126static uint32_t n_processed_spikes = 0;
128static uint32_t n_spikes_sent = 0;
130static uint32_t n_spikes_added = 0;
131
133static uint32_t n_delays = 0;
134
136static uint32_t saturation_count = 0;
137
140
143
146
148static uint32_t timer_period = 0;
149
151static bool spike_processing = false;
152
154static uint32_t n_backgrounds_queued = 0;
155
157static uint32_t n_background_overloads = 0;
158
160static uint32_t max_backgrounds_queued = 0;
161
163static uint32_t n_colour_bits = 0;
164
166static uint32_t colour_mask = 0;
167
169static uint32_t colour = 0;
170
171//---------------------------------------
172// Because we don't want to include string.h or strings.h for memset
179static inline void zero_spike_counters(
180 uint8_t *counters, uint32_t num_items) {
181 for (uint32_t i = 0 ; i < num_items ; i++) {
182 counters[i] = 0;
183 }
184}
185
189static inline uint32_t round_to_next_pot(uint32_t v) {
190 v--;
191 v |= v >> 1;
192 v |= v >> 2;
193 v |= v >> 4;
194 v |= v >> 8;
195 v |= v >> 16;
196 v++;
197 return v;
198}
199
204 log_debug("read_parameters: starting");
205
206 has_key = params->has_key;
207 key = params->key;
208 incoming_key = params->incoming_key;
209 incoming_mask = params->incoming_mask;
210 incoming_neuron_mask = ~incoming_mask;
211 log_debug("\t key = 0x%08x, incoming key = 0x%08x, incoming mask = 0x%08x,"
212 "incoming key mask = 0x%08x",
214
215 num_neurons = params->n_atoms;
216 neuron_bit_field_words = get_bit_field_size(num_neurons);
217
218 num_delay_stages = params->n_delay_stages;
219 n_delay_in_a_stage = params->n_delay_in_a_stage;
221
223
225 // We need an extra slot here (to make one clearable after the maximum delay
226 // time), and a power of 2 (to make it easier to loop)
227 uint32_t num_delay_slots_pot = round_to_next_pot(num_delay_slots + 1);
228 num_delay_slots_mask = num_delay_slots_pot - 1;
229
230 log_info("\t parrot neurons = %u, neuron bit field words = %u,"
231 " num delay stages = %u, num delay slots = %u (pot = %u),"
232 " num delay slots mask = %08x, n delay in a stage = %u",
234 num_delay_stages, num_delay_slots, num_delay_slots_pot,
236
237 // Allocate array of counters for each delay slot
238 spike_counters = spin1_malloc(num_delay_slots_pot * sizeof(uint8_t*));
239 if (spike_counters == NULL) {
240 log_error("failed to allocate memory for array of size %u bytes",
241 num_delay_slots_pot * sizeof(uint8_t*));
242 return false;
243 }
244
245 for (uint32_t s = 0; s < num_delay_slots_pot; s++) {
246 // Allocate an array of counters for each neuron and zero
247 spike_counters[s] = spin1_malloc(num_neurons * sizeof(uint8_t));
248 if (spike_counters[s] == NULL) {
249 log_error("failed to allocate memory for bitfield of size %u bytes",
250 num_neurons * sizeof(uint8_t));
251 return false;
252 }
254 }
255
256 n_colour_bits = params->n_colour_bits;
257 colour_mask = (1 << n_colour_bits) - 1;
258
259 log_debug("read_parameters: completed successfully");
260 return true;
261}
262
286
289static bool initialize(void) {
290 log_info("initialise: started");
291
292 // Get the address this core's DTCM data starts at from SRAM
295
296 // Read the header
297 if (!data_specification_read_header(ds_regions)) {
298 return false;
299 }
300
301 // Get the timing details and set up the simulation interface
303 data_specification_get_region(SYSTEM, ds_regions),
304 APPLICATION_NAME_HASH, &timer_period, &simulation_ticks,
305 &infinite_run, &time, SDP, DMA)) {
306 return false;
307 }
308
309 // set provenance function
312 data_specification_get_region(PROVENANCE_REGION, ds_regions));
313
314 // Get the parameters
315 if (!read_parameters(data_specification_get_region(
316 DELAY_PARAMS, ds_regions))) {
317 return false;
318 }
319
320 log_info("initialise: completed successfully");
321
322 return true;
323}
324
325// Callbacks
333static void incoming_spike_callback(uint key, uint payload) {
334
335 if (payload == 0) {
336 payload = 1;
337 }
338 log_debug("Received spike %x", key);
339
340 for (uint32_t i = payload; i > 0; i--) {
341 n_in_spikes++;
343 }
344
345 if (!spike_processing) {
346 if (spin1_trigger_user_event(0, 0)) {
347 spike_processing = true;
348 }
349 }
350}
351
355static inline index_t key_n(key_t k) {
356 return k & incoming_neuron_mask;
357}
358
360static inline void spike_process(void) {
361
362 // While there are any incoming spikes
363 spike_t s;
364 uint32_t state = spin1_int_disable();
365 while (in_spikes_get_next_spike(&s)) {
366 spin1_mode_restore(state);
368
369 if ((s & incoming_mask) == incoming_key) {
370 // Mask out neuron ID
371 uint32_t spike_id = key_n(s);
372 uint32_t spike_colour = spike_id & colour_mask;
373 uint32_t neuron_id = spike_id >> n_colour_bits;
374 if (neuron_id < num_neurons) {
375
376 // Account for delayed spikes
377 int32_t colour_diff = colour - spike_colour;
378 uint32_t colour_delay = colour_diff & colour_mask;
379
380 // Get current time slot of incoming spike counters
381 uint32_t time_slot = (time + colour_delay) & num_delay_slots_mask;
382 uint8_t *time_slot_spike_counters = spike_counters[time_slot];
383
384 // Increment counter
385 if (time_slot_spike_counters[neuron_id] ==
387 saturation_count += 1;
388 } else {
389 time_slot_spike_counters[neuron_id]++;
390 }
391 log_debug("Incrementing counter %u = %u\n",
392 neuron_id,
393 time_slot_spike_counters[neuron_id]);
395 } else {
397 log_debug("Invalid neuron ID %u", neuron_id);
398 }
399 } else {
401 log_debug("Invalid spike key 0x%08x", s);
402 }
403 state = spin1_int_disable();
404 }
405
406 spike_processing = false;
407 spin1_mode_restore(state);
408}
409
414static void user_callback(UNUSED uint unused0, UNUSED uint unused1) {
416}
417
422static void background_callback(uint local_time, UNUSED uint timer_count) {
423 // Loop through delay stages
424 for (uint32_t d = 0; d < num_delay_stages; d++) {
425 uint32_t delay_stage_delay = (d + 1) * n_delay_in_a_stage;
426 if (local_time >= delay_stage_delay) {
427 uint32_t delay_stage_time_slot =
428 (local_time - delay_stage_delay) & num_delay_slots_mask;
429 uint8_t *delay_stage_spike_counters =
430 spike_counters[delay_stage_time_slot];
431
432 log_debug("%u: Checking time slot %u for delay stage %u (delay %u)",
433 local_time, delay_stage_time_slot, d, delay_stage_delay);
434
435 // Loop through neurons
436 for (uint32_t n = 0; n < num_neurons; n++) {
437
438 // If no spikes to send, skip
439 if (delay_stage_spike_counters[n] == 0) {
440 continue;
441 }
442
443 // Calculate key all spikes coming from this neuron will be
444 // sent with
445 uint32_t neuron_index = ((d * num_neurons) + n);
446 uint32_t spike_key = (key + (neuron_index << n_colour_bits)) | colour;
447
448 log_debug("Neuron %u sending %u spikes after delay"
449 "stage %u with key %x",
450 n, delay_stage_spike_counters[n], d,
451 spike_key);
452
453 // fire n spikes as payload, 1 as none payload.
454 if (has_key) {
455 if (delay_stage_spike_counters[n] > 1) {
456 log_debug(
457 "%d: sending packet with key 0x%08x and payload %d",
458 time, spike_key, delay_stage_spike_counters[n]);
459
460 send_spike_mc_payload(spike_key, delay_stage_spike_counters[n]);
461
462 // update counter
463 n_spikes_sent += delay_stage_spike_counters[n];
464 } else if (delay_stage_spike_counters[n] == 1) {
465 log_debug("%d: sending spike with key 0x%08x", time, spike_key);
466
467 send_spike_mc(spike_key);
468
469 // update counter
471 }
472 }
473 }
474 }
475 }
477}
478
482static void timer_callback(uint timer_count, UNUSED uint unused1) {
483 uint32_t state = spin1_int_disable();
484 uint32_t n_spikes = in_spikes_size();
487 }
488 // Record the count whether clearing or not for provenance
490 time++;
491
492 // Clear counters
493 if (time > num_delay_slots) {
494 uint32_t clearable_slot = ((time - 1) - num_delay_slots) & num_delay_slots_mask;
495 log_debug("%d: Clearing time slot %d", time, clearable_slot);
497 }
498
499 log_debug("Timer tick %u", time);
500
501 // If a fixed number of simulation ticks are specified and these have passed
503 // handle the pause and resume functionality
505
506 log_debug("Delay extension finished at time %u, %u received spikes, "
507 "%u processed spikes, %u sent spikes, %u added spikes",
510
511 log_debug("Delayed %u times", n_delays);
512
513 // Subtract 1 from the time so this tick gets done again on the next
514 // run
515 time--;
516
518 spin1_mode_restore(state);
519 return;
520 }
521
522 // Set the colour for the time step
524
526 // We have failed to do this timer tick!
528 } else {
532 }
533 }
534 spin1_mode_restore(state);
535}
536
538void c_main(void) {
539 log_info("max dtcm supply %d", sark_heap_max(sark.heap, 0));
540 if (!initialize()) {
541 log_error("Error in initialisation - exiting!");
543 }
544
545 // Start the time at "-1" so that the first tick will be 0
546 time = UINT32_MAX;
547
548 // Initialise the incoming spike buffer
551 }
552
553 // Set timer tick (in microseconds)
554 log_debug("Timer period %u", timer_period);
555 spin1_set_timer_tick(timer_period);
556
557 // Register callbacks
562
564}
uint32_t index_t
SYSTEM
PROVENANCE_REGION
uint32_t * address_t
data_specification_metadata_t * data_specification_get_data_address(void)
bool data_specification_read_header(data_specification_metadata_t *ds_regions)
void log_error(const char *message,...)
void log_debug(const char *message,...)
void log_info(const char *message,...)
static bool initialize(void)
Read the application configuration.
static uint8_t ** spike_counters
The spike counters, as a 2D array.
static uint32_t incoming_mask
Mask for incoming_key to say which messages are for this program.
static uint32_t incoming_neuron_mask
Mask for key (that matches incoming_key/incoming_mask) to extract the neuron ID from it.
static uint32_t num_neurons
Number of neurons supported.
uint32_t n_buffer_overflows
Number of circular buffer overflows (spikes internally dropped)
uint32_t n_packets_processed
Number of spikes transferred via queue.
uint32_t n_packets_dropped_due_to_invalid_key
number of packets dropped due to invalid key
static uint32_t simulation_ticks
Simulation speed.
static uint32_t n_spikes_sent
Number of spikes sent.
static uint32_t n_packets_dropped_due_to_invalid_neuron_value
number of packets dropped due to invalid neuron id
static void spike_process(void)
Processes spikes queued by incoming_spike_callback()
uint32_t n_delays
Number of times we had to back off because the comms hardware was busy.
uint32_t n_packets_dropped_due_to_invalid_neuron_value
number of packets dropped due to invalid neuron value
static uint32_t incoming_key
Key for receiving messages.
static void background_callback(uint local_time, uint timer_count)
Background event callback.
static uint32_t colour_mask
The mask to apply to get the colour from the current timestep or key.
static uint32_t n_in_spikes
Number of input spikes.
static uint32_t n_delays
Number of times we had to back off because the comms hardware was busy.
static uint32_t colour
The colour for the current time step.
static void zero_spike_counters(uint8_t *counters, uint32_t num_items)
Sets an array of counters to zero.
static uint32_t n_processed_spikes
Number of spikes transferred via queue.
static bool clear_input_buffers_of_late_packets
Whether to clear packets each timestep.
uint32_t n_packets_received
Number of input spikes.
static uint32_t num_delay_slots
The total number of delay slots.
static void store_provenance_data(address_t provenance_region)
Writes the provenance data.
static uint32_t key
Base multicast key for sending messages.
static uint32_t num_delay_slots_mask
Mask for converting time into the current delay slot.
#define COUNTER_SATURATION_VALUE
the point where the count has saturated.
uint32_t n_packets_sent
Number of spikes sent.
static uint32_t max_keys
number of possible keys.
static uint32_t n_colour_bits
The number of colour bits (both from source and to send)
static void incoming_spike_callback(uint key, uint payload)
Handles incoming spikes (FIQ)
delay_extension_callback_priorities
values for the priority for each callback
@ TIMER
Call timer at 0 to keep it quick.
@ DMA
DMA is not actually used.
@ BACKGROUND
Background processing.
@ SDP
SDP handling is queued.
@ MC_PACKET
multicast packet reception uses FIQ
@ USER
Call user at 0 as well; will be behind timer.
static uint32_t infinite_run
True if we're running forever.
void c_main(void)
Entry point.
uint32_t n_background_queue_overloads
Background queue overloads.
#define IN_BUFFER_SIZE
the size of the circular queue for packets.
static bool has_key
bool in int form for if there is a key
static uint32_t n_backgrounds_queued
The number of background tasks queued / running.
uint32_t n_packets_lost_due_to_count_saturation
number of packets lost due to count saturation of uint8
static uint32_t n_spikes_added
Number of spikes added to delay processing.
static void user_callback(uint unused0, uint unused1)
User event callback.
static bool spike_processing
Is spike processing happening right now?
static uint32_t timer_period
Used for configuring the timer hardware.
static void timer_callback(uint timer_count, uint unused1)
Main timer callback.
static uint32_t round_to_next_pot(uint32_t v)
Rounds up to the next power of two.
static uint32_t max_backgrounds_queued
The maximum number of background tasks queued.
static uint32_t num_delay_stages
The number of delay stages.
uint32_t max_backgrounds_queued
Maximum backgrounds queued.
uint32_t n_packets_added
Number of spikes added to delay processing.
uint32_t count_input_buffer_packets_late
number of packets dropped due to out of time
static uint32_t time
Simulation time.
static uint32_t n_packets_dropped_due_to_invalid_key
number of packets dropped due to invalid key
static uint32_t n_delay_in_a_stage
The number of delays within a delay stage.
static uint32_t count_input_buffer_packets_late
number of packets late
static index_t key_n(key_t k)
Gets the neuron ID of the incoming spike.
static uint32_t saturation_count
Number of packets dropped due to count saturation.
static uint32_t neuron_bit_field_words
Size of each bitfield in ::neuron_delay_stage_config.
static uint32_t n_background_overloads
The number of times the background couldn't be added.
static bool read_parameters(struct delay_parameters *params)
Read the configuration region.
Structure of the provenance data.
Declarations for delay extensions.
@ DELAY_PARAMS
Delay parameters (see delay_parameters)
Delay configuration, as read from SDRAM where it was placed by DSG or by on-chip generation.
Functions for immediate handling of incoming spikes.
static bool in_spikes_get_next_spike(spike_t *spike)
Retrieves a spike from the input spike buffer.
Definition in_spikes.h:66
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.
static uint32_t local_time
The local time step counter.
Definition local_only.c:68
Data type definitions for SpiNNaker Neuron-modelling.
uint32_t key_t
The type of a SpiNNaker multicast message key word.
uint32_t spike_t
The type of a spike.
static key_t spike_key(spike_t s)
helper method to retrieve the key from a spike
static int * counters
Accumulators for each motor direction.
RTE_SWERR
heap_t * heap
sark_data_t sark
uint sark_heap_max(heap_t *heap, uint flag)
void rt_error(uint code,...)
void simulation_handle_pause_resume(resume_callback_t callback)
void simulation_set_provenance_function(prov_callback_t provenance_function, address_t provenance_data_address)
bool simulation_is_finished(void)
void simulation_ready_to_read(void)
void simulation_run(void)
bool simulation_initialise(address_t address, uint32_t expected_application_magic_number, uint32_t *timer_period, uint32_t *simulation_ticks_pointer, uint32_t *infinite_run_pointer, uint32_t *time_pointer, int sdp_packet_callback_priority, int dma_transfer_complete_priority)
MCPL_PACKET_RECEIVED
MC_PACKET_RECEIVED
USER_EVENT
TIMER_TICK
#define NULL
uint spin1_trigger_user_event(uint arg0, uint arg1)
uint spin1_schedule_callback(callback_t cback, uint arg0, uint arg1, uint priority)
uint spin1_int_disable(void)
void spin1_mode_restore(uint value)
void spin1_callback_on(uint event_id, callback_t cback, int priority)
unsigned int uint
static stdp_params params
Configuration parameters.