From 17735ff07272a243b76401147a6ce67557d01003 Mon Sep 17 00:00:00 2001 From: Chiara Bartolozzi Date: Mon, 8 Oct 2018 15:36:17 +0100 Subject: [PATCH 001/108] changes to compile code on Chiara's MAC --- neural_modelling/makefiles/neuron/Makefile | 5 +++-- .../src/neuron/implementations/neuron_impl_semd.h | 2 +- .../src/neuron/implementations/neuron_impl_standard.h | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/neural_modelling/makefiles/neuron/Makefile b/neural_modelling/makefiles/neuron/Makefile index fd293d46835..efe436be414 100644 --- a/neural_modelling/makefiles/neuron/Makefile +++ b/neural_modelling/makefiles/neuron/Makefile @@ -7,7 +7,6 @@ MODELS = IF_curr_exp \ IF_curr_exp_stdp_mad_pair_multiplicative \ IF_cond_exp_stdp_mad_pair_additive \ external_device_lif_control \ - IF_cond_exp_stoc \ IF_curr_exp_stdp_mad_recurrent_pre_stochastic_multiplicative \ IF_curr_exp_stdp_mad_recurrent_dual_fsm_multiplicative \ IF_curr_exp_stdp_mad_vogels_2011_additive \ @@ -22,7 +21,9 @@ MODELS = IF_curr_exp \ IF_curr_exp_stdp_mad_pair_additive_structural \ IF_curr_exp_structural \ IF_cond_exp_stdp_mad_pair_additive_structural \ - IF_curr_exp_sEMD + IF_curr_exp_sEMD \ + #IF_cond_exp_stoc + all: for d in $(MODELS); do $(MAKE) -C $$d || exit $$?; done diff --git a/neural_modelling/src/neuron/implementations/neuron_impl_semd.h b/neural_modelling/src/neuron/implementations/neuron_impl_semd.h index 678ad1c707b..987dd849ac5 100644 --- a/neural_modelling/src/neuron/implementations/neuron_impl_semd.h +++ b/neural_modelling/src/neuron/implementations/neuron_impl_semd.h @@ -12,7 +12,7 @@ #include #include #include -#include +//#include #define V_RECORDING_INDEX 0 #define GSYN_EXCITATORY_RECORDING_INDEX 1 diff --git a/neural_modelling/src/neuron/implementations/neuron_impl_standard.h b/neural_modelling/src/neuron/implementations/neuron_impl_standard.h index 053d7f30412..7a4d672a493 100644 --- a/neural_modelling/src/neuron/implementations/neuron_impl_standard.h +++ b/neural_modelling/src/neuron/implementations/neuron_impl_standard.h @@ -14,7 +14,7 @@ #include #include #include -#include +//#include #define V_RECORDING_INDEX 0 #define GSYN_EXCITATORY_RECORDING_INDEX 1 From 6e6d5bc75add6208d2d044567b32caa6ba0b9669 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Tue, 9 Oct 2018 21:06:45 +0100 Subject: [PATCH 002/108] Sketched out cerebellum neuron model and plasticity update --- .../neuron/IF_cond_exp_cerebellum/Makefile | 11 ++ .../Makefile | 15 ++ .../models/neuron_model_lif_t_last_impl.c | 83 ++++++++ .../models/neuron_model_lif_t_last_impl.h | 41 ++++ neural_modelling/src/neuron/neuron.c | 2 +- .../src/neuron/plasticity/stdp/post_events.h | 8 +- .../stdp/synapse_dynamics_stdp_mad_impl.c | 12 +- .../stdp/timing_dependence/timing_pfpc_impl.c | 28 +++ .../stdp/timing_dependence/timing_pfpc_impl.h | 158 +++++++++++++++ .../stdp/weight_dependence/weight_pfpc_impl.c | 59 ++++++ .../stdp/weight_dependence/weight_pfpc_impl.h | 88 +++++++++ neural_modelling/src/neuron/synapses.c | 15 ++ .../neuron/builds/if_cond_exp_cerebellum.py | 39 ++++ .../models/neuron/neuron_models/__init__.py | 6 +- ...n_model_leaky_integrate_and_fire_t_last.py | 186 ++++++++++++++++++ .../stdp/timing_dependence/__init__.py | 4 +- .../timing_dependence_pfpc.py | 102 ++++++++++ .../stdp/weight_dependence/__init__.py | 3 +- .../weight_dependence_pfpc.py | 77 ++++++++ 19 files changed, 925 insertions(+), 12 deletions(-) create mode 100644 neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile create mode 100644 neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile create mode 100644 neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.c create mode 100644 neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h create mode 100644 neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c create mode 100644 neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h create mode 100644 neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c create mode 100644 neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h create mode 100644 spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py create mode 100644 spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py create mode 100644 spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py create mode 100644 spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile new file mode 100644 index 00000000000..211b47d1a0b --- /dev/null +++ b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile @@ -0,0 +1,11 @@ +APP = $(notdir $(CURDIR)) + +NEURON_MODEL = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.c +NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.h +INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_conductance.h +NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h +THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h +SYNAPSE_TYPE_H = $(NEURON_DIR)/neuron/synapse_types/synapse_types_exponential_impl.h +SYNAPSE_DYNAMICS = $(NEURON_DIR)/neuron/plasticity/synapse_dynamics_static_impl.c + +include ../neural_build.mk diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile new file mode 100644 index 00000000000..045d8a47452 --- /dev/null +++ b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile @@ -0,0 +1,15 @@ +APP = $(notdir $(CURDIR)) + +NEURON_MODEL = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.c +NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.h +INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_conductance.h +NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h +THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h +SYNAPSE_TYPE_H = $(NEURON_DIR)/neuron/synapse_types/synapse_types_exponential_impl.h +SYNAPSE_DYNAMICS = $(NEURON_DIR)/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c +TIMING_DEPENDENCE = $(NEURON_DIR)/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c +TIMING_DEPENDENCE_H = $(NEURON_DIR)/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +WEIGHT_DEPENDENCE = $(NEURON_DIR)/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c +WEIGHT_DEPENDENCE_H = $(NEURON_DIR)/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h + +include ../neural_build.mk diff --git a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.c b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.c new file mode 100644 index 00000000000..04d9ef3be3b --- /dev/null +++ b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.c @@ -0,0 +1,83 @@ +#include "neuron_model_lif_t_last_impl.h" + +#include + +// simple Leaky I&F ODE +static inline void _lif_neuron_closed_form( + neuron_pointer_t neuron, REAL V_prev, input_t input_this_timestep) { + + REAL alpha = input_this_timestep * neuron->R_membrane + neuron->V_rest; + + // update membrane voltage + neuron->V_membrane = alpha - (neuron->exp_TC * (alpha - V_prev)); +} + +void neuron_model_set_global_neuron_params( + global_neuron_params_pointer_t params) { + use(params); + + // Does Nothing - no params +} + +state_t neuron_model_state_update( + uint16_t num_excitatory_inputs, input_t* exc_input, + uint16_t num_inhibitory_inputs, input_t* inh_input, + input_t external_bias, neuron_pointer_t neuron) { + + log_debug("Exc 1: %12.6k, Exc 2: %12.6k", exc_input[0], exc_input[1]); + log_debug("Inh 1: %12.6k, Inh 2: %12.6k", inh_input[0], inh_input[1]); + + + // If outside of the refractory period + if (neuron->refract_timer <= 0) { + REAL total_exc = 0; + REAL total_inh = 0; + + for (int i=0; i < num_excitatory_inputs; i++){ + total_exc += exc_input[i]; + } + for (int i=0; i< num_inhibitory_inputs; i++){ + total_inh += inh_input[i]; + } + // Get the input in nA + input_t input_this_timestep = + total_exc - total_inh + external_bias + neuron->I_offset; + + _lif_neuron_closed_form( + neuron, neuron->V_membrane, input_this_timestep); + } else { + + // countdown refractory timer + neuron->refract_timer -= 1; + } + return neuron->V_membrane; +} + +void neuron_model_has_spiked(neuron_pointer_t neuron) { + + // reset membrane voltage + neuron->V_membrane = neuron->V_reset; + + // reset refractory timer + neuron->refract_timer = neuron->T_refract; +} + +state_t neuron_model_get_membrane_voltage(neuron_pointer_t neuron) { + return neuron->V_membrane; +} + +void neuron_model_print_state_variables(restrict neuron_pointer_t neuron) { + log_debug("V membrane = %11.4k mv", neuron->V_membrane); +} + +void neuron_model_print_parameters(restrict neuron_pointer_t neuron) { + log_debug("V reset = %11.4k mv", neuron->V_reset); + log_debug("V rest = %11.4k mv", neuron->V_rest); + + log_debug("I offset = %11.4k nA", neuron->I_offset); + log_debug("R membrane = %11.4k Mohm", neuron->R_membrane); + + log_debug("exp(-ms/(RC)) = %11.4k [.]", neuron->exp_TC); + + log_debug("T refract = %u timesteps", neuron->T_refract); +} diff --git a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h new file mode 100644 index 00000000000..68cb436a255 --- /dev/null +++ b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h @@ -0,0 +1,41 @@ +#ifndef _NEURON_MODEL_LIF_CURR_T_LAST_IMPL_H_ +#define _NEURON_MODEL_LIF_CURR_T_LAST_IMPL_H_ + +#include "neuron_model.h" + +///////////////////////////////////////////////////////////// +// definition for LIF neuron parameters +typedef struct neuron_t { + // membrane voltage [mV] + REAL V_membrane; + + // membrane resting voltage [mV] + REAL V_rest; + + // membrane resistance [MOhm] + REAL R_membrane; + + // 'fixed' computation parameter - time constant multiplier for + // closed-form solution + // exp(-(machine time step in ms)/(R * C)) [.] + REAL exp_TC; + + // offset current [nA] + REAL I_offset; + + // countdown to end of next refractory period [timesteps] + int32_t refract_timer; + + // post-spike reset membrane voltage [mV] + REAL V_reset; + + // refractory time of neuron [timesteps] + int32_t T_refract; + + int32_t t_last; // time of last CF spike +} neuron_t; + +typedef struct global_neuron_params_t { +} global_neuron_params_t; + +#endif // _NEURON_MODEL_LIF_CURR_T_LAST_IMPL_H_ diff --git a/neural_modelling/src/neuron/neuron.c b/neural_modelling/src/neuron/neuron.c index 57100648e72..009c0e4d015 100644 --- a/neural_modelling/src/neuron/neuron.c +++ b/neural_modelling/src/neuron/neuron.c @@ -337,7 +337,7 @@ void neuron_do_timestep_update(timer_t time) { out_spikes_set_spike(spike_recording_indexes[neuron_index]); // Do any required synapse processing - synapse_dynamics_process_post_synaptic_event(time, neuron_index); +// synapse_dynamics_process_post_synaptic_event(time, neuron_index); if (use_key) { diff --git a/neural_modelling/src/neuron/plasticity/stdp/post_events.h b/neural_modelling/src/neuron/plasticity/stdp/post_events.h index 96dd0b7a0a9..5e8b88d3e00 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/post_events.h +++ b/neural_modelling/src/neuron/plasticity/stdp/post_events.h @@ -193,9 +193,9 @@ static inline void post_events_add(uint32_t time, post_event_history_t *events, static inline void print_event_history(post_event_history_t *events){ - log_debug(" ## printing entire post event history ##"); + io_printf(IO_BUF, "\n\n ## printing entire post event history ##\n"); for (uint i = 0; i <= events->count_minus_one; i++){ - log_debug("post event: %u, time: %u, trace: %u", + io_printf(IO_BUF, " post event: %u, time: %u, trace: %u\n", i, events->times[i], events->traces[i] @@ -205,14 +205,14 @@ static inline void print_event_history(post_event_history_t *events){ static inline void print_delayed_window_events(post_event_history_t *post_event_history, uint32_t begin_time, uint32_t end_time, uint32_t delay_dendritic){ - log_debug(" ## printing post window ##"); + io_printf(IO_BUF, "\n\n ## printing post window ##\n"); post_event_window_t post_window = post_events_get_window_delayed( post_event_history, begin_time, end_time); while (post_window.num_events > 0) { const uint32_t delayed_post_time = *post_window.next_time + delay_dendritic; - log_debug("post spike: %u, time: %u, trace: %u", + io_printf(IO_BUF, " post spike: %u, time: %u, trace: %u\n", post_window.num_events, delayed_post_time, *post_window.next_trace); diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c index 75430d795fb..63c6a94bb7f 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c @@ -87,9 +87,12 @@ static inline final_state_t _plasticity_update_synapse( window_begin_time, window_end_time, post_window.prev_time, post_window.num_events); - // print_event_history(post_event_history); - // print_delayed_window_events(post_event_history, window_begin_time, - // window_end_time, delay_dendritic); + print_event_history(post_event_history); + print_delayed_window_events(post_event_history, window_begin_time, + window_end_time, delay_dendritic); + + + io_printf(IO_BUF, "\n Looping over climbing fibre spikes:\n"); // Process events in post-synaptic window while (post_window.num_events > 0) { @@ -264,8 +267,9 @@ bool synapse_dynamics_process_plastic_synapses( const pre_trace_t last_pre_trace = event_history->prev_trace; // Update pre-synaptic trace - log_debug("Adding pre-synaptic event to trace at time:%u", time); + io_printf(IO_BUF, "\nAdding pre-synaptic event (Purkinje fibre spike) at time: %u\n", time); event_history->prev_time = time; + event_history->prev_trace = timing_add_pre_spike(time, last_pre_time, last_pre_trace); diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c new file mode 100644 index 00000000000..89dc65802fe --- /dev/null +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c @@ -0,0 +1,28 @@ +#include "timing_pfpc_impl.h" + +//--------------------------------------- +// Globals +//--------------------------------------- +// Exponential lookup-tables +int16_t tau_plus_lookup[TAU_PLUS_SIZE]; +int16_t tau_minus_lookup[TAU_MINUS_SIZE]; + +//--------------------------------------- +// Functions +//--------------------------------------- +address_t timing_initialise(address_t address) { + + log_debug("timing_initialise: starting"); + log_debug("\tSTDP pair rule"); + // **TODO** assert number of neurons is less than max + + // Copy LUTs from following memory + address_t lut_address = maths_copy_int16_lut(&address[0], TAU_PLUS_SIZE, + &tau_plus_lookup[0]); + lut_address = maths_copy_int16_lut(lut_address, TAU_MINUS_SIZE, + &tau_minus_lookup[0]); + + log_debug("timing_initialise: completed successfully"); + + return lut_address; +} diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h new file mode 100644 index 00000000000..5e17a89d3e1 --- /dev/null +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -0,0 +1,158 @@ +#ifndef _TIMING_CEREBELLUM_IMPL_H_ +#define _TIMING_CEREBELLUM_IMPL_H_ + +//--------------------------------------- +// Typedefines +//--------------------------------------- +typedef int16_t post_trace_t; +typedef int16_t pre_trace_t; + +#include +#include "timing.h" +#include + +// Include debug header for log_info etc +#include + +// Include generic plasticity maths functions +#include +#include + +//--------------------------------------- +// Macros +//--------------------------------------- +// Exponential decay lookup parameters +#define TAU_PLUS_TIME_SHIFT 0 +#define TAU_PLUS_SIZE 256 + +#define TAU_MINUS_TIME_SHIFT 0 +#define TAU_MINUS_SIZE 256 + +// Helper macros for looking up decays +#define DECAY_LOOKUP_TAU_PLUS(time) \ + maths_lut_exponential_decay( \ + time, TAU_PLUS_TIME_SHIFT, TAU_PLUS_SIZE, tau_plus_lookup) +#define DECAY_LOOKUP_TAU_MINUS(time) \ + maths_lut_exponential_decay( \ + time, TAU_MINUS_TIME_SHIFT, TAU_MINUS_SIZE, tau_minus_lookup) + +//--------------------------------------- +// Externals +//--------------------------------------- +extern int16_t tau_plus_lookup[TAU_PLUS_SIZE]; +extern int16_t tau_minus_lookup[TAU_MINUS_SIZE]; + +//--------------------------------------- +// Timing dependence inline functions +//--------------------------------------- +static inline post_trace_t timing_get_initial_post_trace() { + return 0; +} + +//--------------------------------------- +static inline post_trace_t timing_add_post_spike( + uint32_t time, uint32_t last_time, post_trace_t last_trace) { + + io_printf(IO_BUF, "Adding pre spike to event history (from climbing fibre)\n"); + +// // Get time since last spike +// uint32_t delta_time = time - last_time; + +// // Decay previous o1 and o2 traces +// int32_t decayed_o1_trace = STDP_FIXED_MUL_16X16(last_trace, +// DECAY_LOOKUP_TAU_MINUS(delta_time)); + + // Add energy caused by new spike to trace + // **NOTE** o2 trace is pre-multiplied by a3_plus + int32_t new_o1_trace = 0; //decayed_o1_trace + STDP_FIXED_POINT_ONE; + +// log_debug("\tdelta_time=%d, o1=%d\n", delta_time, new_o1_trace); + + // Return new pre- synaptic event with decayed trace values with energy + // for new spike added + return (post_trace_t) new_o1_trace; +} + +//--------------------------------------- +static inline pre_trace_t timing_add_pre_spike( + uint32_t time, uint32_t last_time, pre_trace_t last_trace) { + +// // Get time since last spike +// uint32_t delta_time = time - last_time; +// +// // Decay previous r1 and r2 traces +// int32_t decayed_r1_trace = STDP_FIXED_MUL_16X16( +// last_trace, DECAY_LOOKUP_TAU_PLUS(delta_time)); +// +// // Add energy caused by new spike to trace +// int32_t new_r1_trace = decayed_r1_trace + STDP_FIXED_POINT_ONE; +// +// log_debug("\tdelta_time=%u, r1=%d\n", delta_time, new_r1_trace); +// +// // Return new pre-synaptic event with decayed trace values with energy +// // for new spike added + return (pre_trace_t) 0; //new_r1_trace; +} + +//--------------------------------------- +static inline 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) { + use(&trace); + use(last_pre_time); + use(&last_pre_trace); + + // Here we will potentiate by the fixed amount alpha + io_printf(IO_BUF, " This is where we'll do potentiation\n"); + + + // Get time of event relative to last post-synaptic event + uint32_t time_since_last_post = time - last_post_time; + if (time_since_last_post > 0) { + int32_t decayed_o1 = STDP_FIXED_MUL_16X16( + last_post_trace, DECAY_LOOKUP_TAU_MINUS(time_since_last_post)); + + log_debug("\t\t\ttime_since_last_post_event=%u, decayed_o1=%d\n", + time_since_last_post, decayed_o1); + + // Apply depression to state (which is a weight_state) + return weight_one_term_apply_depression(previous_state, decayed_o1); + } else { + return previous_state; + } +} + +//--------------------------------------- +static inline 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) { + use(&trace); + use(last_post_time); + use(&last_post_trace); + + // This is where we calculate the e^(-x) * sin(x)^20 + + + + // Get time of event relative to last pre-synaptic event + uint32_t time_since_last_pre = time - last_pre_time; + + io_printf(IO_BUF, " delta t = %u\n", time_since_last_pre); + + if (time_since_last_pre > 0) { + int32_t decayed_r1 = STDP_FIXED_MUL_16X16( + last_pre_trace, DECAY_LOOKUP_TAU_PLUS(time_since_last_pre)); + + log_debug("\t\t\ttime_since_last_pre_event=%u, decayed_r1=%d\n", + time_since_last_pre, decayed_r1); + + // Apply potentiation to state (which is a weight_state) + return weight_one_term_apply_potentiation(previous_state, decayed_r1); + } else { + return previous_state; + } +} + +#endif // _TIMING_CEREBELLUM_IMPL_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c new file mode 100644 index 00000000000..9c396173a43 --- /dev/null +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c @@ -0,0 +1,59 @@ +#include "weight_multiplicative_impl.h" + +//--------------------------------------- +// Globals +//--------------------------------------- +// Global plasticity parameter data +plasticity_weight_region_data_t *plasticity_weight_region_data; +uint32_t *weight_multiply_right_shift; + +//--------------------------------------- +// Functions +//--------------------------------------- +uint32_t *weight_initialise(uint32_t *address, uint32_t n_synapse_types, + uint32_t *ring_buffer_to_input_buffer_left_shifts) { + + log_debug("weight_initialise: starting"); + log_debug("\tSTDP multiplicative weight dependence"); + + // Copy plasticity region data from address + // **NOTE** this seems somewhat safer than relying on sizeof + int32_t *plasticity_word = (int32_t*) address; + plasticity_weight_region_data = (plasticity_weight_region_data_t *) + spin1_malloc(sizeof(plasticity_weight_region_data_t) * n_synapse_types); + if (plasticity_weight_region_data == NULL) { + log_error("Could not initialise weight region data"); + return NULL; + } + weight_multiply_right_shift = (uint32_t *) + spin1_malloc(sizeof(uint32_t) * n_synapse_types); + if (weight_multiply_right_shift == NULL) { + log_error("Could not initialise weight region data"); + return NULL; + } + for (uint32_t s = 0; s < n_synapse_types; s++) { + // Copy parameters + plasticity_weight_region_data[s].min_weight = *plasticity_word++; + plasticity_weight_region_data[s].max_weight = *plasticity_word++; + plasticity_weight_region_data[s].a2_plus = *plasticity_word++; + plasticity_weight_region_data[s].a2_minus = *plasticity_word++; + + // Calculate the right shift required to fixed-point multiply weights + weight_multiply_right_shift[s] = + 16 - (ring_buffer_to_input_buffer_left_shifts[s] + 1); + + log_debug( + "\tSynapse type %u: Min weight:%d, Max weight:%d, A2+:%d, A2-:%d," + " Weight multiply right shift:%u", + s, plasticity_weight_region_data[s].min_weight, + plasticity_weight_region_data[s].max_weight, + plasticity_weight_region_data[s].a2_plus, + plasticity_weight_region_data[s].a2_minus, + weight_multiply_right_shift[s]); + } + + log_debug("weight_initialise: completed successfully"); + + // Return end address of region + return (address_t) plasticity_word; +} diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h new file mode 100644 index 00000000000..35a5ae1e59c --- /dev/null +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h @@ -0,0 +1,88 @@ +#ifndef _WEIGHT_MULTIPLICATIVE_IMPL_H_ +#define _WEIGHT_MULTIPLICATIVE_IMPL_H_ + +// Include generic plasticity maths functions +#include +#include +#include + +#include + +//--------------------------------------- +// Structures +//--------------------------------------- +typedef struct { + int32_t min_weight; + int32_t max_weight; + + int32_t a2_plus; + int32_t a2_minus; +} plasticity_weight_region_data_t; + +typedef struct { + int32_t weight; + + uint32_t weight_multiply_right_shift; + const plasticity_weight_region_data_t *weight_region; +} weight_state_t; + +#include "weight_one_term.h" + +//--------------------------------------- +// Externals +//--------------------------------------- +extern plasticity_weight_region_data_t *plasticity_weight_region_data; +extern uint32_t *weight_multiply_right_shift; + +//--------------------------------------- +// Weight dependance functions +//--------------------------------------- +static inline weight_state_t weight_get_initial(weight_t weight, + index_t synapse_type) { + return (weight_state_t ) { + .weight = (int32_t) weight, + .weight_multiply_right_shift = + weight_multiply_right_shift[synapse_type], + .weight_region = &plasticity_weight_region_data[synapse_type] + }; +} + +//--------------------------------------- +static inline weight_state_t weight_one_term_apply_depression( + weight_state_t state, int32_t depression) { + + // Calculate scale + // **NOTE** this calculation must be done at runtime-defined weight + // fixed-point format + int32_t scale = maths_fixed_mul16( + state.weight - state.weight_region->min_weight, + state.weight_region->a2_minus, state.weight_multiply_right_shift); + + // Multiply scale by depression and subtract + // **NOTE** using standard STDP fixed-point format handles format conversion + state.weight -= STDP_FIXED_MUL_16X16(scale, depression); + return state; +} +//--------------------------------------- +static inline weight_state_t weight_one_term_apply_potentiation( + weight_state_t state, int32_t potentiation) { + // Calculate scale + // **NOTE** this calculation must be done at runtime-defined weight + // fixed-point format + int32_t scale = maths_fixed_mul16( + state.weight_region->max_weight - state.weight, + state.weight_region->a2_plus, state.weight_multiply_right_shift); + + // Multiply scale by potentiation and add + // **NOTE** using standard STDP fixed-point format handles format conversion + state.weight += STDP_FIXED_MUL_16X16(scale, potentiation); + return state; +} +//--------------------------------------- +static inline weight_t weight_get_final(weight_state_t new_state) { + log_debug("\tnew_weight:%d\n", new_state.weight); + + return (weight_t) new_state.weight; +} + +#endif // _WEIGHT_MULTIPLICATIVE_IMPL_H_ diff --git a/neural_modelling/src/neuron/synapses.c b/neural_modelling/src/neuron/synapses.c index 25c9ff33b83..9980e3e6204 100644 --- a/neural_modelling/src/neuron/synapses.c +++ b/neural_modelling/src/neuron/synapses.c @@ -185,6 +185,21 @@ static inline void _process_fixed_synapses( synaptic_word, synapse_type_index_mask); uint32_t weight = synapse_row_sparse_weight(synaptic_word); + // *********************************** + // For Cerebellum plasticity + uint32_t type = synapse_row_sparse_type(synaptic_word, + synapse_index_bits, synapse_type_mask); + + if (type == 0){ + index_t neuron_index = synapse_row_sparse_index(synaptic_word, synapse_index_mask); + + io_printf(IO_BUF, "\nSpike on type: %u at time: %u\n", type, time); + synapse_dynamics_process_post_synaptic_event(time, neuron_index); + } + + // *********************************** + + // Convert into ring buffer offset uint32_t ring_buffer_index = synapses_get_ring_buffer_index_combined( delay + time, combined_synapse_neuron_index, diff --git a/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py b/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py new file mode 100644 index 00000000000..bf9fb511b6f --- /dev/null +++ b/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py @@ -0,0 +1,39 @@ +from spynnaker.pyNN.models.neuron import AbstractPyNNNeuronModelStandard +from spynnaker.pyNN.models.defaults import default_initial_values +from spynnaker.pyNN.models.neuron.neuron_models \ + import NeuronModelLeakyIntegrateAndFire +from spynnaker.pyNN.models.neuron.input_types import InputTypeConductance +from spynnaker.pyNN.models.neuron.synapse_types import SynapseTypeExponential +from spynnaker.pyNN.models.neuron.threshold_types import ThresholdTypeStatic + +MAX_ATOMS_PER_CORE = 128 + +class IFCondExpCerebellum(AbstractPyNNNeuronModelStandard): + """ Leaky integrate and fire neuron with an exponentially decaying \ + conductance input. Also includes ability to record last spike down + a particular receptor + """ + + @default_initial_values({"v", "isyn_exc", "isyn_inh"}) + def __init__( + self, tau_m=20.0, cm=1.0, v_rest=-65.0, v_reset=-65.0, + v_thresh=-50.0, tau_syn_E=5.0, tau_syn_I=5.0, tau_refrac=0.1, + i_offset=0.0, e_rev_E=0.0, e_rev_I=-70.0, v=-65.0, + isyn_exc=0.0, isyn_inh=0.0): + # pylint: disable=too-many-arguments, too-many-locals + neuron_model = NeuronModelLeakyIntegrateAndFire( + v, v_rest, tau_m, cm, i_offset, v_reset, tau_refrac) + synapse_type = SynapseTypeExponential( + tau_syn_E, tau_syn_I, isyn_exc, isyn_inh) + input_type = InputTypeConductance(e_rev_E, e_rev_I) + threshold_type = ThresholdTypeStatic(v_thresh) + + +# super(IFCondExpCerebellum, self).set_model_max_atoms_per_core( +# IFCondExpCerebellum, n_atoms=MAX_ATOMS_PER_CORE) + + super(IFCondExpCerebellum, self).__init__( + model_name="IF_cond_exp_cerebellum", + binary="IF_cond_exp_cerebellum.aplx", + neuron_model=neuron_model, input_type=input_type, + synapse_type=synapse_type, threshold_type=threshold_type) diff --git a/spynnaker/pyNN/models/neuron/neuron_models/__init__.py b/spynnaker/pyNN/models/neuron/neuron_models/__init__.py index 94f4ef28863..7e001df81bd 100644 --- a/spynnaker/pyNN/models/neuron/neuron_models/__init__.py +++ b/spynnaker/pyNN/models/neuron/neuron_models/__init__.py @@ -2,6 +2,10 @@ from .neuron_model_izh import NeuronModelIzh from .neuron_model_leaky_integrate_and_fire \ import NeuronModelLeakyIntegrateAndFire +from .neuron_model_leaky_integrate_and_fire_t_last \ + import NeuronModelLeakyIntegrateAndFireTLast __all__ = ["AbstractNeuronModel", "NeuronModelIzh", - "NeuronModelLeakyIntegrateAndFire"] + "NeuronModelLeakyIntegrateAndFire", + "NeuronModelLeakyIntegrateAndFireTLast" + ] diff --git a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py new file mode 100644 index 00000000000..572800e875e --- /dev/null +++ b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py @@ -0,0 +1,186 @@ +from spinn_utilities.overrides import overrides +from pacman.executor.injection_decorator import inject_items +from .abstract_neuron_model import AbstractNeuronModel +from data_specification.enums import DataType + +import numpy + +V = "v" +V_REST = "v_rest" +TAU_M = "tau_m" +CM = "cm" +I_OFFSET = "i_offset" +V_RESET = "v_reset" +TAU_REFRAC = "tau_refrac" +COUNT_REFRAC = "count_refrac" +T_LAST = "t_last" + +UNITS = { + V: 'mV', + V_REST: 'mV', + TAU_M: 'ms', + CM: 'nF', + I_OFFSET: 'nA', + V_RESET: 'mV', + TAU_REFRAC: 'ms', + T_LAST: "ms" +} + + +class NeuronModelLeakyIntegrateAndFireTLast(AbstractNeuronModel): + __slots__ = [ + "_v_init", + "_v_rest", + "_tau_m", + "_cm", + "_i_offset", + "_v_reset", + "_tau_refrac" + ] + + def __init__( + self, v_init, v_rest, tau_m, cm, i_offset, v_reset, tau_refrac): + super(NeuronModelLeakyIntegrateAndFireTLast, self).__init__( + [DataType.S1615, # v + DataType.S1615, # v_rest + DataType.S1615, # r_membrane (= tau_m / cm) + DataType.S1615, # exp_tc (= e^(-ts / tau_m)) + DataType.S1615, # i_offset + DataType.INT32, # count_refrac + DataType.S1615, # v_reset + DataType.INT32, # tau_refrac + DataType.INT32 # t_last + ]) + + if v_init is None: + v_init = v_rest + + self._v_init = v_init + self._v_rest = v_rest + self._tau_m = tau_m + self._cm = cm + self._i_offset = i_offset + self._v_reset = v_reset + self._tau_refrac = tau_refrac + + @overrides(AbstractNeuronModel.get_n_cpu_cycles) + def get_n_cpu_cycles(self, n_neurons): + # A bit of a guess + return 100 * n_neurons + + @overrides(AbstractNeuronModel.add_parameters) + def add_parameters(self, parameters): + parameters[V_REST] = self._v_rest + parameters[TAU_M] = self._tau_m + parameters[CM] = self._cm + parameters[I_OFFSET] = self._i_offset + parameters[V_RESET] = self._v_reset + parameters[TAU_REFRAC] = self._tau_refrac + + @overrides(AbstractNeuronModel.add_state_variables) + def add_state_variables(self, state_variables): + state_variables[V] = self._v_init + state_variables[COUNT_REFRAC] = 0 + state_variables[T_LAST] = 0 + + @overrides(AbstractNeuronModel.get_units) + def get_units(self, variable): + return UNITS[variable] + + @overrides(AbstractNeuronModel.has_variable) + def has_variable(self, variable): + return variable in UNITS + + @inject_items({"ts": "MachineTimeStep"}) + @overrides(AbstractNeuronModel.get_values, additional_arguments={'ts'}) + def get_values(self, parameters, state_variables, vertex_slice, ts): + + # Add the rest of the data + return [ + state_variables[V], + parameters[V_REST], + parameters[TAU_M] / parameters[CM], + parameters[TAU_M].apply_operation( + operation=lambda x: numpy.exp(float(-ts) / (1000.0 * x))), + parameters[I_OFFSET], + state_variables[COUNT_REFRAC], + parameters[V_RESET], + parameters[TAU_REFRAC].apply_operation( + operation=lambda x: int(numpy.ceil(x / (ts / 1000.0)))), + state_variables[T_LAST] + ] + + @overrides(AbstractNeuronModel.update_values) + def update_values(self, values, parameters, state_variables): + + # Read the data + (v, + _v_rest, + _r_membrane, + _exp_tc, + _i_offset, + count_refrac, + _v_reset, + _tau_refrac, + t_last) = values + + # Copy the changed data only + state_variables[V] = v + state_variables[COUNT_REFRAC] = count_refrac + state_varaibles[T_LAST] = t_last + + @property + def v_init(self): + return self._v + + @v_init.setter + def v_init(self, v_init): + self._v = v_init + + @property + def v_rest(self): + return self._v_rest + + @v_rest.setter + def v_rest(self, v_rest): + self._v_rest = v_rest + + @property + def tau_m(self): + return self._tau_m + + @tau_m.setter + def tau_m(self, tau_m): + self._tau_m = tau_m + + @property + def cm(self): + return self._cm + + @cm.setter + def cm(self, cm): + self._cm = cm + + @property + def i_offset(self): + return self._i_offset + + @i_offset.setter + def i_offset(self, i_offset): + self._i_offset = i_offset + + @property + def v_reset(self): + return self._v_reset + + @v_reset.setter + def v_reset(self, v_reset): + self._v_reset = v_reset + + @property + def tau_refrac(self): + return self._tau_refrac + + @tau_refrac.setter + def tau_refrac(self, tau_refrac): + self._tau_refrac = tau_refrac diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/__init__.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/__init__.py index 1ab01446291..de659e9b9b6 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/__init__.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/__init__.py @@ -6,9 +6,11 @@ from .timing_dependence_spike_nearest_pair \ import TimingDependenceSpikeNearestPair from .timing_dependence_vogels_2011 import TimingDependenceVogels2011 +from .timing_dependence_pfpc import TimingDependencePFPC __all__ = [ "AbstractTimingDependence", "TimingDependenceSpikePair", "TimingDependencePfisterSpikeTriplet", "TimingDependenceRecurrent", - "TimingDependenceSpikeNearestPair", "TimingDependenceVogels2011" + "TimingDependenceSpikeNearestPair", "TimingDependenceVogels2011", + "TimingDependencePFPC" ] diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py new file mode 100644 index 00000000000..668ee8fb0af --- /dev/null +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -0,0 +1,102 @@ +from spinn_utilities.overrides import overrides +from spynnaker.pyNN.models.neuron.plasticity.stdp.common \ + import plasticity_helpers +from .abstract_timing_dependence import AbstractTimingDependence +from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure\ + import SynapseStructureWeightOnly + + +import logging +logger = logging.getLogger(__name__) + +LOOKUP_TAU_PLUS_SIZE = 256 +LOOKUP_TAU_PLUS_SHIFT = 0 +LOOKUP_TAU_MINUS_SIZE = 256 +LOOKUP_TAU_MINUS_SHIFT = 0 + + +class TimingDependencePFPC(AbstractTimingDependence): + __slots__ = [ + "_synapse_structure", + "_tau_minus", + "_tau_minus_last_entry", + "_tau_plus", + "_tau_plus_last_entry"] + + def __init__(self, tau_plus=20.0, tau_minus=20.0): + self._tau_plus = tau_plus + self._tau_minus = tau_minus + + self._synapse_structure = SynapseStructureWeightOnly() + + # provenance data + self._tau_plus_last_entry = None + self._tau_minus_last_entry = None + + @property + def tau_plus(self): + return self._tau_plus + + @property + def tau_minus(self): + return self._tau_minus + + @overrides(AbstractTimingDependence.is_same_as) + def is_same_as(self, timing_dependence): + if not isinstance(timing_dependence, TimingDependencePFPC): + return False + return (self.tau_plus == timing_dependence.tau_plus and + self.tau_minus == timing_dependence.tau_minus) + + @property + def vertex_executable_suffix(self): + return "pfpc" + + @property + def pre_trace_n_bytes(self): + + # Pair rule requires no pre-synaptic trace when only the nearest + # Neighbours are considered and, a single 16-bit R1 trace + return 2 + + @overrides(AbstractTimingDependence.get_parameters_sdram_usage_in_bytes) + def get_parameters_sdram_usage_in_bytes(self): + return 2 * (LOOKUP_TAU_PLUS_SIZE + LOOKUP_TAU_MINUS_SIZE) + + @property + def n_weight_terms(self): + return 1 + + @overrides(AbstractTimingDependence.write_parameters) + def write_parameters(self, spec, machine_time_step, weight_scales): + # Check timestep is valid + if machine_time_step != 1000: + raise NotImplementedError( + "STDP LUT generation currently only supports 1ms timesteps") + + # Write lookup tables + self._tau_plus_last_entry = plasticity_helpers.write_exp_lut( + spec, self._tau_plus, LOOKUP_TAU_PLUS_SIZE, + LOOKUP_TAU_PLUS_SHIFT) + self._tau_minus_last_entry = plasticity_helpers.write_exp_lut( + spec, self._tau_minus, LOOKUP_TAU_MINUS_SIZE, + LOOKUP_TAU_MINUS_SHIFT) + + @property + def synaptic_structure(self): + return self._synapse_structure + + @overrides(AbstractTimingDependence.get_provenance_data) + def get_provenance_data(self, pre_population_label, post_population_label): + prov_data = list() + prov_data.append(plasticity_helpers.get_lut_provenance( + pre_population_label, post_population_label, "PFPCRule", + "tau_plus_last_entry", "tau_plus", self._tau_plus_last_entry)) + prov_data.append(plasticity_helpers.get_lut_provenance( + pre_population_label, post_population_label, "PFPCRule", + "tau_minus_last_entry", "tau_minus", self._tau_minus_last_entry)) + return prov_data + + @overrides(AbstractTimingDependence.get_parameter_names) + def get_parameter_names(self): + return ['tau_plus', 'tau_minus'] diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/__init__.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/__init__.py index 62c96130d09..d3fad33f19a 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/__init__.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/__init__.py @@ -3,7 +3,8 @@ from .weight_dependence_additive import WeightDependenceAdditive from .weight_dependence_multiplicative import WeightDependenceMultiplicative from .weight_dependence_additive_triplet import WeightDependenceAdditiveTriplet +from .weight_dependence_pfpc import WeightDependencePFPC __all__ = ["AbstractHasAPlusAMinus", "AbstractWeightDependence", "WeightDependenceAdditive", "WeightDependenceMultiplicative", - "WeightDependenceAdditiveTriplet"] + "WeightDependenceAdditiveTriplet", "WeightDependencePFPC"] diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py new file mode 100644 index 00000000000..e6cac3642f4 --- /dev/null +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py @@ -0,0 +1,77 @@ +from data_specification.enums import DataType +from spinn_utilities.overrides import overrides +from .abstract_has_a_plus_a_minus import AbstractHasAPlusAMinus +from .abstract_weight_dependence import AbstractWeightDependence + + +class WeightDependencePFPC( + AbstractHasAPlusAMinus, AbstractWeightDependence): + __slots__ = [ + "_w_max", + "_w_min"] + + # noinspection PyPep8Naming + def __init__(self, w_min=0.0, w_max=1.0): + super(WeightDependencePFPC, self).__init__() + self._w_min = w_min + self._w_max = w_max + + @property + def w_min(self): + return self._w_min + + @property + def w_max(self): + return self._w_max + + @overrides(AbstractWeightDependence.is_same_as) + def is_same_as(self, weight_dependence): + if not isinstance(weight_dependence, WeightDependencePFPC): + return False + return ( + (self._w_min == weight_dependence.w_min) and + (self._w_max == weight_dependence.w_max) and + (self._a_plus == weight_dependence.A_plus) and + (self._a_minus == weight_dependence.A_minus)) + + @property + def vertex_executable_suffix(self): + return "pfpc" + + @overrides(AbstractWeightDependence.get_parameters_sdram_usage_in_bytes) + def get_parameters_sdram_usage_in_bytes( + self, n_synapse_types, n_weight_terms): + if n_weight_terms != 1: + raise NotImplementedError( + "PFPC weight dependence only supports one term") + return (4 * 4) * n_synapse_types + + @overrides(AbstractWeightDependence.write_parameters) + def write_parameters( + self, spec, machine_time_step, weight_scales, n_weight_terms): + # Loop through each synapse type's weight scale + for w in weight_scales: + + # Scale the weights + spec.write_value( + data=int(round(self._w_min * w)), data_type=DataType.INT32) + spec.write_value( + data=int(round(self._w_max * w)), data_type=DataType.INT32) + + # Based on http://data.andrewdavison.info/docs/PyNN/_modules/pyNN + # /standardmodels/synapses.html + # Pre-multiply A+ and A- by Wmax + spec.write_value( + data=int(round(self._a_plus * self._w_max * w)), + data_type=DataType.INT32) + spec.write_value( + data=int(round(self._a_minus * self._w_max * w)), + data_type=DataType.INT32) + + @property + def weight_maximum(self): + return self._w_max + + @overrides(AbstractWeightDependence.get_parameter_names) + def get_parameter_names(self): + return ['w_min', 'w_max', 'A_plus', 'A_minus'] From c4385e8002d35620c76803047dcf8bf96f76bcd8 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Wed, 10 Oct 2018 10:22:40 +0100 Subject: [PATCH 003/108] add logging to timing initialisation --- .../plasticity/stdp/timing_dependence/timing_pfpc_impl.c | 6 +++--- .../stdp/timing_dependence/timing_dependence_pfpc.py | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c index 89dc65802fe..b31b834e680 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c @@ -12,8 +12,8 @@ int16_t tau_minus_lookup[TAU_MINUS_SIZE]; //--------------------------------------- address_t timing_initialise(address_t address) { - log_debug("timing_initialise: starting"); - log_debug("\tSTDP pair rule"); + io_printf(IO_BUF, "timing_pfpc_initialise: starting"); + io_printf(IO_BUF, "\tCerebellum PFPC rule"); // **TODO** assert number of neurons is less than max // Copy LUTs from following memory @@ -22,7 +22,7 @@ address_t timing_initialise(address_t address) { lut_address = maths_copy_int16_lut(lut_address, TAU_MINUS_SIZE, &tau_minus_lookup[0]); - log_debug("timing_initialise: completed successfully"); + io_printf(IO_BUF, "timing_pfpc_initialise: completed successfully"); return lut_address; } diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index 668ee8fb0af..e40239965a1 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -74,6 +74,11 @@ def write_parameters(self, spec, machine_time_step, weight_scales): raise NotImplementedError( "STDP LUT generation currently only supports 1ms timesteps") + ################# + # Add new LUT generation here + ################# + + # Write lookup tables self._tau_plus_last_entry = plasticity_helpers.write_exp_lut( spec, self._tau_plus, LOOKUP_TAU_PLUS_SIZE, From e0e03c49b5da84a849054fe2cb52b6d6c5376006 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Wed, 10 Oct 2018 16:02:31 +0100 Subject: [PATCH 004/108] Add potentiation on PF spike --- .../stdp/timing_dependence/timing_pfpc_impl.h | 73 ++++++++++++------- .../stdp/weight_dependence/weight_pfpc_impl.h | 36 ++++++--- .../weight_dependence_pfpc.py | 4 +- 3 files changed, 74 insertions(+), 39 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index 5e17a89d3e1..bc4eabc2aa7 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -106,21 +106,32 @@ static inline update_state_t timing_apply_pre_spike( // Here we will potentiate by the fixed amount alpha io_printf(IO_BUF, " This is where we'll do potentiation\n"); + return weight_one_term_apply_potentiation(previous_state, 0); - // Get time of event relative to last post-synaptic event - uint32_t time_since_last_post = time - last_post_time; - if (time_since_last_post > 0) { - int32_t decayed_o1 = STDP_FIXED_MUL_16X16( - last_post_trace, DECAY_LOOKUP_TAU_MINUS(time_since_last_post)); - log_debug("\t\t\ttime_since_last_post_event=%u, decayed_o1=%d\n", - time_since_last_post, decayed_o1); - // Apply depression to state (which is a weight_state) - return weight_one_term_apply_depression(previous_state, decayed_o1); - } else { - return previous_state; - } +// +// // Get time of event relative to last post-synaptic event +// uint32_t time_since_last_post = time - last_post_time; +// if (time_since_last_post > 0) { +// int32_t decayed_o1 = STDP_FIXED_MUL_16X16( +// last_post_trace, DECAY_LOOKUP_TAU_MINUS(time_since_last_post)); +// +// log_debug("\t\t\ttime_since_last_post_event=%u, decayed_o1=%d\n", +// time_since_last_post, decayed_o1); +// +// // Apply depression to state (which is a weight_state) +// return weight_one_term_apply_depression(previous_state, decayed_o1); +// +// +// +// +// +// +// +// } else { +// return previous_state; +// } } //--------------------------------------- @@ -132,27 +143,33 @@ static inline update_state_t timing_apply_post_spike( use(last_post_time); use(&last_post_trace); - // This is where we calculate the e^(-x) * sin(x)^20 +// // This is where we calculate the e^(-x) * sin(x)^20 +// +// +// weight_one_term_apply_depression( +// weight_state_t state, int32_t depression) - // Get time of event relative to last pre-synaptic event - uint32_t time_since_last_pre = time - last_pre_time; - - io_printf(IO_BUF, " delta t = %u\n", time_since_last_pre); - - if (time_since_last_pre > 0) { - int32_t decayed_r1 = STDP_FIXED_MUL_16X16( - last_pre_trace, DECAY_LOOKUP_TAU_PLUS(time_since_last_pre)); - - log_debug("\t\t\ttime_since_last_pre_event=%u, decayed_r1=%d\n", - time_since_last_pre, decayed_r1); - // Apply potentiation to state (which is a weight_state) - return weight_one_term_apply_potentiation(previous_state, decayed_r1); - } else { +// +// // Get time of event relative to last pre-synaptic event +// uint32_t time_since_last_pre = time - last_pre_time; +// +// io_printf(IO_BUF, " delta t = %u\n", time_since_last_pre); +// +// if (time_since_last_pre > 0) { +// int32_t decayed_r1 = STDP_FIXED_MUL_16X16( +// last_pre_trace, DECAY_LOOKUP_TAU_PLUS(time_since_last_pre)); +// +// log_debug("\t\t\ttime_since_last_pre_event=%u, decayed_r1=%d\n", +// time_since_last_pre, decayed_r1); +// +// // Apply potentiation to state (which is a weight_state) +// return weight_one_term_apply_potentiation(previous_state, decayed_r1); +// } else { return previous_state; - } + //} } #endif // _TIMING_CEREBELLUM_IMPL_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h index 35a5ae1e59c..936f3ccd06d 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h @@ -22,6 +22,9 @@ typedef struct { typedef struct { int32_t weight; + int32_t a2_plus; + int32_t a2_minus; + uint32_t weight_multiply_right_shift; const plasticity_weight_region_data_t *weight_region; } weight_state_t; @@ -66,22 +69,37 @@ static inline weight_state_t weight_one_term_apply_depression( //--------------------------------------- static inline weight_state_t weight_one_term_apply_potentiation( weight_state_t state, int32_t potentiation) { - // Calculate scale - // **NOTE** this calculation must be done at runtime-defined weight - // fixed-point format - int32_t scale = maths_fixed_mul16( - state.weight_region->max_weight - state.weight, - state.weight_region->a2_plus, state.weight_multiply_right_shift); - // Multiply scale by potentiation and add - // **NOTE** using standard STDP fixed-point format handles format conversion - state.weight += STDP_FIXED_MUL_16X16(scale, potentiation); + // add fixed amount + state.a2_plus += state.weight_region->a2_plus; + return state; + } //--------------------------------------- static inline weight_t weight_get_final(weight_state_t new_state) { log_debug("\tnew_weight:%d\n", new_state.weight); + // first do Depression (as this would have happened first) + + +// // Now do potentiation (check against lower limit) +// int32_t scaled_a2_plus = STDP_FIXED_MUL_16X16( +// new_state.a2_plus, new_state.weight_region->a2_plus); + + + // Apply all terms to initial weight + int32_t new_weight = new_state.weight + new_state.a2_plus; + // - scaled_a2_minus; + + io_printf(IO_BUF, "old weight: %u, new weight: %u\n", new_state.weight, new_weight); + + // Clamp new weight + new_weight = MIN(new_state.weight_region->max_weight, + new_weight); + + new_state.weight = new_weight; + return (weight_t) new_state.weight; } diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py index e6cac3642f4..0fc9f0fd1ba 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py @@ -62,10 +62,10 @@ def write_parameters( # /standardmodels/synapses.html # Pre-multiply A+ and A- by Wmax spec.write_value( - data=int(round(self._a_plus * self._w_max * w)), + data=int(round(self._a_plus * w)), data_type=DataType.INT32) spec.write_value( - data=int(round(self._a_minus * self._w_max * w)), + data=int(round(self._a_minus * w)), data_type=DataType.INT32) @property From 1bc6fdc19e2c5865c9b6dcaab7c0b739b17720f6 Mon Sep 17 00:00:00 2001 From: Chiara Bartolozzi Date: Wed, 10 Oct 2018 16:13:47 +0100 Subject: [PATCH 005/108] added look up table for PFPC learning rule --- .../stdp/common/plasticity_helpers.py | 58 ++++++++++++++++++- .../timing_dependence_pfpc.py | 16 ++--- 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py index a945fe34e55..2e5210dab0f 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py @@ -1,5 +1,7 @@ import math import logging +import matplotlib.pyplot as plt +import numpy as np from data_specification.enums import DataType @@ -10,7 +12,6 @@ # Default value of fixed-point one for STDP STDP_FIXED_POINT_ONE = (1 << 11) - def float_to_fixed(value, fixed_point_one): return int(round(float(value) * float(fixed_point_one))) @@ -55,3 +56,58 @@ def get_lut_provenance( " increasing the timestep".format( param_name, rule_name, pre_population_label, post_population_label, last_entry))) + +def write_pfpc_lut(spec, time_constant, lut_size, shift, + fixed_point_one=STDP_FIXED_POINT_ONE): + peak_time = 100.0 + tau = peak_time * 2/math.pi; + machine_time_step = 1.0 + + # This offset is the quasi-symmetry point + sin_pwr = 20 + +# Write peak time in timesteps + peak_time_data = int(peak_time * (1000.0 / machine_time_step) - lut_size/2 + 0.5) + print "peak time data:", peak_time_data, "peak_time:", peak_time + + if spec is not None: + spec.write_value(data=peak_time_data, + data_type=DataType.INT32) + + # Calculate 1/tau in machine time steps + inv_tau = (1.0 / float(tau)) #* (machine_time_step / 1000.0) + + zero_offset = math.atan(-1./sin_pwr) # abscissae of the max point obtained by deriving the kernel and equal to zero + max_value = math.exp(-zero_offset)*math.sin(zero_offset)**sin_pwr + + if spec is None : + print tau, inv_tau, zero_offset, max_value + # Generate LUT + #last_value = None + + t = np.arange(0,lut_size) + out = [] + + for i in range(0,lut_size): # the sign needs to be checked and has to be consistent with the dt used in the synapse + + # Multiply by time constant and calculate negative exponential + value = float(i) * inv_tau + # we want a single bump only, so we clip the arg at pi/2 +# if (value) < 0:# math.pi*2: +# exp_float = 0.0 +# print "clamp @ value = ", value +# else: + exp_float = math.exp(-value) * math.sin(value)**sin_pwr # / max_value + + # Convert to fixed-point and write to spec + exp_fix = float_to_fixed(exp_float, fixed_point_one) + + if spec is None : + out.append(exp_float) + print i, exp_float, exp_fix + else : + spec.write_value(data=exp_fix, data_type=DataType.INT16) + + if spec is None : + plt.plot(t,out) + plt.show() diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index e40239965a1..be7ac00b8bb 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -9,11 +9,7 @@ import logging logger = logging.getLogger(__name__) -LOOKUP_TAU_PLUS_SIZE = 256 -LOOKUP_TAU_PLUS_SHIFT = 0 -LOOKUP_TAU_MINUS_SIZE = 256 -LOOKUP_TAU_MINUS_SHIFT = 0 - +LUT_SIZE = 256 class TimingDependencePFPC(AbstractTimingDependence): __slots__ = [ @@ -61,7 +57,7 @@ def pre_trace_n_bytes(self): @overrides(AbstractTimingDependence.get_parameters_sdram_usage_in_bytes) def get_parameters_sdram_usage_in_bytes(self): - return 2 * (LOOKUP_TAU_PLUS_SIZE + LOOKUP_TAU_MINUS_SIZE) + return 2 * LUT_SIZE #in bytes: 256 * 16 bit values @property def n_weight_terms(self): @@ -80,12 +76,8 @@ def write_parameters(self, spec, machine_time_step, weight_scales): # Write lookup tables - self._tau_plus_last_entry = plasticity_helpers.write_exp_lut( - spec, self._tau_plus, LOOKUP_TAU_PLUS_SIZE, - LOOKUP_TAU_PLUS_SHIFT) - self._tau_minus_last_entry = plasticity_helpers.write_exp_lut( - spec, self._tau_minus, LOOKUP_TAU_MINUS_SIZE, - LOOKUP_TAU_MINUS_SHIFT) + self._tau_plus_last_entry = plasticity_helpers.write_pfpc_lut(spec, + time_constant=20, lut_size=LUT_SIZE, shift=0) @property def synaptic_structure(self): From f1b00603b34fd7ba0359c3ef3134ed415f46ecc7 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Wed, 10 Oct 2018 16:21:40 +0100 Subject: [PATCH 006/108] Configure to use exp_sin_lookup --- .../stdp/timing_dependence/timing_pfpc_impl.c | 9 +++------ .../stdp/timing_dependence/timing_pfpc_impl.h | 18 +++++++----------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c index b31b834e680..82a455cb5c4 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c @@ -4,8 +4,7 @@ // Globals //--------------------------------------- // Exponential lookup-tables -int16_t tau_plus_lookup[TAU_PLUS_SIZE]; -int16_t tau_minus_lookup[TAU_MINUS_SIZE]; +int16_t exp_sin_lookup[EXP_SIN_LUT_SIZE]; //--------------------------------------- // Functions @@ -17,10 +16,8 @@ address_t timing_initialise(address_t address) { // **TODO** assert number of neurons is less than max // Copy LUTs from following memory - address_t lut_address = maths_copy_int16_lut(&address[0], TAU_PLUS_SIZE, - &tau_plus_lookup[0]); - lut_address = maths_copy_int16_lut(lut_address, TAU_MINUS_SIZE, - &tau_minus_lookup[0]); + address_t lut_address = maths_copy_int16_lut(&address[0], EXP_SIN_LUT_SIZE, + &exp_sin_lookup[0]); io_printf(IO_BUF, "timing_pfpc_initialise: completed successfully"); diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index bc4eabc2aa7..64b507c1960 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -23,24 +23,20 @@ typedef int16_t pre_trace_t; //--------------------------------------- // Exponential decay lookup parameters #define TAU_PLUS_TIME_SHIFT 0 -#define TAU_PLUS_SIZE 256 - -#define TAU_MINUS_TIME_SHIFT 0 -#define TAU_MINUS_SIZE 256 +#define EXP_SIN_LUT_SIZE 256 // Helper macros for looking up decays -#define DECAY_LOOKUP_TAU_PLUS(time) \ - maths_lut_exponential_decay( \ - time, TAU_PLUS_TIME_SHIFT, TAU_PLUS_SIZE, tau_plus_lookup) -#define DECAY_LOOKUP_TAU_MINUS(time) \ +#define EXP_SIN_LOOKUP(time) \ maths_lut_exponential_decay( \ - time, TAU_MINUS_TIME_SHIFT, TAU_MINUS_SIZE, tau_minus_lookup) + time, TAU_PLUS_TIME_SHIFT, EXP_SIN_LUT_SIZE, exp_sin_lookup) +//#define DECAY_LOOKUP_TAU_MINUS(time) \ +// maths_lut_exponential_decay( \ +// time, TAU_MINUS_TIME_SHIFT, TAU_MINUS_SIZE, tau_minus_lookup) //--------------------------------------- // Externals //--------------------------------------- -extern int16_t tau_plus_lookup[TAU_PLUS_SIZE]; -extern int16_t tau_minus_lookup[TAU_MINUS_SIZE]; +extern int16_t exp_sin_lookup[EXP_SIN_LUT_SIZE]; //--------------------------------------- // Timing dependence inline functions From 67f3ecd02f38d34e393f946c9c9747a86fb060a3 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Wed, 10 Oct 2018 16:24:46 +0100 Subject: [PATCH 007/108] add back dt printing --- .../plasticity/stdp/timing_dependence/timing_pfpc_impl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index 64b507c1960..f84c7e853d7 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -141,7 +141,7 @@ static inline update_state_t timing_apply_post_spike( -// // This is where we calculate the e^(-x) * sin(x)^20 +// // This is where we lookup the value of e^(-x) * sin(x)^20 // // // weight_one_term_apply_depression( @@ -152,7 +152,7 @@ static inline update_state_t timing_apply_post_spike( // // Get time of event relative to last pre-synaptic event // uint32_t time_since_last_pre = time - last_pre_time; // -// io_printf(IO_BUF, " delta t = %u\n", time_since_last_pre); + io_printf(IO_BUF, " delta t = %u\n", time_since_last_pre); // // if (time_since_last_pre > 0) { // int32_t decayed_r1 = STDP_FIXED_MUL_16X16( From 7efaf58e4e54ac9e7b27f51930995259c39c6c70 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Wed, 10 Oct 2018 16:26:04 +0100 Subject: [PATCH 008/108] add missing variable initialisation --- .../neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index f84c7e853d7..ab58cb090ab 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -150,7 +150,7 @@ static inline update_state_t timing_apply_post_spike( // // // Get time of event relative to last pre-synaptic event -// uint32_t time_since_last_pre = time - last_pre_time; + uint32_t time_since_last_pre = time - last_pre_time; // io_printf(IO_BUF, " delta t = %u\n", time_since_last_pre); // From 58a3f2b544ebce56cea0f3a9715f4ff0c46833c7 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Wed, 10 Oct 2018 18:12:58 +0100 Subject: [PATCH 009/108] Sorry Chiara - this extra variable misaligned things! --- .../neuron/plasticity/stdp/common/plasticity_helpers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py index 2e5210dab0f..d585b63b978 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py @@ -70,9 +70,9 @@ def write_pfpc_lut(spec, time_constant, lut_size, shift, peak_time_data = int(peak_time * (1000.0 / machine_time_step) - lut_size/2 + 0.5) print "peak time data:", peak_time_data, "peak_time:", peak_time - if spec is not None: - spec.write_value(data=peak_time_data, - data_type=DataType.INT32) +# if spec is not None: +# spec.write_value(data=peak_time_data, +# data_type=DataType.INT32) # Calculate 1/tau in machine time steps inv_tau = (1.0 / float(tau)) #* (machine_time_step / 1000.0) From 5d335c945e2309629aa1dfce51178439f46b56b1 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Wed, 10 Oct 2018 18:24:10 +0100 Subject: [PATCH 010/108] Add logging of exp_sin table lookup --- .../plasticity/stdp/timing_dependence/timing_pfpc_impl.h | 6 +++++- .../plasticity/stdp/weight_dependence/weight_pfpc_impl.c | 3 ++- .../plasticity/stdp/weight_dependence/weight_pfpc_impl.h | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index ab58cb090ab..5c6675b74c2 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -152,8 +152,12 @@ static inline update_state_t timing_apply_post_spike( // // Get time of event relative to last pre-synaptic event uint32_t time_since_last_pre = time - last_pre_time; // - io_printf(IO_BUF, " delta t = %u\n", time_since_last_pre); + io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); // + + uint32_t multiplier = EXP_SIN_LOOKUP(time_since_last_pre); + + io_printf(IO_BUF, "multiplier: %k\n", multiplier << 4); // if (time_since_last_pre > 0) { // int32_t decayed_r1 = STDP_FIXED_MUL_16X16( // last_pre_trace, DECAY_LOOKUP_TAU_PLUS(time_since_last_pre)); diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c index 9c396173a43..ec8528a4759 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c @@ -42,7 +42,8 @@ uint32_t *weight_initialise(uint32_t *address, uint32_t n_synapse_types, weight_multiply_right_shift[s] = 16 - (ring_buffer_to_input_buffer_left_shifts[s] + 1); - log_debug( +// log_debug( + io_printf(IO_BUF, "\tSynapse type %u: Min weight:%d, Max weight:%d, A2+:%d, A2-:%d," " Weight multiply right shift:%u", s, plasticity_weight_region_data[s].min_weight, diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h index 936f3ccd06d..a75924677d3 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h @@ -92,7 +92,7 @@ static inline weight_t weight_get_final(weight_state_t new_state) { int32_t new_weight = new_state.weight + new_state.a2_plus; // - scaled_a2_minus; - io_printf(IO_BUF, "old weight: %u, new weight: %u\n", new_state.weight, new_weight); + io_printf(IO_BUF, " old weight: %u, new weight: %u\n", new_state.weight, new_weight); // Clamp new weight new_weight = MIN(new_state.weight_region->max_weight, From ea065da9993339b826ddbcc57e162b87baccefea Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Wed, 10 Oct 2018 19:06:44 +0100 Subject: [PATCH 011/108] Tweak logging and reading of exp_sin_lut --- .../plasticity/stdp/timing_dependence/timing_pfpc_impl.c | 6 +++--- .../plasticity/stdp/weight_dependence/weight_pfpc_impl.c | 6 +++--- .../neuron/plasticity/stdp/common/plasticity_helpers.py | 4 +++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c index 82a455cb5c4..29ed9d8fd92 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c @@ -11,15 +11,15 @@ int16_t exp_sin_lookup[EXP_SIN_LUT_SIZE]; //--------------------------------------- address_t timing_initialise(address_t address) { - io_printf(IO_BUF, "timing_pfpc_initialise: starting"); - io_printf(IO_BUF, "\tCerebellum PFPC rule"); + io_printf(IO_BUF, "timing_pfpc_initialise: starting\n"); + io_printf(IO_BUF, "\tCerebellum PFPC rule\n"); // **TODO** assert number of neurons is less than max // Copy LUTs from following memory address_t lut_address = maths_copy_int16_lut(&address[0], EXP_SIN_LUT_SIZE, &exp_sin_lookup[0]); - io_printf(IO_BUF, "timing_pfpc_initialise: completed successfully"); + io_printf(IO_BUF, "timing_pfpc_initialise: completed successfully\n"); return lut_address; } diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c index ec8528a4759..4a0fa7e6424 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c @@ -13,8 +13,8 @@ uint32_t *weight_multiply_right_shift; uint32_t *weight_initialise(uint32_t *address, uint32_t n_synapse_types, uint32_t *ring_buffer_to_input_buffer_left_shifts) { - log_debug("weight_initialise: starting"); - log_debug("\tSTDP multiplicative weight dependence"); + log_debug("weight_initialise: starting\n"); + log_debug("\tSTDP multiplicative weight dependence\n"); // Copy plasticity region data from address // **NOTE** this seems somewhat safer than relying on sizeof @@ -45,7 +45,7 @@ uint32_t *weight_initialise(uint32_t *address, uint32_t n_synapse_types, // log_debug( io_printf(IO_BUF, "\tSynapse type %u: Min weight:%d, Max weight:%d, A2+:%d, A2-:%d," - " Weight multiply right shift:%u", + " Weight multiply right shift:%u\n", s, plasticity_weight_region_data[s].min_weight, plasticity_weight_region_data[s].max_weight, plasticity_weight_region_data[s].a2_plus, diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py index d585b63b978..e6f950f82bd 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py @@ -97,7 +97,8 @@ def write_pfpc_lut(spec, time_constant, lut_size, shift, # exp_float = 0.0 # print "clamp @ value = ", value # else: - exp_float = math.exp(-value) * math.sin(value)**sin_pwr # / max_value + exp_float = math.exp(-value) * math.sin(value)**sin_pwr / 0.213122689799 + # Convert to fixed-point and write to spec exp_fix = float_to_fixed(exp_float, fixed_point_one) @@ -109,5 +110,6 @@ def write_pfpc_lut(spec, time_constant, lut_size, shift, spec.write_value(data=exp_fix, data_type=DataType.INT16) if spec is None : + print max(out) plt.plot(t,out) plt.show() From 99f7d3afb36c96228760d213fd34cd9f5b0901a1 Mon Sep 17 00:00:00 2001 From: Chiara Bartolozzi Date: Thu, 11 Oct 2018 09:51:57 +0100 Subject: [PATCH 012/108] added prints --- .../stdp/common/plasticity_helpers.py | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py index 2e5210dab0f..e74450ca9c5 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py @@ -57,7 +57,7 @@ def get_lut_provenance( param_name, rule_name, pre_population_label, post_population_label, last_entry))) -def write_pfpc_lut(spec, time_constant, lut_size, shift, +def write_pfpc_lut(spec, time_constant, lut_size, shift,time_probe, fixed_point_one=STDP_FIXED_POINT_ONE): peak_time = 100.0 tau = peak_time * 2/math.pi; @@ -78,16 +78,17 @@ def write_pfpc_lut(spec, time_constant, lut_size, shift, inv_tau = (1.0 / float(tau)) #* (machine_time_step / 1000.0) zero_offset = math.atan(-1./sin_pwr) # abscissae of the max point obtained by deriving the kernel and equal to zero - max_value = math.exp(-zero_offset)*math.sin(zero_offset)**sin_pwr + max_value = math.exp(-math.pi/2)*math.sin(-math.pi/2)**sin_pwr if spec is None : print tau, inv_tau, zero_offset, max_value + # Generate LUT #last_value = None - t = np.arange(0,lut_size) - out = [] - +# t = np.arange(0,lut_size) +# out = [] +# out_fixed = [] for i in range(0,lut_size): # the sign needs to be checked and has to be consistent with the dt used in the synapse # Multiply by time constant and calculate negative exponential @@ -97,17 +98,18 @@ def write_pfpc_lut(spec, time_constant, lut_size, shift, # exp_float = 0.0 # print "clamp @ value = ", value # else: - exp_float = math.exp(-value) * math.sin(value)**sin_pwr # / max_value + exp_float = math.exp(-value) * math.sin(value)**sin_pwr / max_value # Convert to fixed-point and write to spec exp_fix = float_to_fixed(exp_float, fixed_point_one) if spec is None : - out.append(exp_float) - print i, exp_float, exp_fix + #out.append(exp_float) + if i == time_probe: + print "dt = ", time_probe, "weight update = ", exp_float, "fixed = ", exp_fix else : spec.write_value(data=exp_fix, data_type=DataType.INT16) - if spec is None : - plt.plot(t,out) - plt.show() +# if spec is None : +# plt.plot(t,out) +# plt.show() From a2af197078b3cbde6db6ce50f6b90db7f1a1a3f3 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Thu, 11 Oct 2018 14:26:15 +0100 Subject: [PATCH 013/108] Implemented depression for single spike cases --- .../stdp/timing_dependence/timing_pfpc_impl.h | 21 +++++++++++++------ .../stdp/weight_dependence/weight_pfpc_impl.h | 17 ++++++++++----- .../stdp/common/plasticity_helpers.py | 2 +- .../timing_dependence_pfpc.py | 2 +- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index 5c6675b74c2..8159b3ac194 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -144,20 +144,29 @@ static inline update_state_t timing_apply_post_spike( // // This is where we lookup the value of e^(-x) * sin(x)^20 // // -// weight_one_term_apply_depression( -// weight_state_t state, int32_t depression) + // // // Get time of event relative to last pre-synaptic event uint32_t time_since_last_pre = time - last_pre_time; -// io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); -// - uint32_t multiplier = EXP_SIN_LOOKUP(time_since_last_pre); + if (time_since_last_pre < 255){ + + + uint32_t multiplier = EXP_SIN_LOOKUP(time_since_last_pre); + + io_printf(IO_BUF, "multiplier: %k (fixed = %u)\n", multiplier << 4, multiplier); + + return weight_one_term_apply_depression(previous_state, multiplier); + + + } +// + io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); + io_printf(IO_BUF, " out of LUT range - do nothing"); - io_printf(IO_BUF, "multiplier: %k\n", multiplier << 4); // if (time_since_last_pre > 0) { // int32_t decayed_r1 = STDP_FIXED_MUL_16X16( // last_pre_trace, DECAY_LOOKUP_TAU_PLUS(time_since_last_pre)); diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h index a75924677d3..99e6515e987 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h @@ -52,18 +52,25 @@ static inline weight_state_t weight_get_initial(weight_t weight, //--------------------------------------- static inline weight_state_t weight_one_term_apply_depression( - weight_state_t state, int32_t depression) { + weight_state_t state, int32_t depression_multiplier) { + + io_printf(IO_BUF, " Weight prior to depression: %u\n",state.weight); // Calculate scale // **NOTE** this calculation must be done at runtime-defined weight // fixed-point format - int32_t scale = maths_fixed_mul16( - state.weight - state.weight_region->min_weight, - state.weight_region->a2_minus, state.weight_multiply_right_shift); +// int32_t scale = maths_fixed_mul16( +// state.weight - state.weight_region->min_weight, +//// state.weight_region->a2_minus, +// depression_multiplier, +// state.weight_multiply_right_shift); // Multiply scale by depression and subtract // **NOTE** using standard STDP fixed-point format handles format conversion - state.weight -= STDP_FIXED_MUL_16X16(scale, depression); + state.weight -= STDP_FIXED_MUL_16X16(state.weight, depression_multiplier); + + io_printf(IO_BUF, " Weight after depression: %u\n",state.weight); + return state; } //--------------------------------------- diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py index 1db4b4f5993..76dc30904a5 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py @@ -57,7 +57,7 @@ def get_lut_provenance( param_name, rule_name, pre_population_label, post_population_label, last_entry))) -def write_pfpc_lut(spec, time_constant, lut_size, shift,time_probe, +def write_pfpc_lut(spec, time_constant, lut_size, shift, time_probe, fixed_point_one=STDP_FIXED_POINT_ONE): peak_time = 100.0 tau = peak_time * 2/math.pi; diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index be7ac00b8bb..c477f3d2f57 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -77,7 +77,7 @@ def write_parameters(self, spec, machine_time_step, weight_scales): # Write lookup tables self._tau_plus_last_entry = plasticity_helpers.write_pfpc_lut(spec, - time_constant=20, lut_size=LUT_SIZE, shift=0) + time_constant=20, time_probe=None, lut_size=LUT_SIZE, shift=0) @property def synaptic_structure(self): From fa3e30a6349d3471b8d1f62eadc8d7d1838f8011 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Thu, 11 Oct 2018 18:06:18 +0100 Subject: [PATCH 014/108] It works!! --- .../src/neuron/plasticity/stdp/post_events.h | 5 +- .../stdp/synapse_dynamics_stdp_mad_impl.c | 112 ++++++++++++++---- .../stdp/timing_dependence/timing_pfpc_impl.h | 17 +-- .../stdp/weight_dependence/weight_pfpc_impl.h | 3 +- .../stdp/common/plasticity_helpers.py | 8 +- .../timing_dependence_pfpc.py | 14 +-- 6 files changed, 108 insertions(+), 51 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/post_events.h b/neural_modelling/src/neuron/plasticity/stdp/post_events.h index 5e8b88d3e00..c65b81fd48a 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/post_events.h +++ b/neural_modelling/src/neuron/plasticity/stdp/post_events.h @@ -193,7 +193,7 @@ static inline void post_events_add(uint32_t time, post_event_history_t *events, static inline void print_event_history(post_event_history_t *events){ - io_printf(IO_BUF, "\n\n ## printing entire post event history ##\n"); + io_printf(IO_BUF, "\n ## printing entire post event history ##\n"); for (uint i = 0; i <= events->count_minus_one; i++){ io_printf(IO_BUF, " post event: %u, time: %u, trace: %u\n", i, @@ -205,7 +205,7 @@ static inline void print_event_history(post_event_history_t *events){ static inline void print_delayed_window_events(post_event_history_t *post_event_history, uint32_t begin_time, uint32_t end_time, uint32_t delay_dendritic){ - io_printf(IO_BUF, "\n\n ## printing post window ##\n"); + io_printf(IO_BUF, "\n ## printing post window ##\n"); post_event_window_t post_window = post_events_get_window_delayed( post_event_history, begin_time, end_time); @@ -218,6 +218,7 @@ static inline void print_delayed_window_events(post_event_history_t *post_event_ post_window = post_events_next_delayed(post_window, delayed_post_time); } + io_printf(IO_BUF, "\n"); } #endif // _POST_EVENTS_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c index 63c6a94bb7f..3d8133dc9f7 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c @@ -55,11 +55,35 @@ uint32_t plastic_saturation_count = 0; //--------------------------------------- // Structures //--------------------------------------- +//typedef struct { +// pre_trace_t prev_trace; +// uint32_t prev_time; +//} pre_event_history_t; + +#define NUM_PF_SPIKES_TO_RECORD 16 + typedef struct { - pre_trace_t prev_trace; - uint32_t prev_time; + uint32_t num_recorded_pf_spikes_minus_one; + uint32_t pf_times[NUM_PF_SPIKES_TO_RECORD]; + post_trace_t traces[NUM_PF_SPIKES_TO_RECORD]; } pre_event_history_t; + + +_print_pre_event_history(pre_event_history_t pre_eve_hist){ + + io_printf(IO_BUF, "\n\n************************\n\n"); + io_printf(IO_BUF, "Number recorded spikes: %u\n", pre_eve_hist.num_recorded_pf_spikes_minus_one); + io_printf(IO_BUF, "Prev time: %u\n", + pre_eve_hist.pf_times[pre_eve_hist.num_recorded_pf_spikes_minus_one]); + + for (int i =0; i < NUM_PF_SPIKES_TO_RECORD; i ++){ + io_printf(IO_BUF, " Entry %u: %u\n", i ,pre_eve_hist.pf_times[i]); + } + +} + + post_event_history_t *post_event_history; //--------------------------------------- @@ -68,9 +92,11 @@ post_event_history_t *post_event_history; static inline final_state_t _plasticity_update_synapse( 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 pre_trace_t new_pre_trace, + uint32_t delay_dendritic, const uint32_t delay_axonal, update_state_t current_state, - const post_event_history_t *post_event_history) { + const post_event_history_t *post_event_history, + const pre_event_history_t *pre_event_history) { // Apply axonal delay to time of last presynaptic spike const uint32_t delayed_last_pre_time = last_pre_time + delay_axonal; @@ -87,25 +113,59 @@ static inline final_state_t _plasticity_update_synapse( window_begin_time, window_end_time, post_window.prev_time, post_window.num_events); - print_event_history(post_event_history); - print_delayed_window_events(post_event_history, window_begin_time, - window_end_time, delay_dendritic); + + io_printf(IO_BUF, " Printing CF history\n"); + print_event_history(post_event_history); +// print_delayed_window_events(post_event_history, window_begin_time, +// window_end_time, delay_dendritic); io_printf(IO_BUF, "\n Looping over climbing fibre spikes:\n"); + delay_dendritic = 0; + // Process events in post-synaptic window while (post_window.num_events > 0) { const uint32_t delayed_post_time = *post_window.next_time + delay_dendritic; - log_debug("\t\tApplying post-synaptic event at delayed time:%u\n", + + uint32_t pf_begin_time = (delayed_post_time < 255) ? 0 : (delayed_post_time - 255); + + + io_printf(IO_BUF, " Applying post-synaptic event at delayed time:%u\n", delayed_post_time); - // Apply spike to state - current_state = timing_apply_post_spike( - delayed_post_time, *post_window.next_trace, delayed_last_pre_time, - last_pre_trace, post_window.prev_time, post_window.prev_trace, - current_state); +// // Get window of pf events based on cf spikes +// print_delayed_window_events(pre_event_history, +// //(delayed_post_time-255) +// pf_begin_time, delayed_post_time, delay_dendritic); + post_event_window_t pre_window = post_events_get_window_delayed( + pre_event_history, pf_begin_time, delayed_post_time); + + + io_printf(IO_BUF, " Looping over PF window\n", + delayed_post_time); + while (pre_window.num_events > 0) { + const uint32_t delayed_pre_time = *pre_window.next_time + + delay_dendritic; + + io_printf(IO_BUF, " delta t = %u\n", delayed_post_time - delayed_pre_time); + + + current_state = timing_apply_post_spike( + delayed_post_time, *post_window.next_trace, + (delayed_post_time - delayed_pre_time), + last_pre_trace, post_window.prev_time, post_window.prev_trace, + current_state); + + + + pre_window = post_events_next_delayed(pre_window, delayed_pre_time); + + + } +// // Apply spike to state + // Go onto next event post_window = post_events_next_delayed(post_window, delayed_post_time); @@ -263,15 +323,22 @@ bool synapse_dynamics_process_plastic_synapses( plastic_region_address); // Get last pre-synaptic event from event history - const uint32_t last_pre_time = event_history->prev_time; - const pre_trace_t last_pre_trace = event_history->prev_trace; + const uint32_t last_pre_time = event_history->pf_times[event_history->num_recorded_pf_spikes_minus_one]; + + // no longer need to manage this trace + const pre_trace_t last_pre_trace = 0; + + + // add pre spike to struct capturing pre synaptic event history + // NOTE: this uses the post_event_history_t handling code + post_events_add(time, event_history, 0); + // Update pre-synaptic trace - io_printf(IO_BUF, "\nAdding pre-synaptic event (Purkinje fibre spike) at time: %u\n", time); - event_history->prev_time = time; + io_printf(IO_BUF, "\nAdding pre-synaptic event (parallel fibre spike) at time: %u\n\n", time); - event_history->prev_trace = timing_add_pre_spike(time, last_pre_time, - last_pre_trace); + + timing_add_pre_spike(time, last_pre_time, last_pre_trace); // Loop through plastic synapses for (; plastic_synapse > 0; plastic_synapse--) { @@ -292,15 +359,18 @@ bool synapse_dynamics_process_plastic_synapses( uint32_t type_index = synapse_row_sparse_type_index( control_word, synapse_type_index_mask); +// io_printf(IO_BUF, "PRINTING PRE EVENT HISTORY"); +// print_delayed_window_events(event_history, begin_time, time, delay_dendritic); + // Create update state from the plastic synaptic word update_state_t current_state = synapse_structure_get_update_state( *plastic_words, type); // Update the synapse state final_state_t final_state = _plasticity_update_synapse( - time, last_pre_time, last_pre_trace, event_history->prev_trace, + time, last_pre_time, last_pre_trace, last_pre_trace, delay_dendritic, delay_axonal, current_state, - &post_event_history[index]); + &post_event_history[index], event_history); // Convert into ring buffer offset uint32_t ring_buffer_index = synapses_get_ring_buffer_index_combined( diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index 8159b3ac194..2d3bef750df 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -73,20 +73,7 @@ static inline post_trace_t timing_add_post_spike( static inline pre_trace_t timing_add_pre_spike( uint32_t time, uint32_t last_time, pre_trace_t last_trace) { -// // Get time since last spike -// uint32_t delta_time = time - last_time; -// -// // Decay previous r1 and r2 traces -// int32_t decayed_r1_trace = STDP_FIXED_MUL_16X16( -// last_trace, DECAY_LOOKUP_TAU_PLUS(delta_time)); -// -// // Add energy caused by new spike to trace -// int32_t new_r1_trace = decayed_r1_trace + STDP_FIXED_POINT_ONE; -// -// log_debug("\tdelta_time=%u, r1=%d\n", delta_time, new_r1_trace); -// -// // Return new pre-synaptic event with decayed trace values with energy -// // for new spike added + return (pre_trace_t) 0; //new_r1_trace; } @@ -149,7 +136,7 @@ static inline update_state_t timing_apply_post_spike( // // // Get time of event relative to last pre-synaptic event - uint32_t time_since_last_pre = time - last_pre_time; + uint32_t time_since_last_pre = last_pre_time; //time - last_pre_time; io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); if (time_since_last_pre < 255){ diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h index 99e6515e987..97f7c1c71ef 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h @@ -54,6 +54,7 @@ static inline weight_state_t weight_get_initial(weight_t weight, static inline weight_state_t weight_one_term_apply_depression( weight_state_t state, int32_t depression_multiplier) { + io_printf(IO_BUF, "\n Do Depression\n"); io_printf(IO_BUF, " Weight prior to depression: %u\n",state.weight); // Calculate scale @@ -69,7 +70,7 @@ static inline weight_state_t weight_one_term_apply_depression( // **NOTE** using standard STDP fixed-point format handles format conversion state.weight -= STDP_FIXED_MUL_16X16(state.weight, depression_multiplier); - io_printf(IO_BUF, " Weight after depression: %u\n",state.weight); + io_printf(IO_BUF, " Weight after depression: %u\n\n",state.weight); return state; } diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py index 76dc30904a5..9d35d906848 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py @@ -68,7 +68,7 @@ def write_pfpc_lut(spec, time_constant, lut_size, shift, time_probe, # Write peak time in timesteps peak_time_data = int(peak_time * (1000.0 / machine_time_step) - lut_size/2 + 0.5) - print "peak time data:", peak_time_data, "peak_time:", peak_time + #print "peak time data:", peak_time_data, "peak_time:", peak_time # if spec is not None: # spec.write_value(data=peak_time_data, @@ -89,6 +89,7 @@ def write_pfpc_lut(spec, time_constant, lut_size, shift, time_probe, # t = np.arange(0,lut_size) # out = [] # out_fixed = [] + exp_list = [] for i in range(0,lut_size): # the sign needs to be checked and has to be consistent with the dt used in the synapse # Multiply by time constant and calculate negative exponential @@ -98,10 +99,11 @@ def write_pfpc_lut(spec, time_constant, lut_size, shift, time_probe, # exp_float = 0.0 # print "clamp @ value = ", value # else: - exp_float = math.exp(-value) * math.sin(value)**sin_pwr / max_value + exp_float = math.exp(-value) * math.sin(value)**sin_pwr / 0.213122689799 #max_value # Convert to fixed-point and write to spec exp_fix = float_to_fixed(exp_float, fixed_point_one) + exp_list.append(exp_float) if spec is None : #out.append(exp_float) @@ -111,7 +113,9 @@ def write_pfpc_lut(spec, time_constant, lut_size, shift, time_probe, spec.write_value(data=exp_fix, data_type=DataType.INT16) + # if spec is None : # plt.plot(t,out) # plt.show() + diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index c477f3d2f57..847f9378aa3 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -51,9 +51,8 @@ def vertex_executable_suffix(self): @property def pre_trace_n_bytes(self): - # Pair rule requires no pre-synaptic trace when only the nearest - # Neighbours are considered and, a single 16-bit R1 trace - return 2 + # Here we will record the last 16 spikes, these will be 32-bit quantities, + return (16 * 4) + (2 * 16) # 16 4-byte entries, plus one counter for the number of spikes @overrides(AbstractTimingDependence.get_parameters_sdram_usage_in_bytes) def get_parameters_sdram_usage_in_bytes(self): @@ -68,14 +67,9 @@ def write_parameters(self, spec, machine_time_step, weight_scales): # Check timestep is valid if machine_time_step != 1000: raise NotImplementedError( - "STDP LUT generation currently only supports 1ms timesteps") + "exp_sin LUT generation currently only supports 1ms timesteps") - ################# - # Add new LUT generation here - ################# - - - # Write lookup tables + # Write exp_sin lookup table self._tau_plus_last_entry = plasticity_helpers.write_pfpc_lut(spec, time_constant=20, time_probe=None, lut_size=LUT_SIZE, shift=0) From cc5b5e9b353808bf62b25967c592c23d363fb4d7 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Fri, 12 Oct 2018 10:05:16 +0100 Subject: [PATCH 015/108] add template code for vn neurons --- .../Makefile | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile new file mode 100644 index 00000000000..045d8a47452 --- /dev/null +++ b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile @@ -0,0 +1,15 @@ +APP = $(notdir $(CURDIR)) + +NEURON_MODEL = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.c +NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.h +INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_conductance.h +NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h +THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h +SYNAPSE_TYPE_H = $(NEURON_DIR)/neuron/synapse_types/synapse_types_exponential_impl.h +SYNAPSE_DYNAMICS = $(NEURON_DIR)/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c +TIMING_DEPENDENCE = $(NEURON_DIR)/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c +TIMING_DEPENDENCE_H = $(NEURON_DIR)/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +WEIGHT_DEPENDENCE = $(NEURON_DIR)/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c +WEIGHT_DEPENDENCE_H = $(NEURON_DIR)/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h + +include ../neural_build.mk From 17881a6ecbe3f37d5dce4d610722f8ce2af88eff Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Mon, 10 Dec 2018 15:49:19 +0000 Subject: [PATCH 016/108] Update to separate synapse dynamics for cerebellum neurons --- .../Makefile | 2 +- .../stdp/synapse_dynamics_stdp_mad_impl.c | 116 +--- .../synapse_dynamics_stdp_mad_pfpc_impl.c | 550 ++++++++++++++++++ 3 files changed, 572 insertions(+), 96 deletions(-) create mode 100644 neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile index 045d8a47452..6af8b14cabf 100644 --- a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile +++ b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile @@ -6,7 +6,7 @@ INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_conductance.h NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h SYNAPSE_TYPE_H = $(NEURON_DIR)/neuron/synapse_types/synapse_types_exponential_impl.h -SYNAPSE_DYNAMICS = $(NEURON_DIR)/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c +SYNAPSE_DYNAMICS = $(NEURON_DIR)/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c TIMING_DEPENDENCE = $(NEURON_DIR)/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c TIMING_DEPENDENCE_H = $(NEURON_DIR)/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h WEIGHT_DEPENDENCE = $(NEURON_DIR)/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c index 3d8133dc9f7..75430d795fb 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c @@ -55,35 +55,11 @@ uint32_t plastic_saturation_count = 0; //--------------------------------------- // Structures //--------------------------------------- -//typedef struct { -// pre_trace_t prev_trace; -// uint32_t prev_time; -//} pre_event_history_t; - -#define NUM_PF_SPIKES_TO_RECORD 16 - typedef struct { - uint32_t num_recorded_pf_spikes_minus_one; - uint32_t pf_times[NUM_PF_SPIKES_TO_RECORD]; - post_trace_t traces[NUM_PF_SPIKES_TO_RECORD]; + pre_trace_t prev_trace; + uint32_t prev_time; } pre_event_history_t; - - -_print_pre_event_history(pre_event_history_t pre_eve_hist){ - - io_printf(IO_BUF, "\n\n************************\n\n"); - io_printf(IO_BUF, "Number recorded spikes: %u\n", pre_eve_hist.num_recorded_pf_spikes_minus_one); - io_printf(IO_BUF, "Prev time: %u\n", - pre_eve_hist.pf_times[pre_eve_hist.num_recorded_pf_spikes_minus_one]); - - for (int i =0; i < NUM_PF_SPIKES_TO_RECORD; i ++){ - io_printf(IO_BUF, " Entry %u: %u\n", i ,pre_eve_hist.pf_times[i]); - } - -} - - post_event_history_t *post_event_history; //--------------------------------------- @@ -92,11 +68,9 @@ post_event_history_t *post_event_history; static inline final_state_t _plasticity_update_synapse( uint32_t time, const uint32_t last_pre_time, const pre_trace_t last_pre_trace, - const pre_trace_t new_pre_trace, - uint32_t delay_dendritic, + const pre_trace_t new_pre_trace, const uint32_t delay_dendritic, const uint32_t delay_axonal, update_state_t current_state, - const post_event_history_t *post_event_history, - const pre_event_history_t *pre_event_history) { + const post_event_history_t *post_event_history) { // Apply axonal delay to time of last presynaptic spike const uint32_t delayed_last_pre_time = last_pre_time + delay_axonal; @@ -113,59 +87,22 @@ static inline final_state_t _plasticity_update_synapse( window_begin_time, window_end_time, post_window.prev_time, post_window.num_events); - - io_printf(IO_BUF, " Printing CF history\n"); - print_event_history(post_event_history); -// print_delayed_window_events(post_event_history, window_begin_time, -// window_end_time, delay_dendritic); - - - io_printf(IO_BUF, "\n Looping over climbing fibre spikes:\n"); - - delay_dendritic = 0; + // print_event_history(post_event_history); + // print_delayed_window_events(post_event_history, window_begin_time, + // window_end_time, delay_dendritic); // Process events in post-synaptic window while (post_window.num_events > 0) { const uint32_t delayed_post_time = *post_window.next_time + delay_dendritic; - - uint32_t pf_begin_time = (delayed_post_time < 255) ? 0 : (delayed_post_time - 255); - - - io_printf(IO_BUF, " Applying post-synaptic event at delayed time:%u\n", + log_debug("\t\tApplying post-synaptic event at delayed time:%u\n", delayed_post_time); -// // Get window of pf events based on cf spikes -// print_delayed_window_events(pre_event_history, -// //(delayed_post_time-255) -// pf_begin_time, delayed_post_time, delay_dendritic); - post_event_window_t pre_window = post_events_get_window_delayed( - pre_event_history, pf_begin_time, delayed_post_time); - - - io_printf(IO_BUF, " Looping over PF window\n", - delayed_post_time); - while (pre_window.num_events > 0) { - const uint32_t delayed_pre_time = *pre_window.next_time - + delay_dendritic; - - io_printf(IO_BUF, " delta t = %u\n", delayed_post_time - delayed_pre_time); - - - current_state = timing_apply_post_spike( - delayed_post_time, *post_window.next_trace, - (delayed_post_time - delayed_pre_time), - last_pre_trace, post_window.prev_time, post_window.prev_trace, - current_state); - - - - pre_window = post_events_next_delayed(pre_window, delayed_pre_time); - - - } -// // Apply spike to state - + // Apply spike to state + current_state = timing_apply_post_spike( + delayed_post_time, *post_window.next_trace, delayed_last_pre_time, + last_pre_trace, post_window.prev_time, post_window.prev_trace, + current_state); // Go onto next event post_window = post_events_next_delayed(post_window, delayed_post_time); @@ -323,22 +260,14 @@ bool synapse_dynamics_process_plastic_synapses( plastic_region_address); // Get last pre-synaptic event from event history - const uint32_t last_pre_time = event_history->pf_times[event_history->num_recorded_pf_spikes_minus_one]; - - // no longer need to manage this trace - const pre_trace_t last_pre_trace = 0; - - - // add pre spike to struct capturing pre synaptic event history - // NOTE: this uses the post_event_history_t handling code - post_events_add(time, event_history, 0); - + const uint32_t last_pre_time = event_history->prev_time; + const pre_trace_t last_pre_trace = event_history->prev_trace; // Update pre-synaptic trace - io_printf(IO_BUF, "\nAdding pre-synaptic event (parallel fibre spike) at time: %u\n\n", time); - - - timing_add_pre_spike(time, last_pre_time, last_pre_trace); + log_debug("Adding pre-synaptic event to trace at time:%u", time); + event_history->prev_time = time; + event_history->prev_trace = timing_add_pre_spike(time, last_pre_time, + last_pre_trace); // Loop through plastic synapses for (; plastic_synapse > 0; plastic_synapse--) { @@ -359,18 +288,15 @@ bool synapse_dynamics_process_plastic_synapses( uint32_t type_index = synapse_row_sparse_type_index( control_word, synapse_type_index_mask); -// io_printf(IO_BUF, "PRINTING PRE EVENT HISTORY"); -// print_delayed_window_events(event_history, begin_time, time, delay_dendritic); - // Create update state from the plastic synaptic word update_state_t current_state = synapse_structure_get_update_state( *plastic_words, type); // Update the synapse state final_state_t final_state = _plasticity_update_synapse( - time, last_pre_time, last_pre_trace, last_pre_trace, + time, last_pre_time, last_pre_trace, event_history->prev_trace, delay_dendritic, delay_axonal, current_state, - &post_event_history[index], event_history); + &post_event_history[index]); // Convert into ring buffer offset uint32_t ring_buffer_index = synapses_get_ring_buffer_index_combined( diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c new file mode 100644 index 00000000000..3d8133dc9f7 --- /dev/null +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c @@ -0,0 +1,550 @@ +// Spinn_common includes +#include "static-assert.h" + +// sPyNNaker neural modelling includes +#include + +// Plasticity includes +#include "maths.h" +#include "post_events.h" + +#include "weight_dependence/weight.h" +#include "timing_dependence/timing.h" +#include +#include +#include + +static uint32_t synapse_type_index_bits; +static uint32_t synapse_index_bits; +static uint32_t synapse_index_mask; +static uint32_t synapse_type_index_mask; +static uint32_t synapse_delay_index_type_bits; +static uint32_t synapse_type_mask; + +uint32_t num_plastic_pre_synaptic_events = 0; +uint32_t plastic_saturation_count = 0; + +//--------------------------------------- +// Macros +//--------------------------------------- +// The plastic control words used by Morrison synapses store an axonal delay +// in the upper 3 bits. +// Assuming a maximum of 16 delay slots, this is all that is required as: +// +// 1) Dendritic + Axonal <= 15 +// 2) Dendritic >= Axonal +// +// Therefore: +// +// * Maximum value of dendritic delay is 15 (with axonal delay of 0) +// - It requires 4 bits +// * Maximum value of axonal delay is 7 (with dendritic delay of 8) +// - It requires 3 bits +// +// | Axonal delay | Dendritic delay | Type | Index | +// |---------------------------|--------------------|-------------------|--------------------| +// | SYNAPSE_AXONAL_DELAY_BITS | SYNAPSE_DELAY_BITS | SYNAPSE_TYPE_BITS | SYNAPSE_INDEX_BITS | +// | | | SYNAPSE_TYPE_INDEX_BITS | +// |---------------------------|--------------------|----------------------------------------| +#ifndef SYNAPSE_AXONAL_DELAY_BITS +#define SYNAPSE_AXONAL_DELAY_BITS 3 +#endif + +#define SYNAPSE_AXONAL_DELAY_MASK ((1 << SYNAPSE_AXONAL_DELAY_BITS) - 1) + +//--------------------------------------- +// Structures +//--------------------------------------- +//typedef struct { +// pre_trace_t prev_trace; +// uint32_t prev_time; +//} pre_event_history_t; + +#define NUM_PF_SPIKES_TO_RECORD 16 + +typedef struct { + uint32_t num_recorded_pf_spikes_minus_one; + uint32_t pf_times[NUM_PF_SPIKES_TO_RECORD]; + post_trace_t traces[NUM_PF_SPIKES_TO_RECORD]; +} pre_event_history_t; + + + +_print_pre_event_history(pre_event_history_t pre_eve_hist){ + + io_printf(IO_BUF, "\n\n************************\n\n"); + io_printf(IO_BUF, "Number recorded spikes: %u\n", pre_eve_hist.num_recorded_pf_spikes_minus_one); + io_printf(IO_BUF, "Prev time: %u\n", + pre_eve_hist.pf_times[pre_eve_hist.num_recorded_pf_spikes_minus_one]); + + for (int i =0; i < NUM_PF_SPIKES_TO_RECORD; i ++){ + io_printf(IO_BUF, " Entry %u: %u\n", i ,pre_eve_hist.pf_times[i]); + } + +} + + +post_event_history_t *post_event_history; + +//--------------------------------------- +// Synapse update loop +//--------------------------------------- +static inline final_state_t _plasticity_update_synapse( + uint32_t time, + const uint32_t last_pre_time, const pre_trace_t last_pre_trace, + const pre_trace_t new_pre_trace, + uint32_t delay_dendritic, + const uint32_t delay_axonal, update_state_t current_state, + const post_event_history_t *post_event_history, + const pre_event_history_t *pre_event_history) { + + // Apply axonal delay to time of last presynaptic spike + const uint32_t delayed_last_pre_time = last_pre_time + delay_axonal; + + // Get the post-synaptic window of events to be processed + const uint32_t window_begin_time = (delayed_last_pre_time >= + delay_dendritic) ? (delayed_last_pre_time - delay_dendritic) : 0; + const uint32_t window_end_time = time + delay_axonal - delay_dendritic; + post_event_window_t post_window = post_events_get_window_delayed( + post_event_history, window_begin_time, window_end_time); + + log_debug("\tPerforming deferred synapse update at time:%u", time); + log_debug("\t\tbegin_time:%u, end_time:%u - prev_time:%u, num_events:%u", + window_begin_time, window_end_time, post_window.prev_time, + post_window.num_events); + + + io_printf(IO_BUF, " Printing CF history\n"); + print_event_history(post_event_history); +// print_delayed_window_events(post_event_history, window_begin_time, +// window_end_time, delay_dendritic); + + + io_printf(IO_BUF, "\n Looping over climbing fibre spikes:\n"); + + delay_dendritic = 0; + + // Process events in post-synaptic window + while (post_window.num_events > 0) { + const uint32_t delayed_post_time = *post_window.next_time + + delay_dendritic; + + uint32_t pf_begin_time = (delayed_post_time < 255) ? 0 : (delayed_post_time - 255); + + + io_printf(IO_BUF, " Applying post-synaptic event at delayed time:%u\n", + delayed_post_time); + +// // Get window of pf events based on cf spikes +// print_delayed_window_events(pre_event_history, +// //(delayed_post_time-255) +// pf_begin_time, delayed_post_time, delay_dendritic); + post_event_window_t pre_window = post_events_get_window_delayed( + pre_event_history, pf_begin_time, delayed_post_time); + + + io_printf(IO_BUF, " Looping over PF window\n", + delayed_post_time); + while (pre_window.num_events > 0) { + const uint32_t delayed_pre_time = *pre_window.next_time + + delay_dendritic; + + io_printf(IO_BUF, " delta t = %u\n", delayed_post_time - delayed_pre_time); + + + current_state = timing_apply_post_spike( + delayed_post_time, *post_window.next_trace, + (delayed_post_time - delayed_pre_time), + last_pre_trace, post_window.prev_time, post_window.prev_trace, + current_state); + + + + pre_window = post_events_next_delayed(pre_window, delayed_pre_time); + + + } +// // Apply spike to state + + + // Go onto next event + post_window = post_events_next_delayed(post_window, delayed_post_time); + } + + const uint32_t delayed_pre_time = time + delay_axonal; + log_debug("\t\tApplying pre-synaptic event at time:%u last post time:%u\n", + delayed_pre_time, post_window.prev_time); + + // Apply spike to state + // **NOTE** dendritic delay is subtracted + current_state = timing_apply_pre_spike( + delayed_pre_time, new_pre_trace, delayed_last_pre_time, last_pre_trace, + post_window.prev_time, post_window.prev_trace, current_state); + + // Return final synaptic word and weight + return synapse_structure_get_final_state(current_state); +} + +//--------------------------------------- +// Synaptic row plastic-region implementation +//--------------------------------------- +static inline plastic_synapse_t* _plastic_synapses( + address_t plastic_region_address) { + const uint32_t pre_event_history_size_words = + sizeof(pre_event_history_t) / sizeof(uint32_t); + static_assert(pre_event_history_size_words * sizeof(uint32_t) + == sizeof(pre_event_history_t), + "Size of pre_event_history_t structure should be a multiple" + " of 32-bit words"); + + return (plastic_synapse_t*) + (&plastic_region_address[pre_event_history_size_words]); +} + +//--------------------------------------- +static inline pre_event_history_t *_plastic_event_history( + address_t plastic_region_address) { + return (pre_event_history_t*) (&plastic_region_address[0]); +} + +void synapse_dynamics_print_plastic_synapses( + address_t plastic_region_address, address_t fixed_region_address, + uint32_t *ring_buffer_to_input_buffer_left_shifts) { + use(plastic_region_address); + use(fixed_region_address); + use(ring_buffer_to_input_buffer_left_shifts); +#if LOG_LEVEL >= LOG_DEBUG + + // Extract separate arrays of weights (from plastic region), + // Control words (from fixed region) and number of plastic synapses + weight_t *plastic_words = _plastic_synapses(plastic_region_address); + const control_t *control_words = synapse_row_plastic_controls( + fixed_region_address); + size_t plastic_synapse = synapse_row_num_plastic_controls( + fixed_region_address); + const pre_event_history_t *event_history = _plastic_event_history( + plastic_region_address); + + log_debug("Plastic region %u synapses\n", plastic_synapse); + + // Loop through plastic synapses + for (uint32_t i = 0; i < plastic_synapse; i++) { + + // Get next weight and control word (auto incrementing control word) + uint32_t weight = *plastic_words++; + uint32_t control_word = *control_words++; + uint32_t synapse_type = synapse_row_sparse_type( + control_word, synapse_index_bits, synapse_type_mask); + + log_debug("%08x [%3d: (w: %5u (=", control_word, i, weight); + synapses_print_weight( + weight, ring_buffer_to_input_buffer_left_shifts[synapse_type]); + log_debug("nA) d: %2u, %s, n = %3u)] - {%08x %08x}\n", + synapse_row_sparse_delay( + control_word, synapse_type_index_bits), + synapse_types_get_type_char(synapse_type), + synapse_row_sparse_index(control_word, synapse_index_mask), + SYNAPSE_DELAY_MASK, synapse_type_index_bits); + } +#endif // LOG_LEVEL >= LOG_DEBUG +} + +//--------------------------------------- +static inline index_t _sparse_axonal_delay(uint32_t x) { + return ((x >> synapse_delay_index_type_bits) & SYNAPSE_AXONAL_DELAY_MASK); +} + +address_t synapse_dynamics_initialise( + address_t address, uint32_t n_neurons, uint32_t n_synapse_types, + uint32_t *ring_buffer_to_input_buffer_left_shifts) { + + // Load timing dependence data + address_t weight_region_address = timing_initialise(address); + if (address == NULL) { + return NULL; + } + + // Load weight dependence data + address_t weight_result = weight_initialise( + weight_region_address, n_synapse_types, + ring_buffer_to_input_buffer_left_shifts); + if (weight_result == NULL) { + return NULL; + } + + post_event_history = post_events_init_buffers(n_neurons); + if (post_event_history == NULL) { + return NULL; + } + + uint32_t n_neurons_power_2 = n_neurons; + uint32_t log_n_neurons = 1; + if (n_neurons != 1) { + if (!is_power_of_2(n_neurons)) { + n_neurons_power_2 = next_power_of_2(n_neurons); + } + log_n_neurons = ilog_2(n_neurons_power_2); + } + + uint32_t n_synapse_types_power_2 = n_synapse_types; + if (!is_power_of_2(n_synapse_types)) { + n_synapse_types_power_2 = next_power_of_2(n_synapse_types); + } + uint32_t log_n_synapse_types = ilog_2(n_synapse_types_power_2); + + synapse_type_index_bits = log_n_neurons + log_n_synapse_types; + synapse_type_index_mask = (1 << synapse_type_index_bits) - 1; + synapse_index_bits = log_n_neurons; + synapse_index_mask = (1 << synapse_index_bits) - 1; + synapse_delay_index_type_bits = + SYNAPSE_DELAY_BITS + synapse_type_index_bits; + synapse_type_mask = (1 << log_n_synapse_types) - 1; + + return weight_result; +} + +bool synapse_dynamics_process_plastic_synapses( + address_t plastic_region_address, address_t fixed_region_address, + weight_t *ring_buffers, uint32_t time) { + + // Extract separate arrays of plastic synapses (from plastic region), + // Control words (from fixed region) and number of plastic synapses + plastic_synapse_t *plastic_words = _plastic_synapses( + plastic_region_address); + const control_t *control_words = synapse_row_plastic_controls( + fixed_region_address); + size_t plastic_synapse = synapse_row_num_plastic_controls( + fixed_region_address); + + num_plastic_pre_synaptic_events += plastic_synapse; + + // Get event history from synaptic row + pre_event_history_t *event_history = _plastic_event_history( + plastic_region_address); + + // Get last pre-synaptic event from event history + const uint32_t last_pre_time = event_history->pf_times[event_history->num_recorded_pf_spikes_minus_one]; + + // no longer need to manage this trace + const pre_trace_t last_pre_trace = 0; + + + // add pre spike to struct capturing pre synaptic event history + // NOTE: this uses the post_event_history_t handling code + post_events_add(time, event_history, 0); + + + // Update pre-synaptic trace + io_printf(IO_BUF, "\nAdding pre-synaptic event (parallel fibre spike) at time: %u\n\n", time); + + + timing_add_pre_spike(time, last_pre_time, last_pre_trace); + + // Loop through plastic synapses + for (; plastic_synapse > 0; plastic_synapse--) { + + // Get next control word (auto incrementing) + uint32_t control_word = *control_words++; + + // Extract control-word components + // **NOTE** cunningly, control word is just the same as lower + // 16-bits of 32-bit fixed synapse so same functions can be used + uint32_t delay_axonal = 0; //_sparse_axonal_delay(control_word); + uint32_t delay_dendritic = synapse_row_sparse_delay( + control_word, synapse_type_index_bits); + uint32_t type = synapse_row_sparse_type( + control_word, synapse_index_bits, synapse_type_mask); + uint32_t index = synapse_row_sparse_index( + control_word, synapse_index_mask); + uint32_t type_index = synapse_row_sparse_type_index( + control_word, synapse_type_index_mask); + +// io_printf(IO_BUF, "PRINTING PRE EVENT HISTORY"); +// print_delayed_window_events(event_history, begin_time, time, delay_dendritic); + + // Create update state from the plastic synaptic word + update_state_t current_state = synapse_structure_get_update_state( + *plastic_words, type); + + // Update the synapse state + final_state_t final_state = _plasticity_update_synapse( + time, last_pre_time, last_pre_trace, last_pre_trace, + delay_dendritic, delay_axonal, current_state, + &post_event_history[index], event_history); + + // Convert into ring buffer offset + uint32_t ring_buffer_index = synapses_get_ring_buffer_index_combined( + delay_axonal + delay_dendritic + time, type_index, + synapse_type_index_bits); + + // Add weight to ring-buffer entry + // **NOTE** Dave suspects that this could be a + // potential location for overflow + + uint32_t accumulation = ring_buffers[ring_buffer_index] + + synapse_structure_get_final_weight(final_state); + + uint32_t sat_test = accumulation & 0x10000; + if (sat_test){ + accumulation = sat_test - 1; + plastic_saturation_count += 1; + } + + ring_buffers[ring_buffer_index] = accumulation; + + // Write back updated synaptic word to plastic region + *plastic_words++ = synapse_structure_get_final_synaptic_word( + final_state); + } + return true; +} + +void synapse_dynamics_process_post_synaptic_event( + uint32_t time, index_t neuron_index) { + log_debug("Adding post-synaptic event to trace at time:%u", time); + + // Add post-event + post_event_history_t *history = &post_event_history[neuron_index]; + const uint32_t last_post_time = history->times[history->count_minus_one]; + const post_trace_t last_post_trace = + history->traces[history->count_minus_one]; + post_events_add(time, history, timing_add_post_spike(time, last_post_time, + last_post_trace)); +} + +input_t synapse_dynamics_get_intrinsic_bias(uint32_t time, + index_t neuron_index) { + use(time); + use(neuron_index); + return 0.0k; +} + +uint32_t synapse_dynamics_get_plastic_pre_synaptic_events(){ + return num_plastic_pre_synaptic_events; +} + +uint32_t synapse_dynamics_get_plastic_saturation_count(){ + return plastic_saturation_count; +} + +#if SYNGEN_ENABLED == 1 + +//! \brief Searches the synaptic row for the the connection with the +//! specified post-synaptic ID +//! \param[in] id: the (core-local) ID of the neuron to search for in the +//! synaptic row +//! \param[in] row: the core-local address of the synaptic row +//! \param[out] sp_data: the address of a struct through which to return +//! weight, delay information +//! \return bool: was the search successful? +bool find_plastic_neuron_with_id(uint32_t id, address_t row, + structural_plasticity_data_t *sp_data){ + address_t fixed_region = synapse_row_fixed_region(row); + address_t plastic_region_address = synapse_row_plastic_region(row); + plastic_synapse_t *plastic_words = + _plastic_synapses(plastic_region_address); + control_t *control_words = synapse_row_plastic_controls(fixed_region); + int32_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); + plastic_synapse_t weight; + uint32_t delay; + + // Loop through plastic synapses + bool found = false; + for (; plastic_synapse > 0; plastic_synapse--) { + + // Get next control word (auto incrementing) + weight = *plastic_words++; + uint32_t control_word = *control_words++; + + // Check if index is the one I'm looking for + delay = synapse_row_sparse_delay(control_word, synapse_type_index_bits); + if (synapse_row_sparse_index(control_word, synapse_index_mask)==id) { + found = true; + break; + } + } + + if (found){ + sp_data -> weight = weight; + sp_data -> offset = synapse_row_num_plastic_controls(fixed_region) - + plastic_synapse; + sp_data -> delay = delay; + return true; + } + else{ + sp_data -> weight = -1; + sp_data -> offset = -1; + sp_data -> delay = -1; + return false; + } +} + +//! \brief Remove the entry at the specified offset in the synaptic row +//! \param[in] offset: the offset in the row at which to remove the entry +//! \param[in] row: the core-local address of the synaptic row +//! \return bool: was the removal successful? +bool remove_plastic_neuron_at_offset(uint32_t offset, address_t row){ + address_t fixed_region = synapse_row_fixed_region(row); + plastic_synapse_t *plastic_words = + _plastic_synapses(synapse_row_plastic_region(row)); + control_t *control_words = synapse_row_plastic_controls(fixed_region); + int32_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); + + // Delete weight at offset + plastic_words[offset] = plastic_words[plastic_synapse-1]; + plastic_words[plastic_synapse-1] = 0; + + // Delete control word at offset + control_words[offset] = control_words[plastic_synapse-1]; + control_words[plastic_synapse-1] = 0; + + // Decrement FP + fixed_region[1] = fixed_region[1] - 1; + + return true; +} + +//! ensuring the weight is of the correct type and size +static inline plastic_synapse_t _weight_conversion(uint32_t weight){ + return (plastic_synapse_t)(0xFFFF & weight); +} + +//! packing all of the information into the required plastic control word +static inline control_t _control_conversion(uint32_t id, uint32_t delay, + uint32_t type){ + control_t new_control = + ((delay & ((1< Date: Tue, 11 Dec 2018 09:04:14 +0000 Subject: [PATCH 017/108] Add template code for Mossy-Fibre/Vestibular Nuclei plasticity --- .../Makefile | 10 +- neural_modelling/makefiles/neuron/Makefile | 8 +- .../synapse_dynamics_stdp_mad_mfvn_impl.c | 550 ++++++++++++++++++ .../stdp/timing_dependence/timing_mfvn_impl.c | 25 + .../stdp/timing_dependence/timing_mfvn_impl.h | 171 ++++++ .../stdp/timing_dependence/timing_pfpc_impl.h | 6 +- .../stdp/weight_dependence/weight_mfvn_impl.c | 63 ++ .../stdp/weight_dependence/weight_mfvn_impl.h | 114 ++++ .../stdp/weight_dependence/weight_pfpc_impl.c | 11 +- .../stdp/common/plasticity_helpers.py | 60 ++ .../stdp/timing_dependence/__init__.py | 5 +- .../timing_dependence_mfvn.py | 93 +++ .../timing_dependence_pfpc.py | 12 +- .../stdp/weight_dependence/__init__.py | 4 +- .../weight_dependence_mfvn.py | 77 +++ 15 files changed, 1185 insertions(+), 24 deletions(-) create mode 100644 neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c create mode 100644 neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c create mode 100644 neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h create mode 100644 neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c create mode 100644 neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h create mode 100644 spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py create mode 100644 spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile index 045d8a47452..fd777befbd8 100644 --- a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile +++ b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile @@ -6,10 +6,10 @@ INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_conductance.h NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h SYNAPSE_TYPE_H = $(NEURON_DIR)/neuron/synapse_types/synapse_types_exponential_impl.h -SYNAPSE_DYNAMICS = $(NEURON_DIR)/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c -TIMING_DEPENDENCE = $(NEURON_DIR)/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c -TIMING_DEPENDENCE_H = $(NEURON_DIR)/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h -WEIGHT_DEPENDENCE = $(NEURON_DIR)/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c -WEIGHT_DEPENDENCE_H = $(NEURON_DIR)/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h +SYNAPSE_DYNAMICS = $(NEURON_DIR)/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c +TIMING_DEPENDENCE = $(NEURON_DIR)/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c +TIMING_DEPENDENCE_H = $(NEURON_DIR)/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h +WEIGHT_DEPENDENCE = $(NEURON_DIR)/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c +WEIGHT_DEPENDENCE_H = $(NEURON_DIR)/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h include ../neural_build.mk diff --git a/neural_modelling/makefiles/neuron/Makefile b/neural_modelling/makefiles/neuron/Makefile index efe436be414..5fc23547a89 100644 --- a/neural_modelling/makefiles/neuron/Makefile +++ b/neural_modelling/makefiles/neuron/Makefile @@ -1,10 +1,12 @@ -MODELS = IF_curr_exp \ +MODELS = IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc \ + IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn \ + IF_curr_exp \ IF_cond_exp \ IZK_curr_exp \ IZK_cond_exp \ IF_curr_exp_dual \ IF_curr_exp_stdp_mad_pair_additive \ - IF_curr_exp_stdp_mad_pair_multiplicative \ + #IF_curr_exp_stdp_mad_pair_multiplicative \ IF_cond_exp_stdp_mad_pair_additive \ external_device_lif_control \ IF_curr_exp_stdp_mad_recurrent_pre_stochastic_multiplicative \ @@ -22,7 +24,7 @@ MODELS = IF_curr_exp \ IF_curr_exp_structural \ IF_cond_exp_stdp_mad_pair_additive_structural \ IF_curr_exp_sEMD \ - #IF_cond_exp_stoc + #IF_cond_exp_stoc all: diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c new file mode 100644 index 00000000000..3d8133dc9f7 --- /dev/null +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c @@ -0,0 +1,550 @@ +// Spinn_common includes +#include "static-assert.h" + +// sPyNNaker neural modelling includes +#include + +// Plasticity includes +#include "maths.h" +#include "post_events.h" + +#include "weight_dependence/weight.h" +#include "timing_dependence/timing.h" +#include +#include +#include + +static uint32_t synapse_type_index_bits; +static uint32_t synapse_index_bits; +static uint32_t synapse_index_mask; +static uint32_t synapse_type_index_mask; +static uint32_t synapse_delay_index_type_bits; +static uint32_t synapse_type_mask; + +uint32_t num_plastic_pre_synaptic_events = 0; +uint32_t plastic_saturation_count = 0; + +//--------------------------------------- +// Macros +//--------------------------------------- +// The plastic control words used by Morrison synapses store an axonal delay +// in the upper 3 bits. +// Assuming a maximum of 16 delay slots, this is all that is required as: +// +// 1) Dendritic + Axonal <= 15 +// 2) Dendritic >= Axonal +// +// Therefore: +// +// * Maximum value of dendritic delay is 15 (with axonal delay of 0) +// - It requires 4 bits +// * Maximum value of axonal delay is 7 (with dendritic delay of 8) +// - It requires 3 bits +// +// | Axonal delay | Dendritic delay | Type | Index | +// |---------------------------|--------------------|-------------------|--------------------| +// | SYNAPSE_AXONAL_DELAY_BITS | SYNAPSE_DELAY_BITS | SYNAPSE_TYPE_BITS | SYNAPSE_INDEX_BITS | +// | | | SYNAPSE_TYPE_INDEX_BITS | +// |---------------------------|--------------------|----------------------------------------| +#ifndef SYNAPSE_AXONAL_DELAY_BITS +#define SYNAPSE_AXONAL_DELAY_BITS 3 +#endif + +#define SYNAPSE_AXONAL_DELAY_MASK ((1 << SYNAPSE_AXONAL_DELAY_BITS) - 1) + +//--------------------------------------- +// Structures +//--------------------------------------- +//typedef struct { +// pre_trace_t prev_trace; +// uint32_t prev_time; +//} pre_event_history_t; + +#define NUM_PF_SPIKES_TO_RECORD 16 + +typedef struct { + uint32_t num_recorded_pf_spikes_minus_one; + uint32_t pf_times[NUM_PF_SPIKES_TO_RECORD]; + post_trace_t traces[NUM_PF_SPIKES_TO_RECORD]; +} pre_event_history_t; + + + +_print_pre_event_history(pre_event_history_t pre_eve_hist){ + + io_printf(IO_BUF, "\n\n************************\n\n"); + io_printf(IO_BUF, "Number recorded spikes: %u\n", pre_eve_hist.num_recorded_pf_spikes_minus_one); + io_printf(IO_BUF, "Prev time: %u\n", + pre_eve_hist.pf_times[pre_eve_hist.num_recorded_pf_spikes_minus_one]); + + for (int i =0; i < NUM_PF_SPIKES_TO_RECORD; i ++){ + io_printf(IO_BUF, " Entry %u: %u\n", i ,pre_eve_hist.pf_times[i]); + } + +} + + +post_event_history_t *post_event_history; + +//--------------------------------------- +// Synapse update loop +//--------------------------------------- +static inline final_state_t _plasticity_update_synapse( + uint32_t time, + const uint32_t last_pre_time, const pre_trace_t last_pre_trace, + const pre_trace_t new_pre_trace, + uint32_t delay_dendritic, + const uint32_t delay_axonal, update_state_t current_state, + const post_event_history_t *post_event_history, + const pre_event_history_t *pre_event_history) { + + // Apply axonal delay to time of last presynaptic spike + const uint32_t delayed_last_pre_time = last_pre_time + delay_axonal; + + // Get the post-synaptic window of events to be processed + const uint32_t window_begin_time = (delayed_last_pre_time >= + delay_dendritic) ? (delayed_last_pre_time - delay_dendritic) : 0; + const uint32_t window_end_time = time + delay_axonal - delay_dendritic; + post_event_window_t post_window = post_events_get_window_delayed( + post_event_history, window_begin_time, window_end_time); + + log_debug("\tPerforming deferred synapse update at time:%u", time); + log_debug("\t\tbegin_time:%u, end_time:%u - prev_time:%u, num_events:%u", + window_begin_time, window_end_time, post_window.prev_time, + post_window.num_events); + + + io_printf(IO_BUF, " Printing CF history\n"); + print_event_history(post_event_history); +// print_delayed_window_events(post_event_history, window_begin_time, +// window_end_time, delay_dendritic); + + + io_printf(IO_BUF, "\n Looping over climbing fibre spikes:\n"); + + delay_dendritic = 0; + + // Process events in post-synaptic window + while (post_window.num_events > 0) { + const uint32_t delayed_post_time = *post_window.next_time + + delay_dendritic; + + uint32_t pf_begin_time = (delayed_post_time < 255) ? 0 : (delayed_post_time - 255); + + + io_printf(IO_BUF, " Applying post-synaptic event at delayed time:%u\n", + delayed_post_time); + +// // Get window of pf events based on cf spikes +// print_delayed_window_events(pre_event_history, +// //(delayed_post_time-255) +// pf_begin_time, delayed_post_time, delay_dendritic); + post_event_window_t pre_window = post_events_get_window_delayed( + pre_event_history, pf_begin_time, delayed_post_time); + + + io_printf(IO_BUF, " Looping over PF window\n", + delayed_post_time); + while (pre_window.num_events > 0) { + const uint32_t delayed_pre_time = *pre_window.next_time + + delay_dendritic; + + io_printf(IO_BUF, " delta t = %u\n", delayed_post_time - delayed_pre_time); + + + current_state = timing_apply_post_spike( + delayed_post_time, *post_window.next_trace, + (delayed_post_time - delayed_pre_time), + last_pre_trace, post_window.prev_time, post_window.prev_trace, + current_state); + + + + pre_window = post_events_next_delayed(pre_window, delayed_pre_time); + + + } +// // Apply spike to state + + + // Go onto next event + post_window = post_events_next_delayed(post_window, delayed_post_time); + } + + const uint32_t delayed_pre_time = time + delay_axonal; + log_debug("\t\tApplying pre-synaptic event at time:%u last post time:%u\n", + delayed_pre_time, post_window.prev_time); + + // Apply spike to state + // **NOTE** dendritic delay is subtracted + current_state = timing_apply_pre_spike( + delayed_pre_time, new_pre_trace, delayed_last_pre_time, last_pre_trace, + post_window.prev_time, post_window.prev_trace, current_state); + + // Return final synaptic word and weight + return synapse_structure_get_final_state(current_state); +} + +//--------------------------------------- +// Synaptic row plastic-region implementation +//--------------------------------------- +static inline plastic_synapse_t* _plastic_synapses( + address_t plastic_region_address) { + const uint32_t pre_event_history_size_words = + sizeof(pre_event_history_t) / sizeof(uint32_t); + static_assert(pre_event_history_size_words * sizeof(uint32_t) + == sizeof(pre_event_history_t), + "Size of pre_event_history_t structure should be a multiple" + " of 32-bit words"); + + return (plastic_synapse_t*) + (&plastic_region_address[pre_event_history_size_words]); +} + +//--------------------------------------- +static inline pre_event_history_t *_plastic_event_history( + address_t plastic_region_address) { + return (pre_event_history_t*) (&plastic_region_address[0]); +} + +void synapse_dynamics_print_plastic_synapses( + address_t plastic_region_address, address_t fixed_region_address, + uint32_t *ring_buffer_to_input_buffer_left_shifts) { + use(plastic_region_address); + use(fixed_region_address); + use(ring_buffer_to_input_buffer_left_shifts); +#if LOG_LEVEL >= LOG_DEBUG + + // Extract separate arrays of weights (from plastic region), + // Control words (from fixed region) and number of plastic synapses + weight_t *plastic_words = _plastic_synapses(plastic_region_address); + const control_t *control_words = synapse_row_plastic_controls( + fixed_region_address); + size_t plastic_synapse = synapse_row_num_plastic_controls( + fixed_region_address); + const pre_event_history_t *event_history = _plastic_event_history( + plastic_region_address); + + log_debug("Plastic region %u synapses\n", plastic_synapse); + + // Loop through plastic synapses + for (uint32_t i = 0; i < plastic_synapse; i++) { + + // Get next weight and control word (auto incrementing control word) + uint32_t weight = *plastic_words++; + uint32_t control_word = *control_words++; + uint32_t synapse_type = synapse_row_sparse_type( + control_word, synapse_index_bits, synapse_type_mask); + + log_debug("%08x [%3d: (w: %5u (=", control_word, i, weight); + synapses_print_weight( + weight, ring_buffer_to_input_buffer_left_shifts[synapse_type]); + log_debug("nA) d: %2u, %s, n = %3u)] - {%08x %08x}\n", + synapse_row_sparse_delay( + control_word, synapse_type_index_bits), + synapse_types_get_type_char(synapse_type), + synapse_row_sparse_index(control_word, synapse_index_mask), + SYNAPSE_DELAY_MASK, synapse_type_index_bits); + } +#endif // LOG_LEVEL >= LOG_DEBUG +} + +//--------------------------------------- +static inline index_t _sparse_axonal_delay(uint32_t x) { + return ((x >> synapse_delay_index_type_bits) & SYNAPSE_AXONAL_DELAY_MASK); +} + +address_t synapse_dynamics_initialise( + address_t address, uint32_t n_neurons, uint32_t n_synapse_types, + uint32_t *ring_buffer_to_input_buffer_left_shifts) { + + // Load timing dependence data + address_t weight_region_address = timing_initialise(address); + if (address == NULL) { + return NULL; + } + + // Load weight dependence data + address_t weight_result = weight_initialise( + weight_region_address, n_synapse_types, + ring_buffer_to_input_buffer_left_shifts); + if (weight_result == NULL) { + return NULL; + } + + post_event_history = post_events_init_buffers(n_neurons); + if (post_event_history == NULL) { + return NULL; + } + + uint32_t n_neurons_power_2 = n_neurons; + uint32_t log_n_neurons = 1; + if (n_neurons != 1) { + if (!is_power_of_2(n_neurons)) { + n_neurons_power_2 = next_power_of_2(n_neurons); + } + log_n_neurons = ilog_2(n_neurons_power_2); + } + + uint32_t n_synapse_types_power_2 = n_synapse_types; + if (!is_power_of_2(n_synapse_types)) { + n_synapse_types_power_2 = next_power_of_2(n_synapse_types); + } + uint32_t log_n_synapse_types = ilog_2(n_synapse_types_power_2); + + synapse_type_index_bits = log_n_neurons + log_n_synapse_types; + synapse_type_index_mask = (1 << synapse_type_index_bits) - 1; + synapse_index_bits = log_n_neurons; + synapse_index_mask = (1 << synapse_index_bits) - 1; + synapse_delay_index_type_bits = + SYNAPSE_DELAY_BITS + synapse_type_index_bits; + synapse_type_mask = (1 << log_n_synapse_types) - 1; + + return weight_result; +} + +bool synapse_dynamics_process_plastic_synapses( + address_t plastic_region_address, address_t fixed_region_address, + weight_t *ring_buffers, uint32_t time) { + + // Extract separate arrays of plastic synapses (from plastic region), + // Control words (from fixed region) and number of plastic synapses + plastic_synapse_t *plastic_words = _plastic_synapses( + plastic_region_address); + const control_t *control_words = synapse_row_plastic_controls( + fixed_region_address); + size_t plastic_synapse = synapse_row_num_plastic_controls( + fixed_region_address); + + num_plastic_pre_synaptic_events += plastic_synapse; + + // Get event history from synaptic row + pre_event_history_t *event_history = _plastic_event_history( + plastic_region_address); + + // Get last pre-synaptic event from event history + const uint32_t last_pre_time = event_history->pf_times[event_history->num_recorded_pf_spikes_minus_one]; + + // no longer need to manage this trace + const pre_trace_t last_pre_trace = 0; + + + // add pre spike to struct capturing pre synaptic event history + // NOTE: this uses the post_event_history_t handling code + post_events_add(time, event_history, 0); + + + // Update pre-synaptic trace + io_printf(IO_BUF, "\nAdding pre-synaptic event (parallel fibre spike) at time: %u\n\n", time); + + + timing_add_pre_spike(time, last_pre_time, last_pre_trace); + + // Loop through plastic synapses + for (; plastic_synapse > 0; plastic_synapse--) { + + // Get next control word (auto incrementing) + uint32_t control_word = *control_words++; + + // Extract control-word components + // **NOTE** cunningly, control word is just the same as lower + // 16-bits of 32-bit fixed synapse so same functions can be used + uint32_t delay_axonal = 0; //_sparse_axonal_delay(control_word); + uint32_t delay_dendritic = synapse_row_sparse_delay( + control_word, synapse_type_index_bits); + uint32_t type = synapse_row_sparse_type( + control_word, synapse_index_bits, synapse_type_mask); + uint32_t index = synapse_row_sparse_index( + control_word, synapse_index_mask); + uint32_t type_index = synapse_row_sparse_type_index( + control_word, synapse_type_index_mask); + +// io_printf(IO_BUF, "PRINTING PRE EVENT HISTORY"); +// print_delayed_window_events(event_history, begin_time, time, delay_dendritic); + + // Create update state from the plastic synaptic word + update_state_t current_state = synapse_structure_get_update_state( + *plastic_words, type); + + // Update the synapse state + final_state_t final_state = _plasticity_update_synapse( + time, last_pre_time, last_pre_trace, last_pre_trace, + delay_dendritic, delay_axonal, current_state, + &post_event_history[index], event_history); + + // Convert into ring buffer offset + uint32_t ring_buffer_index = synapses_get_ring_buffer_index_combined( + delay_axonal + delay_dendritic + time, type_index, + synapse_type_index_bits); + + // Add weight to ring-buffer entry + // **NOTE** Dave suspects that this could be a + // potential location for overflow + + uint32_t accumulation = ring_buffers[ring_buffer_index] + + synapse_structure_get_final_weight(final_state); + + uint32_t sat_test = accumulation & 0x10000; + if (sat_test){ + accumulation = sat_test - 1; + plastic_saturation_count += 1; + } + + ring_buffers[ring_buffer_index] = accumulation; + + // Write back updated synaptic word to plastic region + *plastic_words++ = synapse_structure_get_final_synaptic_word( + final_state); + } + return true; +} + +void synapse_dynamics_process_post_synaptic_event( + uint32_t time, index_t neuron_index) { + log_debug("Adding post-synaptic event to trace at time:%u", time); + + // Add post-event + post_event_history_t *history = &post_event_history[neuron_index]; + const uint32_t last_post_time = history->times[history->count_minus_one]; + const post_trace_t last_post_trace = + history->traces[history->count_minus_one]; + post_events_add(time, history, timing_add_post_spike(time, last_post_time, + last_post_trace)); +} + +input_t synapse_dynamics_get_intrinsic_bias(uint32_t time, + index_t neuron_index) { + use(time); + use(neuron_index); + return 0.0k; +} + +uint32_t synapse_dynamics_get_plastic_pre_synaptic_events(){ + return num_plastic_pre_synaptic_events; +} + +uint32_t synapse_dynamics_get_plastic_saturation_count(){ + return plastic_saturation_count; +} + +#if SYNGEN_ENABLED == 1 + +//! \brief Searches the synaptic row for the the connection with the +//! specified post-synaptic ID +//! \param[in] id: the (core-local) ID of the neuron to search for in the +//! synaptic row +//! \param[in] row: the core-local address of the synaptic row +//! \param[out] sp_data: the address of a struct through which to return +//! weight, delay information +//! \return bool: was the search successful? +bool find_plastic_neuron_with_id(uint32_t id, address_t row, + structural_plasticity_data_t *sp_data){ + address_t fixed_region = synapse_row_fixed_region(row); + address_t plastic_region_address = synapse_row_plastic_region(row); + plastic_synapse_t *plastic_words = + _plastic_synapses(plastic_region_address); + control_t *control_words = synapse_row_plastic_controls(fixed_region); + int32_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); + plastic_synapse_t weight; + uint32_t delay; + + // Loop through plastic synapses + bool found = false; + for (; plastic_synapse > 0; plastic_synapse--) { + + // Get next control word (auto incrementing) + weight = *plastic_words++; + uint32_t control_word = *control_words++; + + // Check if index is the one I'm looking for + delay = synapse_row_sparse_delay(control_word, synapse_type_index_bits); + if (synapse_row_sparse_index(control_word, synapse_index_mask)==id) { + found = true; + break; + } + } + + if (found){ + sp_data -> weight = weight; + sp_data -> offset = synapse_row_num_plastic_controls(fixed_region) - + plastic_synapse; + sp_data -> delay = delay; + return true; + } + else{ + sp_data -> weight = -1; + sp_data -> offset = -1; + sp_data -> delay = -1; + return false; + } +} + +//! \brief Remove the entry at the specified offset in the synaptic row +//! \param[in] offset: the offset in the row at which to remove the entry +//! \param[in] row: the core-local address of the synaptic row +//! \return bool: was the removal successful? +bool remove_plastic_neuron_at_offset(uint32_t offset, address_t row){ + address_t fixed_region = synapse_row_fixed_region(row); + plastic_synapse_t *plastic_words = + _plastic_synapses(synapse_row_plastic_region(row)); + control_t *control_words = synapse_row_plastic_controls(fixed_region); + int32_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); + + // Delete weight at offset + plastic_words[offset] = plastic_words[plastic_synapse-1]; + plastic_words[plastic_synapse-1] = 0; + + // Delete control word at offset + control_words[offset] = control_words[plastic_synapse-1]; + control_words[plastic_synapse-1] = 0; + + // Decrement FP + fixed_region[1] = fixed_region[1] - 1; + + return true; +} + +//! ensuring the weight is of the correct type and size +static inline plastic_synapse_t _weight_conversion(uint32_t weight){ + return (plastic_synapse_t)(0xFFFF & weight); +} + +//! packing all of the information into the required plastic control word +static inline control_t _control_conversion(uint32_t id, uint32_t delay, + uint32_t type){ + control_t new_control = + ((delay & ((1< +#include "timing.h" +#include + +// Include debug header for log_info etc +#include + +// Include generic plasticity maths functions +#include +#include + +//--------------------------------------- +// Macros +//--------------------------------------- +// Exponential decay lookup parameters +#define TAU_PLUS_TIME_SHIFT 0 +#define EXP_SIN_LUT_SIZE 256 + +// Helper macros for looking up decays +#define EXP_SIN_LOOKUP(time) \ + maths_lut_exponential_decay( \ + time, TAU_PLUS_TIME_SHIFT, EXP_SIN_LUT_SIZE, exp_sin_lookup) +//#define DECAY_LOOKUP_TAU_MINUS(time) \ +// maths_lut_exponential_decay( \ +// time, TAU_MINUS_TIME_SHIFT, TAU_MINUS_SIZE, tau_minus_lookup) + +//--------------------------------------- +// Externals +//--------------------------------------- +extern int16_t exp_sin_lookup[EXP_SIN_LUT_SIZE]; + +//--------------------------------------- +// Timing dependence inline functions +//--------------------------------------- +static inline post_trace_t timing_get_initial_post_trace() { + return 0; +} + +//--------------------------------------- +static inline post_trace_t timing_add_post_spike( + uint32_t time, uint32_t last_time, post_trace_t last_trace) { + + io_printf(IO_BUF, "Adding pre spike to event history (from climbing fibre)\n"); + +// // Get time since last spike +// uint32_t delta_time = time - last_time; + +// // Decay previous o1 and o2 traces +// int32_t decayed_o1_trace = STDP_FIXED_MUL_16X16(last_trace, +// DECAY_LOOKUP_TAU_MINUS(delta_time)); + + // Add energy caused by new spike to trace + // **NOTE** o2 trace is pre-multiplied by a3_plus + int32_t new_o1_trace = 0; //decayed_o1_trace + STDP_FIXED_POINT_ONE; + +// log_debug("\tdelta_time=%d, o1=%d\n", delta_time, new_o1_trace); + + // Return new pre- synaptic event with decayed trace values with energy + // for new spike added + return (post_trace_t) new_o1_trace; +} + +//--------------------------------------- +static inline pre_trace_t timing_add_pre_spike( + uint32_t time, uint32_t last_time, pre_trace_t last_trace) { + + + return (pre_trace_t) 0; //new_r1_trace; +} + +//--------------------------------------- +static inline 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) { + use(&trace); + use(last_pre_time); + use(&last_pre_trace); + + // Here we will potentiate by the fixed amount alpha + io_printf(IO_BUF, " This is where we'll do potentiation\n"); + + return weight_one_term_apply_potentiation(previous_state, 0); + + + +// +// // Get time of event relative to last post-synaptic event +// uint32_t time_since_last_post = time - last_post_time; +// if (time_since_last_post > 0) { +// int32_t decayed_o1 = STDP_FIXED_MUL_16X16( +// last_post_trace, DECAY_LOOKUP_TAU_MINUS(time_since_last_post)); +// +// log_debug("\t\t\ttime_since_last_post_event=%u, decayed_o1=%d\n", +// time_since_last_post, decayed_o1); +// +// // Apply depression to state (which is a weight_state) +// return weight_one_term_apply_depression(previous_state, decayed_o1); +// +// +// +// +// +// +// +// } else { +// return previous_state; +// } +} + +//--------------------------------------- +static inline 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) { + use(&trace); + use(last_post_time); + use(&last_post_trace); + + + +// // This is where we lookup the value of e^(-x) * sin(x)^20 +// +// + + + +// +// // Get time of event relative to last pre-synaptic event + uint32_t time_since_last_pre = last_pre_time; //time - last_pre_time; + io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); + + if (time_since_last_pre < 255){ + + + uint32_t multiplier = EXP_SIN_LOOKUP(time_since_last_pre); + + io_printf(IO_BUF, "multiplier: %k (fixed = %u)\n", multiplier << 4, multiplier); + + return weight_one_term_apply_depression(previous_state, multiplier); + + + } +// + io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); + io_printf(IO_BUF, " out of LUT range - do nothing"); + +// if (time_since_last_pre > 0) { +// int32_t decayed_r1 = STDP_FIXED_MUL_16X16( +// last_pre_trace, DECAY_LOOKUP_TAU_PLUS(time_since_last_pre)); +// +// log_debug("\t\t\ttime_since_last_pre_event=%u, decayed_r1=%d\n", +// time_since_last_pre, decayed_r1); +// +// // Apply potentiation to state (which is a weight_state) +// return weight_one_term_apply_potentiation(previous_state, decayed_r1); +// } else { + return previous_state; + //} +} + +#endif // _TIMING_MFVN_IMPL_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index 2d3bef750df..d9ca591d00e 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -1,5 +1,5 @@ -#ifndef _TIMING_CEREBELLUM_IMPL_H_ -#define _TIMING_CEREBELLUM_IMPL_H_ +#ifndef _TIMING_PFPC_IMPL_H_ +#define _TIMING_PFPC_IMPL_H_ //--------------------------------------- // Typedefines @@ -168,4 +168,4 @@ static inline update_state_t timing_apply_post_spike( //} } -#endif // _TIMING_CEREBELLUM_IMPL_H_ +#endif // _TIMING_PFPC_IMPL_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c new file mode 100644 index 00000000000..bf55ff09b33 --- /dev/null +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c @@ -0,0 +1,63 @@ +#include "weight_multiplicative_impl.h" + +//--------------------------------------- +// Globals +//--------------------------------------- +// Global plasticity parameter data +plasticity_weight_region_data_t *plasticity_weight_region_data; +uint32_t *weight_multiply_right_shift; + +//--------------------------------------- +// Functions +//--------------------------------------- +uint32_t *weight_initialise(uint32_t *address, uint32_t n_synapse_types, + uint32_t *ring_buffer_to_input_buffer_left_shifts) { + + io_printf(IO_BUF, "mfvn weight_initialise: starting\n"); + io_printf(IO_BUF, "\tSTDP mfvn weight dependence\n"); + + // Copy plasticity region data from address + // **NOTE** this seems somewhat safer than relying on sizeof + int32_t *plasticity_word = (int32_t*) address; + + plasticity_weight_region_data = (plasticity_weight_region_data_t *) + spin1_malloc(sizeof(plasticity_weight_region_data_t) * n_synapse_types); + + if (plasticity_weight_region_data == NULL) { + log_error("Could not initialise weight region data"); + return NULL; + } + + weight_multiply_right_shift = (uint32_t *) + spin1_malloc(sizeof(uint32_t) * n_synapse_types); + + if (weight_multiply_right_shift == NULL) { + log_error("Could not initialise weight region data"); + return NULL; + } + for (uint32_t s = 0; s < n_synapse_types; s++) { + // Copy parameters + plasticity_weight_region_data[s].min_weight = *plasticity_word++; + plasticity_weight_region_data[s].max_weight = *plasticity_word++; + plasticity_weight_region_data[s].a2_plus = *plasticity_word++; + plasticity_weight_region_data[s].a2_minus = *plasticity_word++; + + // Calculate the right shift required to fixed-point multiply weights + weight_multiply_right_shift[s] = + 16 - (ring_buffer_to_input_buffer_left_shifts[s] + 1); + + io_printf(IO_BUF, + "\tSynapse type %u: Min weight:%d, Max weight:%d, A2+:%d, A2-:%d," + " Weight multiply right shift:%u\n", + s, plasticity_weight_region_data[s].min_weight, + plasticity_weight_region_data[s].max_weight, + plasticity_weight_region_data[s].a2_plus, + plasticity_weight_region_data[s].a2_minus, + weight_multiply_right_shift[s]); + } + + io_printf(IO_BUF, "mfvn weight initialisation: completed successfully"); + + // Return end address of region + return (address_t) plasticity_word; +} diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h new file mode 100644 index 00000000000..2e34f044c68 --- /dev/null +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h @@ -0,0 +1,114 @@ +#ifndef _WEIGHT_MFVN_IMPL_H_ +#define _WEIGHT_MFVN_IMPL_H_ + +// Include generic plasticity maths functions +#include +#include +#include + +#include + +//--------------------------------------- +// Structures +//--------------------------------------- +typedef struct { + int32_t min_weight; + int32_t max_weight; + + int32_t a2_plus; + int32_t a2_minus; +} plasticity_weight_region_data_t; + +typedef struct { + int32_t weight; + + int32_t a2_plus; + int32_t a2_minus; + + uint32_t weight_multiply_right_shift; + const plasticity_weight_region_data_t *weight_region; +} weight_state_t; + +#include "weight_one_term.h" + +//--------------------------------------- +// Externals +//--------------------------------------- +extern plasticity_weight_region_data_t *plasticity_weight_region_data; +extern uint32_t *weight_multiply_right_shift; + +//--------------------------------------- +// Weight dependance functions +//--------------------------------------- +static inline weight_state_t weight_get_initial(weight_t weight, + index_t synapse_type) { + return (weight_state_t ) { + .weight = (int32_t) weight, + .weight_multiply_right_shift = + weight_multiply_right_shift[synapse_type], + .weight_region = &plasticity_weight_region_data[synapse_type] + }; +} + +//--------------------------------------- +static inline weight_state_t weight_one_term_apply_depression( + weight_state_t state, int32_t depression_multiplier) { + + io_printf(IO_BUF, "\n Do Depression\n"); + io_printf(IO_BUF, " Weight prior to depression: %u\n",state.weight); + + // Calculate scale + // **NOTE** this calculation must be done at runtime-defined weight + // fixed-point format +// int32_t scale = maths_fixed_mul16( +// state.weight - state.weight_region->min_weight, +//// state.weight_region->a2_minus, +// depression_multiplier, +// state.weight_multiply_right_shift); + + // Multiply scale by depression and subtract + // **NOTE** using standard STDP fixed-point format handles format conversion + state.weight -= STDP_FIXED_MUL_16X16(state.weight, depression_multiplier); + + io_printf(IO_BUF, " Weight after depression: %u\n\n",state.weight); + + return state; +} +//--------------------------------------- +static inline weight_state_t weight_one_term_apply_potentiation( + weight_state_t state, int32_t potentiation) { + + // add fixed amount + state.a2_plus += state.weight_region->a2_plus; + + return state; + +} +//--------------------------------------- +static inline weight_t weight_get_final(weight_state_t new_state) { + log_debug("\tnew_weight:%d\n", new_state.weight); + + // first do Depression (as this would have happened first) + + +// // Now do potentiation (check against lower limit) +// int32_t scaled_a2_plus = STDP_FIXED_MUL_16X16( +// new_state.a2_plus, new_state.weight_region->a2_plus); + + + // Apply all terms to initial weight + int32_t new_weight = new_state.weight + new_state.a2_plus; + // - scaled_a2_minus; + + io_printf(IO_BUF, " old weight: %u, new weight: %u\n", new_state.weight, new_weight); + + // Clamp new weight + new_weight = MIN(new_state.weight_region->max_weight, + new_weight); + + new_state.weight = new_weight; + + return (weight_t) new_state.weight; +} + +#endif // _WEIGHT_MFVN_IMPL_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c index 4a0fa7e6424..82de61ad065 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c @@ -13,20 +13,23 @@ uint32_t *weight_multiply_right_shift; uint32_t *weight_initialise(uint32_t *address, uint32_t n_synapse_types, uint32_t *ring_buffer_to_input_buffer_left_shifts) { - log_debug("weight_initialise: starting\n"); - log_debug("\tSTDP multiplicative weight dependence\n"); + io_printf(IO_BUF, "PFPC weight_initialise: starting\n"); + io_printf(IO_BUF, "\tSTDP multiplicative weight dependence\n"); // Copy plasticity region data from address // **NOTE** this seems somewhat safer than relying on sizeof int32_t *plasticity_word = (int32_t*) address; + plasticity_weight_region_data = (plasticity_weight_region_data_t *) spin1_malloc(sizeof(plasticity_weight_region_data_t) * n_synapse_types); + if (plasticity_weight_region_data == NULL) { log_error("Could not initialise weight region data"); return NULL; } weight_multiply_right_shift = (uint32_t *) spin1_malloc(sizeof(uint32_t) * n_synapse_types); + if (weight_multiply_right_shift == NULL) { log_error("Could not initialise weight region data"); return NULL; @@ -42,7 +45,7 @@ uint32_t *weight_initialise(uint32_t *address, uint32_t n_synapse_types, weight_multiply_right_shift[s] = 16 - (ring_buffer_to_input_buffer_left_shifts[s] + 1); -// log_debug( + io_printf(IO_BUF, "\tSynapse type %u: Min weight:%d, Max weight:%d, A2+:%d, A2-:%d," " Weight multiply right shift:%u\n", @@ -53,7 +56,7 @@ uint32_t *weight_initialise(uint32_t *address, uint32_t n_synapse_types, weight_multiply_right_shift[s]); } - log_debug("weight_initialise: completed successfully"); + io_printf(IO_BUF, "PFPC weight_initialise: completed successfully"); // Return end address of region return (address_t) plasticity_word; diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py index 9d35d906848..c8ad49b2147 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py @@ -118,4 +118,64 @@ def write_pfpc_lut(spec, time_constant, lut_size, shift, time_probe, # plt.plot(t,out) # plt.show() +def write_mfvn_lut(spec, time_constant, lut_size, shift, time_probe, + fixed_point_one=STDP_FIXED_POINT_ONE): + peak_time = 100.0 + tau = peak_time * 2/math.pi; + machine_time_step = 1.0 + + # This offset is the quasi-symmetry point + sin_pwr = 20 + +# Write peak time in timesteps + peak_time_data = int(peak_time * (1000.0 / machine_time_step) - lut_size/2 + 0.5) + #print "peak time data:", peak_time_data, "peak_time:", peak_time + +# if spec is not None: +# spec.write_value(data=peak_time_data, +# data_type=DataType.INT32) + + # Calculate 1/tau in machine time steps + inv_tau = (1.0 / float(tau)) #* (machine_time_step / 1000.0) + + zero_offset = math.atan(-1./sin_pwr) # abscissae of the max point obtained by deriving the kernel and equal to zero + max_value = math.exp(-math.pi/2)*math.sin(-math.pi/2)**sin_pwr + + if spec is None : + print tau, inv_tau, zero_offset, max_value + + # Generate LUT + #last_value = None + +# t = np.arange(0,lut_size) +# out = [] +# out_fixed = [] + exp_list = [] + for i in range(0,lut_size): # the sign needs to be checked and has to be consistent with the dt used in the synapse + + # Multiply by time constant and calculate negative exponential + value = float(i) * inv_tau + # we want a single bump only, so we clip the arg at pi/2 +# if (value) < 0:# math.pi*2: +# exp_float = 0.0 +# print "clamp @ value = ", value +# else: + exp_float = math.exp(-value) * math.sin(value)**sin_pwr / 0.213122689799 #max_value + + # Convert to fixed-point and write to spec + exp_fix = float_to_fixed(exp_float, fixed_point_one) + exp_list.append(exp_float) + + if spec is None : + #out.append(exp_float) + if i == time_probe: + print "dt = ", time_probe, "weight update = ", exp_float, "fixed = ", exp_fix + else : + spec.write_value(data=exp_fix, data_type=DataType.INT16) + + + +# if spec is None : +# plt.plot(t,out) +# plt.show() diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/__init__.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/__init__.py index de659e9b9b6..2e53cc8b8fa 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/__init__.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/__init__.py @@ -7,10 +7,11 @@ import TimingDependenceSpikeNearestPair from .timing_dependence_vogels_2011 import TimingDependenceVogels2011 from .timing_dependence_pfpc import TimingDependencePFPC +from .timing_dependence_mfvn import TimingDependenceMFVN __all__ = [ "AbstractTimingDependence", "TimingDependenceSpikePair", "TimingDependencePfisterSpikeTriplet", "TimingDependenceRecurrent", "TimingDependenceSpikeNearestPair", "TimingDependenceVogels2011", - "TimingDependencePFPC" -] + "TimingDependencePFPC", "TimingDependenceMFVN" + ] diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py new file mode 100644 index 00000000000..847f9378aa3 --- /dev/null +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py @@ -0,0 +1,93 @@ +from spinn_utilities.overrides import overrides +from spynnaker.pyNN.models.neuron.plasticity.stdp.common \ + import plasticity_helpers +from .abstract_timing_dependence import AbstractTimingDependence +from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure\ + import SynapseStructureWeightOnly + + +import logging +logger = logging.getLogger(__name__) + +LUT_SIZE = 256 + +class TimingDependencePFPC(AbstractTimingDependence): + __slots__ = [ + "_synapse_structure", + "_tau_minus", + "_tau_minus_last_entry", + "_tau_plus", + "_tau_plus_last_entry"] + + def __init__(self, tau_plus=20.0, tau_minus=20.0): + self._tau_plus = tau_plus + self._tau_minus = tau_minus + + self._synapse_structure = SynapseStructureWeightOnly() + + # provenance data + self._tau_plus_last_entry = None + self._tau_minus_last_entry = None + + @property + def tau_plus(self): + return self._tau_plus + + @property + def tau_minus(self): + return self._tau_minus + + @overrides(AbstractTimingDependence.is_same_as) + def is_same_as(self, timing_dependence): + if not isinstance(timing_dependence, TimingDependencePFPC): + return False + return (self.tau_plus == timing_dependence.tau_plus and + self.tau_minus == timing_dependence.tau_minus) + + @property + def vertex_executable_suffix(self): + return "pfpc" + + @property + def pre_trace_n_bytes(self): + + # Here we will record the last 16 spikes, these will be 32-bit quantities, + return (16 * 4) + (2 * 16) # 16 4-byte entries, plus one counter for the number of spikes + + @overrides(AbstractTimingDependence.get_parameters_sdram_usage_in_bytes) + def get_parameters_sdram_usage_in_bytes(self): + return 2 * LUT_SIZE #in bytes: 256 * 16 bit values + + @property + def n_weight_terms(self): + return 1 + + @overrides(AbstractTimingDependence.write_parameters) + def write_parameters(self, spec, machine_time_step, weight_scales): + # Check timestep is valid + if machine_time_step != 1000: + raise NotImplementedError( + "exp_sin LUT generation currently only supports 1ms timesteps") + + # Write exp_sin lookup table + self._tau_plus_last_entry = plasticity_helpers.write_pfpc_lut(spec, + time_constant=20, time_probe=None, lut_size=LUT_SIZE, shift=0) + + @property + def synaptic_structure(self): + return self._synapse_structure + + @overrides(AbstractTimingDependence.get_provenance_data) + def get_provenance_data(self, pre_population_label, post_population_label): + prov_data = list() + prov_data.append(plasticity_helpers.get_lut_provenance( + pre_population_label, post_population_label, "PFPCRule", + "tau_plus_last_entry", "tau_plus", self._tau_plus_last_entry)) + prov_data.append(plasticity_helpers.get_lut_provenance( + pre_population_label, post_population_label, "PFPCRule", + "tau_minus_last_entry", "tau_minus", self._tau_minus_last_entry)) + return prov_data + + @overrides(AbstractTimingDependence.get_parameter_names) + def get_parameter_names(self): + return ['tau_plus', 'tau_minus'] diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index 847f9378aa3..f0c4902d9c4 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -11,7 +11,7 @@ LUT_SIZE = 256 -class TimingDependencePFPC(AbstractTimingDependence): +class TimingDependenceMFVN(AbstractTimingDependence): __slots__ = [ "_synapse_structure", "_tau_minus", @@ -39,14 +39,14 @@ def tau_minus(self): @overrides(AbstractTimingDependence.is_same_as) def is_same_as(self, timing_dependence): - if not isinstance(timing_dependence, TimingDependencePFPC): + if not isinstance(timing_dependence, TimingDependenceMFVN): return False return (self.tau_plus == timing_dependence.tau_plus and self.tau_minus == timing_dependence.tau_minus) @property def vertex_executable_suffix(self): - return "pfpc" + return "mfvn" @property def pre_trace_n_bytes(self): @@ -70,7 +70,7 @@ def write_parameters(self, spec, machine_time_step, weight_scales): "exp_sin LUT generation currently only supports 1ms timesteps") # Write exp_sin lookup table - self._tau_plus_last_entry = plasticity_helpers.write_pfpc_lut(spec, + self._tau_plus_last_entry = plasticity_helpers.write_mfvn_lut(spec, time_constant=20, time_probe=None, lut_size=LUT_SIZE, shift=0) @property @@ -81,10 +81,10 @@ def synaptic_structure(self): def get_provenance_data(self, pre_population_label, post_population_label): prov_data = list() prov_data.append(plasticity_helpers.get_lut_provenance( - pre_population_label, post_population_label, "PFPCRule", + pre_population_label, post_population_label, "MFVNRule", "tau_plus_last_entry", "tau_plus", self._tau_plus_last_entry)) prov_data.append(plasticity_helpers.get_lut_provenance( - pre_population_label, post_population_label, "PFPCRule", + pre_population_label, post_population_label, "MFVNRule", "tau_minus_last_entry", "tau_minus", self._tau_minus_last_entry)) return prov_data diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/__init__.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/__init__.py index d3fad33f19a..f175f73cff3 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/__init__.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/__init__.py @@ -4,7 +4,9 @@ from .weight_dependence_multiplicative import WeightDependenceMultiplicative from .weight_dependence_additive_triplet import WeightDependenceAdditiveTriplet from .weight_dependence_pfpc import WeightDependencePFPC +from .weight_dependence_mfvn import WeightDependenceMFVN __all__ = ["AbstractHasAPlusAMinus", "AbstractWeightDependence", "WeightDependenceAdditive", "WeightDependenceMultiplicative", - "WeightDependenceAdditiveTriplet", "WeightDependencePFPC"] + "WeightDependenceAdditiveTriplet", "WeightDependencePFPC", + "WeightDependenceMFVN"] diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py new file mode 100644 index 00000000000..fb732b3352d --- /dev/null +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py @@ -0,0 +1,77 @@ +from data_specification.enums import DataType +from spinn_utilities.overrides import overrides +from .abstract_has_a_plus_a_minus import AbstractHasAPlusAMinus +from .abstract_weight_dependence import AbstractWeightDependence + + +class WeightDependenceMFVN( + AbstractHasAPlusAMinus, AbstractWeightDependence): + __slots__ = [ + "_w_max", + "_w_min"] + + # noinspection PyPep8Naming + def __init__(self, w_min=0.0, w_max=1.0): + super(WeightDependenceMFVN, self).__init__() + self._w_min = w_min + self._w_max = w_max + + @property + def w_min(self): + return self._w_min + + @property + def w_max(self): + return self._w_max + + @overrides(AbstractWeightDependence.is_same_as) + def is_same_as(self, weight_dependence): + if not isinstance(weight_dependence, WeightDependenceMFVN): + return False + return ( + (self._w_min == weight_dependence.w_min) and + (self._w_max == weight_dependence.w_max) and + (self._a_plus == weight_dependence.A_plus) and + (self._a_minus == weight_dependence.A_minus)) + + @property + def vertex_executable_suffix(self): + return "mfvn" + + @overrides(AbstractWeightDependence.get_parameters_sdram_usage_in_bytes) + def get_parameters_sdram_usage_in_bytes( + self, n_synapse_types, n_weight_terms): + if n_weight_terms != 1: + raise NotImplementedError( + "MFVN weight dependence only supports one term") + return (4 * 4) * n_synapse_types + + @overrides(AbstractWeightDependence.write_parameters) + def write_parameters( + self, spec, machine_time_step, weight_scales, n_weight_terms): + # Loop through each synapse type's weight scale + for w in weight_scales: + + # Scale the weights + spec.write_value( + data=int(round(self._w_min * w)), data_type=DataType.INT32) + spec.write_value( + data=int(round(self._w_max * w)), data_type=DataType.INT32) + + # Based on http://data.andrewdavison.info/docs/PyNN/_modules/pyNN + # /standardmodels/synapses.html + # Pre-multiply A+ and A- by Wmax + spec.write_value( + data=int(round(self._a_plus * w)), + data_type=DataType.INT32) + spec.write_value( + data=int(round(self._a_minus * w)), + data_type=DataType.INT32) + + @property + def weight_maximum(self): + return self._w_max + + @overrides(AbstractWeightDependence.get_parameter_names) + def get_parameter_names(self): + return ['w_min', 'w_max', 'A_plus', 'A_minus'] From 2b88adb3668adec1cf13881a1c9d47d34f65b7e9 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Tue, 11 Dec 2018 09:25:42 +0000 Subject: [PATCH 018/108] Correct naming mismatch --- .../stdp/timing_dependence/timing_dependence_mfvn.py | 12 ++++++------ .../stdp/timing_dependence/timing_dependence_pfpc.py | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py index 847f9378aa3..f0c4902d9c4 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py @@ -11,7 +11,7 @@ LUT_SIZE = 256 -class TimingDependencePFPC(AbstractTimingDependence): +class TimingDependenceMFVN(AbstractTimingDependence): __slots__ = [ "_synapse_structure", "_tau_minus", @@ -39,14 +39,14 @@ def tau_minus(self): @overrides(AbstractTimingDependence.is_same_as) def is_same_as(self, timing_dependence): - if not isinstance(timing_dependence, TimingDependencePFPC): + if not isinstance(timing_dependence, TimingDependenceMFVN): return False return (self.tau_plus == timing_dependence.tau_plus and self.tau_minus == timing_dependence.tau_minus) @property def vertex_executable_suffix(self): - return "pfpc" + return "mfvn" @property def pre_trace_n_bytes(self): @@ -70,7 +70,7 @@ def write_parameters(self, spec, machine_time_step, weight_scales): "exp_sin LUT generation currently only supports 1ms timesteps") # Write exp_sin lookup table - self._tau_plus_last_entry = plasticity_helpers.write_pfpc_lut(spec, + self._tau_plus_last_entry = plasticity_helpers.write_mfvn_lut(spec, time_constant=20, time_probe=None, lut_size=LUT_SIZE, shift=0) @property @@ -81,10 +81,10 @@ def synaptic_structure(self): def get_provenance_data(self, pre_population_label, post_population_label): prov_data = list() prov_data.append(plasticity_helpers.get_lut_provenance( - pre_population_label, post_population_label, "PFPCRule", + pre_population_label, post_population_label, "MFVNRule", "tau_plus_last_entry", "tau_plus", self._tau_plus_last_entry)) prov_data.append(plasticity_helpers.get_lut_provenance( - pre_population_label, post_population_label, "PFPCRule", + pre_population_label, post_population_label, "MFVNRule", "tau_minus_last_entry", "tau_minus", self._tau_minus_last_entry)) return prov_data diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index f0c4902d9c4..847f9378aa3 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -11,7 +11,7 @@ LUT_SIZE = 256 -class TimingDependenceMFVN(AbstractTimingDependence): +class TimingDependencePFPC(AbstractTimingDependence): __slots__ = [ "_synapse_structure", "_tau_minus", @@ -39,14 +39,14 @@ def tau_minus(self): @overrides(AbstractTimingDependence.is_same_as) def is_same_as(self, timing_dependence): - if not isinstance(timing_dependence, TimingDependenceMFVN): + if not isinstance(timing_dependence, TimingDependencePFPC): return False return (self.tau_plus == timing_dependence.tau_plus and self.tau_minus == timing_dependence.tau_minus) @property def vertex_executable_suffix(self): - return "mfvn" + return "pfpc" @property def pre_trace_n_bytes(self): @@ -70,7 +70,7 @@ def write_parameters(self, spec, machine_time_step, weight_scales): "exp_sin LUT generation currently only supports 1ms timesteps") # Write exp_sin lookup table - self._tau_plus_last_entry = plasticity_helpers.write_mfvn_lut(spec, + self._tau_plus_last_entry = plasticity_helpers.write_pfpc_lut(spec, time_constant=20, time_probe=None, lut_size=LUT_SIZE, shift=0) @property @@ -81,10 +81,10 @@ def synaptic_structure(self): def get_provenance_data(self, pre_population_label, post_population_label): prov_data = list() prov_data.append(plasticity_helpers.get_lut_provenance( - pre_population_label, post_population_label, "MFVNRule", + pre_population_label, post_population_label, "PFPCRule", "tau_plus_last_entry", "tau_plus", self._tau_plus_last_entry)) prov_data.append(plasticity_helpers.get_lut_provenance( - pre_population_label, post_population_label, "MFVNRule", + pre_population_label, post_population_label, "PFPCRule", "tau_minus_last_entry", "tau_minus", self._tau_minus_last_entry)) return prov_data From 4ad42075712eec6904207b52a6099ec8b64433ea Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Tue, 11 Dec 2018 10:44:55 +0000 Subject: [PATCH 019/108] Tidy PFPC LUT generation --- .../stdp/common/plasticity_helpers.py | 79 +++++++++---------- .../timing_dependence_pfpc.py | 2 +- 2 files changed, 38 insertions(+), 43 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py index c8ad49b2147..61e09002dda 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py @@ -57,66 +57,61 @@ def get_lut_provenance( param_name, rule_name, pre_population_label, post_population_label, last_entry))) -def write_pfpc_lut(spec, time_constant, lut_size, shift, time_probe, +def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, fixed_point_one=STDP_FIXED_POINT_ONE): - peak_time = 100.0 - tau = peak_time * 2/math.pi; - machine_time_step = 1.0 - # This offset is the quasi-symmetry point + # Add this to function arguments in the future + machine_time_step = 1.0 sin_pwr = 20 -# Write peak time in timesteps - peak_time_data = int(peak_time * (1000.0 / machine_time_step) - lut_size/2 + 0.5) - #print "peak time data:", peak_time_data, "peak_time:", peak_time - -# if spec is not None: -# spec.write_value(data=peak_time_data, -# data_type=DataType.INT32) - - # Calculate 1/tau in machine time steps - inv_tau = (1.0 / float(tau)) #* (machine_time_step / 1000.0) + # Calculate required time constant + time_constant = 1/(math.atan(sin_pwr)/peak_time) + inv_tau = (1.0 / float(time_constant)) #* (machine_time_step / 1000.0) - zero_offset = math.atan(-1./sin_pwr) # abscissae of the max point obtained by deriving the kernel and equal to zero - max_value = math.exp(-math.pi/2)*math.sin(-math.pi/2)**sin_pwr +# # caluclate time of peak (from differentiating kernel and setting to zero) +# kernel_peak_time = math.atan(20) / inv_tau - if spec is None : - print tau, inv_tau, zero_offset, max_value + # evaluate peak value of kernel to normalise LUT + kernel_peak_value = (math.exp(-peak_time*inv_tau) * + math.sin(peak_time*inv_tau)**sin_pwr) # Generate LUT - #last_value = None + out_float = [] + out_fixed = [] -# t = np.arange(0,lut_size) -# out = [] -# out_fixed = [] - exp_list = [] - for i in range(0,lut_size): # the sign needs to be checked and has to be consistent with the dt used in the synapse + for i in range(0,lut_size): # note that i corresponds to 1 timestep!!!!!! - # Multiply by time constant and calculate negative exponential + # Multiply by inverse of time constant value = float(i) * inv_tau - # we want a single bump only, so we clip the arg at pi/2 -# if (value) < 0:# math.pi*2: -# exp_float = 0.0 -# print "clamp @ value = ", value -# else: - exp_float = math.exp(-value) * math.sin(value)**sin_pwr / 0.213122689799 #max_value - # Convert to fixed-point and write to spec + # Only take first peak from kernel + if (value > math.pi): + exp_float = 0 + else: + # Evaluate kernel + exp_float = math.exp(-value) * math.sin(value)**sin_pwr / kernel_peak_value + + # Convert to fixed-point exp_fix = float_to_fixed(exp_float, fixed_point_one) - exp_list.append(exp_float) - if spec is None : - #out.append(exp_float) + if spec is None: # in testing mode so print + out_float.append(exp_float) + out_fixed.append(exp_fix) if i == time_probe: - print "dt = ", time_probe, "weight update = ", exp_float, "fixed = ", exp_fix - else : - spec.write_value(data=exp_fix, data_type=DataType.INT16) + print "dt = {}, kernel value = {} (fixed-point = {})".format( + time_probe, exp_float, exp_fix) + else: # at runtime, so write to spec + spec.write_value(data=exp_fix, data_type=DataType.INT16) + if spec is None: + print "peak: time {}, value {}".format(peak_time, kernel_peak_value) + t = np.arange(0,lut_size) + plt.plot(t,out_float, label='float') + # plt.plot(t,out_fixed, label='fixed') + plt.legend() + plt.show() -# if spec is None : -# plt.plot(t,out) -# plt.show() def write_mfvn_lut(spec, time_constant, lut_size, shift, time_probe, fixed_point_one=STDP_FIXED_POINT_ONE): diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index 847f9378aa3..148479476c8 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -71,7 +71,7 @@ def write_parameters(self, spec, machine_time_step, weight_scales): # Write exp_sin lookup table self._tau_plus_last_entry = plasticity_helpers.write_pfpc_lut(spec, - time_constant=20, time_probe=None, lut_size=LUT_SIZE, shift=0) + peak_time=100, time_probe=None, lut_size=LUT_SIZE, shift=0) @property def synaptic_structure(self): From f31196e9df6040c49d3fe31155126c93d6c40fae Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Tue, 11 Dec 2018 11:42:05 +0000 Subject: [PATCH 020/108] Add MFVN LUT generation and configuration code --- .../stdp/common/plasticity_helpers.py | 85 +++++++++---------- 1 file changed, 38 insertions(+), 47 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py index 61e09002dda..3e734b707c3 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py @@ -113,64 +113,55 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, plt.show() -def write_mfvn_lut(spec, time_constant, lut_size, shift, time_probe, +def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, fixed_point_one=STDP_FIXED_POINT_ONE): - peak_time = 100.0 - tau = peak_time * 2/math.pi; - machine_time_step = 1.0 - - # This offset is the quasi-symmetry point - sin_pwr = 20 -# Write peak time in timesteps - peak_time_data = int(peak_time * (1000.0 / machine_time_step) - lut_size/2 + 0.5) - #print "peak time data:", peak_time_data, "peak_time:", peak_time + # Add this to function arguments in the future + machine_time_step = 1.0 + cos_pwr = 2 -# if spec is not None: -# spec.write_value(data=peak_time_data, -# data_type=DataType.INT32) + # Calculate required time constant + inv_sigma = (1.0 / float(sigma)) #* (machine_time_step / 1000.0) + peak_time = 0 - # Calculate 1/tau in machine time steps - inv_tau = (1.0 / float(tau)) #* (machine_time_step / 1000.0) + # evaluate peak value of kernel to normalise LUT + kernel_peak_value = (math.exp(-abs(peak_time * inv_sigma * beta)) * + math.cos(peak_time*inv_sigma)**cos_pwr) - zero_offset = math.atan(-1./sin_pwr) # abscissae of the max point obtained by deriving the kernel and equal to zero - max_value = math.exp(-math.pi/2)*math.sin(-math.pi/2)**sin_pwr + # Generate LUT + out_float = [] + out_fixed = [] + plot_times = [] - if spec is None : - print tau, inv_tau, zero_offset, max_value + for i in range(0, lut_size): # note that i corresponds to 1 timestep!!!!!! - # Generate LUT - #last_value = None + # Multiply by inverse of time constant + value = float(i) * inv_sigma -# t = np.arange(0,lut_size) -# out = [] -# out_fixed = [] - exp_list = [] - for i in range(0,lut_size): # the sign needs to be checked and has to be consistent with the dt used in the synapse + # Only take first peak from kernel + if (value > math.pi/2): + exp_float = 0 + else: + # Evaluate kernel + exp_float = math.exp(-abs(value * beta)) * math.cos(value)**cos_pwr / kernel_peak_value - # Multiply by time constant and calculate negative exponential - value = float(i) * inv_tau - # we want a single bump only, so we clip the arg at pi/2 -# if (value) < 0:# math.pi*2: -# exp_float = 0.0 -# print "clamp @ value = ", value -# else: - exp_float = math.exp(-value) * math.sin(value)**sin_pwr / 0.213122689799 #max_value - - # Convert to fixed-point and write to spec + # Convert to fixed-point exp_fix = float_to_fixed(exp_float, fixed_point_one) - exp_list.append(exp_float) - if spec is None : - #out.append(exp_float) + if spec is None: # in testing mode so print + out_float.append(exp_float) + out_fixed.append(exp_fix) + plot_times.append(i) if i == time_probe: - print "dt = ", time_probe, "weight update = ", exp_float, "fixed = ", exp_fix - else : - spec.write_value(data=exp_fix, data_type=DataType.INT16) - - + print "dt = {}, kernel value = {} (fixed-point = {})".format( + time_probe, exp_float, exp_fix) -# if spec is None : -# plt.plot(t,out) -# plt.show() + else: # at runtime, so write to spec + spec.write_value(data=exp_fix, data_type=DataType.INT16) + if spec is None: + print "peak: time {}, value {}".format(peak_time, kernel_peak_value) + plt.plot(plot_times,out_float, label='float') + # plt.plot(t,out_fixed, label='fixed') + plt.legend() + plt.show() From 56d0318a0d0770747fcda7494520f7c14f133ba3 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Tue, 11 Dec 2018 15:58:32 +0000 Subject: [PATCH 021/108] Add mossy fibre plasticity --- .../synapse_dynamics_stdp_mad_mfvn_impl.c | 55 ++++++++---------- .../synapse_dynamics_stdp_mad_pfpc_impl.c | 17 +++--- .../stdp/timing_dependence/timing_mfvn_impl.c | 6 +- .../stdp/timing_dependence/timing_mfvn_impl.h | 57 ++++--------------- .../stdp/timing_dependence/timing_pfpc_impl.h | 17 ++---- .../stdp/weight_dependence/weight_pfpc_impl.h | 6 +- 6 files changed, 55 insertions(+), 103 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c index 3d8133dc9f7..c27a08333d7 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c @@ -60,12 +60,12 @@ uint32_t plastic_saturation_count = 0; // uint32_t prev_time; //} pre_event_history_t; -#define NUM_PF_SPIKES_TO_RECORD 16 +#define NUM_MF_SPIKES_TO_RECORD 16 typedef struct { - uint32_t num_recorded_pf_spikes_minus_one; - uint32_t pf_times[NUM_PF_SPIKES_TO_RECORD]; - post_trace_t traces[NUM_PF_SPIKES_TO_RECORD]; + uint32_t num_recorded_mf_spikes_minus_one; + uint32_t mf_times[NUM_MF_SPIKES_TO_RECORD]; + post_trace_t traces[NUM_MF_SPIKES_TO_RECORD]; } pre_event_history_t; @@ -73,17 +73,15 @@ typedef struct { _print_pre_event_history(pre_event_history_t pre_eve_hist){ io_printf(IO_BUF, "\n\n************************\n\n"); - io_printf(IO_BUF, "Number recorded spikes: %u\n", pre_eve_hist.num_recorded_pf_spikes_minus_one); + io_printf(IO_BUF, "Number recorded MF spikes: %u\n", pre_eve_hist.num_recorded_mf_spikes_minus_one); io_printf(IO_BUF, "Prev time: %u\n", - pre_eve_hist.pf_times[pre_eve_hist.num_recorded_pf_spikes_minus_one]); + pre_eve_hist.mf_times[pre_eve_hist.num_recorded_mf_spikes_minus_one]); - for (int i =0; i < NUM_PF_SPIKES_TO_RECORD; i ++){ - io_printf(IO_BUF, " Entry %u: %u\n", i ,pre_eve_hist.pf_times[i]); + for (int i =0; i < NUM_MF_SPIKES_TO_RECORD; i ++){ + io_printf(IO_BUF, " Entry %u: %u\n", i ,pre_eve_hist.mf_times[i]); } - } - post_event_history_t *post_event_history; //--------------------------------------- @@ -114,13 +112,13 @@ static inline final_state_t _plasticity_update_synapse( post_window.num_events); - io_printf(IO_BUF, " Printing CF history\n"); + io_printf(IO_BUF, " Printing PC history\n"); print_event_history(post_event_history); // print_delayed_window_events(post_event_history, window_begin_time, // window_end_time, delay_dendritic); - io_printf(IO_BUF, "\n Looping over climbing fibre spikes:\n"); + io_printf(IO_BUF, "\n Looping over PC spikes:\n"); delay_dendritic = 0; @@ -129,28 +127,28 @@ static inline final_state_t _plasticity_update_synapse( const uint32_t delayed_post_time = *post_window.next_time + delay_dendritic; - uint32_t pf_begin_time = (delayed_post_time < 255) ? 0 : (delayed_post_time - 255); + uint32_t mf_begin_time = (delayed_post_time < 255) ? 0 : (delayed_post_time - 255); - io_printf(IO_BUF, " Applying post-synaptic event at delayed time:%u\n", + io_printf(IO_BUF, " Applying post-synaptic event at delayed time:%u\n", delayed_post_time); -// // Get window of pf events based on cf spikes -// print_delayed_window_events(pre_event_history, -// //(delayed_post_time-255) -// pf_begin_time, delayed_post_time, delay_dendritic); post_event_window_t pre_window = post_events_get_window_delayed( - pre_event_history, pf_begin_time, delayed_post_time); + pre_event_history, mf_begin_time, delayed_post_time); - io_printf(IO_BUF, " Looping over PF window\n", + io_printf(IO_BUF, " Looping over MF window for this PC spike\n", delayed_post_time); while (pre_window.num_events > 0) { + const uint32_t delayed_pre_time = *pre_window.next_time + delay_dendritic; + io_printf(IO_BUF, " MF Spike: %u \n", delayed_pre_time); - io_printf(IO_BUF, " delta t = %u\n", delayed_post_time - delayed_pre_time); - + io_printf(IO_BUF, " delta t = %u (delayed MF = %u, delayed PC = %u)\n", + delayed_post_time - delayed_pre_time, + delayed_pre_time, + delayed_post_time); current_state = timing_apply_post_spike( delayed_post_time, *post_window.next_trace, @@ -158,14 +156,9 @@ static inline final_state_t _plasticity_update_synapse( last_pre_trace, post_window.prev_time, post_window.prev_trace, current_state); - - pre_window = post_events_next_delayed(pre_window, delayed_pre_time); - } -// // Apply spike to state - // Go onto next event post_window = post_events_next_delayed(post_window, delayed_post_time); @@ -323,7 +316,8 @@ bool synapse_dynamics_process_plastic_synapses( plastic_region_address); // Get last pre-synaptic event from event history - const uint32_t last_pre_time = event_history->pf_times[event_history->num_recorded_pf_spikes_minus_one]; + const uint32_t last_pre_time = + event_history->mf_times[event_history->num_recorded_mf_spikes_minus_one]; // no longer need to manage this trace const pre_trace_t last_pre_trace = 0; @@ -335,7 +329,8 @@ bool synapse_dynamics_process_plastic_synapses( // Update pre-synaptic trace - io_printf(IO_BUF, "\nAdding pre-synaptic event (parallel fibre spike) at time: %u\n\n", time); + io_printf(IO_BUF, + "\nAdding pre-synaptic event (mossy fibre spike) at time: %u\n\n", time); timing_add_pre_spike(time, last_pre_time, last_pre_trace); @@ -401,7 +396,7 @@ bool synapse_dynamics_process_plastic_synapses( void synapse_dynamics_process_post_synaptic_event( uint32_t time, index_t neuron_index) { - log_debug("Adding post-synaptic event to trace at time:%u", time); + log_debug("Adding post-synaptic event (PC spike)to history at time:%u", time); // Add post-event post_event_history_t *history = &post_event_history[neuron_index]; diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c index 3d8133dc9f7..66a77aeabca 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c @@ -132,7 +132,7 @@ static inline final_state_t _plasticity_update_synapse( uint32_t pf_begin_time = (delayed_post_time < 255) ? 0 : (delayed_post_time - 255); - io_printf(IO_BUF, " Applying post-synaptic event at delayed time:%u\n", + io_printf(IO_BUF, " Applying post-synaptic event at delayed time:%u\n", delayed_post_time); // // Get window of pf events based on cf spikes @@ -143,14 +143,18 @@ static inline final_state_t _plasticity_update_synapse( pre_event_history, pf_begin_time, delayed_post_time); - io_printf(IO_BUF, " Looping over PF window\n", + io_printf(IO_BUF, " Looping over PF window for this CF spike\n", delayed_post_time); while (pre_window.num_events > 0) { + const uint32_t delayed_pre_time = *pre_window.next_time + delay_dendritic; + io_printf(IO_BUF, " PF Spike: %u \n", delayed_pre_time); - io_printf(IO_BUF, " delta t = %u\n", delayed_post_time - delayed_pre_time); - + io_printf(IO_BUF, " delta t = %u (delayed PF = %u, delayed CF = %u)\n", + delayed_post_time - delayed_pre_time, + delayed_pre_time, + delayed_post_time); current_state = timing_apply_post_spike( delayed_post_time, *post_window.next_trace, @@ -158,14 +162,9 @@ static inline final_state_t _plasticity_update_synapse( last_pre_trace, post_window.prev_time, post_window.prev_trace, current_state); - - pre_window = post_events_next_delayed(pre_window, delayed_pre_time); - } -// // Apply spike to state - // Go onto next event post_window = post_events_next_delayed(post_window, delayed_post_time); diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c index 8be64f6f176..611559ccd10 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c @@ -4,7 +4,7 @@ // Globals //--------------------------------------- // Exponential lookup-tables -int16_t exp_sin_lookup[EXP_SIN_LUT_SIZE]; +int16_t exp_cos_lookup[EXP_COS_LUT_SIZE]; //--------------------------------------- // Functions @@ -16,8 +16,8 @@ address_t timing_initialise(address_t address) { // **TODO** assert number of neurons is less than max // Copy LUTs from following memory - address_t lut_address = maths_copy_int16_lut(&address[0], EXP_SIN_LUT_SIZE, - &exp_sin_lookup[0]); + address_t lut_address = maths_copy_int16_lut(&address[0], EXP_COS_LUT_SIZE, + &exp_cos_lookup[0]); io_printf(IO_BUF, "Timing_mfvn_initialise: completed successfully\n"); diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h index 302728b852a..3e669abdff5 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h @@ -23,12 +23,12 @@ typedef int16_t pre_trace_t; //--------------------------------------- // Exponential decay lookup parameters #define TAU_PLUS_TIME_SHIFT 0 -#define EXP_SIN_LUT_SIZE 256 +#define EXP_COS_LUT_SIZE 256 // Helper macros for looking up decays -#define EXP_SIN_LOOKUP(time) \ +#define EXP_COS_LOOKUP(time) \ maths_lut_exponential_decay( \ - time, TAU_PLUS_TIME_SHIFT, EXP_SIN_LUT_SIZE, exp_sin_lookup) + time, TAU_PLUS_TIME_SHIFT, EXP_COS_LUT_SIZE, exp_cos_lookup) //#define DECAY_LOOKUP_TAU_MINUS(time) \ // maths_lut_exponential_decay( \ // time, TAU_MINUS_TIME_SHIFT, TAU_MINUS_SIZE, tau_minus_lookup) @@ -36,7 +36,7 @@ typedef int16_t pre_trace_t; //--------------------------------------- // Externals //--------------------------------------- -extern int16_t exp_sin_lookup[EXP_SIN_LUT_SIZE]; +extern int16_t exp_cos_lookup[EXP_COS_LUT_SIZE]; //--------------------------------------- // Timing dependence inline functions @@ -49,7 +49,7 @@ static inline post_trace_t timing_get_initial_post_trace() { static inline post_trace_t timing_add_post_spike( uint32_t time, uint32_t last_time, post_trace_t last_trace) { - io_printf(IO_BUF, "Adding pre spike to event history (from climbing fibre)\n"); + io_printf(IO_BUF, "Adding pre spike to event history (from purkinje cell)\n"); // // Get time since last spike // uint32_t delta_time = time - last_time; @@ -91,30 +91,6 @@ static inline update_state_t timing_apply_pre_spike( return weight_one_term_apply_potentiation(previous_state, 0); - - -// -// // Get time of event relative to last post-synaptic event -// uint32_t time_since_last_post = time - last_post_time; -// if (time_since_last_post > 0) { -// int32_t decayed_o1 = STDP_FIXED_MUL_16X16( -// last_post_trace, DECAY_LOOKUP_TAU_MINUS(time_since_last_post)); -// -// log_debug("\t\t\ttime_since_last_post_event=%u, decayed_o1=%d\n", -// time_since_last_post, decayed_o1); -// -// // Apply depression to state (which is a weight_state) -// return weight_one_term_apply_depression(previous_state, decayed_o1); -// -// -// -// -// -// -// -// } else { -// return previous_state; -// } } //--------------------------------------- @@ -128,9 +104,7 @@ static inline update_state_t timing_apply_post_spike( -// // This is where we lookup the value of e^(-x) * sin(x)^20 -// -// +// // This is where we lookup the value of e^(-bx) * cos(x)^2 @@ -142,7 +116,7 @@ static inline update_state_t timing_apply_post_spike( if (time_since_last_pre < 255){ - uint32_t multiplier = EXP_SIN_LOOKUP(time_since_last_pre); + uint32_t multiplier = EXP_COS_LOOKUP(time_since_last_pre); io_printf(IO_BUF, "multiplier: %k (fixed = %u)\n", multiplier << 4, multiplier); @@ -150,22 +124,11 @@ static inline update_state_t timing_apply_post_spike( } -// - io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); + + io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); io_printf(IO_BUF, " out of LUT range - do nothing"); -// if (time_since_last_pre > 0) { -// int32_t decayed_r1 = STDP_FIXED_MUL_16X16( -// last_pre_trace, DECAY_LOOKUP_TAU_PLUS(time_since_last_pre)); -// -// log_debug("\t\t\ttime_since_last_pre_event=%u, decayed_r1=%d\n", -// time_since_last_pre, decayed_r1); -// -// // Apply potentiation to state (which is a weight_state) -// return weight_one_term_apply_potentiation(previous_state, decayed_r1); -// } else { - return previous_state; - //} + return previous_state; } #endif // _TIMING_MFVN_IMPL_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index d9ca591d00e..7b4a7a766a2 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -49,7 +49,7 @@ static inline post_trace_t timing_get_initial_post_trace() { static inline post_trace_t timing_add_post_spike( uint32_t time, uint32_t last_time, post_trace_t last_trace) { - io_printf(IO_BUF, "Adding pre spike to event history (from climbing fibre)\n"); + io_printf(IO_BUF, "Adding climbing fibre spike to post-event history (stored on neuron\n"); // // Get time since last spike // uint32_t delta_time = time - last_time; @@ -128,16 +128,11 @@ static inline update_state_t timing_apply_post_spike( -// // This is where we lookup the value of e^(-x) * sin(x)^20 -// -// - + // This is where we lookup the value of e^(-x) * sin(x)^20 - -// -// // Get time of event relative to last pre-synaptic event + // Get time of event relative to last pre-synaptic event uint32_t time_since_last_pre = last_pre_time; //time - last_pre_time; - io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); + io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); if (time_since_last_pre < 255){ @@ -151,8 +146,8 @@ static inline update_state_t timing_apply_post_spike( } // - io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); - io_printf(IO_BUF, " out of LUT range - do nothing"); + io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); + io_printf(IO_BUF, " out of LUT range (do nothing)"); // if (time_since_last_pre > 0) { // int32_t decayed_r1 = STDP_FIXED_MUL_16X16( diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h index 97f7c1c71ef..00b5d3a7ca6 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h @@ -54,8 +54,8 @@ static inline weight_state_t weight_get_initial(weight_t weight, static inline weight_state_t weight_one_term_apply_depression( weight_state_t state, int32_t depression_multiplier) { - io_printf(IO_BUF, "\n Do Depression\n"); - io_printf(IO_BUF, " Weight prior to depression: %u\n",state.weight); + io_printf(IO_BUF, "\n Do Depression\n"); + io_printf(IO_BUF, " Weight prior to depression: %u\n",state.weight); // Calculate scale // **NOTE** this calculation must be done at runtime-defined weight @@ -70,7 +70,7 @@ static inline weight_state_t weight_one_term_apply_depression( // **NOTE** using standard STDP fixed-point format handles format conversion state.weight -= STDP_FIXED_MUL_16X16(state.weight, depression_multiplier); - io_printf(IO_BUF, " Weight after depression: %u\n\n",state.weight); + io_printf(IO_BUF, " Weight after depression: %u\n\n",state.weight); return state; } From d02781df66e75ab0d4a20758a70d088fc049102d Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Wed, 12 Dec 2018 10:28:46 +0000 Subject: [PATCH 022/108] Add forward processing of mfvn spikes --- .../synapse_dynamics_stdp_mad_mfvn_impl.c | 44 ++++++++++++++++--- .../stdp/timing_dependence/timing_mfvn_impl.h | 3 +- .../stdp/weight_dependence/weight_mfvn_impl.h | 13 ++++-- .../timing_dependence_mfvn.py | 2 +- 4 files changed, 51 insertions(+), 11 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c index c27a08333d7..c57c20c77a1 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c @@ -117,7 +117,7 @@ static inline final_state_t _plasticity_update_synapse( // print_delayed_window_events(post_event_history, window_begin_time, // window_end_time, delay_dendritic); - + io_printf(IO_BUF, "\n############ Phase 1 #############\n"); io_printf(IO_BUF, "\n Looping over PC spikes:\n"); delay_dendritic = 0; @@ -130,15 +130,13 @@ static inline final_state_t _plasticity_update_synapse( uint32_t mf_begin_time = (delayed_post_time < 255) ? 0 : (delayed_post_time - 255); - io_printf(IO_BUF, " Applying post-synaptic event at delayed time:%u\n", - delayed_post_time); - post_event_window_t pre_window = post_events_get_window_delayed( pre_event_history, mf_begin_time, delayed_post_time); - io_printf(IO_BUF, " Looping over MF window for this PC spike\n", + io_printf(IO_BUF, " Looping over MF window for this PC spike: %u \n", delayed_post_time); + while (pre_window.num_events > 0) { const uint32_t delayed_pre_time = *pre_window.next_time @@ -160,10 +158,42 @@ static inline final_state_t _plasticity_update_synapse( } + // Go onto next event post_window = post_events_next_delayed(post_window, delayed_post_time); } + // ************** + // Now look forward to current MF spike from each PC spike. + const uint32_t fwd_window_begin_time = ((time-delay_dendritic) < 255) ? + 0 : ((time-delay_dendritic) - 255); + + post_event_window_t fwd_post_window = post_events_get_window_delayed( + post_event_history, fwd_window_begin_time, window_end_time); + + io_printf(IO_BUF, "\n############ Phase 2 #############\n"); + io_printf(IO_BUF, + " Looping over all PC spikes and comparing to latest MF spike at: %u\n", + time+delay_dendritic); + + while (fwd_post_window.num_events > 0) { + const uint32_t delayed_mf_time = *fwd_post_window.next_time + delay_dendritic; + io_printf(IO_BUF, " PC spike: %u, dt: %u\n", + delayed_mf_time, + (time+delay_dendritic - delayed_mf_time) + ); + + current_state = timing_apply_post_spike( + delayed_mf_time, *fwd_post_window.next_trace, + (time+delay_dendritic - delayed_mf_time), + last_pre_trace, fwd_post_window.prev_time, fwd_post_window.prev_trace, // these variables aren't used + current_state); + + fwd_post_window = post_events_next_delayed(fwd_post_window, delayed_mf_time); + } + + // ************** + const uint32_t delayed_pre_time = time + delay_axonal; log_debug("\t\tApplying pre-synaptic event at time:%u last post time:%u\n", delayed_pre_time, post_window.prev_time); @@ -300,6 +330,8 @@ bool synapse_dynamics_process_plastic_synapses( address_t plastic_region_address, address_t fixed_region_address, weight_t *ring_buffers, uint32_t time) { + io_printf(IO_BUF, "\n############ New Plasticity Update #############\n"); + // Extract separate arrays of plastic synapses (from plastic region), // Control words (from fixed region) and number of plastic synapses plastic_synapse_t *plastic_words = _plastic_synapses( @@ -391,6 +423,8 @@ bool synapse_dynamics_process_plastic_synapses( *plastic_words++ = synapse_structure_get_final_synaptic_word( final_state); } + + io_printf(IO_BUF, "\n############ Completed Plasticity Update #############\n"); return true; } diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h index 3e669abdff5..d82e99d1556 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h @@ -87,7 +87,8 @@ static inline update_state_t timing_apply_pre_spike( use(&last_pre_trace); // Here we will potentiate by the fixed amount alpha - io_printf(IO_BUF, " This is where we'll do potentiation\n"); + io_printf(IO_BUF, "\n############ Phase 3 #############"); + io_printf(IO_BUF, "\n Now do potentiation\n"); return weight_one_term_apply_potentiation(previous_state, 0); diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h index 2e34f044c68..d6bc070d8da 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h @@ -54,8 +54,8 @@ static inline weight_state_t weight_get_initial(weight_t weight, static inline weight_state_t weight_one_term_apply_depression( weight_state_t state, int32_t depression_multiplier) { - io_printf(IO_BUF, "\n Do Depression\n"); - io_printf(IO_BUF, " Weight prior to depression: %u\n",state.weight); + io_printf(IO_BUF, "\n Do Depression\n"); + io_printf(IO_BUF, " Weight prior to depression: %u\n",state.weight); // Calculate scale // **NOTE** this calculation must be done at runtime-defined weight @@ -70,7 +70,7 @@ static inline weight_state_t weight_one_term_apply_depression( // **NOTE** using standard STDP fixed-point format handles format conversion state.weight -= STDP_FIXED_MUL_16X16(state.weight, depression_multiplier); - io_printf(IO_BUF, " Weight after depression: %u\n\n",state.weight); + io_printf(IO_BUF, " Weight after depression: %u\n\n",state.weight); return state; } @@ -79,6 +79,10 @@ static inline weight_state_t weight_one_term_apply_potentiation( weight_state_t state, int32_t potentiation) { // add fixed amount + io_printf(IO_BUF, " Adding fixed coontribution: %k (int %u)\n", + state.weight_region->a2_plus << 4, + state.weight_region->a2_plus); + state.a2_plus += state.weight_region->a2_plus; return state; @@ -100,12 +104,13 @@ static inline weight_t weight_get_final(weight_state_t new_state) { int32_t new_weight = new_state.weight + new_state.a2_plus; // - scaled_a2_minus; - io_printf(IO_BUF, " old weight: %u, new weight: %u\n", new_state.weight, new_weight); // Clamp new weight new_weight = MIN(new_state.weight_region->max_weight, new_weight); + io_printf(IO_BUF, " old weight: %u, new weight: %u\n", new_state.weight, new_weight); + new_state.weight = new_weight; return (weight_t) new_state.weight; diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py index f0c4902d9c4..954b4e7aa34 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py @@ -71,7 +71,7 @@ def write_parameters(self, spec, machine_time_step, weight_scales): # Write exp_sin lookup table self._tau_plus_last_entry = plasticity_helpers.write_mfvn_lut(spec, - time_constant=20, time_probe=None, lut_size=LUT_SIZE, shift=0) + sigma=200, beta=10, time_probe=None, lut_size=LUT_SIZE, shift=0) @property def synaptic_structure(self): From 55798ba16a63113fa7a86a53ab70b7716c178c29 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Wed, 12 Dec 2018 11:50:42 +0000 Subject: [PATCH 023/108] Bubble down kernel/plasticity config params --- .../timing_dependence_mfvn.py | 31 +++++++++++++++---- .../timing_dependence_pfpc.py | 19 +++++++++--- .../weight_dependence_mfvn.py | 21 ++++++++----- .../weight_dependence_pfpc.py | 21 ++++++++----- 4 files changed, 68 insertions(+), 24 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py index 954b4e7aa34..e1f73736f61 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py @@ -17,14 +17,20 @@ class TimingDependenceMFVN(AbstractTimingDependence): "_tau_minus", "_tau_minus_last_entry", "_tau_plus", - "_tau_plus_last_entry"] + "_tau_plus_last_entry", + "_beta", + "_sigma" + ] - def __init__(self, tau_plus=20.0, tau_minus=20.0): + def __init__(self, tau_plus=20.0, tau_minus=20.0, beta=10, sigma=200): self._tau_plus = tau_plus self._tau_minus = tau_minus self._synapse_structure = SynapseStructureWeightOnly() + self._beta = beta + self._sigma = sigma + # provenance data self._tau_plus_last_entry = None self._tau_minus_last_entry = None @@ -37,6 +43,14 @@ def tau_plus(self): def tau_minus(self): return self._tau_minus + @property + def beta(self): + return self._beta + + @property + def sigma(self): + return self._sigma + @overrides(AbstractTimingDependence.is_same_as) def is_same_as(self, timing_dependence): if not isinstance(timing_dependence, TimingDependenceMFVN): @@ -67,11 +81,16 @@ def write_parameters(self, spec, machine_time_step, weight_scales): # Check timestep is valid if machine_time_step != 1000: raise NotImplementedError( - "exp_sin LUT generation currently only supports 1ms timesteps") + "exp cos LUT generation currently only supports 1ms timesteps") # Write exp_sin lookup table - self._tau_plus_last_entry = plasticity_helpers.write_mfvn_lut(spec, - sigma=200, beta=10, time_probe=None, lut_size=LUT_SIZE, shift=0) + self._tau_plus_last_entry = plasticity_helpers.write_mfvn_lut( + spec, + sigma=self._sigma, + beta=self._beta, + time_probe=None, + lut_size=LUT_SIZE, + shift=0) @property def synaptic_structure(self): @@ -90,4 +109,4 @@ def get_provenance_data(self, pre_population_label, post_population_label): @overrides(AbstractTimingDependence.get_parameter_names) def get_parameter_names(self): - return ['tau_plus', 'tau_minus'] + return ['tau_plus', 'tau_minus', 'beta', 'sigma'] diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index 148479476c8..8fa2d950189 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -17,11 +17,14 @@ class TimingDependencePFPC(AbstractTimingDependence): "_tau_minus", "_tau_minus_last_entry", "_tau_plus", - "_tau_plus_last_entry"] + "_tau_plus_last_entry", + "_t_peak"] - def __init__(self, tau_plus=20.0, tau_minus=20.0): + def __init__(self, tau_plus=20.0, tau_minus=20.0, + t_peak=100): self._tau_plus = tau_plus self._tau_minus = tau_minus + self._t_peak = t_peak self._synapse_structure = SynapseStructureWeightOnly() @@ -37,6 +40,10 @@ def tau_plus(self): def tau_minus(self): return self._tau_minus + @property + def t_peak(self): + return self._t_peak + @overrides(AbstractTimingDependence.is_same_as) def is_same_as(self, timing_dependence): if not isinstance(timing_dependence, TimingDependencePFPC): @@ -70,8 +77,12 @@ def write_parameters(self, spec, machine_time_step, weight_scales): "exp_sin LUT generation currently only supports 1ms timesteps") # Write exp_sin lookup table - self._tau_plus_last_entry = plasticity_helpers.write_pfpc_lut(spec, - peak_time=100, time_probe=None, lut_size=LUT_SIZE, shift=0) + self._tau_plus_last_entry = plasticity_helpers.write_pfpc_lut( + spec, + peak_time=self._t_peak, + time_probe=None, + lut_size=LUT_SIZE, + shift=0) @property def synaptic_structure(self): diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py index fb732b3352d..0a48bbc12cc 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py @@ -8,13 +8,16 @@ class WeightDependenceMFVN( AbstractHasAPlusAMinus, AbstractWeightDependence): __slots__ = [ "_w_max", - "_w_min"] + "_w_min", + "_pot_alpha" + ] # noinspection PyPep8Naming - def __init__(self, w_min=0.0, w_max=1.0): + def __init__(self, w_min=0.0, w_max=1.0, pot_alpha=0.01): super(WeightDependenceMFVN, self).__init__() self._w_min = w_min self._w_max = w_max + self._pot_alpha = pot_alpha @property def w_min(self): @@ -24,6 +27,10 @@ def w_min(self): def w_max(self): return self._w_max + @property + def pot_alpha(self): + return self._pot_alpha + @overrides(AbstractWeightDependence.is_same_as) def is_same_as(self, weight_dependence): if not isinstance(weight_dependence, WeightDependenceMFVN): @@ -58,12 +65,12 @@ def write_parameters( spec.write_value( data=int(round(self._w_max * w)), data_type=DataType.INT32) - # Based on http://data.andrewdavison.info/docs/PyNN/_modules/pyNN - # /standardmodels/synapses.html - # Pre-multiply A+ and A- by Wmax + # Pre-multiply weight parameters by Wmax spec.write_value( - data=int(round(self._a_plus * w)), + data=int(round(self._pot_alpha * w)), data_type=DataType.INT32) + + # This parameter is actually currently unused spec.write_value( data=int(round(self._a_minus * w)), data_type=DataType.INT32) @@ -74,4 +81,4 @@ def weight_maximum(self): @overrides(AbstractWeightDependence.get_parameter_names) def get_parameter_names(self): - return ['w_min', 'w_max', 'A_plus', 'A_minus'] + return ['w_min', 'w_max', 'A_plus', 'A_minus', 'pot_alpha'] diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py index 0fc9f0fd1ba..330e34992ab 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py @@ -8,13 +8,16 @@ class WeightDependencePFPC( AbstractHasAPlusAMinus, AbstractWeightDependence): __slots__ = [ "_w_max", - "_w_min"] + "_w_min", + "_pot_alpha" + ] # noinspection PyPep8Naming - def __init__(self, w_min=0.0, w_max=1.0): + def __init__(self, w_min=0.0, w_max=1.0, pot_alpha=0.01): super(WeightDependencePFPC, self).__init__() self._w_min = w_min self._w_max = w_max + self._pot_alpha = pot_alpha @property def w_min(self): @@ -24,6 +27,10 @@ def w_min(self): def w_max(self): return self._w_max + @property + def pot_alpha(self): + return self._pot_alpha + @overrides(AbstractWeightDependence.is_same_as) def is_same_as(self, weight_dependence): if not isinstance(weight_dependence, WeightDependencePFPC): @@ -58,12 +65,12 @@ def write_parameters( spec.write_value( data=int(round(self._w_max * w)), data_type=DataType.INT32) - # Based on http://data.andrewdavison.info/docs/PyNN/_modules/pyNN - # /standardmodels/synapses.html - # Pre-multiply A+ and A- by Wmax + # Pre-multiply weight parameters by Wmax spec.write_value( - data=int(round(self._a_plus * w)), + data=int(round(self._pot_alpha * w)), data_type=DataType.INT32) + + # This parameter is actually currently unused spec.write_value( data=int(round(self._a_minus * w)), data_type=DataType.INT32) @@ -74,4 +81,4 @@ def weight_maximum(self): @overrides(AbstractWeightDependence.get_parameter_names) def get_parameter_names(self): - return ['w_min', 'w_max', 'A_plus', 'A_minus'] + return ['w_min', 'w_max', 'A_plus', 'A_minus', "pot_alpha"] From 32cdb96c47b0f5533a9530abeda4b6ca89603b12 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Wed, 12 Dec 2018 12:50:59 +0000 Subject: [PATCH 024/108] Simplify PFPC LUT generation --- .../models/neuron/plasticity/stdp/common/plasticity_helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py index 3e734b707c3..877484d2049 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py @@ -65,7 +65,7 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, sin_pwr = 20 # Calculate required time constant - time_constant = 1/(math.atan(sin_pwr)/peak_time) + time_constant = peak_time/math.atan(sin_pwr) inv_tau = (1.0 / float(time_constant)) #* (machine_time_step / 1000.0) # # caluclate time of peak (from differentiating kernel and setting to zero) From 2b4ea0072e98e97d7d034f343b2c8ec7937bc472 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Wed, 6 Feb 2019 08:47:29 +0000 Subject: [PATCH 025/108] Updates to logging for testing in real network --- .../neuron/plasticity/stdp/stdp_typedefs.h | 2 + .../synapse_dynamics_stdp_mad_mfvn_impl.c | 63 +++++++++++++------ .../synapse_dynamics_stdp_mad_pfpc_impl.c | 47 +++++++++----- .../stdp/timing_dependence/timing_mfvn_impl.h | 27 +++++--- .../stdp/timing_dependence/timing_pfpc_impl.h | 27 +++++--- .../stdp/weight_dependence/weight_mfvn_impl.h | 23 ++++--- .../stdp/weight_dependence/weight_pfpc_impl.h | 16 +++-- neural_modelling/src/neuron/synapses.c | 2 +- .../pyNN/models/neuron/synaptic_manager.py | 3 + 9 files changed, 146 insertions(+), 64 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h b/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h index 1e216a65b00..cc0e9e614e5 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h +++ b/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h @@ -11,4 +11,6 @@ // Helper macros for 16-bit fixed-point multiplication #define STDP_FIXED_MUL_16X16(a, b) maths_fixed_mul16(a, b, STDP_FIXED_POINT) +#define print_plasticity false + #endif // _STDP_TYPEDEFS_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c index c57c20c77a1..44eda3a2b6f 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c @@ -3,6 +3,7 @@ // sPyNNaker neural modelling includes #include +#include // Plasticity includes #include "maths.h" @@ -70,7 +71,7 @@ typedef struct { -_print_pre_event_history(pre_event_history_t pre_eve_hist){ +void _print_pre_event_history(pre_event_history_t pre_eve_hist){ io_printf(IO_BUF, "\n\n************************\n\n"); io_printf(IO_BUF, "Number recorded MF spikes: %u\n", pre_eve_hist.num_recorded_mf_spikes_minus_one); @@ -111,14 +112,17 @@ static inline final_state_t _plasticity_update_synapse( window_begin_time, window_end_time, post_window.prev_time, post_window.num_events); - - io_printf(IO_BUF, " Printing PC history\n"); - print_event_history(post_event_history); + if (print_plasticity){ + io_printf(IO_BUF, " Printing PC history\n"); + print_event_history(post_event_history); + } // print_delayed_window_events(post_event_history, window_begin_time, // window_end_time, delay_dendritic); - io_printf(IO_BUF, "\n############ Phase 1 #############\n"); - io_printf(IO_BUF, "\n Looping over PC spikes:\n"); + if (print_plasticity){ + io_printf(IO_BUF, "\n############ Phase 1 #############\n"); + io_printf(IO_BUF, "\n Looping over PC spikes:\n"); + } delay_dendritic = 0; @@ -133,20 +137,24 @@ static inline final_state_t _plasticity_update_synapse( post_event_window_t pre_window = post_events_get_window_delayed( pre_event_history, mf_begin_time, delayed_post_time); - - io_printf(IO_BUF, " Looping over MF window for this PC spike: %u \n", + if (print_plasticity){ + io_printf(IO_BUF, " Looping over MF window for this PC spike: %u \n", delayed_post_time); + } while (pre_window.num_events > 0) { const uint32_t delayed_pre_time = *pre_window.next_time + delay_dendritic; - io_printf(IO_BUF, " MF Spike: %u \n", delayed_pre_time); - io_printf(IO_BUF, " delta t = %u (delayed MF = %u, delayed PC = %u)\n", + if (print_plasticity){ + io_printf(IO_BUF, " MF Spike: %u \n", delayed_pre_time); + + io_printf(IO_BUF, " delta t = %u (delayed MF = %u, delayed PC = %u)\n", delayed_post_time - delayed_pre_time, delayed_pre_time, delayed_post_time); + } current_state = timing_apply_post_spike( delayed_post_time, *post_window.next_trace, @@ -171,17 +179,23 @@ static inline final_state_t _plasticity_update_synapse( post_event_window_t fwd_post_window = post_events_get_window_delayed( post_event_history, fwd_window_begin_time, window_end_time); - io_printf(IO_BUF, "\n############ Phase 2 #############\n"); - io_printf(IO_BUF, + + if (print_plasticity){ + io_printf(IO_BUF, "\n############ Phase 2 #############\n"); + io_printf(IO_BUF, " Looping over all PC spikes and comparing to latest MF spike at: %u\n", time+delay_dendritic); + } while (fwd_post_window.num_events > 0) { const uint32_t delayed_mf_time = *fwd_post_window.next_time + delay_dendritic; - io_printf(IO_BUF, " PC spike: %u, dt: %u\n", + + if (print_plasticity){ + io_printf(IO_BUF, " PC spike: %u, dt: %u\n", delayed_mf_time, (time+delay_dendritic - delayed_mf_time) ); + } current_state = timing_apply_post_spike( delayed_mf_time, *fwd_post_window.next_trace, @@ -195,8 +209,11 @@ static inline final_state_t _plasticity_update_synapse( // ************** const uint32_t delayed_pre_time = time + delay_axonal; - log_debug("\t\tApplying pre-synaptic event at time:%u last post time:%u\n", + + if (print_plasticity){ + log_debug("\t\tApplying pre-synaptic event at time:%u last post time:%u\n", delayed_pre_time, post_window.prev_time); + } // Apply spike to state // **NOTE** dendritic delay is subtracted @@ -330,7 +347,9 @@ bool synapse_dynamics_process_plastic_synapses( address_t plastic_region_address, address_t fixed_region_address, weight_t *ring_buffers, uint32_t time) { - io_printf(IO_BUF, "\n############ New Plasticity Update #############\n"); + if (print_plasticity){ + io_printf(IO_BUF, "\n############ New Plasticity Update #############\n"); + } // Extract separate arrays of plastic synapses (from plastic region), // Control words (from fixed region) and number of plastic synapses @@ -359,10 +378,11 @@ bool synapse_dynamics_process_plastic_synapses( // NOTE: this uses the post_event_history_t handling code post_events_add(time, event_history, 0); - // Update pre-synaptic trace - io_printf(IO_BUF, + if (print_plasticity){ + io_printf(IO_BUF, "\nAdding pre-synaptic event (mossy fibre spike) at time: %u\n\n", time); + } timing_add_pre_spike(time, last_pre_time, last_pre_trace); @@ -424,13 +444,18 @@ bool synapse_dynamics_process_plastic_synapses( final_state); } - io_printf(IO_BUF, "\n############ Completed Plasticity Update #############\n"); + if (print_plasticity){ + io_printf(IO_BUF, "\n############ Completed Plasticity Update #############\n"); + } return true; } void synapse_dynamics_process_post_synaptic_event( uint32_t time, index_t neuron_index) { - log_debug("Adding post-synaptic event (PC spike)to history at time:%u", time); + + if (print_plasticity){ + log_debug("Adding post-synaptic event (PC spike)to history at time:%u", time); + } // Add post-event post_event_history_t *history = &post_event_history[neuron_index]; diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c index 66a77aeabca..eb59c008b50 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c @@ -3,6 +3,7 @@ // sPyNNaker neural modelling includes #include +#include // Plasticity includes #include "maths.h" @@ -70,7 +71,7 @@ typedef struct { -_print_pre_event_history(pre_event_history_t pre_eve_hist){ +void _print_pre_event_history(pre_event_history_t pre_eve_hist){ io_printf(IO_BUF, "\n\n************************\n\n"); io_printf(IO_BUF, "Number recorded spikes: %u\n", pre_eve_hist.num_recorded_pf_spikes_minus_one); @@ -113,14 +114,17 @@ static inline final_state_t _plasticity_update_synapse( window_begin_time, window_end_time, post_window.prev_time, post_window.num_events); + if (print_plasticity){ + io_printf(IO_BUF, " Printing CF history\n"); + print_event_history(post_event_history); + } - io_printf(IO_BUF, " Printing CF history\n"); - print_event_history(post_event_history); // print_delayed_window_events(post_event_history, window_begin_time, // window_end_time, delay_dendritic); - - io_printf(IO_BUF, "\n Looping over climbing fibre spikes:\n"); + if (print_plasticity){ + io_printf(IO_BUF, "\n Looping over climbing fibre spikes:\n"); + } delay_dendritic = 0; @@ -131,9 +135,10 @@ static inline final_state_t _plasticity_update_synapse( uint32_t pf_begin_time = (delayed_post_time < 255) ? 0 : (delayed_post_time - 255); - - io_printf(IO_BUF, " Applying post-synaptic event at delayed time:%u\n", + if (print_plasticity){ + io_printf(IO_BUF, " Applying post-synaptic event at delayed time:%u\n", delayed_post_time); + } // // Get window of pf events based on cf spikes // print_delayed_window_events(pre_event_history, @@ -142,19 +147,24 @@ static inline final_state_t _plasticity_update_synapse( post_event_window_t pre_window = post_events_get_window_delayed( pre_event_history, pf_begin_time, delayed_post_time); - - io_printf(IO_BUF, " Looping over PF window for this CF spike\n", + if (print_plasticity){ + io_printf(IO_BUF, " Looping over PF window for this CF spike\n", delayed_post_time); + } + while (pre_window.num_events > 0) { const uint32_t delayed_pre_time = *pre_window.next_time + delay_dendritic; - io_printf(IO_BUF, " PF Spike: %u \n", delayed_pre_time); - io_printf(IO_BUF, " delta t = %u (delayed PF = %u, delayed CF = %u)\n", + if (print_plasticity){ + io_printf(IO_BUF, " PF Spike: %u \n", delayed_pre_time); + + io_printf(IO_BUF, " delta t = %u (delayed PF = %u, delayed CF = %u)\n", delayed_post_time - delayed_pre_time, delayed_pre_time, delayed_post_time); + } current_state = timing_apply_post_spike( delayed_post_time, *post_window.next_trace, @@ -171,8 +181,11 @@ static inline final_state_t _plasticity_update_synapse( } const uint32_t delayed_pre_time = time + delay_axonal; - log_debug("\t\tApplying pre-synaptic event at time:%u last post time:%u\n", + + if (print_plasticity){ + log_debug("\t\tApplying pre-synaptic event at time:%u last post time:%u\n", delayed_pre_time, post_window.prev_time); + } // Apply spike to state // **NOTE** dendritic delay is subtracted @@ -334,7 +347,10 @@ bool synapse_dynamics_process_plastic_synapses( // Update pre-synaptic trace - io_printf(IO_BUF, "\nAdding pre-synaptic event (parallel fibre spike) at time: %u\n\n", time); + + if (print_plasticity){ + io_printf(IO_BUF, "\nAdding pre-synaptic event (parallel fibre spike) at time: %u\n\n", time); + } timing_add_pre_spike(time, last_pre_time, last_pre_trace); @@ -400,7 +416,10 @@ bool synapse_dynamics_process_plastic_synapses( void synapse_dynamics_process_post_synaptic_event( uint32_t time, index_t neuron_index) { - log_debug("Adding post-synaptic event to trace at time:%u", time); + + if (print_plasticity){ + log_debug("Adding post-synaptic event to trace at time:%u", time); + } // Add post-event post_event_history_t *history = &post_event_history[neuron_index]; diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h index d82e99d1556..48d46d37041 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h @@ -48,9 +48,9 @@ static inline post_trace_t timing_get_initial_post_trace() { //--------------------------------------- static inline post_trace_t timing_add_post_spike( uint32_t time, uint32_t last_time, post_trace_t last_trace) { - - io_printf(IO_BUF, "Adding pre spike to event history (from purkinje cell)\n"); - + if (print_plasticity){ + io_printf(IO_BUF, "Adding pre spike to event history (from purkinje cell)\n"); + } // // Get time since last spike // uint32_t delta_time = time - last_time; @@ -87,8 +87,10 @@ static inline update_state_t timing_apply_pre_spike( use(&last_pre_trace); // Here we will potentiate by the fixed amount alpha - io_printf(IO_BUF, "\n############ Phase 3 #############"); - io_printf(IO_BUF, "\n Now do potentiation\n"); + if (print_plasticity){ + io_printf(IO_BUF, "\n############ Phase 3 #############"); + io_printf(IO_BUF, "\n Now do potentiation\n"); + } return weight_one_term_apply_potentiation(previous_state, 0); @@ -112,22 +114,29 @@ static inline update_state_t timing_apply_post_spike( // // // Get time of event relative to last pre-synaptic event uint32_t time_since_last_pre = last_pre_time; //time - last_pre_time; - io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); + + if (print_plasticity){ + io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); + } if (time_since_last_pre < 255){ uint32_t multiplier = EXP_COS_LOOKUP(time_since_last_pre); - io_printf(IO_BUF, "multiplier: %k (fixed = %u)\n", multiplier << 4, multiplier); + if (print_plasticity){ + io_printf(IO_BUF, "multiplier: %k (fixed = %u)\n", multiplier << 4, multiplier); + } return weight_one_term_apply_depression(previous_state, multiplier); } - io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); - io_printf(IO_BUF, " out of LUT range - do nothing"); + if (print_plasticity){ + io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); + io_printf(IO_BUF, " out of LUT range - do nothing"); + } return previous_state; } diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index 7b4a7a766a2..bafc7d18a82 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -48,8 +48,9 @@ static inline post_trace_t timing_get_initial_post_trace() { //--------------------------------------- static inline post_trace_t timing_add_post_spike( uint32_t time, uint32_t last_time, post_trace_t last_trace) { - - io_printf(IO_BUF, "Adding climbing fibre spike to post-event history (stored on neuron\n"); + if (print_plasticity){ + io_printf(IO_BUF, "Adding climbing fibre spike to post-event history (stored on neuron\n"); + } // // Get time since last spike // uint32_t delta_time = time - last_time; @@ -87,7 +88,9 @@ static inline update_state_t timing_apply_pre_spike( use(&last_pre_trace); // Here we will potentiate by the fixed amount alpha - io_printf(IO_BUF, " This is where we'll do potentiation\n"); + if (print_plasticity){ + io_printf(IO_BUF, " This is where we'll do potentiation\n"); + } return weight_one_term_apply_potentiation(previous_state, 0); @@ -132,22 +135,28 @@ static inline update_state_t timing_apply_post_spike( // Get time of event relative to last pre-synaptic event uint32_t time_since_last_pre = last_pre_time; //time - last_pre_time; - io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); - if (time_since_last_pre < 255){ + if (print_plasticity){ + io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); + } + if (time_since_last_pre < 255){ uint32_t multiplier = EXP_SIN_LOOKUP(time_since_last_pre); - io_printf(IO_BUF, "multiplier: %k (fixed = %u)\n", multiplier << 4, multiplier); + if (print_plasticity){ + io_printf(IO_BUF, "multiplier: %k (fixed = %u)\n", multiplier << 4, multiplier); + } return weight_one_term_apply_depression(previous_state, multiplier); } -// - io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); - io_printf(IO_BUF, " out of LUT range (do nothing)"); + + if (print_plasticity){ + io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); + io_printf(IO_BUF, " out of LUT range (do nothing)"); + } // if (time_since_last_pre > 0) { // int32_t decayed_r1 = STDP_FIXED_MUL_16X16( diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h index d6bc070d8da..559e91ff477 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h @@ -53,9 +53,10 @@ static inline weight_state_t weight_get_initial(weight_t weight, //--------------------------------------- static inline weight_state_t weight_one_term_apply_depression( weight_state_t state, int32_t depression_multiplier) { - - io_printf(IO_BUF, "\n Do Depression\n"); - io_printf(IO_BUF, " Weight prior to depression: %u\n",state.weight); + if (print_plasticity){ + io_printf(IO_BUF, "\n Do Depression\n"); + io_printf(IO_BUF, " Weight prior to depression: %u\n",state.weight); + } // Calculate scale // **NOTE** this calculation must be done at runtime-defined weight @@ -70,7 +71,10 @@ static inline weight_state_t weight_one_term_apply_depression( // **NOTE** using standard STDP fixed-point format handles format conversion state.weight -= STDP_FIXED_MUL_16X16(state.weight, depression_multiplier); - io_printf(IO_BUF, " Weight after depression: %u\n\n",state.weight); + if (print_plasticity){ + io_printf(IO_BUF, " Weight after depression: %u\n\n", + state.weight); + } return state; } @@ -79,9 +83,11 @@ static inline weight_state_t weight_one_term_apply_potentiation( weight_state_t state, int32_t potentiation) { // add fixed amount - io_printf(IO_BUF, " Adding fixed coontribution: %k (int %u)\n", + if (print_plasticity){ + io_printf(IO_BUF, " Adding fixed coontribution: %k (int %u)\n", state.weight_region->a2_plus << 4, state.weight_region->a2_plus); + } state.a2_plus += state.weight_region->a2_plus; @@ -90,6 +96,7 @@ static inline weight_state_t weight_one_term_apply_potentiation( } //--------------------------------------- static inline weight_t weight_get_final(weight_state_t new_state) { + log_debug("\tnew_weight:%d\n", new_state.weight); // first do Depression (as this would have happened first) @@ -104,12 +111,14 @@ static inline weight_t weight_get_final(weight_state_t new_state) { int32_t new_weight = new_state.weight + new_state.a2_plus; // - scaled_a2_minus; - // Clamp new weight new_weight = MIN(new_state.weight_region->max_weight, new_weight); - io_printf(IO_BUF, " old weight: %u, new weight: %u\n", new_state.weight, new_weight); + if (print_plasticity){ + io_printf(IO_BUF, " old weight: %u, new weight: %u\n", + new_state.weight, new_weight); + } new_state.weight = new_weight; diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h index 00b5d3a7ca6..2225c5c8227 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h @@ -54,8 +54,10 @@ static inline weight_state_t weight_get_initial(weight_t weight, static inline weight_state_t weight_one_term_apply_depression( weight_state_t state, int32_t depression_multiplier) { - io_printf(IO_BUF, "\n Do Depression\n"); - io_printf(IO_BUF, " Weight prior to depression: %u\n",state.weight); + if (print_plasticity){ + io_printf(IO_BUF, "\n Do Depression\n"); + io_printf(IO_BUF, " Weight prior to depression: %u\n",state.weight); + } // Calculate scale // **NOTE** this calculation must be done at runtime-defined weight @@ -70,7 +72,9 @@ static inline weight_state_t weight_one_term_apply_depression( // **NOTE** using standard STDP fixed-point format handles format conversion state.weight -= STDP_FIXED_MUL_16X16(state.weight, depression_multiplier); - io_printf(IO_BUF, " Weight after depression: %u\n\n",state.weight); + if (print_plasticity){ + io_printf(IO_BUF, " Weight after depression: %u\n\n",state.weight); + } return state; } @@ -99,8 +103,10 @@ static inline weight_t weight_get_final(weight_state_t new_state) { // Apply all terms to initial weight int32_t new_weight = new_state.weight + new_state.a2_plus; // - scaled_a2_minus; - - io_printf(IO_BUF, " old weight: %u, new weight: %u\n", new_state.weight, new_weight); + if (print_plasticity){ + io_printf(IO_BUF, " old weight: %u, new weight: %u\n", + new_state.weight, new_weight); + } // Clamp new weight new_weight = MIN(new_state.weight_region->max_weight, diff --git a/neural_modelling/src/neuron/synapses.c b/neural_modelling/src/neuron/synapses.c index 9980e3e6204..b276f9bf760 100644 --- a/neural_modelling/src/neuron/synapses.c +++ b/neural_modelling/src/neuron/synapses.c @@ -193,7 +193,7 @@ static inline void _process_fixed_synapses( if (type == 0){ index_t neuron_index = synapse_row_sparse_index(synaptic_word, synapse_index_mask); - io_printf(IO_BUF, "\nSpike on type: %u at time: %u\n", type, time); + // io_printf(IO_BUF, "\nSpike on type: %u at time: %u\n", type, time); synapse_dynamics_process_post_synaptic_event(time, neuron_index); } diff --git a/spynnaker/pyNN/models/neuron/synaptic_manager.py b/spynnaker/pyNN/models/neuron/synaptic_manager.py index a1d85dbcba6..5a309445d17 100644 --- a/spynnaker/pyNN/models/neuron/synaptic_manager.py +++ b/spynnaker/pyNN/models/neuron/synaptic_manager.py @@ -509,6 +509,9 @@ def _get_ring_buffer_to_input_left_shifts( w + 1 if (2 ** w) <= a else w for w, a in zip(max_weight_powers, max_weights)) + max_weight_powers = [6 for w in max_weight_powers] + + # If we have synapse dynamics that uses signed weights, # Add another bit of shift to prevent overflows if weights_signed: From d5068858c9af9ada6521b5e520fa7f8e49fd2b0c Mon Sep 17 00:00:00 2001 From: Chiara Bartolozzi Date: Mon, 29 Apr 2019 23:32:35 +0200 Subject: [PATCH 026/108] run forever working and correct addresses as output --- .../neuron/plasticity/stdp/common/plasticity_helpers.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py index 0840dfbd07f..c891b431423 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py @@ -1,11 +1,9 @@ import math import logging -<<<<<<< HEAD + import matplotlib.pyplot as plt import numpy as np -======= ->>>>>>> refs/remotes/origin/master from data_specification.enums import DataType from spinn_front_end_common.utilities.utility_objs import ProvenanceDataItem From 0dce290e9f37fa193c9721f81269e11e20322f64 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Sun, 1 Sep 2019 19:19:52 +0100 Subject: [PATCH 027/108] Merge master and bring up to date --- neural_modelling/makefiles/neuron/Makefile | 2 +- .../stdp/weight_dependence/weight_dependence_mfvn.py | 10 +++++----- .../stdp/weight_dependence/weight_dependence_pfpc.py | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/neural_modelling/makefiles/neuron/Makefile b/neural_modelling/makefiles/neuron/Makefile index 0394c734d29..fdec37db981 100644 --- a/neural_modelling/makefiles/neuron/Makefile +++ b/neural_modelling/makefiles/neuron/Makefile @@ -41,7 +41,7 @@ MODELS = IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc \ IF_curr_exp_structural \ IF_cond_exp_stdp_mad_pair_additive_structural \ IF_curr_exp_sEMD \ - #IF_cond_exp_stoc + #IF_cond_exp_stoc \ IF_curr_exp_sEMD \ IZK_curr_exp_stdp_mad_pair_additive \ IZK_cond_exp_stdp_mad_pair_additive diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py index 0a48bbc12cc..c4613af0bca 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py @@ -36,10 +36,10 @@ def is_same_as(self, weight_dependence): if not isinstance(weight_dependence, WeightDependenceMFVN): return False return ( - (self._w_min == weight_dependence.w_min) and - (self._w_max == weight_dependence.w_max) and - (self._a_plus == weight_dependence.A_plus) and - (self._a_minus == weight_dependence.A_minus)) + (self.__w_min == weight_dependence.w_min) and + (self.__w_max == weight_dependence.w_max) and + (self.A_plus == weight_dependence.A_plus) and + (self.A_minus == weight_dependence.A_minus)) @property def vertex_executable_suffix(self): @@ -72,7 +72,7 @@ def write_parameters( # This parameter is actually currently unused spec.write_value( - data=int(round(self._a_minus * w)), + data=int(round(self.A_minus * w)), data_type=DataType.INT32) @property diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py index 330e34992ab..ac3ed501caf 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py @@ -36,10 +36,10 @@ def is_same_as(self, weight_dependence): if not isinstance(weight_dependence, WeightDependencePFPC): return False return ( - (self._w_min == weight_dependence.w_min) and - (self._w_max == weight_dependence.w_max) and - (self._a_plus == weight_dependence.A_plus) and - (self._a_minus == weight_dependence.A_minus)) + (self.__w_min == weight_dependence.w_min) and + (self.__w_max == weight_dependence.w_max) and + (self.A_plus == weight_dependence.A_plus) and + (self.A_minus == weight_dependence.A_minus)) @property def vertex_executable_suffix(self): @@ -72,7 +72,7 @@ def write_parameters( # This parameter is actually currently unused spec.write_value( - data=int(round(self._a_minus * w)), + data=int(round(self.A_minus * w)), data_type=DataType.INT32) @property From 6294aa57ee3a353cbcfbddfec2acc2397661a88c Mon Sep 17 00:00:00 2001 From: mbassor2 Date: Fri, 6 Sep 2019 10:32:53 +0100 Subject: [PATCH 028/108] Get models working inside cerebellum_tb.py (reduced to 128 neurons per core to fit into DTCM) --- neural_modelling/src/neuron/c_main.c | 1 + .../stdp/weight_dependence/weight_mfvn_impl.c | 2 +- neural_modelling/src/neuron/spike_processing.c | 1 + .../neuron/builds/if_cond_exp_cerebellum.py | 4 ++-- .../plasticity/stdp/common/plasticity_helpers.py | 15 +++++++-------- .../weight_dependence/weight_dependence_mfvn.py | 4 ++++ .../weight_dependence/weight_dependence_pfpc.py | 4 ++++ 7 files changed, 20 insertions(+), 11 deletions(-) diff --git a/neural_modelling/src/neuron/c_main.c b/neural_modelling/src/neuron/c_main.c index f055a118623..31ff8e0bd8d 100644 --- a/neural_modelling/src/neuron/c_main.c +++ b/neural_modelling/src/neuron/c_main.c @@ -339,6 +339,7 @@ void timer_callback(uint timer_count, uint unused) { void c_main(void) { // initialise the model if (!initialise()) { + io_printf(IO_BUF, "c_main initialise failed\n"); rt_error(RTE_API); } diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c index bf55ff09b33..d94b161dfdf 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c @@ -56,7 +56,7 @@ uint32_t *weight_initialise(uint32_t *address, uint32_t n_synapse_types, weight_multiply_right_shift[s]); } - io_printf(IO_BUF, "mfvn weight initialisation: completed successfully"); + io_printf(IO_BUF, "mfvn weight initialisation: completed successfully\n"); // Return end address of region return (address_t) plasticity_word; diff --git a/neural_modelling/src/neuron/spike_processing.c b/neural_modelling/src/neuron/spike_processing.c index 08e29346c13..48f1a213ad2 100644 --- a/neural_modelling/src/neuron/spike_processing.c +++ b/neural_modelling/src/neuron/spike_processing.c @@ -257,6 +257,7 @@ bool spike_processing_initialise( // EXPORTED // Allocate incoming spike buffer if (!in_spikes_initialize_spike_buffer(incoming_spike_buffer_size)) { + io_printf(IO_BUF, "Spike buffer failed to initialise - insufficient DTCM \n"); return false; } diff --git a/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py b/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py index bf9fb511b6f..4b5313f022d 100644 --- a/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py +++ b/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py @@ -29,8 +29,8 @@ def __init__( threshold_type = ThresholdTypeStatic(v_thresh) -# super(IFCondExpCerebellum, self).set_model_max_atoms_per_core( -# IFCondExpCerebellum, n_atoms=MAX_ATOMS_PER_CORE) + super(IFCondExpCerebellum, self).set_model_max_atoms_per_core( + n_atoms=MAX_ATOMS_PER_CORE) super(IFCondExpCerebellum, self).__init__( model_name="IF_cond_exp_cerebellum", diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py index a2fb25644f1..8f332dcca70 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py @@ -15,10 +15,9 @@ import math import logging - import matplotlib.pyplot as plt import numpy as np - +from __future__ import print function from data_specification.enums import DataType from spinn_front_end_common.utilities.utility_objs import ProvenanceDataItem @@ -115,14 +114,14 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, out_float.append(exp_float) out_fixed.append(exp_fix) if i == time_probe: - print "dt = {}, kernel value = {} (fixed-point = {})".format( - time_probe, exp_float, exp_fix) + print("dt = {}, kernel value = {} (fixed-point = {})".format( + time_probe, exp_float, exp_fix)) else: # at runtime, so write to spec spec.write_value(data=exp_fix, data_type=DataType.INT16) if spec is None: - print "peak: time {}, value {}".format(peak_time, kernel_peak_value) + print("peak: time {}, value {}".format(peak_time, kernel_peak_value)) t = np.arange(0,lut_size) plt.plot(t,out_float, label='float') # plt.plot(t,out_fixed, label='fixed') @@ -170,14 +169,14 @@ def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, out_fixed.append(exp_fix) plot_times.append(i) if i == time_probe: - print "dt = {}, kernel value = {} (fixed-point = {})".format( - time_probe, exp_float, exp_fix) + print("dt = {}, kernel value = {} (fixed-point = {})".format( + time_probe, exp_float, exp_fix)) else: # at runtime, so write to spec spec.write_value(data=exp_fix, data_type=DataType.INT16) if spec is None: - print "peak: time {}, value {}".format(peak_time, kernel_peak_value) + print("peak: time {}, value {}".format(peak_time, kernel_peak_value)) plt.plot(plot_times,out_float, label='float') # plt.plot(t,out_fixed, label='fixed') plt.legend() diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py index c4613af0bca..73d6b8fdb40 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py @@ -30,6 +30,10 @@ def w_max(self): @property def pot_alpha(self): return self._pot_alpha + + @pot_alpha.setter + def pot_alpha(self, new_value): + self._pot_alpha = new_value @overrides(AbstractWeightDependence.is_same_as) def is_same_as(self, weight_dependence): diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py index ac3ed501caf..ce0c2c76ccd 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py @@ -30,6 +30,10 @@ def w_max(self): @property def pot_alpha(self): return self._pot_alpha + + @pot_alpha.setter + def pot_alpha(self, new_value): + self._pot_alpha = new_value @overrides(AbstractWeightDependence.is_same_as) def is_same_as(self, weight_dependence): From fdb8a3040f5f0dbc46910f8db5f19141ea79719f Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Fri, 6 Sep 2019 10:51:24 +0100 Subject: [PATCH 029/108] Check under python 2 --- .../models/neuron/plasticity/stdp/common/plasticity_helpers.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py index 8f332dcca70..fb76fd667b3 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common/plasticity_helpers.py @@ -12,12 +12,11 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - +from __future__ import print_function import math import logging import matplotlib.pyplot as plt import numpy as np -from __future__ import print function from data_specification.enums import DataType from spinn_front_end_common.utilities.utility_objs import ProvenanceDataItem From a29b1c18717479645b61e89b145f14bad5e937a1 Mon Sep 17 00:00:00 2001 From: oliverrhodes Date: Wed, 22 Jan 2020 09:50:26 +0000 Subject: [PATCH 030/108] make poisson source able to change rate without re-map --- spynnaker/pyNN/models/spike_source/spike_source_poisson.py | 2 +- .../pyNN/models/spike_source/spike_source_poisson_vertex.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spynnaker/pyNN/models/spike_source/spike_source_poisson.py b/spynnaker/pyNN/models/spike_source/spike_source_poisson.py index deffb7065c6..c709a28890c 100644 --- a/spynnaker/pyNN/models/spike_source/spike_source_poisson.py +++ b/spynnaker/pyNN/models/spike_source/spike_source_poisson.py @@ -17,7 +17,7 @@ from spynnaker.pyNN.models.abstract_pynn_model import AbstractPyNNModel from spinn_utilities.overrides import overrides -_population_parameters = {"seed": None, "max_rate": None} +_population_parameters = {"seed": None, "max_rate": 1000} # Technically, this is ~2900 in terms of DTCM, but is timescale dependent # in terms of CPU (2900 at 10 times slow down is fine, but not at diff --git a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py index f6874c1bf9b..99891876e77 100644 --- a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py +++ b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py @@ -136,7 +136,7 @@ def __init__( self.__n_data_specs = 0 # check for changes parameters - self.__change_requires_mapping = True + self.__change_requires_mapping = False #True self.__change_requires_neuron_parameters_reload = False self.__spike_recorder = MultiSpikeRecorder() From 784adc35519e32f9daefb3c15d31be642e0ae45d Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Wed, 2 Sep 2020 13:23:35 +0100 Subject: [PATCH 031/108] master merged in and tested --- .../src/neuron/plasticity/stdp/maths.h | 17 ++ .../src/neuron/plasticity/stdp/post_events.h | 24 --- .../synapse_dynamics_stdp_mad_mfvn_impl.c | 23 ++- .../synapse_dynamics_stdp_mad_pfpc_impl.c | 23 ++- .../stdp/timing_dependence/timing_mfvn_impl.c | 12 +- .../stdp/timing_dependence/timing_mfvn_impl.h | 22 ++- .../stdp/timing_dependence/timing_pfpc_impl.c | 15 +- .../stdp/timing_dependence/timing_pfpc_impl.h | 17 +- .../stdp/weight_dependence/weight_pfpc_impl.h | 1 + ...n_model_leaky_integrate_and_fire_t_last.py | 2 +- .../models/neuron/plasticity/stdp/common.py | 161 +++++++++++++++++- .../timing_dependence_mfvn.py | 8 +- .../timing_dependence_pfpc.py | 8 +- .../pyNN/models/neuron/synaptic_manager.py | 12 ++ 14 files changed, 283 insertions(+), 62 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/maths.h b/neural_modelling/src/neuron/plasticity/stdp/maths.h index 5abfb034b3a..31e15f8e5e9 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/maths.h +++ b/neural_modelling/src/neuron/plasticity/stdp/maths.h @@ -59,6 +59,7 @@ static inline int16_lut *maths_copy_int16_lut(address_t *address) { int16_lut *sdram_lut = (int16_lut *) *address; uint32_t size = sizeof(int16_lut) + (sdram_lut->size * sizeof(int16_t)); int16_lut *lut = spin1_malloc(size); + log_info("lut size %d", size); if (lut == NULL) { log_error("Not enough space to allocate LUT. Try reducing the timestep," " the number of neurons per core, or the tau value"); @@ -73,6 +74,22 @@ static inline int16_lut *maths_copy_int16_lut(address_t *address) { return lut; } +//--------------------------------------- +// Plasticity maths function inline implementation +//--------------------------------------- +static inline address_t maths_copy_int16_lut_with_size( + address_t start_address, uint32_t num_entries, int16_t *lut) { + // Pad to number of words + const uint32_t num_words = + (num_entries / 2) + (((num_entries & 1) != 0) ? 1 : 0); + + // Copy entries to LUT + spin1_memcpy(lut, start_address, sizeof(int16_t) * num_entries); + + // Return address after words + return start_address + num_words; +} + //! \brief Get value from lookup table //! \param[in] time: The time that we are mapping //! \param[in] lut: The lookup table (result of maths_copy_int16_lut()) diff --git a/neural_modelling/src/neuron/plasticity/stdp/post_events.h b/neural_modelling/src/neuron/plasticity/stdp/post_events.h index 91ad290c158..32c4819e6d0 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/post_events.h +++ b/neural_modelling/src/neuron/plasticity/stdp/post_events.h @@ -187,21 +187,6 @@ static inline post_event_window_t post_events_next_delayed( return window; } -//--------------------------------------- -static inline post_event_window_t post_events_next_delayed( - post_event_window_t window, uint32_t delayed_time) { - // Update previous time and increment next time - window.prev_time = delayed_time; - window.prev_trace = *window.next_trace++; - - // Go onto next event - window.next_time++; - - // Decrement remaining events - window.num_events--; - return window; -} - //--------------------------------------- //! \brief Add a post-synaptic event to the history //! \param[in] time: the time of the event @@ -230,15 +215,6 @@ static inline void post_events_add( } } -// TODO This function is removed in master. Does this still serve any purpose? -static inline void print_event_history(post_event_history_t *events) { - log_debug(" ## printing entire post event history ##"); - for (uint32_t i = 0; i <= events->count_minus_one; i++) { - log_debug("post event: %u, time: %u, trace: %u", - i, events->times[i], events->traces[i]); - } -} - //! \brief Print the post-synaptic event history //! \param[in] post_event_history: the history //! \param[in] begin_time: The start time of the history diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c index 44eda3a2b6f..6470c88fbb3 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c @@ -24,7 +24,14 @@ static uint32_t synapse_type_mask; uint32_t num_plastic_pre_synaptic_events = 0; uint32_t plastic_saturation_count = 0; - +//! The type of configuration parameters in SDRAM (written by host) +typedef struct stdp_params { + //! The back-propagation delay, in basic simulation timesteps + uint32_t backprop_delay; +} stdp_params; + +//! Configuration parameters +static stdp_params params; //--------------------------------------- // Macros //--------------------------------------- @@ -294,14 +301,18 @@ static inline index_t _sparse_axonal_delay(uint32_t x) { return ((x >> synapse_delay_index_type_bits) & SYNAPSE_AXONAL_DELAY_MASK); } -address_t synapse_dynamics_initialise( +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) { + stdp_params *sdram_params = (stdp_params *) address; + spin1_memcpy(¶ms, sdram_params, sizeof(stdp_params)); + address = (address_t) &sdram_params[1]; + // Load timing dependence data address_t weight_region_address = timing_initialise(address); if (address == NULL) { - return NULL; + return false; } // Load weight dependence data @@ -309,12 +320,12 @@ address_t synapse_dynamics_initialise( weight_region_address, n_synapse_types, ring_buffer_to_input_buffer_left_shifts); if (weight_result == NULL) { - return NULL; + return false; } post_event_history = post_events_init_buffers(n_neurons); if (post_event_history == NULL) { - return NULL; + return false; } uint32_t n_neurons_power_2 = n_neurons; @@ -340,7 +351,7 @@ address_t synapse_dynamics_initialise( SYNAPSE_DELAY_BITS + synapse_type_index_bits; synapse_type_mask = (1 << log_n_synapse_types) - 1; - return weight_result; + return true; } bool synapse_dynamics_process_plastic_synapses( diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c index eb59c008b50..8a394ecc824 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c @@ -25,6 +25,14 @@ static uint32_t synapse_type_mask; uint32_t num_plastic_pre_synaptic_events = 0; uint32_t plastic_saturation_count = 0; +//! The type of configuration parameters in SDRAM (written by host) +typedef struct stdp_params { + //! The back-propagation delay, in basic simulation timesteps + uint32_t backprop_delay; +} stdp_params; + +//! Configuration parameters +static stdp_params params; //--------------------------------------- // Macros //--------------------------------------- @@ -109,8 +117,8 @@ static inline final_state_t _plasticity_update_synapse( post_event_window_t post_window = post_events_get_window_delayed( post_event_history, window_begin_time, window_end_time); - log_debug("\tPerforming deferred synapse update at time:%u", time); - log_debug("\t\tbegin_time:%u, end_time:%u - prev_time:%u, num_events:%u", + log_info("\tPerforming deferred synapse update at time:%u", time); + log_info("\t\tbegin_time:%u, end_time:%u - prev_time:%u, num_events:%u", window_begin_time, window_end_time, post_window.prev_time, post_window.num_events); @@ -266,9 +274,12 @@ static inline index_t _sparse_axonal_delay(uint32_t x) { return ((x >> synapse_delay_index_type_bits) & SYNAPSE_AXONAL_DELAY_MASK); } -address_t synapse_dynamics_initialise( +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) { + stdp_params *sdram_params = (stdp_params *) address; + spin1_memcpy(¶ms, sdram_params, sizeof(stdp_params)); + address = (address_t) &sdram_params[1]; // Load timing dependence data address_t weight_region_address = timing_initialise(address); @@ -281,12 +292,12 @@ address_t synapse_dynamics_initialise( weight_region_address, n_synapse_types, ring_buffer_to_input_buffer_left_shifts); if (weight_result == NULL) { - return NULL; + return false; } post_event_history = post_events_init_buffers(n_neurons); if (post_event_history == NULL) { - return NULL; + return false; } uint32_t n_neurons_power_2 = n_neurons; @@ -312,7 +323,7 @@ address_t synapse_dynamics_initialise( SYNAPSE_DELAY_BITS + synapse_type_index_bits; synapse_type_mask = (1 << log_n_synapse_types) - 1; - return weight_result; + return true; } bool synapse_dynamics_process_plastic_synapses( diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c index 611559ccd10..06d79a25c34 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c @@ -5,6 +5,7 @@ //--------------------------------------- // Exponential lookup-tables int16_t exp_cos_lookup[EXP_COS_LUT_SIZE]; +//int16_lut *exp_cos_lookup; //--------------------------------------- // Functions @@ -16,9 +17,18 @@ address_t timing_initialise(address_t address) { // **TODO** assert number of neurons is less than max // Copy LUTs from following memory - address_t lut_address = maths_copy_int16_lut(&address[0], EXP_COS_LUT_SIZE, + address_t lut_address = maths_copy_int16_lut_with_size(&address[0], EXP_COS_LUT_SIZE, &exp_cos_lookup[0]); +// exp_cos_lookup = maths_copy_int16_lut(&address); +// address_t lut_address = &exp_cos_lookup; + + + log_info("# of entries in exp_cos_lookup %u", sizeof(exp_cos_lookup)); + log_info("first value %u", exp_cos_lookup[0]); + log_info("mid value %u", exp_cos_lookup[EXP_COS_LUT_SIZE/2]); + log_info("last value %u", exp_cos_lookup[EXP_COS_LUT_SIZE-1]); + io_printf(IO_BUF, "Timing_mfvn_initialise: completed successfully\n"); return lut_address; diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h index 48d46d37041..a91e77a7a9a 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h @@ -28,7 +28,7 @@ typedef int16_t pre_trace_t; // Helper macros for looking up decays #define EXP_COS_LOOKUP(time) \ maths_lut_exponential_decay( \ - time, TAU_PLUS_TIME_SHIFT, EXP_COS_LUT_SIZE, exp_cos_lookup) + time, exp_cos_lookup) //#define DECAY_LOOKUP_TAU_MINUS(time) \ // maths_lut_exponential_decay( \ // time, TAU_MINUS_TIME_SHIFT, TAU_MINUS_SIZE, tau_minus_lookup) @@ -37,6 +37,7 @@ typedef int16_t pre_trace_t; // Externals //--------------------------------------- extern int16_t exp_cos_lookup[EXP_COS_LUT_SIZE]; +//extern int16_lut *exp_cos_lookup; //--------------------------------------- // Timing dependence inline functions @@ -48,6 +49,10 @@ static inline post_trace_t timing_get_initial_post_trace() { //--------------------------------------- static inline post_trace_t timing_add_post_spike( uint32_t time, uint32_t last_time, post_trace_t last_trace) { + use(time); + use(last_time); + use(&last_trace); + if (print_plasticity){ io_printf(IO_BUF, "Adding pre spike to event history (from purkinje cell)\n"); } @@ -72,7 +77,9 @@ static inline post_trace_t timing_add_post_spike( //--------------------------------------- static inline pre_trace_t timing_add_pre_spike( uint32_t time, uint32_t last_time, pre_trace_t last_trace) { - + use(time); + use(last_time); + use(&last_trace); return (pre_trace_t) 0; //new_r1_trace; } @@ -82,9 +89,12 @@ static inline 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) { + use(time); use(&trace); use(last_pre_time); + use(last_post_time); use(&last_pre_trace); + use(&last_post_trace); // Here we will potentiate by the fixed amount alpha if (print_plasticity){ @@ -101,16 +111,14 @@ static inline 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) { + use(time); use(&trace); + use(last_pre_time); use(last_post_time); + use(&last_pre_trace); use(&last_post_trace); - - - // // This is where we lookup the value of e^(-bx) * cos(x)^2 - - // // // Get time of event relative to last pre-synaptic event uint32_t time_since_last_pre = last_pre_time; //time - last_pre_time; diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c index 29ed9d8fd92..ac118952a3e 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c @@ -5,6 +5,7 @@ //--------------------------------------- // Exponential lookup-tables int16_t exp_sin_lookup[EXP_SIN_LUT_SIZE]; +//int16_lut *exp_sin_lookup; //--------------------------------------- // Functions @@ -16,9 +17,21 @@ address_t timing_initialise(address_t address) { // **TODO** assert number of neurons is less than max // Copy LUTs from following memory - address_t lut_address = maths_copy_int16_lut(&address[0], EXP_SIN_LUT_SIZE, + address_t lut_address = maths_copy_int16_lut_with_size(&address[0], EXP_SIN_LUT_SIZE, &exp_sin_lookup[0]); + // Copy LUTs from following memory +// address_t lut_address = address; +// exp_sin_lookup = maths_copy_int16_lut(&lut_address); +// exp_sin_lookup = maths_copy_int16_lut(&lut_address); +// address_t lut_address = &exp_sin_lookup; + + log_info("# of entries in exp_sin_lookup %u", sizeof(exp_sin_lookup)); + log_info("first value %u", exp_sin_lookup[0]); + log_info("mid value %u", exp_sin_lookup[EXP_SIN_LUT_SIZE/2]); + log_info("last value %u", exp_sin_lookup[EXP_SIN_LUT_SIZE-1]); + + io_printf(IO_BUF, "timing_pfpc_initialise: completed successfully\n"); return lut_address; diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index bafc7d18a82..c2e91cedf06 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -28,7 +28,7 @@ typedef int16_t pre_trace_t; // Helper macros for looking up decays #define EXP_SIN_LOOKUP(time) \ maths_lut_exponential_decay( \ - time, TAU_PLUS_TIME_SHIFT, EXP_SIN_LUT_SIZE, exp_sin_lookup) + time, exp_sin_lookup) //#define DECAY_LOOKUP_TAU_MINUS(time) \ // maths_lut_exponential_decay( \ // time, TAU_MINUS_TIME_SHIFT, TAU_MINUS_SIZE, tau_minus_lookup) @@ -37,6 +37,7 @@ typedef int16_t pre_trace_t; // Externals //--------------------------------------- extern int16_t exp_sin_lookup[EXP_SIN_LUT_SIZE]; +//extern int16_lut *exp_sin_lookup; //--------------------------------------- // Timing dependence inline functions @@ -48,6 +49,10 @@ static inline post_trace_t timing_get_initial_post_trace() { //--------------------------------------- static inline post_trace_t timing_add_post_spike( uint32_t time, uint32_t last_time, post_trace_t last_trace) { + use(time); + use(last_time); + use(&last_trace); + if (print_plasticity){ io_printf(IO_BUF, "Adding climbing fibre spike to post-event history (stored on neuron\n"); } @@ -73,7 +78,9 @@ static inline post_trace_t timing_add_post_spike( //--------------------------------------- static inline pre_trace_t timing_add_pre_spike( uint32_t time, uint32_t last_time, pre_trace_t last_trace) { - + use(time); + use(last_time); + use(&last_trace); return (pre_trace_t) 0; //new_r1_trace; } @@ -83,9 +90,12 @@ static inline 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) { + use(time); use(&trace); use(last_pre_time); + use(last_post_time); use(&last_pre_trace); + use(&last_post_trace); // Here we will potentiate by the fixed amount alpha if (print_plasticity){ @@ -125,8 +135,11 @@ static inline 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) { + use(time); use(&trace); + use(last_pre_time); use(last_post_time); + use(&last_pre_trace); use(&last_post_trace); diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h index 2225c5c8227..6085da0aefd 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h @@ -81,6 +81,7 @@ static inline weight_state_t weight_one_term_apply_depression( //--------------------------------------- static inline weight_state_t weight_one_term_apply_potentiation( weight_state_t state, int32_t potentiation) { + use(potentiation); // add fixed amount state.a2_plus += state.weight_region->a2_plus; diff --git a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py index 572800e875e..804e49fcd63 100644 --- a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py +++ b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py @@ -92,7 +92,7 @@ def has_variable(self, variable): return variable in UNITS @inject_items({"ts": "MachineTimeStep"}) - @overrides(AbstractNeuronModel.get_values, additional_arguments={'ts'}) + @overrides(AbstractNeuronModel.get_values) def get_values(self, parameters, state_variables, vertex_slice, ts): # Add the rest of the data diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py index c67456a6cda..9ae73375c51 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py @@ -16,19 +16,44 @@ import math import logging import numpy +import matplotlib.pyplot as plt +from data_specification.enums import DataType +from spinn_front_end_common.utilities.utility_objs import ProvenanceDataItem logger = logging.getLogger(__name__) # Default value of fixed-point one for STDP STDP_FIXED_POINT_ONE = (1 << 11) -def float_to_fixed(value): - """ - :param float value: - :rtype: int - """ - return int(round(float(value) * STDP_FIXED_POINT_ONE)) +# def float_to_fixed(value): +# """ +# :param float value: +# :rtype: int +# """ +# return int(round(float(value) * STDP_FIXED_POINT_ONE)) +def float_to_fixed(value, fixed_point_one): + return int(round(float(value) * float(fixed_point_one))) + +def get_lut_provenance( + pre_population_label, post_population_label, rule_name, entry_name, + param_name, last_entry): + # pylint: disable=too-many-arguments + top_level_name = "{}_{}_STDP_{}".format( + pre_population_label, post_population_label, rule_name) + report = False + if last_entry is not None: + report = last_entry > 0 + return ProvenanceDataItem( + [top_level_name, entry_name], last_entry, report=report, + message=( + "The last entry in the STDP exponential lookup table for the {}" + " parameter of the {} between {} and {} was {} rather than 0," + " indicating that the lookup table was not big enough at this" + " timestep and value. Try reducing the parameter value, or" + " increasing the timestep".format( + param_name, rule_name, pre_population_label, + post_population_label, last_entry))) def get_exp_lut_array(time_step, time_constant, shift=0): """ @@ -53,3 +78,127 @@ def get_exp_lut_array(time_step, time_constant, shift=0): # Concatenate with the header header = numpy.array([len(a), shift], dtype="uint16") return numpy.concatenate((header, a.astype("uint16"))).view("uint32") + + +def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, + fixed_point_one=STDP_FIXED_POINT_ONE): + # Add this to function arguments in the future + machine_time_step = 1.0 + sin_pwr = 20 + + # Calculate required time constant + time_constant = peak_time / math.atan(sin_pwr) + inv_tau = (1.0 / float(time_constant)) # * (machine_time_step / 1000.0) + + # # caluclate time of peak (from differentiating kernel and setting to zero) + # kernel_peak_time = math.atan(20) / inv_tau + + # evaluate peak value of kernel to normalise LUT + kernel_peak_value = (math.exp(-peak_time * inv_tau) * + math.sin(peak_time * inv_tau) ** sin_pwr) + + # Generate LUT + out_float = [] + out_fixed = [] + + final_exp_fix = [] + + for i in range(0, lut_size): # note that i corresponds to 1 timestep!!!!!! + + # Multiply by inverse of time constant + value = float(i) * inv_tau + + # Only take first peak from kernel + if (value > math.pi): + exp_float = 0 + else: + # Evaluate kernel + exp_float = math.exp(-value) * math.sin(value) ** sin_pwr / kernel_peak_value + + # Convert to fixed-point + exp_fix = float_to_fixed(exp_float, fixed_point_one) + + if spec is None: # in testing mode so print + out_float.append(exp_float) + out_fixed.append(exp_fix) + if i == time_probe: + print("dt = {}, kernel value = {} (fixed-point = {})".format( + time_probe, exp_float, exp_fix)) + + else: # at runtime, so write to spec + final_exp_fix.append(exp_fix) + # spec.write_value(data=exp_fix, data_type=DataType.INT16) + + if spec is None: + print("peak: time {}, value {}".format(peak_time, kernel_peak_value)) + t = numpy.arange(0, lut_size) + plt.plot(t, out_float, label='float') + # plt.plot(t,out_fixed, label='fixed') + plt.legend() + plt.show() + else: + # exp_fix_array_int16 = numpy.asarray( + # final_exp_fix, dtype="uint16").view("uint32") + + spec.write_array(final_exp_fix, data_type=DataType.INT16) + + +def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, + fixed_point_one=STDP_FIXED_POINT_ONE): + # Add this to function arguments in the future + machine_time_step = 1.0 + cos_pwr = 2 + + # Calculate required time constant + inv_sigma = (1.0 / float(sigma)) # * (machine_time_step / 1000.0) + peak_time = 0 + + # evaluate peak value of kernel to normalise LUT + kernel_peak_value = (math.exp(-abs(peak_time * inv_sigma * beta)) * + math.cos(peak_time * inv_sigma) ** cos_pwr) + + # Generate LUT + out_float = [] + out_fixed = [] + plot_times = [] + + final_exp_fix = [] + + for i in range(0, lut_size): # note that i corresponds to 1 timestep!!!!!! + + # Multiply by inverse of time constant + value = float(i) * inv_sigma + + # Only take first peak from kernel + if (value > math.pi / 2): + exp_float = 0 + else: + # Evaluate kernel + exp_float = math.exp(-abs(value * beta)) * math.cos(value) ** cos_pwr / kernel_peak_value + + # Convert to fixed-point + exp_fix = float_to_fixed(exp_float, fixed_point_one) + + if spec is None: # in testing mode so print + out_float.append(exp_float) + out_fixed.append(exp_fix) + plot_times.append(i) + if i == time_probe: + print("dt = {}, kernel value = {} (fixed-point = {})".format( + time_probe, exp_float, exp_fix)) + + else: # at runtime, so write to spec + final_exp_fix.append(exp_fix) + # spec.write_value(data=exp_fix, data_type=DataType.INT16) + + if spec is None: + print("peak: time {}, value {}".format(peak_time, kernel_peak_value)) + plt.plot(plot_times, out_float, label='float') + # plt.plot(t,out_fixed, label='fixed') + plt.legend() + plt.show() + else: + # exp_fix_array_int16 = numpy.asarray( + # final_exp_fix, dtype="uint16").view("uint32") + + spec.write_array(final_exp_fix, data_type=DataType.INT16) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py index e1f73736f61..a8367e0f5e3 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py @@ -1,6 +1,6 @@ from spinn_utilities.overrides import overrides from spynnaker.pyNN.models.neuron.plasticity.stdp.common \ - import plasticity_helpers + import write_mfvn_lut, get_lut_provenance from .abstract_timing_dependence import AbstractTimingDependence from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure\ import SynapseStructureWeightOnly @@ -84,7 +84,7 @@ def write_parameters(self, spec, machine_time_step, weight_scales): "exp cos LUT generation currently only supports 1ms timesteps") # Write exp_sin lookup table - self._tau_plus_last_entry = plasticity_helpers.write_mfvn_lut( + self._tau_plus_last_entry = write_mfvn_lut( spec, sigma=self._sigma, beta=self._beta, @@ -99,10 +99,10 @@ def synaptic_structure(self): @overrides(AbstractTimingDependence.get_provenance_data) def get_provenance_data(self, pre_population_label, post_population_label): prov_data = list() - prov_data.append(plasticity_helpers.get_lut_provenance( + prov_data.append(get_lut_provenance( pre_population_label, post_population_label, "MFVNRule", "tau_plus_last_entry", "tau_plus", self._tau_plus_last_entry)) - prov_data.append(plasticity_helpers.get_lut_provenance( + prov_data.append(get_lut_provenance( pre_population_label, post_population_label, "MFVNRule", "tau_minus_last_entry", "tau_minus", self._tau_minus_last_entry)) return prov_data diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index 8fa2d950189..7a71b398699 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -1,6 +1,6 @@ from spinn_utilities.overrides import overrides from spynnaker.pyNN.models.neuron.plasticity.stdp.common \ - import plasticity_helpers + import write_pfpc_lut, get_lut_provenance from .abstract_timing_dependence import AbstractTimingDependence from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure\ import SynapseStructureWeightOnly @@ -77,7 +77,7 @@ def write_parameters(self, spec, machine_time_step, weight_scales): "exp_sin LUT generation currently only supports 1ms timesteps") # Write exp_sin lookup table - self._tau_plus_last_entry = plasticity_helpers.write_pfpc_lut( + self._tau_plus_last_entry = write_pfpc_lut( spec, peak_time=self._t_peak, time_probe=None, @@ -91,10 +91,10 @@ def synaptic_structure(self): @overrides(AbstractTimingDependence.get_provenance_data) def get_provenance_data(self, pre_population_label, post_population_label): prov_data = list() - prov_data.append(plasticity_helpers.get_lut_provenance( + prov_data.append(get_lut_provenance( pre_population_label, post_population_label, "PFPCRule", "tau_plus_last_entry", "tau_plus", self._tau_plus_last_entry)) - prov_data.append(plasticity_helpers.get_lut_provenance( + prov_data.append(get_lut_provenance( pre_population_label, post_population_label, "PFPCRule", "tau_minus_last_entry", "tau_minus", self._tau_minus_last_entry)) return prov_data diff --git a/spynnaker/pyNN/models/neuron/synaptic_manager.py b/spynnaker/pyNN/models/neuron/synaptic_manager.py index e3c9225631e..395f67280d7 100644 --- a/spynnaker/pyNN/models/neuron/synaptic_manager.py +++ b/spynnaker/pyNN/models/neuron/synaptic_manager.py @@ -1165,11 +1165,23 @@ def _get_ring_buffer_shifts( :param float weight_scale: :rtype: list(int) """ + if (self.__ring_buffer_shifts is None and + hasattr(application_vertex, "rb_left_shifts")): + print("=" * 80) + print("Using given values for RB left shifts.") + self.__ring_buffer_shifts = application_vertex.rb_left_shifts + print("RB left shifts for {:20}".format(application_vertex.label), + "=", self.__ring_buffer_shifts) + print("-" * 80) if self.__ring_buffer_shifts is None: + print("=" * 80) + print("Computing values for RB left shifts...") self.__ring_buffer_shifts = \ self._get_ring_buffer_to_input_left_shifts( application_vertex, application_graph, machine_timestep, weight_scale) + print("RB left shifts for {:20}".format(application_vertex.label), + "=", self.__ring_buffer_shifts) return self.__ring_buffer_shifts def write_data_spec( From a980f5563ffa0d1ea0e1883b38d947dbbc8e8e51 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Wed, 2 Sep 2020 13:25:58 +0100 Subject: [PATCH 032/108] removing some unnecessary log infos --- .../stdp/timing_dependence/timing_mfvn_impl.c | 9 --------- .../stdp/timing_dependence/timing_pfpc_impl.c | 12 ------------ 2 files changed, 21 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c index 06d79a25c34..4f81f063da8 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c @@ -20,15 +20,6 @@ address_t timing_initialise(address_t address) { address_t lut_address = maths_copy_int16_lut_with_size(&address[0], EXP_COS_LUT_SIZE, &exp_cos_lookup[0]); -// exp_cos_lookup = maths_copy_int16_lut(&address); -// address_t lut_address = &exp_cos_lookup; - - - log_info("# of entries in exp_cos_lookup %u", sizeof(exp_cos_lookup)); - log_info("first value %u", exp_cos_lookup[0]); - log_info("mid value %u", exp_cos_lookup[EXP_COS_LUT_SIZE/2]); - log_info("last value %u", exp_cos_lookup[EXP_COS_LUT_SIZE-1]); - io_printf(IO_BUF, "Timing_mfvn_initialise: completed successfully\n"); return lut_address; diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c index ac118952a3e..62d98e0a98e 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c @@ -20,18 +20,6 @@ address_t timing_initialise(address_t address) { address_t lut_address = maths_copy_int16_lut_with_size(&address[0], EXP_SIN_LUT_SIZE, &exp_sin_lookup[0]); - // Copy LUTs from following memory -// address_t lut_address = address; -// exp_sin_lookup = maths_copy_int16_lut(&lut_address); -// exp_sin_lookup = maths_copy_int16_lut(&lut_address); -// address_t lut_address = &exp_sin_lookup; - - log_info("# of entries in exp_sin_lookup %u", sizeof(exp_sin_lookup)); - log_info("first value %u", exp_sin_lookup[0]); - log_info("mid value %u", exp_sin_lookup[EXP_SIN_LUT_SIZE/2]); - log_info("last value %u", exp_sin_lookup[EXP_SIN_LUT_SIZE-1]); - - io_printf(IO_BUF, "timing_pfpc_initialise: completed successfully\n"); return lut_address; From 26720badde895028c608c8ad04a7a5018b6732aa Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Tue, 8 Dec 2020 13:18:05 +0000 Subject: [PATCH 033/108] can set custom RB LS once again --- .../pyNN/models/neuron/synaptic_manager.py | 26 ++++++++++++++++--- .../pyNN/models/pynn_population_common.py | 14 ++++++++-- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/synaptic_manager.py b/spynnaker/pyNN/models/neuron/synaptic_manager.py index b039d4de2b0..628b694beba 100644 --- a/spynnaker/pyNN/models/neuron/synaptic_manager.py +++ b/spynnaker/pyNN/models/neuron/synaptic_manager.py @@ -592,10 +592,23 @@ def __update_ring_buffer_shifts_and_weight_scales( :param float weight_scale: """ if self.__ring_buffer_shifts is None: - self.__ring_buffer_shifts = \ - self._get_ring_buffer_to_input_left_shifts( - machine_vertex, machine_graph, machine_time_step, - weight_scale) + if (hasattr(machine_vertex, "rb_left_shifts") and + machine_vertex.rb_left_shifts is not None): + print("=" * 80) + print("Using given values for RB left shifts.") + self.__ring_buffer_shifts = machine_vertex.rb_left_shifts + print("RB left shifts for {:20}".format(machine_vertex.label), + "=", self.__ring_buffer_shifts) + print("-" * 80) + else: + print("=" * 80) + print("Computing values for RB left shifts for", machine_vertex.label) + self.__ring_buffer_shifts = \ + self._get_ring_buffer_to_input_left_shifts( + machine_vertex, machine_graph, machine_time_step, + weight_scale) + print("RB left shifts for {:20}".format(machine_vertex.label), + "=", self.__ring_buffer_shifts) self.__weight_scales = numpy.array([ self.__get_weight_scale(r) * weight_scale for r in self.__ring_buffer_shifts]) @@ -636,6 +649,11 @@ def write_data_spec( spec, post_vertex_slice, all_syn_block_sz, machine_graph, machine_vertex) + # Setting custom RB LS + if (self.__ring_buffer_shifts is None and + hasattr(application_vertex, "rb_left_shifts")): + machine_vertex.rb_left_shifts = application_vertex.rb_left_shifts + self.__update_ring_buffer_shifts_and_weight_scales( machine_vertex, machine_graph, machine_time_step, weight_scale) diff --git a/spynnaker/pyNN/models/pynn_population_common.py b/spynnaker/pyNN/models/pynn_population_common.py index 8584aba26ee..9eb0d0f30e1 100644 --- a/spynnaker/pyNN/models/pynn_population_common.py +++ b/spynnaker/pyNN/models/pynn_population_common.py @@ -93,6 +93,14 @@ def __init__( # pylint: disable=too-many-arguments size = self.__roundsize(size, label) + # Getting custom RB LS + if (additional_parameters is not None and + "rb_left_shifts" in additional_parameters.keys()): + rb_left_shifts = additional_parameters['rb_left_shifts'] + del additional_parameters['rb_left_shifts'] + else: + rb_left_shifts = None + # Use a provided model to create a vertex if isinstance(model, AbstractPyNNModel): if size is not None and size <= 0: @@ -129,8 +137,10 @@ def __init__( raise ConfigurationException( "Model must be either an AbstractPyNNModel or an" " ApplicationVertex") - - # Introspect properties of the vertex + # Setting custom RB LS + if rb_left_shifts is not None: + self.__vertex.rb_left_shifts = rb_left_shifts + # Introspect properties of the vertex self._vertex_population_settable = \ isinstance(self.__vertex, AbstractPopulationSettable) self._vertex_population_initializable = \ From 3c3e2081c481de889c1b11fe22a0629ffa671627 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Wed, 9 Dec 2020 12:40:14 +0000 Subject: [PATCH 034/108] removed del from dict. now can pass same dict to multiple pops --- spynnaker/pyNN/models/pynn_population_common.py | 1 - 1 file changed, 1 deletion(-) diff --git a/spynnaker/pyNN/models/pynn_population_common.py b/spynnaker/pyNN/models/pynn_population_common.py index 9eb0d0f30e1..59b32ef5122 100644 --- a/spynnaker/pyNN/models/pynn_population_common.py +++ b/spynnaker/pyNN/models/pynn_population_common.py @@ -97,7 +97,6 @@ def __init__( if (additional_parameters is not None and "rb_left_shifts" in additional_parameters.keys()): rb_left_shifts = additional_parameters['rb_left_shifts'] - del additional_parameters['rb_left_shifts'] else: rb_left_shifts = None From f3ae48c3bb50c3896d5c12ecc653e55fb7836471 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Wed, 9 Dec 2020 12:40:58 +0000 Subject: [PATCH 035/108] better saving of figures and returning of variables from plasticity common --- .../pyNN/models/neuron/plasticity/stdp/common.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py index 9ae73375c51..f96e6583b97 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py @@ -135,14 +135,16 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, plt.plot(t, out_float, label='float') # plt.plot(t,out_fixed, label='fixed') plt.legend() - plt.show() + plt.title("pf-PC LUT") + plt.savefig("figures/write_pfpc_lut.png") + # plt.show() + return t, out_float else: # exp_fix_array_int16 = numpy.asarray( # final_exp_fix, dtype="uint16").view("uint32") spec.write_array(final_exp_fix, data_type=DataType.INT16) - def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, fixed_point_one=STDP_FIXED_POINT_ONE): # Add this to function arguments in the future @@ -196,7 +198,10 @@ def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, plt.plot(plot_times, out_float, label='float') # plt.plot(t,out_fixed, label='fixed') plt.legend() - plt.show() + plt.title("mf-VN LUT") + plt.savefig("figures/write_mfvn_lut.png") + # plt.show() + return plot_times, out_float else: # exp_fix_array_int16 = numpy.asarray( # final_exp_fix, dtype="uint16").view("uint32") From f4eb254db92651f0906b4c269c5641c0d0a591ea Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Thu, 10 Dec 2020 13:12:01 +0000 Subject: [PATCH 036/108] correct use of LUTs using old-style functions --- .../src/neuron/plasticity/stdp/maths.h | 10 ++++++++++ .../stdp/timing_dependence/timing_mfvn_impl.h | 4 ++-- .../stdp/timing_dependence/timing_pfpc_impl.c | 1 - .../stdp/timing_dependence/timing_pfpc_impl.h | 4 ++-- .../models/neuron/plasticity/stdp/common.py | 20 ++++++++++++++++++- 5 files changed, 33 insertions(+), 6 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/maths.h b/neural_modelling/src/neuron/plasticity/stdp/maths.h index 31e15f8e5e9..18169cdda96 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/maths.h +++ b/neural_modelling/src/neuron/plasticity/stdp/maths.h @@ -103,6 +103,16 @@ static inline int32_t maths_lut_exponential_decay( return (lut_index < lut->size) ? lut->values[lut_index] : 0; } +static inline int32_t maths_lut_exponential_decay_time_shifted( + uint32_t time, const uint32_t time_shift, const uint32_t lut_size, + const int16_t *lut) { + // Calculate lut index + uint32_t lut_index = time >> time_shift; + + // Return value from LUT + return (lut_index < lut_size) ? lut[lut_index] : 0; +} + //! \brief Clamp to fit in number of bits //! \param[in] x: The value to clamp //! \param[in] shift: Width of the field to clamp the value to fit in diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h index a91e77a7a9a..ff20496a8a6 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h @@ -27,8 +27,8 @@ typedef int16_t pre_trace_t; // Helper macros for looking up decays #define EXP_COS_LOOKUP(time) \ - maths_lut_exponential_decay( \ - time, exp_cos_lookup) + maths_lut_exponential_decay_time_shifted( \ + time, TAU_PLUS_TIME_SHIFT, EXP_COS_LUT_SIZE, exp_cos_lookup) //#define DECAY_LOOKUP_TAU_MINUS(time) \ // maths_lut_exponential_decay( \ // time, TAU_MINUS_TIME_SHIFT, TAU_MINUS_SIZE, tau_minus_lookup) diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c index 62d98e0a98e..36e66e91952 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c @@ -14,7 +14,6 @@ address_t timing_initialise(address_t address) { io_printf(IO_BUF, "timing_pfpc_initialise: starting\n"); io_printf(IO_BUF, "\tCerebellum PFPC rule\n"); - // **TODO** assert number of neurons is less than max // Copy LUTs from following memory address_t lut_address = maths_copy_int16_lut_with_size(&address[0], EXP_SIN_LUT_SIZE, diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index c2e91cedf06..d9e68873a5e 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -27,8 +27,8 @@ typedef int16_t pre_trace_t; // Helper macros for looking up decays #define EXP_SIN_LOOKUP(time) \ - maths_lut_exponential_decay( \ - time, exp_sin_lookup) + maths_lut_exponential_decay_time_shifted( \ + time, TAU_PLUS_TIME_SHIFT, EXP_SIN_LUT_SIZE, exp_sin_lookup) //#define DECAY_LOOKUP_TAU_MINUS(time) \ // maths_lut_exponential_decay( \ // time, TAU_MINUS_TIME_SHIFT, TAU_MINUS_SIZE, tau_minus_lookup) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py index f96e6583b97..ee9d9537277 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py @@ -35,6 +35,7 @@ def float_to_fixed(value, fixed_point_one): return int(round(float(value) * float(fixed_point_one))) + def get_lut_provenance( pre_population_label, post_population_label, rule_name, entry_name, param_name, last_entry): @@ -55,6 +56,7 @@ def get_lut_provenance( param_name, rule_name, pre_population_label, post_population_label, last_entry))) + def get_exp_lut_array(time_step, time_constant, shift=0): """ :param int time_step: @@ -137,14 +139,30 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, plt.legend() plt.title("pf-PC LUT") plt.savefig("figures/write_pfpc_lut.png") + + plt.plot(t, out_fixed, label='fixed int16') + plt.legend() + plt.title("pf-PC LUT") + plt.savefig("figures/write_pfpc_lut_final_exp_fix.png") # plt.show() + + out_fixed = numpy.array(out_fixed) + out_float = numpy.array(out_float) + compare_t_values = numpy.array([15, 20, 30, 35, 45, 47, + 99, 115, 135, 140, 150]) + print("LUT VALUES TO COMPARE TO SPINNAKER:") + print("TIME DELTAS | FIXED MULTIPLIERS | FLOAT MULTIPLIERS") + for x, y, z, in zip(compare_t_values, out_fixed[compare_t_values], out_float[compare_t_values]): + print("{:8} | {:8} | {:8.4f}".format(x, y, z)) + return t, out_float else: # exp_fix_array_int16 = numpy.asarray( # final_exp_fix, dtype="uint16").view("uint32") - + # spec.write_array(exp_fix_array_int16) spec.write_array(final_exp_fix, data_type=DataType.INT16) + def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, fixed_point_one=STDP_FIXED_POINT_ONE): # Add this to function arguments in the future From 9a8baa2d3c20331bc7076bbd74f36a4a9a10b806 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Mon, 14 Dec 2020 14:56:42 +0000 Subject: [PATCH 037/108] longer running example of cerebellum + spinngym. more optimisations and checks to come --- .../plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c index 8a394ecc824..53c07435e82 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c @@ -117,12 +117,12 @@ static inline final_state_t _plasticity_update_synapse( post_event_window_t post_window = post_events_get_window_delayed( post_event_history, window_begin_time, window_end_time); - log_info("\tPerforming deferred synapse update at time:%u", time); - log_info("\t\tbegin_time:%u, end_time:%u - prev_time:%u, num_events:%u", - window_begin_time, window_end_time, post_window.prev_time, - post_window.num_events); if (print_plasticity){ + log_info("\tPerforming deferred synapse update at time:%u", time); + log_info("\t\tbegin_time:%u, end_time:%u - prev_time:%u, num_events:%u", + window_begin_time, window_end_time, post_window.prev_time, + post_window.num_events); io_printf(IO_BUF, " Printing CF history\n"); print_event_history(post_event_history); } From f527571d7a3879c308ba555398ed345faddd3c59 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Wed, 16 Dec 2020 09:48:32 +0000 Subject: [PATCH 038/108] resolving weird behaviour with RandomDelays and FromListconnector --- .../neural_projections/connectors/from_list_connector.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/spynnaker/pyNN/models/neural_projections/connectors/from_list_connector.py b/spynnaker/pyNN/models/neural_projections/connectors/from_list_connector.py index 5ee795cf274..2e5290724a5 100644 --- a/spynnaker/pyNN/models/neural_projections/connectors/from_list_connector.py +++ b/spynnaker/pyNN/models/neural_projections/connectors/from_list_connector.py @@ -15,6 +15,7 @@ import logging import numpy +from pyNN.random import RandomDistribution from spinn_front_end_common.utilities.constants import \ MICRO_TO_MILLISECOND_CONVERSION @@ -83,7 +84,10 @@ def __init__(self, conn_list, safe=True, callback=None, verbose=False, @overrides(AbstractConnector.get_delay_maximum) def get_delay_maximum(self, synapse_info): if self.__delays is None: - return numpy.max(synapse_info.delays) + if isinstance(synapse_info.delays, RandomDistribution): + return synapse_info.delays.parameters['high'] + else: + return numpy.max(synapse_info.delays) else: return numpy.max(self.__delays) From e933e78e0ef499348a7bb33c21e284661babdf92 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Fri, 15 Jan 2021 14:57:58 +0000 Subject: [PATCH 039/108] added ability to scale the kernels via the alpha parameter --- .../timing_dependence_mfvn.py | 9 ++++++--- .../timing_dependence_pfpc.py | 19 ++++++++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py index a8367e0f5e3..29c160f42f8 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py @@ -19,12 +19,14 @@ class TimingDependenceMFVN(AbstractTimingDependence): "_tau_plus", "_tau_plus_last_entry", "_beta", - "_sigma" + "_sigma", + "_kernel_scaling" ] - def __init__(self, tau_plus=20.0, tau_minus=20.0, beta=10, sigma=200): + def __init__(self, tau_plus=20.0, tau_minus=20.0, beta=10, sigma=200, kernel_scaling=1.0): self._tau_plus = tau_plus self._tau_minus = tau_minus + self._kernel_scaling = kernel_scaling self._synapse_structure = SynapseStructureWeightOnly() @@ -90,7 +92,8 @@ def write_parameters(self, spec, machine_time_step, weight_scales): beta=self._beta, time_probe=None, lut_size=LUT_SIZE, - shift=0) + shift=0, + kernel_scaling=self._kernel_scaling) @property def synaptic_structure(self): diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index 7a71b398699..1027beaac79 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -2,15 +2,16 @@ from spynnaker.pyNN.models.neuron.plasticity.stdp.common \ import write_pfpc_lut, get_lut_provenance from .abstract_timing_dependence import AbstractTimingDependence -from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure\ +from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure \ import SynapseStructureWeightOnly - import logging + logger = logging.getLogger(__name__) LUT_SIZE = 256 + class TimingDependencePFPC(AbstractTimingDependence): __slots__ = [ "_synapse_structure", @@ -18,13 +19,15 @@ class TimingDependencePFPC(AbstractTimingDependence): "_tau_minus_last_entry", "_tau_plus", "_tau_plus_last_entry", - "_t_peak"] + "_t_peak", + "_kernel_scaling"] def __init__(self, tau_plus=20.0, tau_minus=20.0, - t_peak=100): + t_peak=100, kernel_scaling=1.0): self._tau_plus = tau_plus self._tau_minus = tau_minus self._t_peak = t_peak + self._kernel_scaling = kernel_scaling self._synapse_structure = SynapseStructureWeightOnly() @@ -59,11 +62,11 @@ def vertex_executable_suffix(self): def pre_trace_n_bytes(self): # Here we will record the last 16 spikes, these will be 32-bit quantities, - return (16 * 4) + (2 * 16) # 16 4-byte entries, plus one counter for the number of spikes + return (16 * 4) + (2 * 16) # 16 4-byte entries, plus one counter for the number of spikes @overrides(AbstractTimingDependence.get_parameters_sdram_usage_in_bytes) def get_parameters_sdram_usage_in_bytes(self): - return 2 * LUT_SIZE #in bytes: 256 * 16 bit values + return 2 * LUT_SIZE # in bytes: 256 * 16 bit values @property def n_weight_terms(self): @@ -82,7 +85,9 @@ def write_parameters(self, spec, machine_time_step, weight_scales): peak_time=self._t_peak, time_probe=None, lut_size=LUT_SIZE, - shift=0) + shift=0, + kernel_scaling=self._kernel_scaling + ) @property def synaptic_structure(self): From dd06842cd913bac013355a9ceee57105ee154e9b Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Mon, 18 Jan 2021 14:06:48 +0000 Subject: [PATCH 040/108] [PF-PC and MF-VN] added ability to scale LUT kernels --- .../models/neuron/plasticity/stdp/common.py | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py index ee9d9537277..ed2ff8ae243 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py @@ -83,7 +83,7 @@ def get_exp_lut_array(time_step, time_constant, shift=0): def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, - fixed_point_one=STDP_FIXED_POINT_ONE): + fixed_point_one=STDP_FIXED_POINT_ONE, kernel_scaling=1.0): # Add this to function arguments in the future machine_time_step = 1.0 sin_pwr = 20 @@ -92,7 +92,7 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, time_constant = peak_time / math.atan(sin_pwr) inv_tau = (1.0 / float(time_constant)) # * (machine_time_step / 1000.0) - # # caluclate time of peak (from differentiating kernel and setting to zero) + # # calculate time of peak (from differentiating kernel and setting to zero) # kernel_peak_time = math.atan(20) / inv_tau # evaluate peak value of kernel to normalise LUT @@ -115,7 +115,7 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, exp_float = 0 else: # Evaluate kernel - exp_float = math.exp(-value) * math.sin(value) ** sin_pwr / kernel_peak_value + exp_float = (math.exp(-value) * math.sin(value) ** sin_pwr / kernel_peak_value) * kernel_scaling # Convert to fixed-point exp_fix = float_to_fixed(exp_float, fixed_point_one) @@ -134,6 +134,9 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, if spec is None: print("peak: time {}, value {}".format(peak_time, kernel_peak_value)) t = numpy.arange(0, lut_size) + out_fixed = numpy.array(out_fixed) + out_float = numpy.array(out_float) + plt.plot(t, out_float, label='float') # plt.plot(t,out_fixed, label='fixed') plt.legend() @@ -146,8 +149,6 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, plt.savefig("figures/write_pfpc_lut_final_exp_fix.png") # plt.show() - out_fixed = numpy.array(out_fixed) - out_float = numpy.array(out_float) compare_t_values = numpy.array([15, 20, 30, 35, 45, 47, 99, 115, 135, 140, 150]) print("LUT VALUES TO COMPARE TO SPINNAKER:") @@ -157,14 +158,11 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, return t, out_float else: - # exp_fix_array_int16 = numpy.asarray( - # final_exp_fix, dtype="uint16").view("uint32") - # spec.write_array(exp_fix_array_int16) spec.write_array(final_exp_fix, data_type=DataType.INT16) def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, - fixed_point_one=STDP_FIXED_POINT_ONE): + fixed_point_one=STDP_FIXED_POINT_ONE, kernel_scaling=1.0): # Add this to function arguments in the future machine_time_step = 1.0 cos_pwr = 2 @@ -194,7 +192,7 @@ def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, exp_float = 0 else: # Evaluate kernel - exp_float = math.exp(-abs(value * beta)) * math.cos(value) ** cos_pwr / kernel_peak_value + exp_float = (math.exp(-abs(value * beta)) * math.cos(value) ** cos_pwr / kernel_peak_value) * kernel_scaling # Convert to fixed-point exp_fix = float_to_fixed(exp_float, fixed_point_one) @@ -213,15 +211,22 @@ def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, if spec is None: print("peak: time {}, value {}".format(peak_time, kernel_peak_value)) + out_fixed = numpy.array(out_fixed) + out_float = numpy.array(out_float) + plt.plot(plot_times, out_float, label='float') # plt.plot(t,out_fixed, label='fixed') plt.legend() plt.title("mf-VN LUT") plt.savefig("figures/write_mfvn_lut.png") + + compare_t_values = numpy.array([15, 20, 30, 35, 45, 47, + 99, 115, 135, 140, 150]) + print("LUT VALUES TO COMPARE TO SPINNAKER:") + print("TIME DELTAS | FIXED MULTIPLIERS | FLOAT MULTIPLIERS") + for x, y, z, in zip(compare_t_values, out_fixed[compare_t_values], out_float[compare_t_values]): + print("{:8} | {:8} | {:8.4f}".format(x, y, z)) # plt.show() return plot_times, out_float else: - # exp_fix_array_int16 = numpy.asarray( - # final_exp_fix, dtype="uint16").view("uint32") - spec.write_array(final_exp_fix, data_type=DataType.INT16) From c1a0b5917421b6d4de4ef6218b103eebb6081682 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Mon, 22 Feb 2021 09:25:56 +0000 Subject: [PATCH 041/108] no TDMA or tx_offset. Everything is as fast as possible --- neural_modelling/src/neuron/neuron.c | 5 +++-- .../src/spike_source/poisson/spike_source_poisson.c | 12 ++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/neural_modelling/src/neuron/neuron.c b/neural_modelling/src/neuron/neuron.c index cd262deb7ff..3c05a4b5540 100644 --- a/neural_modelling/src/neuron/neuron.c +++ b/neural_modelling/src/neuron/neuron.c @@ -171,8 +171,9 @@ void neuron_do_timestep_update(timer_t time, uint timer_count) { // EXPORTED // synapse_dynamics_process_post_synaptic_event(time, neuron_index); if (use_key) { - tdma_processing_send_packet( - (key | neuron_index), 0, NO_PAYLOAD, timer_count); + spin1_send_mc_packet((key | neuron_index), 0, NO_PAYLOAD); +// tdma_processing_send_packet( +// (key | neuron_index), 0, NO_PAYLOAD, timer_count); } } else { log_debug("the neuron %d has been determined to not spike", diff --git a/neural_modelling/src/spike_source/poisson/spike_source_poisson.c b/neural_modelling/src/spike_source/poisson/spike_source_poisson.c index 44c552f78bc..3ac935e2b61 100644 --- a/neural_modelling/src/spike_source/poisson/spike_source_poisson.c +++ b/neural_modelling/src/spike_source/poisson/spike_source_poisson.c @@ -635,8 +635,10 @@ static void process_fast_source( if (ssp_params.has_key) { // Send spikes const uint32_t spike_key = ssp_params.key | s_id; - tdma_processing_send_packet( - spike_key, num_spikes, WITH_PAYLOAD, timer_count); + spin1_send_mc_packet( + spike_key, num_spikes, WITH_PAYLOAD); +// tdma_processing_send_packet( +// spike_key, num_spikes, WITH_PAYLOAD, timer_count); } } } @@ -658,8 +660,10 @@ static void process_slow_source( // if no key has been given, do not send spike to fabric. if (ssp_params.has_key) { // Send package - tdma_processing_send_packet( - ssp_params.key | s_id, 0, NO_PAYLOAD, timer_count); + spin1_send_mc_packet( + ssp_params.key | s_id, 0, NO_PAYLOAD); +// tdma_processing_send_packet( +// ssp_params.key | s_id, 0, NO_PAYLOAD, timer_count); } // Update time to spike (note, this might not get us back above From a7a01ba87693151962d72cd98746b8ce56da995d Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Mon, 22 Feb 2021 09:28:00 +0000 Subject: [PATCH 042/108] Neuron, then synapse with disabled IRQs --- neural_modelling/src/neuron/c_main.c | 39 ++++++++++++++++------------ 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/neural_modelling/src/neuron/c_main.c b/neural_modelling/src/neuron/c_main.c index 40873f90178..b14d356e0f5 100644 --- a/neural_modelling/src/neuron/c_main.c +++ b/neural_modelling/src/neuron/c_main.c @@ -203,7 +203,7 @@ static bool initialise(void) { &clear_input_buffers_of_late_packets_init)) { return false; } - + clear_input_buffers_of_late_packets_init = false; // set up direct synapses address_t direct_synapses_address; if (!direct_synapses_initialise( @@ -289,7 +289,7 @@ void timer_callback(uint timer_count, UNUSED uint unused) { profiler_write_entry_disable_irq_fiq(PROFILER_ENTER | PROFILER_TIMER); time++; - last_rewiring_time++; +// last_rewiring_time++; // This is the part where I save the input and output indices // from the circular buffer @@ -324,25 +324,30 @@ void timer_callback(uint timer_count, UNUSED uint unused) { return; } - // First do synapses timestep update, as this is time-critical - synapses_do_timestep_update(time); // Then do rewiring - if (rewiring && - ((last_rewiring_time >= rewiring_period && !synaptogenesis_is_fast()) - || synaptogenesis_is_fast())) { - last_rewiring_time = 0; - // put flag in spike processing to do synaptic rewiring - if (synaptogenesis_is_fast()) { - spike_processing_do_rewiring(rewiring_period); - } else { - spike_processing_do_rewiring(1); - } - count_rewire_attempts++; - } - + // Squeezing out performance +// if (rewiring && +// ((last_rewiring_time >= rewiring_period && !synaptogenesis_is_fast()) +// || synaptogenesis_is_fast())) { +// last_rewiring_time = 0; +// // put flag in spike processing to do synaptic rewiring +// if (synaptogenesis_is_fast()) { +// spike_processing_do_rewiring(rewiring_period); +// } else { +// spike_processing_do_rewiring(1); +// } +// count_rewire_attempts++; +// } + + uint32_t state = spin1_irq_disable(); // Now do neuron time step update neuron_do_timestep_update(time, timer_count); + // First do synapses timestep update, as this is time-critical + synapses_do_timestep_update(time); + + // Re-enable the interrupts + spin1_mode_restore(state); profiler_write_entry_disable_irq_fiq(PROFILER_EXIT | PROFILER_TIMER); } From e03d7361e5fdf80e8f2f741368efe79397069fce Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Mon, 22 Feb 2021 09:30:17 +0000 Subject: [PATCH 043/108] no flushing of spikes --- .../src/neuron/spike_processing.c | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/neural_modelling/src/neuron/spike_processing.c b/neural_modelling/src/neuron/spike_processing.c index 314e4de9686..3d88d02aeae 100644 --- a/neural_modelling/src/neuron/spike_processing.c +++ b/neural_modelling/src/neuron/spike_processing.c @@ -352,13 +352,13 @@ static void dma_complete_callback(UNUSED uint unused, uint tag) { bool plastic_only = true; // If rewiring, do rewiring first - for (uint32_t i = 0; i < n_rewires; i++) { - if (synaptogenesis_row_restructure(time, current_buffer->row)) { - write_back = true; - plastic_only = false; - n_successful_rewires++; - } - } +// for (uint32_t i = 0; i < n_rewires; i++) { +// if (synaptogenesis_row_restructure(time, current_buffer->row)) { +// write_back = true; +// plastic_only = false; +// n_successful_rewires++; +// } +// } // Process synaptic row repeatedly for any upcoming spikes while (n_spikes > 0) { @@ -423,10 +423,10 @@ void spike_processing_clear_input_buffer(timer_t time) { // Record the count whether clearing or not for provenance count_input_buffer_packets_late += in_spikes_size(); - - if (clear_input_buffers_of_late_packets) { - in_spikes_clear(); - } +// +// if (clear_input_buffers_of_late_packets) { +// in_spikes_clear(); +// } } bool spike_processing_initialise( // EXPORTED @@ -446,7 +446,7 @@ bool spike_processing_initialise( // EXPORTED } dma_busy = false; clear_input_buffers_of_late_packets = - clear_input_buffers_of_late_packets_init; + false; next_buffer_to_fill = 0; buffer_being_read = N_DMA_BUFFERS; p_per_ts_region = packets_per_timestep_region; From d5e726b9976b6af860f2310a9ac6156a2ded5b47 Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Mon, 22 Feb 2021 11:02:30 +0000 Subject: [PATCH 044/108] added SpiNNCer-style custom provenance gathering --- neural_modelling/src/neuron/c_main.c | 57 ++++++++++++- .../src/neuron/spike_processing.c | 42 ++++++++++ .../src/neuron/spike_processing.h | 18 +++++ neural_modelling/src/neuron/spike_profiling.h | 79 +++++++++++++++++++ neural_modelling/src/neuron/synapses.c | 7 +- .../neuron/population_machine_vertex.py | 56 +++++++++++++ 6 files changed, 254 insertions(+), 5 deletions(-) create mode 100644 neural_modelling/src/neuron/spike_profiling.h diff --git a/neural_modelling/src/neuron/c_main.c b/neural_modelling/src/neuron/c_main.c index b14d356e0f5..1cb3da76c00 100644 --- a/neural_modelling/src/neuron/c_main.c +++ b/neural_modelling/src/neuron/c_main.c @@ -43,6 +43,7 @@ #include "structural_plasticity/synaptogenesis_dynamics.h" #include "profile_tags.h" #include "direct_synapses.h" +#include "spike_profiling.h" #include #include @@ -58,6 +59,25 @@ #error APPLICATION_NAME_HASH was undefined. Make sure you define this\ constant #endif +// Custom provenance from SpiNNCer +// Counters to assess maximum spikes per timer tick +uint32_t max_spikes_in_a_tick = 0; +uint32_t max_dmas_in_a_tick = 0; +uint32_t max_pipeline_restarts = 0; + +uint32_t timer_callback_completed = 20000000; +uint32_t temp_timer_callback_completed = 0; +uint32_t spike_pipeline_deactivated = 0; + +uint32_t last_spikes = 0; +uint32_t last_restarts = 0; +uint32_t deactivation_time = 0; + +struct spike_holder_t spike_counter; +struct spike_holder_t spike_cache; +struct spike_holder_t spike_counter_inh; +struct spike_holder_t spike_cache_inh; + //! The provenance information written on application shutdown. struct neuron_provenance { @@ -83,6 +103,12 @@ struct neuron_provenance { uint32_t spike_processing_get_max_filled_input_buffer_size; //! the number of times the TDMA fully missed its slots uint32_t n_tdma_mises; + //! Custom provenance from SpiNNCer + uint32_t max_spikes_in_a_tick; + uint32_t max_dmas_in_a_tick; + uint32_t max_pipeline_restarts; + uint32_t timer_callback_completed; + uint32_t spike_pipeline_deactivated; }; //! values for the priority for each callback @@ -109,7 +135,7 @@ static uint32_t simulation_ticks = 0; static uint32_t infinite_run; //! Timer callbacks since last rewiring -static int32_t last_rewiring_time = 0; +//static int32_t last_rewiring_time = 0; //! Rewiring period represented as an integer static int32_t rewiring_period = 0; @@ -151,7 +177,12 @@ static void c_main_store_provenance_data(address_t provenance_region) { prov->spike_processing_get_max_filled_input_buffer_size = spike_processing_get_max_filled_input_buffer_size(); prov->n_tdma_mises = tdma_processing_times_behind(); - + // Custom provenance from SpiNNCer + prov->max_spikes_in_a_tick = max_spikes_in_a_tick; + prov->max_dmas_in_a_tick = max_dmas_in_a_tick; + prov->max_pipeline_restarts = max_pipeline_restarts; + prov->timer_callback_completed = timer_callback_completed; + prov->spike_pipeline_deactivated = spike_pipeline_deactivated; log_debug("finished other provenance data"); } @@ -284,6 +315,28 @@ void resume_callback(void) { //! executed since start of simulation //! \param[in] unused: unused parameter kept for API consistency void timer_callback(uint timer_count, UNUSED uint unused) { + // Custom provenance from SpiNNCer + // Get number of spikes in last tick, and reset spike counter + last_spikes = spike_processing_get_and_reset_spikes_this_tick(); + uint32_t last_dmas = spike_processing_get_and_reset_dmas_this_tick(); + last_restarts = + spike_processing_get_and_reset_pipeline_restarts_this_tick(); + deactivation_time = spike_processing_get_pipeline_deactivation_time(); + + // cache and flush spike counters + // /localhome/mbax3pb2/py3_venv/spinnaker/sPyNNaker/neural_modelling/src/neuron/spike_profiling.h + spike_profiling_cache_and_flush_spike_holder(&spike_counter, + &spike_cache); + spike_profiling_cache_and_flush_spike_holder(&spike_counter_inh, + &spike_cache_inh); + + if (last_spikes > max_spikes_in_a_tick){ + max_spikes_in_a_tick = last_spikes; + max_dmas_in_a_tick = last_dmas; + max_pipeline_restarts = last_restarts; + timer_callback_completed = temp_timer_callback_completed; + spike_pipeline_deactivated = deactivation_time; + } global_timer_count = timer_count; profiler_write_entry_disable_irq_fiq(PROFILER_ENTER | PROFILER_TIMER); diff --git a/neural_modelling/src/neuron/spike_processing.c b/neural_modelling/src/neuron/spike_processing.c index 3d88d02aeae..6be8af0b030 100644 --- a/neural_modelling/src/neuron/spike_processing.c +++ b/neural_modelling/src/neuron/spike_processing.c @@ -28,6 +28,13 @@ #include #include +// Custom provenance from SpiNNCer +// counter for number of spikes between timer events +uint32_t spikes_this_tick = 0; +uint32_t dmas_this_tick = 0; +uint32_t pipeline_restarts_this_tick = 0; +uint32_t spike_pipeline_deactivation_time = 0; + //! DMA buffer structure combines the row read from SDRAM with information //! about the read. typedef struct dma_buffer { @@ -293,6 +300,9 @@ static inline void setup_synaptic_dma_write( static void multicast_packet_received_callback(uint key, uint payload) { p_per_ts_struct.packets_this_time_step += 1; + // Increment the count of number of spikes received this tick by this core + spikes_this_tick++; + // handle the 2 cases separately if (payload == 0) { log_debug( @@ -329,6 +339,7 @@ static void multicast_packet_received_callback(uint key, uint payload) { static void dma_complete_callback(UNUSED uint unused, uint tag) { // increment the dma complete count for provenance generation + dmas_this_tick++; dma_complete_count++; log_debug("DMA transfer complete at time %u with tag %u", time, tag); @@ -400,6 +411,9 @@ void user_event_callback(UNUSED uint unused0, UNUSED uint unused1) { dma_n_rewires = 0; dma_n_spikes = 0; + // Increment counter for spike processing pipeline restarts + pipeline_restarts_this_tick++; + if (buffer_being_read < N_DMA_BUFFERS) { // If the DMA buffer is full of valid data, attempt to reuse it on the // next data to be used, as this might be able to make use of the buffer @@ -515,3 +529,31 @@ bool spike_processing_do_rewiring(int number_of_rewires) { spin1_mode_restore(cpsr); return true; } + +// Custom provenance from SpiNNCer +uint32_t spike_processing_get_and_reset_spikes_this_tick(){ + + uint32_t spikes_to_return = spikes_this_tick; + spikes_this_tick = 0; + + return spikes_to_return; +} + +uint32_t spike_processing_get_and_reset_dmas_this_tick(){ + + uint32_t dmas_to_return = dmas_this_tick; + dmas_this_tick = 0; + + return dmas_to_return; +} + +uint32_t spike_processing_get_and_reset_pipeline_restarts_this_tick(){ + uint32_t pipeline_restarts_to_return = pipeline_restarts_this_tick; + pipeline_restarts_this_tick = 0; + + return pipeline_restarts_to_return; +} + +uint32_t spike_processing_get_pipeline_deactivation_time(){ + return spike_pipeline_deactivation_time; +} diff --git a/neural_modelling/src/neuron/spike_processing.h b/neural_modelling/src/neuron/spike_processing.h index 0958e78b874..ab124276556 100644 --- a/neural_modelling/src/neuron/spike_processing.h +++ b/neural_modelling/src/neuron/spike_processing.h @@ -74,4 +74,22 @@ void spike_processing_clear_input_buffer(timer_t time); //! \return the max size the input buffer reached uint32_t spike_processing_get_max_filled_input_buffer_size(void); +// Custom provenance from SpiNNCer + +//! \brief get number of spikes received since last timer event +//! \return uint32_t number of spikes +uint32_t spike_processing_get_and_reset_spikes_this_tick(); + +//! \brief get number of dmas completed since last timer event +//! \return uint32_t number of DMAs +uint32_t spike_processing_get_and_reset_dmas_this_tick(); + +//! \brief get number of time pipeline was restarted since last timer event +//! \return uint32_t number of pipeline restarts +uint32_t spike_processing_get_and_reset_pipeline_restarts_this_tick(); + +//! \brief get time from T1 clock at which spike pipeline completed +//! \return uint32_t pipeline deactivation time +uint32_t spike_processing_get_pipeline_deactivation_time(); + #endif // _SPIKE_PROCESSING_H_ diff --git a/neural_modelling/src/neuron/spike_profiling.h b/neural_modelling/src/neuron/spike_profiling.h new file mode 100644 index 00000000000..7b21687caf7 --- /dev/null +++ b/neural_modelling/src/neuron/spike_profiling.h @@ -0,0 +1,79 @@ +#include + +typedef struct spike_holder_t { + uint8_t spikes_a; + uint8_t spikes_b; + uint8_t spikes_c; + uint8_t spikes_d; +} spike_holder_t; + +static inline void spike_profiling_cache_and_flush_spike_holder( + struct spike_holder_t* counter_spikes, + struct spike_holder_t* cache_levels) { + + cache_levels->spikes_a = counter_spikes->spikes_a; + cache_levels->spikes_b = counter_spikes->spikes_b; + cache_levels->spikes_c = counter_spikes->spikes_c; + cache_levels->spikes_d = counter_spikes->spikes_d; + + // zero counters + counter_spikes->spikes_a = 0; + counter_spikes->spikes_b = 0; + counter_spikes->spikes_c = 0; + counter_spikes->spikes_d = 0; +} + +static inline void spike_profiling_add_count(uint32_t row_length, + struct spike_holder_t* spike_counter) { + + uint32_t a = 0; + uint32_t b = 1; + uint32_t c = 5; + + if (row_length <= a) { + spike_counter->spikes_a++; + } else if (row_length > a && row_length <= b) { + spike_counter->spikes_b++; + } else if (row_length > b && row_length <= c) { + spike_counter->spikes_c++; + } else if (row_length > c) { + spike_counter->spikes_d++; + } +} + +static inline int32_t spike_profiling_get_spike_holder_as_int( + struct spike_holder_t spikes) { + + union { + int32_t inty; + struct spike_holder_t sh; + } x; + + x.sh = spikes; + + return x.inty; +} + +static inline accum spike_profiling_get_spike_holder_as_accum( + struct spike_holder_t spikes) { + union { + accum acc; + struct spike_holder_t sh; + } x; + x.sh = spikes; + + return x.acc; +} + +static inline void spike_profiling_print_spikes_from_spike_holder( + struct spike_holder_t spikes_orig) { + io_printf(IO_BUF, "Spikes from input: a %u, b %u, c %u, d %u \n", + spikes_orig.spikes_a, spikes_orig.spikes_b, spikes_orig.spikes_c, + spikes_orig.spikes_d); +} + +static inline void spike_profiling_print_spikes_from_int(int32_t output) { + io_printf(IO_BUF, "Spikes from output: a %d, b %d, c %d, d %d \n", + (output & 0xFF), (output >> 8 & 0xFF), (output >> 16 & 0xFF), + (output >> 24 & 0xFF)); +} diff --git a/neural_modelling/src/neuron/synapses.c b/neural_modelling/src/neuron/synapses.c index ea07cbf1bea..6d01c3bf0aa 100644 --- a/neural_modelling/src/neuron/synapses.c +++ b/neural_modelling/src/neuron/synapses.c @@ -338,7 +338,8 @@ bool synapses_initialise( } void synapses_do_timestep_update(timer_t time) { - print_ring_buffers(time); +// Squeezing out performance +// print_ring_buffers(time); // Disable interrupts to stop DMAs interfering with the ring buffers uint32_t state = spin1_irq_disable(); @@ -370,8 +371,8 @@ void synapses_do_timestep_update(timer_t time) { ring_buffers[ring_buffer_index] = 0; } } - - print_inputs(); +// Squeezing out performance +// print_inputs(); // Re-enable the interrupts spin1_mode_restore(state); diff --git a/spynnaker/pyNN/models/neuron/population_machine_vertex.py b/spynnaker/pyNN/models/neuron/population_machine_vertex.py index 16ef7719638..9f06e53de0b 100644 --- a/spynnaker/pyNN/models/neuron/population_machine_vertex.py +++ b/spynnaker/pyNN/models/neuron/population_machine_vertex.py @@ -79,6 +79,12 @@ class EXTRA_PROVENANCE_DATA_ENTRIES(Enum): INPUT_BUFFER_FILLED_SIZE = 13 # the number of tdma misses TDMA_MISSES = 14 + # Custom provenance from SpiNNCer + MAX_SPIKES_IN_A_TICK = 15 + MAX_DMAS_IN_A_TICK = 16 + MAX_PIPELINE_RESTARTS = 17 + TIMER_CALLBACK_COMPLETED = 18 + SPIKES_PIPELINE_ACTIVATED = 19 SATURATION_COUNT_NAME = "Times_synaptic_weights_have_saturated" SATURATION_COUNT_MESSAGE = ( @@ -269,6 +275,23 @@ def get_provenance_data_from_machine(self, transceiver, placement): tdma_misses = provenance_data[ self.EXTRA_PROVENANCE_DATA_ENTRIES.TDMA_MISSES.value] + # Custom provenance from SpiNNCer + max_spikes_in_a_tick = provenance_data[ + self.EXTRA_PROVENANCE_DATA_ENTRIES. + MAX_SPIKES_IN_A_TICK.value] + max_dmas_in_a_tick = provenance_data[ + self.EXTRA_PROVENANCE_DATA_ENTRIES. + MAX_DMAS_IN_A_TICK.value] + max_pipeline_restarts = provenance_data[ + self.EXTRA_PROVENANCE_DATA_ENTRIES. + MAX_PIPELINE_RESTARTS.value] + timer_callback_completed = provenance_data[ + self.EXTRA_PROVENANCE_DATA_ENTRIES. + TIMER_CALLBACK_COMPLETED.value] + spike_pipeline_deactivated = provenance_data[ + self.EXTRA_PROVENANCE_DATA_ENTRIES. + SPIKES_PIPELINE_ACTIVATED.value] + label, x, y, p, names = self._get_placement_details(placement) # translate into provenance data items @@ -345,6 +368,39 @@ def get_provenance_data_from_machine(self, transceiver, placement): "packets are filtered in the router to improve " "performance.".format( n_packets_filtered_by_bit_field_filter, x, y, p))))) + + # Custom provenance from SpiNNCer + provenance_items.append(ProvenanceDataItem( + self._add_name(names, + "MAX_SPIKES_IN_A_TICK"), + max_spikes_in_a_tick, + report=max_spikes_in_a_tick > 200, + message=( + "Max number of spikes for {} on {}, {}, {} " + "was {}. Empirically, we can deal with ~200 for real time " + "performance using a 1.0 ms timestep.".format( + label, x, y, p, max_spikes_in_a_tick)))) + provenance_items.append(ProvenanceDataItem( + self._add_name(names, + "MAX_DMAS_IN_A_TICK"), + max_dmas_in_a_tick)) + provenance_items.append(ProvenanceDataItem( + self._add_name(names, + "MAX_PIPELINE_RESTARTS"), + max_pipeline_restarts)) + provenance_items.append(ProvenanceDataItem( + self._add_name(names, + "MAX_PIPELINE_RESTARTS"), + max_pipeline_restarts)) + provenance_items.append(ProvenanceDataItem( + self._add_name(names, + "TIMER_CALLBACK_COMPLETED"), + timer_callback_completed)) + provenance_items.append(ProvenanceDataItem( + self._add_name(names, + "SPIKES_PIPELINE_ACTIVATED"), + spike_pipeline_deactivated)) + late_message = ( self._N_LATE_SPIKES_MESSAGE_DROP if self.__drop_late_spikes else self._N_LATE_SPIKES_MESSAGE_NO_DROP) From c5de292837c2dfcd04d912a6deac8ace8445d87e Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Mon, 22 Feb 2021 14:24:48 +0000 Subject: [PATCH 045/108] added code for spike flushing, but not doing any flushing in this state --- neural_modelling/src/common/in_spikes.h | 9 +++++ neural_modelling/src/neuron/c_main.c | 12 ++++++- .../src/neuron/spike_processing.c | 36 +++++++++++++++++++ .../src/neuron/spike_processing.h | 10 ++++++ .../neuron/population_machine_vertex.py | 30 ++++++++++++++++ 5 files changed, 96 insertions(+), 1 deletion(-) diff --git a/neural_modelling/src/common/in_spikes.h b/neural_modelling/src/common/in_spikes.h index 5f1ee26a83e..8fbd36ec83b 100644 --- a/neural_modelling/src/common/in_spikes.h +++ b/neural_modelling/src/common/in_spikes.h @@ -136,4 +136,13 @@ static inline void in_spikes_clear(void) { static inline spike_t in_spikes_value_at_index(uint32_t index) { return circular_buffer_value_at_index(buffer, index); } + +// FLUSH SPIKES +static inline uint32_t in_spikes_flush_buffer() { + + uint32_t num_spikes_left = circular_buffer_size(buffer); + circular_buffer_clear(buffer); + + return num_spikes_left; +} #endif // _IN_SPIKES_H_ diff --git a/neural_modelling/src/neuron/c_main.c b/neural_modelling/src/neuron/c_main.c index 1cb3da76c00..fa127f39921 100644 --- a/neural_modelling/src/neuron/c_main.c +++ b/neural_modelling/src/neuron/c_main.c @@ -78,6 +78,9 @@ struct spike_holder_t spike_cache; struct spike_holder_t spike_counter_inh; struct spike_holder_t spike_cache_inh; +// FLUSH SPIKES +bool timer_callback_active = false; +extern volatile bool dma_busy; //! The provenance information written on application shutdown. struct neuron_provenance { @@ -109,6 +112,9 @@ struct neuron_provenance { uint32_t max_pipeline_restarts; uint32_t timer_callback_completed; uint32_t spike_pipeline_deactivated; + // FLUSH SPIKES + uint32_t max_flushed_spikes; + uint32_t total_flushed_spikes; }; //! values for the priority for each callback @@ -183,6 +189,9 @@ static void c_main_store_provenance_data(address_t provenance_region) { prov->max_pipeline_restarts = max_pipeline_restarts; prov->timer_callback_completed = timer_callback_completed; prov->spike_pipeline_deactivated = spike_pipeline_deactivated; + // FLUSH SPIKES + prov->max_flushed_spikes = spike_processing_get_max_flushed_spikes(); + prov->total_flushed_spikes = spike_processing_get_total_flushed_spikes(); log_debug("finished other provenance data"); } @@ -393,7 +402,7 @@ void timer_callback(uint timer_count, UNUSED uint unused) { // count_rewire_attempts++; // } - uint32_t state = spin1_irq_disable(); + uint32_t state = spin1_int_disable(); // Now do neuron time step update neuron_do_timestep_update(time, timer_count); // First do synapses timestep update, as this is time-critical @@ -401,6 +410,7 @@ void timer_callback(uint timer_count, UNUSED uint unused) { // Re-enable the interrupts spin1_mode_restore(state); + timer_callback_active = false; profiler_write_entry_disable_irq_fiq(PROFILER_EXIT | PROFILER_TIMER); } diff --git a/neural_modelling/src/neuron/spike_processing.c b/neural_modelling/src/neuron/spike_processing.c index 6be8af0b030..9b27c1e1fec 100644 --- a/neural_modelling/src/neuron/spike_processing.c +++ b/neural_modelling/src/neuron/spike_processing.c @@ -35,6 +35,11 @@ uint32_t dmas_this_tick = 0; uint32_t pipeline_restarts_this_tick = 0; uint32_t spike_pipeline_deactivation_time = 0; +// FLUSH SPIKES variables needed +static uint32_t total_flushed_spikes; +static uint32_t max_flushed_spikes; +extern bool timer_callback_active; + //! DMA buffer structure combines the row read from SDRAM with information //! about the read. typedef struct dma_buffer { @@ -331,6 +336,28 @@ static void multicast_packet_received_callback(uint key, uint payload) { log_warning("Could not trigger user event\n"); } } + + // if timer is getting low, don't do next DMA and instead flush spike buffer + // originally 6657 clock cycles from the end of the interval was used +// if (tc[T1_COUNT] < 6657){//6657){ +// uint cpsr = spin1_int_disable(); +// uint32_t spikes_remaining = in_spikes_flush_buffer(); +// timer_callback_active = true; +// spin1_mode_restore(cpsr); +// +// if (spikes_remaining > 0){ +// total_flushed_spikes += spikes_remaining; +// +// if (spikes_remaining > max_flushed_spikes){ +// max_flushed_spikes = spikes_remaining; +// } +// +//// log_info("--------At time: %u, flushed spikes: %u", time, spikes_remaining); +// +// //io_printf(IO_BUF, "At time: %u, flushed spikes: %u\n", +// // time, spikes_remaining); +// } +// } } //! \brief Called when a DMA completes @@ -557,3 +584,12 @@ uint32_t spike_processing_get_and_reset_pipeline_restarts_this_tick(){ uint32_t spike_processing_get_pipeline_deactivation_time(){ return spike_pipeline_deactivation_time; } + +// FLUSH SPIKES +uint32_t spike_processing_get_total_flushed_spikes(){ + return total_flushed_spikes; +} + +uint32_t spike_processing_get_max_flushed_spikes(){ + return max_flushed_spikes; +} \ No newline at end of file diff --git a/neural_modelling/src/neuron/spike_processing.h b/neural_modelling/src/neuron/spike_processing.h index ab124276556..7daabe0fad7 100644 --- a/neural_modelling/src/neuron/spike_processing.h +++ b/neural_modelling/src/neuron/spike_processing.h @@ -92,4 +92,14 @@ uint32_t spike_processing_get_and_reset_pipeline_restarts_this_tick(); //! \return uint32_t pipeline deactivation time uint32_t spike_processing_get_pipeline_deactivation_time(); +// FLUSH SPIKES +//! \brief returns the total unprocessed spikes from a simulation +//! \return total unprocessed spikes +uint32_t spike_processing_get_total_flushed_spikes(); + +//! \brief returns the maximum unprocessed spikes from a single +//! simulation timestep. +//! \return maximum unprocessed spikes from a single timestep. +uint32_t spike_processing_get_max_flushed_spikes(); + #endif // _SPIKE_PROCESSING_H_ diff --git a/spynnaker/pyNN/models/neuron/population_machine_vertex.py b/spynnaker/pyNN/models/neuron/population_machine_vertex.py index 9f06e53de0b..5f1739fc001 100644 --- a/spynnaker/pyNN/models/neuron/population_machine_vertex.py +++ b/spynnaker/pyNN/models/neuron/population_machine_vertex.py @@ -85,6 +85,9 @@ class EXTRA_PROVENANCE_DATA_ENTRIES(Enum): MAX_PIPELINE_RESTARTS = 17 TIMER_CALLBACK_COMPLETED = 18 SPIKES_PIPELINE_ACTIVATED = 19 + # FLUSH SPIKES + MAX_FLUSHED_SPIKES = 20 + TOTAL_FLUSHED_SPIKES = 21 SATURATION_COUNT_NAME = "Times_synaptic_weights_have_saturated" SATURATION_COUNT_MESSAGE = ( @@ -291,6 +294,13 @@ def get_provenance_data_from_machine(self, transceiver, placement): spike_pipeline_deactivated = provenance_data[ self.EXTRA_PROVENANCE_DATA_ENTRIES. SPIKES_PIPELINE_ACTIVATED.value] + # FLUSH SPIKES + max_flushed_spikes = provenance_data[ + self.EXTRA_PROVENANCE_DATA_ENTRIES. + MAX_FLUSHED_SPIKES.value] + total_flushed_spikes = provenance_data[ + self.EXTRA_PROVENANCE_DATA_ENTRIES. + TOTAL_FLUSHED_SPIKES.value] label, x, y, p, names = self._get_placement_details(placement) @@ -400,6 +410,26 @@ def get_provenance_data_from_machine(self, transceiver, placement): self._add_name(names, "SPIKES_PIPELINE_ACTIVATED"), spike_pipeline_deactivated)) + # FLUSHED SPIKES + provenance_items.append(ProvenanceDataItem( + self._add_name(names, + "MAX_FLUSHED_SPIKES"), + max_flushed_spikes, + report=max_flushed_spikes > 0, + message=( + "Max number of flushed spikes for {} on {}, {}, {} " + "was {}. ".format( + label, x, y, p, max_flushed_spikes)))) + + provenance_items.append(ProvenanceDataItem( + self._add_name(names, + "TOTAL_FLUSHED_SPIKES"), + total_flushed_spikes, + report=total_flushed_spikes > 0, + message=( + "Total number of flushed spikes for {} on {}, {}, {} " + "was {}. ".format( + label, x, y, p, total_flushed_spikes)))) late_message = ( self._N_LATE_SPIKES_MESSAGE_DROP if self.__drop_late_spikes From a2cdd9c2219fddbf1d7bf84ee555e3a4fde3065f Mon Sep 17 00:00:00 2001 From: Petrut Bogdan Date: Fri, 5 Mar 2021 11:48:35 +0000 Subject: [PATCH 046/108] going back to irq disable. int disabling would also disable fiqs --- neural_modelling/src/neuron/c_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neural_modelling/src/neuron/c_main.c b/neural_modelling/src/neuron/c_main.c index fa127f39921..6eb266c1d7d 100644 --- a/neural_modelling/src/neuron/c_main.c +++ b/neural_modelling/src/neuron/c_main.c @@ -402,7 +402,7 @@ void timer_callback(uint timer_count, UNUSED uint unused) { // count_rewire_attempts++; // } - uint32_t state = spin1_int_disable(); + uint32_t state = spin1_irq_disable(); // Now do neuron time step update neuron_do_timestep_update(time, timer_count); // First do synapses timestep update, as this is time-critical From 8f972bd0ce287547441cd955b143bf1de107f8a5 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 18 Nov 2021 11:50:31 +0000 Subject: [PATCH 047/108] Merge correctly and make MFVN and PFPC STDP (single-neuron) models work --- neural_modelling/src/common/in_spikes.h | 2 +- .../src/neuron/plasticity/stdp/maths.h | 46 +- .../src/neuron/plasticity/stdp/post_events.h | 4 +- .../neuron/plasticity/stdp/stdp_typedefs.h | 2 +- .../stdp/synapse_dynamics_stdp_common.h | 18 +- ...dynamics_stdp_izhikevich_neuromodulation.c | 10 + .../stdp/synapse_dynamics_stdp_mad_impl.c | 10 + .../synapse_dynamics_stdp_mad_mfvn_impl.c | 390 +++++++---------- .../synapse_dynamics_stdp_mad_pfpc_impl.c | 396 ++++++++---------- .../stdp/timing_dependence/timing_mfvn_impl.c | 10 +- .../stdp/timing_dependence/timing_mfvn_impl.h | 34 +- .../stdp/timing_dependence/timing_pfpc_impl.c | 10 +- .../stdp/timing_dependence/timing_pfpc_impl.h | 33 +- .../stdp/weight_dependence/weight_mfvn_impl.c | 49 ++- .../stdp/weight_dependence/weight_mfvn_impl.h | 80 ++-- .../stdp/weight_dependence/weight_pfpc_impl.c | 52 +-- .../stdp/weight_dependence/weight_pfpc_impl.h | 73 ++-- neural_modelling/src/neuron/send_spike.h | 2 +- .../src/neuron/spike_processing.c | 11 +- .../src/neuron/spike_processing.h | 32 +- neural_modelling/src/neuron/synapses.c | 8 - .../projection_application_edge.py | 2 + .../models/neuron/plasticity/stdp/common.py | 72 ++-- .../abstract_timing_dependence.py | 6 + .../timing_dependence_mfvn.py | 102 ++++- .../timing_dependence_pfpc.py | 158 +++++-- .../timing_dependence_spike_pair.py | 2 + .../weight_dependence_mfvn.py | 49 ++- .../weight_dependence_pfpc.py | 52 ++- .../population_machine_synapses_provenance.py | 18 +- .../synapse_dynamics/synapse_dynamics_stdp.py | 4 + .../timing_dependence_mfvn.py | 2 +- .../timing_dependence_pfpc.py | 6 +- .../weight_dependence/__init__.py | 2 +- 34 files changed, 970 insertions(+), 777 deletions(-) diff --git a/neural_modelling/src/common/in_spikes.h b/neural_modelling/src/common/in_spikes.h index 8fbd36ec83b..ca9edfd41e3 100644 --- a/neural_modelling/src/common/in_spikes.h +++ b/neural_modelling/src/common/in_spikes.h @@ -138,7 +138,7 @@ static inline spike_t in_spikes_value_at_index(uint32_t index) { } // FLUSH SPIKES -static inline uint32_t in_spikes_flush_buffer() { +static inline uint32_t in_spikes_flush_buffer(void) { uint32_t num_spikes_left = circular_buffer_size(buffer); circular_buffer_clear(buffer); diff --git a/neural_modelling/src/neuron/plasticity/stdp/maths.h b/neural_modelling/src/neuron/plasticity/stdp/maths.h index f4b0eecf56d..78a6e5dd219 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/maths.h +++ b/neural_modelling/src/neuron/plasticity/stdp/maths.h @@ -59,7 +59,7 @@ static inline int16_lut *maths_copy_int16_lut(address_t *address) { int16_lut *sdram_lut = (int16_lut *) *address; uint32_t size = sizeof(int16_lut) + (sdram_lut->size * sizeof(int16_t)); int16_lut *lut = spin1_malloc(size); - log_info("lut size %d", size); + log_info("lut size %d sdram_lut size %d", size, sdram_lut->size); if (lut == NULL) { log_error("Not enough space to allocate LUT. Try reducing the timestep," " the number of neurons per core, or the tau value; size = %u", size); @@ -74,28 +74,28 @@ static inline int16_lut *maths_copy_int16_lut(address_t *address) { return lut; } -//--------------------------------------- -// Plasticity maths function inline implementation -//--------------------------------------- -static inline address_t maths_copy_int16_lut_with_size( - address_t start_address, uint32_t num_entries, int16_t *lut) { - // Pad to number of words - const uint32_t num_words = - (num_entries / 2) + (((num_entries & 1) != 0) ? 1 : 0); - - // Copy entries to LUT - spin1_memcpy(lut, start_address, sizeof(int16_t) * num_entries); - - // Return address after words - return start_address + num_words; -} +////--------------------------------------- +//// Plasticity maths function inline implementation +////--------------------------------------- +//static inline address_t maths_copy_int16_lut_with_size( +// address_t *start_address, uint32_t num_entries, int16_t *lut) { +// // Pad to number of words +// const uint32_t num_words = +// (num_entries / 2) + (((num_entries & 1) != 0) ? 1 : 0); +// +// // Copy entries to LUT +// spin1_memcpy(lut, start_address, sizeof(int16_t) * num_entries); +// +// // Return address after words +// return start_address + num_words; +//} //! \brief Get value from lookup table //! \param[in] time: The time that we are mapping //! \param[in] lut: The lookup table (result of maths_copy_int16_lut()) //! \return The value from the LUT, or zero if out of range static inline int32_t maths_lut_exponential_decay( - uint32_t time, const int16_lut *lut) { + const uint32_t time, const int16_lut *lut) { // Calculate lut index uint32_t lut_index = time >> lut->shift; @@ -104,13 +104,17 @@ static inline int32_t maths_lut_exponential_decay( } static inline int32_t maths_lut_exponential_decay_time_shifted( - uint32_t time, const uint32_t time_shift, const uint32_t lut_size, - const int16_t *lut) { + const uint32_t time, const uint32_t time_shift, const int16_lut *lut) { + + // uint32_t time, const uint32_t time_shift, const uint32_t lut_size, + // const int16_t *lut) { + // Calculate lut index - uint32_t lut_index = time >> time_shift; + uint32_t lut_index = (time >> lut->shift) >> time_shift; // Return value from LUT - return (lut_index < lut_size) ? lut[lut_index] : 0; +// return (lut_index < lut_size) ? lut[lut_index] : 0; + return (lut_index < lut->size) ? lut->values[lut_index] : 0; } //! \brief Clamp to fit in number of bits diff --git a/neural_modelling/src/neuron/plasticity/stdp/post_events.h b/neural_modelling/src/neuron/plasticity/stdp/post_events.h index 1b0fbeccb00..996b598be70 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/post_events.h +++ b/neural_modelling/src/neuron/plasticity/stdp/post_events.h @@ -66,7 +66,7 @@ typedef struct { // Inline functions //--------------------------------------- -#if LOG_LEVEL >= LOG_DEBUG +//#if LOG_LEVEL >= LOG_DEBUG //! \brief Print a post-synaptic event history //! \param[in] events: The history static inline void print_event_history(const post_event_history_t *events) { @@ -76,7 +76,7 @@ static inline void print_event_history(const post_event_history_t *events) { i, events->times[i], events->traces[i]); } } -#endif +//#endif //! \brief Initialise an array of post-synaptic event histories //! \param[in] n_neurons: Number of neurons diff --git a/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h b/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h index df98303dbb4..f279b333f77 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h +++ b/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h @@ -38,7 +38,7 @@ //! \return The product #define STDP_FIXED_MUL_16X16(a, b) maths_fixed_mul16(a, b, STDP_FIXED_POINT) -#define print_plasticity false +#define print_plasticity true // false //! The amount of right shift required to take a weight from s1615 format //! to STDP_FIXED_POINT format (s4,11) diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_common.h b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_common.h index fbdcf62f077..99add85a5f0 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_common.h +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_common.h @@ -67,15 +67,15 @@ //--------------------------------------- // Structures //--------------------------------------- -//! \brief The type of history data of pre-events -//! -//! This data is stored in SDRAM in the plastic part of the synaptic matrix -typedef struct { - //! The event time - uint32_t prev_time; - //! The event trace - pre_trace_t prev_trace; -} pre_event_history_t; +////! \brief The type of history data of pre-events +////! +////! This data is stored in SDRAM in the plastic part of the synaptic matrix +//typedef struct { +// //! The event time +// uint32_t prev_time; +// //! The event trace +// pre_trace_t prev_trace; +//} pre_event_history_t; //! The type of configuration parameters in SDRAM (written by host) typedef struct stdp_params { diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_izhikevich_neuromodulation.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_izhikevich_neuromodulation.c index 2bb637bb3f4..0ec5f3f1dfd 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_izhikevich_neuromodulation.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_izhikevich_neuromodulation.c @@ -43,6 +43,16 @@ typedef struct nm_final_state_t { final_state_t final_state; } nm_final_state_t; +//! \brief The type of history data of pre-events +//! +//! This data is stored in SDRAM in the plastic part of the synaptic matrix +typedef struct { + //! The event time + uint32_t prev_time; + //! The event trace + pre_trace_t prev_trace; +} pre_event_history_t; + struct synapse_row_plastic_data_t { union { struct { diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c index e7408f679b0..ffb304d6206 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_impl.c @@ -20,6 +20,16 @@ #include "post_events.h" #include "synapse_dynamics_stdp_common.h" +//! \brief The type of history data of pre-events +//! +//! This data is stored in SDRAM in the plastic part of the synaptic matrix +typedef struct { + //! The event time + uint32_t prev_time; + //! The event trace + pre_trace_t prev_trace; +} pre_event_history_t; + //! The format of the plastic data region of a synaptic row struct synapse_row_plastic_data_t { //! The pre-event history diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c index 6470c88fbb3..a15d6d51f7f 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c @@ -1,72 +1,26 @@ -// Spinn_common includes -#include "static-assert.h" - -// sPyNNaker neural modelling includes -#include -#include - -// Plasticity includes -#include "maths.h" +/* + * Copyright (c) 2017-2019 The University of Manchester + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +//! \file +//! \brief STDP core implementation #include "post_events.h" - -#include "weight_dependence/weight.h" -#include "timing_dependence/timing.h" -#include -#include -#include - -static uint32_t synapse_type_index_bits; -static uint32_t synapse_index_bits; -static uint32_t synapse_index_mask; -static uint32_t synapse_type_index_mask; -static uint32_t synapse_delay_index_type_bits; -static uint32_t synapse_type_mask; - -uint32_t num_plastic_pre_synaptic_events = 0; -uint32_t plastic_saturation_count = 0; -//! The type of configuration parameters in SDRAM (written by host) -typedef struct stdp_params { - //! The back-propagation delay, in basic simulation timesteps - uint32_t backprop_delay; -} stdp_params; - -//! Configuration parameters -static stdp_params params; -//--------------------------------------- -// Macros -//--------------------------------------- -// The plastic control words used by Morrison synapses store an axonal delay -// in the upper 3 bits. -// Assuming a maximum of 16 delay slots, this is all that is required as: -// -// 1) Dendritic + Axonal <= 15 -// 2) Dendritic >= Axonal -// -// Therefore: -// -// * Maximum value of dendritic delay is 15 (with axonal delay of 0) -// - It requires 4 bits -// * Maximum value of axonal delay is 7 (with dendritic delay of 8) -// - It requires 3 bits -// -// | Axonal delay | Dendritic delay | Type | Index | -// |---------------------------|--------------------|-------------------|--------------------| -// | SYNAPSE_AXONAL_DELAY_BITS | SYNAPSE_DELAY_BITS | SYNAPSE_TYPE_BITS | SYNAPSE_INDEX_BITS | -// | | | SYNAPSE_TYPE_INDEX_BITS | -// |---------------------------|--------------------|----------------------------------------| -#ifndef SYNAPSE_AXONAL_DELAY_BITS -#define SYNAPSE_AXONAL_DELAY_BITS 3 -#endif - -#define SYNAPSE_AXONAL_DELAY_MASK ((1 << SYNAPSE_AXONAL_DELAY_BITS) - 1) - -//--------------------------------------- -// Structures -//--------------------------------------- -//typedef struct { -// pre_trace_t prev_trace; -// uint32_t prev_time; -//} pre_event_history_t; +#include "synapse_dynamics_stdp_common.h" +#include "stdp_typedefs.h" +#include #define NUM_MF_SPIKES_TO_RECORD 16 @@ -76,7 +30,13 @@ typedef struct { post_trace_t traces[NUM_MF_SPIKES_TO_RECORD]; } pre_event_history_t; - +//! The format of the plastic data region of a synaptic row +struct synapse_row_plastic_data_t { + //! The pre-event history + pre_event_history_t history; + //! The per-synapse information + plastic_synapse_t synapses[]; +}; void _print_pre_event_history(pre_event_history_t pre_eve_hist){ @@ -90,16 +50,13 @@ void _print_pre_event_history(pre_event_history_t pre_eve_hist){ } } -post_event_history_t *post_event_history; - //--------------------------------------- // Synapse update loop //--------------------------------------- -static inline final_state_t _plasticity_update_synapse( - uint32_t time, +static inline final_state_t 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, - uint32_t delay_dendritic, + const pre_trace_t new_pre_trace, uint32_t delay_dendritic, const uint32_t delay_axonal, update_state_t current_state, const post_event_history_t *post_event_history, const pre_event_history_t *pre_event_history) { @@ -254,72 +211,24 @@ static inline pre_event_history_t *_plastic_event_history( return (pre_event_history_t*) (&plastic_region_address[0]); } -void synapse_dynamics_print_plastic_synapses( - address_t plastic_region_address, address_t fixed_region_address, - uint32_t *ring_buffer_to_input_buffer_left_shifts) { - use(plastic_region_address); - use(fixed_region_address); - use(ring_buffer_to_input_buffer_left_shifts); -#if LOG_LEVEL >= LOG_DEBUG - - // Extract separate arrays of weights (from plastic region), - // Control words (from fixed region) and number of plastic synapses - weight_t *plastic_words = _plastic_synapses(plastic_region_address); - const control_t *control_words = synapse_row_plastic_controls( - fixed_region_address); - size_t plastic_synapse = synapse_row_num_plastic_controls( - fixed_region_address); - const pre_event_history_t *event_history = _plastic_event_history( - plastic_region_address); - - log_debug("Plastic region %u synapses\n", plastic_synapse); - - // Loop through plastic synapses - for (uint32_t i = 0; i < plastic_synapse; i++) { - - // Get next weight and control word (auto incrementing control word) - uint32_t weight = *plastic_words++; - uint32_t control_word = *control_words++; - uint32_t synapse_type = synapse_row_sparse_type( - control_word, synapse_index_bits, synapse_type_mask); - - log_debug("%08x [%3d: (w: %5u (=", control_word, i, weight); - synapses_print_weight( - weight, ring_buffer_to_input_buffer_left_shifts[synapse_type]); - log_debug("nA) d: %2u, %s, n = %3u)] - {%08x %08x}\n", - synapse_row_sparse_delay( - control_word, synapse_type_index_bits), - synapse_types_get_type_char(synapse_type), - synapse_row_sparse_index(control_word, synapse_index_mask), - SYNAPSE_DELAY_MASK, synapse_type_index_bits); - } -#endif // LOG_LEVEL >= LOG_DEBUG -} //--------------------------------------- static inline index_t _sparse_axonal_delay(uint32_t x) { - return ((x >> synapse_delay_index_type_bits) & SYNAPSE_AXONAL_DELAY_MASK); +#if 1 + // No axonal delay, ever + __use(x); + return 0; +#else + return (x >> synapse_delay_index_type_bits) & SYNAPSE_AXONAL_DELAY_MASK; +#endif } 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) { - stdp_params *sdram_params = (stdp_params *) address; - spin1_memcpy(¶ms, sdram_params, sizeof(stdp_params)); - address = (address_t) &sdram_params[1]; - - // Load timing dependence data - address_t weight_region_address = timing_initialise(address); - if (address == NULL) { - return false; - } - - // Load weight dependence data - address_t weight_result = weight_initialise( - weight_region_address, n_synapse_types, - ring_buffer_to_input_buffer_left_shifts); - if (weight_result == NULL) { + if (!synapse_dynamics_stdp_init(&address, ¶ms, n_synapse_types, + ring_buffer_to_input_buffer_left_shifts)) { return false; } @@ -328,35 +237,41 @@ bool synapse_dynamics_initialise( return false; } - uint32_t n_neurons_power_2 = n_neurons; - uint32_t log_n_neurons = 1; - if (n_neurons != 1) { - if (!is_power_of_2(n_neurons)) { - n_neurons_power_2 = next_power_of_2(n_neurons); - } - log_n_neurons = ilog_2(n_neurons_power_2); - } - - uint32_t n_synapse_types_power_2 = n_synapse_types; - if (!is_power_of_2(n_synapse_types)) { - n_synapse_types_power_2 = next_power_of_2(n_synapse_types); - } - uint32_t log_n_synapse_types = ilog_2(n_synapse_types_power_2); - - synapse_type_index_bits = log_n_neurons + log_n_synapse_types; - synapse_type_index_mask = (1 << synapse_type_index_bits) - 1; - synapse_index_bits = log_n_neurons; - synapse_index_mask = (1 << synapse_index_bits) - 1; - synapse_delay_index_type_bits = - SYNAPSE_DELAY_BITS + synapse_type_index_bits; - synapse_type_mask = (1 << log_n_synapse_types) - 1; - return true; } +//--------------------------------------- +static inline plastic_synapse_t process_plastic_synapse( + uint32_t control_word, uint32_t last_pre_time, pre_trace_t last_pre_trace, + pre_trace_t new_pre_trace, weight_t *ring_buffers, uint32_t time, + plastic_synapse_t synapse, pre_event_history_t *pre_event_history) { + fixed_stdp_synapse s = synapse_dynamics_stdp_get_fixed(control_word, time); + + // Create update state from the plastic synaptic word + update_state_t current_state = synapse_structure_get_update_state( + synapse, s.type); + + // Update the synapse state + uint32_t post_delay = s.delay_dendritic; +// if (!params.backprop_delay) { +// post_delay = 0; +// } + final_state_t final_state = plasticity_update_synapse( + time, last_pre_time, last_pre_trace, new_pre_trace, + post_delay, s.delay_axonal, current_state, + &post_event_history[s.index], pre_event_history); + + // Add weight to ring-buffer entry + int32_t weight = synapse_structure_get_final_weight(final_state); + synapse_dynamics_stdp_update_ring_buffers(ring_buffers, s, weight); + + return synapse_structure_get_final_synaptic_word(final_state); +} + bool synapse_dynamics_process_plastic_synapses( - address_t plastic_region_address, address_t fixed_region_address, - weight_t *ring_buffers, uint32_t time) { + synapse_row_plastic_data_t *plastic_region_address, + synapse_row_fixed_part_t *fixed_region, + weight_t *ring_buffers, uint32_t time, bool *write_back) { if (print_plasticity){ io_printf(IO_BUF, "\n############ New Plasticity Update #############\n"); @@ -364,22 +279,25 @@ bool synapse_dynamics_process_plastic_synapses( // Extract separate arrays of plastic synapses (from plastic region), // Control words (from fixed region) and number of plastic synapses - plastic_synapse_t *plastic_words = _plastic_synapses( - plastic_region_address); - const control_t *control_words = synapse_row_plastic_controls( - fixed_region_address); - size_t plastic_synapse = synapse_row_num_plastic_controls( - fixed_region_address); +// plastic_synapse_t *plastic_words = _plastic_synapses( +// plastic_region_address); + plastic_synapse_t *plastic_words = plastic_region_address->synapses; + const control_t *control_words = synapse_row_plastic_controls(fixed_region); + size_t n_plastic_synapses = synapse_row_num_plastic_controls(fixed_region); - num_plastic_pre_synaptic_events += plastic_synapse; + num_plastic_pre_synaptic_events += n_plastic_synapses; // Get event history from synaptic row - pre_event_history_t *event_history = _plastic_event_history( - plastic_region_address); +// pre_event_history_t *event_history = _plastic_event_history( +// plastic_region_address); +// pre_event_history_t *event_history = plastic_region_address->history; // Get last pre-synaptic event from event history + // Get last pre-synaptic event from event history + const uint32_t recorded_spikes_minus_one = + plastic_region_address->history.num_recorded_mf_spikes_minus_one; const uint32_t last_pre_time = - event_history->mf_times[event_history->num_recorded_mf_spikes_minus_one]; + plastic_region_address->history.mf_times[recorded_spikes_minus_one]; // no longer need to manage this trace const pre_trace_t last_pre_trace = 0; @@ -387,7 +305,7 @@ bool synapse_dynamics_process_plastic_synapses( // add pre spike to struct capturing pre synaptic event history // NOTE: this uses the post_event_history_t handling code - post_events_add(time, event_history, 0); + post_events_add(time, &plastic_region_address->history, 0); // Update pre-synaptic trace if (print_plasticity){ @@ -395,69 +313,26 @@ bool synapse_dynamics_process_plastic_synapses( "\nAdding pre-synaptic event (mossy fibre spike) at time: %u\n\n", time); } - timing_add_pre_spike(time, last_pre_time, last_pre_trace); // Loop through plastic synapses - for (; plastic_synapse > 0; plastic_synapse--) { + for (; n_plastic_synapses > 0; n_plastic_synapses--) { // Get next control word (auto incrementing) uint32_t control_word = *control_words++; - // Extract control-word components - // **NOTE** cunningly, control word is just the same as lower - // 16-bits of 32-bit fixed synapse so same functions can be used - uint32_t delay_axonal = 0; //_sparse_axonal_delay(control_word); - uint32_t delay_dendritic = synapse_row_sparse_delay( - control_word, synapse_type_index_bits); - uint32_t type = synapse_row_sparse_type( - control_word, synapse_index_bits, synapse_type_mask); - uint32_t index = synapse_row_sparse_index( - control_word, synapse_index_mask); - uint32_t type_index = synapse_row_sparse_type_index( - control_word, synapse_type_index_mask); - -// io_printf(IO_BUF, "PRINTING PRE EVENT HISTORY"); -// print_delayed_window_events(event_history, begin_time, time, delay_dendritic); - - // Create update state from the plastic synaptic word - update_state_t current_state = synapse_structure_get_update_state( - *plastic_words, type); - - // Update the synapse state - final_state_t final_state = _plasticity_update_synapse( - time, last_pre_time, last_pre_trace, last_pre_trace, - delay_dendritic, delay_axonal, current_state, - &post_event_history[index], event_history); - - // Convert into ring buffer offset - uint32_t ring_buffer_index = synapses_get_ring_buffer_index_combined( - delay_axonal + delay_dendritic + time, type_index, - synapse_type_index_bits); - - // Add weight to ring-buffer entry - // **NOTE** Dave suspects that this could be a - // potential location for overflow - - uint32_t accumulation = ring_buffers[ring_buffer_index] + - synapse_structure_get_final_weight(final_state); - - uint32_t sat_test = accumulation & 0x10000; - if (sat_test){ - accumulation = sat_test - 1; - plastic_saturation_count += 1; - } - - ring_buffers[ring_buffer_index] = accumulation; - - // Write back updated synaptic word to plastic region - *plastic_words++ = synapse_structure_get_final_synaptic_word( - final_state); + plastic_words[0] = process_plastic_synapse( + control_word, last_pre_time, last_pre_trace, + last_pre_trace, ring_buffers, time, + plastic_words[0], &plastic_region_address->history); + plastic_words++; } if (print_plasticity){ io_printf(IO_BUF, "\n############ Completed Plasticity Update #############\n"); } + + *write_back = true; return true; } @@ -477,19 +352,78 @@ void synapse_dynamics_process_post_synaptic_event( last_post_trace)); } -input_t synapse_dynamics_get_intrinsic_bias(uint32_t time, - index_t neuron_index) { - use(time); - use(neuron_index); - return 0.0k; +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) { + synapse_row_fixed_part_t *fixed_region = synapse_row_fixed_region(row); + const synapse_row_plastic_data_t *plastic_data = (void *) + synapse_row_plastic_region(row); + const plastic_synapse_t *plastic_words = plastic_data->synapses; + const control_t *control_words = synapse_row_plastic_controls(fixed_region); + const size_t n_plastic_synapses = synapse_row_num_plastic_controls(fixed_region); + + // Loop through plastic synapses + for (size_t plastic_synapse = n_plastic_synapses; plastic_synapse > 0; + plastic_synapse--) { + // Take the weight anyway as this updates the plastic words + *weight = synapse_structure_get_weight(*plastic_words++); + + // Check if index is the one I'm looking for + uint32_t control_word = *control_words++; + if (synapse_row_sparse_index(control_word, synapse_index_mask) == id) { + *offset = n_plastic_synapses - plastic_synapse; + *delay = synapse_row_sparse_delay(control_word, + synapse_type_index_bits, synapse_delay_mask); + *synapse_type = synapse_row_sparse_type( + control_word, synapse_index_bits, synapse_type_mask); + return true; + } + } + + return false; } -uint32_t synapse_dynamics_get_plastic_pre_synaptic_events(){ - return num_plastic_pre_synaptic_events; +bool synapse_dynamics_remove_neuron(uint32_t offset, synaptic_row_t row) { + synapse_row_fixed_part_t *fixed_region = synapse_row_fixed_region(row); + synapse_row_plastic_data_t *plastic_data = (void *) + synapse_row_plastic_region(row); + plastic_synapse_t *plastic_words = plastic_data->synapses; + + control_t *control_words = synapse_row_plastic_controls(fixed_region); + int32_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); + + // Delete weight at offset + plastic_words[offset] = plastic_words[plastic_synapse - 1]; + + // Delete control word at offset + control_words[offset] = control_words[plastic_synapse - 1]; + control_words[plastic_synapse - 1] = 0; + + // Decrement FP + fixed_region->num_plastic--; + return true; } -uint32_t synapse_dynamics_get_plastic_saturation_count(){ - return plastic_saturation_count; +bool synapse_dynamics_add_neuron(uint32_t id, synaptic_row_t row, + weight_t weight, uint32_t delay, uint32_t type) { + synapse_row_fixed_part_t *fixed_region = synapse_row_fixed_region(row); + synapse_row_plastic_data_t *plastic_data = synapse_row_plastic_region(row); + plastic_synapse_t *plastic_words = plastic_data->synapses; + plastic_synapse_t new_weight = synapse_structure_create_synapse(weight); + control_t new_control = control_conversion(id, delay, type); + + control_t *control_words = synapse_row_plastic_controls(fixed_region); + int32_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); + + // Add weight at offset + plastic_words[plastic_synapse] = new_weight; + + // Add control word at offset + control_words[plastic_synapse] = new_control; + + // Increment FP + fixed_region->num_plastic++; + return true; } #if SYNGEN_ENABLED == 1 diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c index 53c07435e82..212f51dcef2 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c @@ -1,65 +1,43 @@ -// Spinn_common includes -#include "static-assert.h" - +/* + * Copyright (c) 2017-2019 The University of Manchester + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +//! \file +//! \brief STDP core implementation +#include "post_events.h" +#include "synapse_dynamics_stdp_common.h" // sPyNNaker neural modelling includes #include #include -// Plasticity includes -#include "maths.h" -#include "post_events.h" +#define NUM_PF_SPIKES_TO_RECORD 16 -#include "weight_dependence/weight.h" -#include "timing_dependence/timing.h" -#include -#include -#include - -static uint32_t synapse_type_index_bits; -static uint32_t synapse_index_bits; -static uint32_t synapse_index_mask; -static uint32_t synapse_type_index_mask; -static uint32_t synapse_delay_index_type_bits; -static uint32_t synapse_type_mask; - -uint32_t num_plastic_pre_synaptic_events = 0; -uint32_t plastic_saturation_count = 0; - -//! The type of configuration parameters in SDRAM (written by host) -typedef struct stdp_params { - //! The back-propagation delay, in basic simulation timesteps - uint32_t backprop_delay; -} stdp_params; - -//! Configuration parameters -static stdp_params params; -//--------------------------------------- -// Macros -//--------------------------------------- -// The plastic control words used by Morrison synapses store an axonal delay -// in the upper 3 bits. -// Assuming a maximum of 16 delay slots, this is all that is required as: -// -// 1) Dendritic + Axonal <= 15 -// 2) Dendritic >= Axonal -// -// Therefore: -// -// * Maximum value of dendritic delay is 15 (with axonal delay of 0) -// - It requires 4 bits -// * Maximum value of axonal delay is 7 (with dendritic delay of 8) -// - It requires 3 bits -// -// | Axonal delay | Dendritic delay | Type | Index | -// |---------------------------|--------------------|-------------------|--------------------| -// | SYNAPSE_AXONAL_DELAY_BITS | SYNAPSE_DELAY_BITS | SYNAPSE_TYPE_BITS | SYNAPSE_INDEX_BITS | -// | | | SYNAPSE_TYPE_INDEX_BITS | -// |---------------------------|--------------------|----------------------------------------| -#ifndef SYNAPSE_AXONAL_DELAY_BITS -#define SYNAPSE_AXONAL_DELAY_BITS 3 -#endif +typedef struct { + uint32_t num_recorded_pf_spikes_minus_one; + uint32_t pf_times[NUM_PF_SPIKES_TO_RECORD]; + post_trace_t traces[NUM_PF_SPIKES_TO_RECORD]; +} pre_event_history_t; -#define SYNAPSE_AXONAL_DELAY_MASK ((1 << SYNAPSE_AXONAL_DELAY_BITS) - 1) +//! The format of the plastic data region of a synaptic row +struct synapse_row_plastic_data_t { + //! The pre-event history + pre_event_history_t history; + //! The per-synapse information + plastic_synapse_t synapses[]; +}; //--------------------------------------- // Structures @@ -69,16 +47,6 @@ static stdp_params params; // uint32_t prev_time; //} pre_event_history_t; -#define NUM_PF_SPIKES_TO_RECORD 16 - -typedef struct { - uint32_t num_recorded_pf_spikes_minus_one; - uint32_t pf_times[NUM_PF_SPIKES_TO_RECORD]; - post_trace_t traces[NUM_PF_SPIKES_TO_RECORD]; -} pre_event_history_t; - - - void _print_pre_event_history(pre_event_history_t pre_eve_hist){ io_printf(IO_BUF, "\n\n************************\n\n"); @@ -92,17 +60,13 @@ void _print_pre_event_history(pre_event_history_t pre_eve_hist){ } - -post_event_history_t *post_event_history; - //--------------------------------------- // Synapse update loop //--------------------------------------- -static inline final_state_t _plasticity_update_synapse( - uint32_t time, +static inline final_state_t 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, - uint32_t delay_dendritic, + const pre_trace_t new_pre_trace, uint32_t delay_dendritic, const uint32_t delay_axonal, update_state_t current_state, const post_event_history_t *post_event_history, const pre_event_history_t *pre_event_history) { @@ -227,71 +191,23 @@ static inline pre_event_history_t *_plastic_event_history( return (pre_event_history_t*) (&plastic_region_address[0]); } -void synapse_dynamics_print_plastic_synapses( - address_t plastic_region_address, address_t fixed_region_address, - uint32_t *ring_buffer_to_input_buffer_left_shifts) { - use(plastic_region_address); - use(fixed_region_address); - use(ring_buffer_to_input_buffer_left_shifts); -#if LOG_LEVEL >= LOG_DEBUG - - // Extract separate arrays of weights (from plastic region), - // Control words (from fixed region) and number of plastic synapses - weight_t *plastic_words = _plastic_synapses(plastic_region_address); - const control_t *control_words = synapse_row_plastic_controls( - fixed_region_address); - size_t plastic_synapse = synapse_row_num_plastic_controls( - fixed_region_address); - const pre_event_history_t *event_history = _plastic_event_history( - plastic_region_address); - - log_debug("Plastic region %u synapses\n", plastic_synapse); - - // Loop through plastic synapses - for (uint32_t i = 0; i < plastic_synapse; i++) { - - // Get next weight and control word (auto incrementing control word) - uint32_t weight = *plastic_words++; - uint32_t control_word = *control_words++; - uint32_t synapse_type = synapse_row_sparse_type( - control_word, synapse_index_bits, synapse_type_mask); - - log_debug("%08x [%3d: (w: %5u (=", control_word, i, weight); - synapses_print_weight( - weight, ring_buffer_to_input_buffer_left_shifts[synapse_type]); - log_debug("nA) d: %2u, %s, n = %3u)] - {%08x %08x}\n", - synapse_row_sparse_delay( - control_word, synapse_type_index_bits), - synapse_types_get_type_char(synapse_type), - synapse_row_sparse_index(control_word, synapse_index_mask), - SYNAPSE_DELAY_MASK, synapse_type_index_bits); - } -#endif // LOG_LEVEL >= LOG_DEBUG -} - //--------------------------------------- static inline index_t _sparse_axonal_delay(uint32_t x) { - return ((x >> synapse_delay_index_type_bits) & SYNAPSE_AXONAL_DELAY_MASK); +#if 1 + // No axonal delay, ever + __use(x); + return 0; +#else + return (x >> synapse_delay_index_type_bits) & SYNAPSE_AXONAL_DELAY_MASK; +#endif } 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) { - stdp_params *sdram_params = (stdp_params *) address; - spin1_memcpy(¶ms, sdram_params, sizeof(stdp_params)); - address = (address_t) &sdram_params[1]; - - // Load timing dependence data - address_t weight_region_address = timing_initialise(address); - if (address == NULL) { - return NULL; - } - // Load weight dependence data - address_t weight_result = weight_initialise( - weight_region_address, n_synapse_types, - ring_buffer_to_input_buffer_left_shifts); - if (weight_result == NULL) { + if (!synapse_dynamics_stdp_init(&address, ¶ms, n_synapse_types, + ring_buffer_to_input_buffer_left_shifts)) { return false; } @@ -300,62 +216,70 @@ bool synapse_dynamics_initialise( return false; } - uint32_t n_neurons_power_2 = n_neurons; - uint32_t log_n_neurons = 1; - if (n_neurons != 1) { - if (!is_power_of_2(n_neurons)) { - n_neurons_power_2 = next_power_of_2(n_neurons); - } - log_n_neurons = ilog_2(n_neurons_power_2); - } - - uint32_t n_synapse_types_power_2 = n_synapse_types; - if (!is_power_of_2(n_synapse_types)) { - n_synapse_types_power_2 = next_power_of_2(n_synapse_types); - } - uint32_t log_n_synapse_types = ilog_2(n_synapse_types_power_2); - - synapse_type_index_bits = log_n_neurons + log_n_synapse_types; - synapse_type_index_mask = (1 << synapse_type_index_bits) - 1; - synapse_index_bits = log_n_neurons; - synapse_index_mask = (1 << synapse_index_bits) - 1; - synapse_delay_index_type_bits = - SYNAPSE_DELAY_BITS + synapse_type_index_bits; - synapse_type_mask = (1 << log_n_synapse_types) - 1; - return true; } +//--------------------------------------- +static inline plastic_synapse_t process_plastic_synapse( + uint32_t control_word, uint32_t last_pre_time, pre_trace_t last_pre_trace, + pre_trace_t new_pre_trace, weight_t *ring_buffers, uint32_t time, + plastic_synapse_t synapse, pre_event_history_t *pre_event_history) { + + fixed_stdp_synapse s = synapse_dynamics_stdp_get_fixed(control_word, time); + + // Create update state from the plastic synaptic word + update_state_t current_state = synapse_structure_get_update_state( + synapse, s.type); + + // Update the synapse state + uint32_t post_delay = s.delay_dendritic; +// if (!params.backprop_delay) { +// post_delay = 0; +// } + final_state_t final_state = plasticity_update_synapse( + time, last_pre_time, last_pre_trace, new_pre_trace, + post_delay, s.delay_axonal, current_state, + &post_event_history[s.index], pre_event_history); + + // Add weight to ring-buffer entry + int32_t weight = synapse_structure_get_final_weight(final_state); + synapse_dynamics_stdp_update_ring_buffers(ring_buffers, s, weight); + + return synapse_structure_get_final_synaptic_word(final_state); +} + bool synapse_dynamics_process_plastic_synapses( - address_t plastic_region_address, address_t fixed_region_address, - weight_t *ring_buffers, uint32_t time) { + synapse_row_plastic_data_t *plastic_region_address, + synapse_row_fixed_part_t *fixed_region, + weight_t *ring_buffers, uint32_t time, bool *write_back) { // Extract separate arrays of plastic synapses (from plastic region), // Control words (from fixed region) and number of plastic synapses - plastic_synapse_t *plastic_words = _plastic_synapses( - plastic_region_address); - const control_t *control_words = synapse_row_plastic_controls( - fixed_region_address); - size_t plastic_synapse = synapse_row_num_plastic_controls( - fixed_region_address); +// plastic_synapse_t *plastic_words = _plastic_synapses( +// plastic_region_address); + plastic_synapse_t *plastic_words = plastic_region_address->synapses; + const control_t *control_words = synapse_row_plastic_controls(fixed_region); + size_t n_plastic_synapses = synapse_row_num_plastic_controls(fixed_region); - num_plastic_pre_synaptic_events += plastic_synapse; + num_plastic_pre_synaptic_events += n_plastic_synapses; // Get event history from synaptic row - pre_event_history_t *event_history = _plastic_event_history( - plastic_region_address); +// pre_event_history_t *event_history = plastic_region_address->history; +// _plastic_event_history( +// plastic_region_address); // Get last pre-synaptic event from event history - const uint32_t last_pre_time = event_history->pf_times[event_history->num_recorded_pf_spikes_minus_one]; + const uint32_t recorded_spikes_minus_one = + plastic_region_address->history.num_recorded_pf_spikes_minus_one; + const uint32_t last_pre_time = + plastic_region_address->history.pf_times[recorded_spikes_minus_one]; // no longer need to manage this trace const pre_trace_t last_pre_trace = 0; - // add pre spike to struct capturing pre synaptic event history // NOTE: this uses the post_event_history_t handling code - post_events_add(time, event_history, 0); - + post_events_add(time, &plastic_region_address->history, 0); // Update pre-synaptic trace @@ -363,65 +287,22 @@ bool synapse_dynamics_process_plastic_synapses( io_printf(IO_BUF, "\nAdding pre-synaptic event (parallel fibre spike) at time: %u\n\n", time); } - timing_add_pre_spike(time, last_pre_time, last_pre_trace); // Loop through plastic synapses - for (; plastic_synapse > 0; plastic_synapse--) { + for (; n_plastic_synapses > 0; n_plastic_synapses--) { // Get next control word (auto incrementing) uint32_t control_word = *control_words++; - // Extract control-word components - // **NOTE** cunningly, control word is just the same as lower - // 16-bits of 32-bit fixed synapse so same functions can be used - uint32_t delay_axonal = 0; //_sparse_axonal_delay(control_word); - uint32_t delay_dendritic = synapse_row_sparse_delay( - control_word, synapse_type_index_bits); - uint32_t type = synapse_row_sparse_type( - control_word, synapse_index_bits, synapse_type_mask); - uint32_t index = synapse_row_sparse_index( - control_word, synapse_index_mask); - uint32_t type_index = synapse_row_sparse_type_index( - control_word, synapse_type_index_mask); - -// io_printf(IO_BUF, "PRINTING PRE EVENT HISTORY"); -// print_delayed_window_events(event_history, begin_time, time, delay_dendritic); - - // Create update state from the plastic synaptic word - update_state_t current_state = synapse_structure_get_update_state( - *plastic_words, type); - - // Update the synapse state - final_state_t final_state = _plasticity_update_synapse( - time, last_pre_time, last_pre_trace, last_pre_trace, - delay_dendritic, delay_axonal, current_state, - &post_event_history[index], event_history); - - // Convert into ring buffer offset - uint32_t ring_buffer_index = synapses_get_ring_buffer_index_combined( - delay_axonal + delay_dendritic + time, type_index, - synapse_type_index_bits); - - // Add weight to ring-buffer entry - // **NOTE** Dave suspects that this could be a - // potential location for overflow - - uint32_t accumulation = ring_buffers[ring_buffer_index] + - synapse_structure_get_final_weight(final_state); - - uint32_t sat_test = accumulation & 0x10000; - if (sat_test){ - accumulation = sat_test - 1; - plastic_saturation_count += 1; - } - - ring_buffers[ring_buffer_index] = accumulation; - - // Write back updated synaptic word to plastic region - *plastic_words++ = synapse_structure_get_final_synaptic_word( - final_state); + plastic_words[0] = process_plastic_synapse( + control_word, last_pre_time, last_pre_trace, + last_pre_trace, ring_buffers, time, + plastic_words[0], &plastic_region_address->history); + plastic_words++; } + + *write_back = true; return true; } @@ -441,19 +322,78 @@ void synapse_dynamics_process_post_synaptic_event( last_post_trace)); } -input_t synapse_dynamics_get_intrinsic_bias(uint32_t time, - index_t neuron_index) { - use(time); - use(neuron_index); - return 0.0k; +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) { + synapse_row_fixed_part_t *fixed_region = synapse_row_fixed_region(row); + const synapse_row_plastic_data_t *plastic_data = (void *) + synapse_row_plastic_region(row); + const plastic_synapse_t *plastic_words = plastic_data->synapses; + const control_t *control_words = synapse_row_plastic_controls(fixed_region); + const size_t n_plastic_synapses = synapse_row_num_plastic_controls(fixed_region); + + // Loop through plastic synapses + for (size_t plastic_synapse = n_plastic_synapses; plastic_synapse > 0; + plastic_synapse--) { + // Take the weight anyway as this updates the plastic words + *weight = synapse_structure_get_weight(*plastic_words++); + + // Check if index is the one I'm looking for + uint32_t control_word = *control_words++; + if (synapse_row_sparse_index(control_word, synapse_index_mask) == id) { + *offset = n_plastic_synapses - plastic_synapse; + *delay = synapse_row_sparse_delay(control_word, + synapse_type_index_bits, synapse_delay_mask); + *synapse_type = synapse_row_sparse_type( + control_word, synapse_index_bits, synapse_type_mask); + return true; + } + } + + return false; } -uint32_t synapse_dynamics_get_plastic_pre_synaptic_events(){ - return num_plastic_pre_synaptic_events; +bool synapse_dynamics_remove_neuron(uint32_t offset, synaptic_row_t row) { + synapse_row_fixed_part_t *fixed_region = synapse_row_fixed_region(row); + synapse_row_plastic_data_t *plastic_data = (void *) + synapse_row_plastic_region(row); + plastic_synapse_t *plastic_words = plastic_data->synapses; + + control_t *control_words = synapse_row_plastic_controls(fixed_region); + int32_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); + + // Delete weight at offset + plastic_words[offset] = plastic_words[plastic_synapse - 1]; + + // Delete control word at offset + control_words[offset] = control_words[plastic_synapse - 1]; + control_words[plastic_synapse - 1] = 0; + + // Decrement FP + fixed_region->num_plastic--; + return true; } -uint32_t synapse_dynamics_get_plastic_saturation_count(){ - return plastic_saturation_count; +bool synapse_dynamics_add_neuron(uint32_t id, synaptic_row_t row, + weight_t weight, uint32_t delay, uint32_t type) { + synapse_row_fixed_part_t *fixed_region = synapse_row_fixed_region(row); + synapse_row_plastic_data_t *plastic_data = synapse_row_plastic_region(row); + plastic_synapse_t *plastic_words = plastic_data->synapses; + plastic_synapse_t new_weight = synapse_structure_create_synapse(weight); + control_t new_control = control_conversion(id, delay, type); + + control_t *control_words = synapse_row_plastic_controls(fixed_region); + int32_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); + + // Add weight at offset + plastic_words[plastic_synapse] = new_weight; + + // Add control word at offset + control_words[plastic_synapse] = new_control; + + // Increment FP + fixed_region->num_plastic++; + return true; } #if SYNGEN_ENABLED == 1 diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c index 4f81f063da8..696944da982 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c @@ -4,8 +4,8 @@ // Globals //--------------------------------------- // Exponential lookup-tables -int16_t exp_cos_lookup[EXP_COS_LUT_SIZE]; -//int16_lut *exp_cos_lookup; +//int16_t exp_cos_lookup[EXP_COS_LUT_SIZE]; +int16_lut *exp_cos_lookup; //--------------------------------------- // Functions @@ -17,8 +17,10 @@ address_t timing_initialise(address_t address) { // **TODO** assert number of neurons is less than max // Copy LUTs from following memory - address_t lut_address = maths_copy_int16_lut_with_size(&address[0], EXP_COS_LUT_SIZE, - &exp_cos_lookup[0]); +// address_t lut_address = maths_copy_int16_lut_with_size( +// &address[0], EXP_COS_LUT_SIZE, &exp_cos_lookup[0]); + address_t lut_address = address; + exp_cos_lookup = maths_copy_int16_lut(&lut_address); io_printf(IO_BUF, "Timing_mfvn_initialise: completed successfully\n"); diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h index ff20496a8a6..e45292418e7 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h @@ -26,9 +26,9 @@ typedef int16_t pre_trace_t; #define EXP_COS_LUT_SIZE 256 // Helper macros for looking up decays -#define EXP_COS_LOOKUP(time) \ - maths_lut_exponential_decay_time_shifted( \ - time, TAU_PLUS_TIME_SHIFT, EXP_COS_LUT_SIZE, exp_cos_lookup) +//#define EXP_COS_LOOKUP(time) maths_lut_exponential_decay(time, exp_cos_lookup) +// maths_lut_exponential_decay_time_shifted( \ +// time, TAU_PLUS_TIME_SHIFT, EXP_COS_LUT_SIZE, exp_cos_lookup) //#define DECAY_LOOKUP_TAU_MINUS(time) \ // maths_lut_exponential_decay( \ // time, TAU_MINUS_TIME_SHIFT, TAU_MINUS_SIZE, tau_minus_lookup) @@ -36,16 +36,27 @@ typedef int16_t pre_trace_t; //--------------------------------------- // Externals //--------------------------------------- -extern int16_t exp_cos_lookup[EXP_COS_LUT_SIZE]; +//extern int16_t exp_cos_lookup[EXP_COS_LUT_SIZE]; //extern int16_lut *exp_cos_lookup; //--------------------------------------- // Timing dependence inline functions //--------------------------------------- -static inline post_trace_t timing_get_initial_post_trace() { +static inline post_trace_t timing_get_initial_post_trace(void) { return 0; } +static inline post_trace_t timing_decay_post( + uint32_t time, uint32_t last_time, post_trace_t last_trace) { + extern int16_lut *exp_cos_lookup; + // Get time since last spike + uint32_t delta_time = time - last_time; + + // Decay previous o1 and o2 traces + return (post_trace_t) STDP_FIXED_MUL_16X16(last_trace, + maths_lut_exponential_decay(delta_time, exp_cos_lookup)); +} + //--------------------------------------- static inline post_trace_t timing_add_post_spike( uint32_t time, uint32_t last_time, post_trace_t last_trace) { @@ -117,7 +128,9 @@ static inline update_state_t timing_apply_post_spike( use(last_post_time); use(&last_pre_trace); use(&last_post_trace); -// // This is where we lookup the value of e^(-bx) * cos(x)^2 + extern int16_lut *exp_cos_lookup; + + // // This is where we lookup the value of e^(-bx) * cos(x)^2 // // // Get time of event relative to last pre-synaptic event @@ -130,7 +143,14 @@ static inline update_state_t timing_apply_post_spike( if (time_since_last_pre < 255){ - uint32_t multiplier = EXP_COS_LOOKUP(time_since_last_pre); +// int32_t multiplier = EXP_COS_LOOKUP(time_since_last_pre); +// int32_t multiplier = STDP_FIXED_MUL_16X16(last_pre_trace, +// maths_lut_exponential_decay_time_shifted( +// time_since_last_pre, TAU_PLUS_TIME_SHIFT, exp_cos_lookup)); + int32_t multiplier = maths_lut_exponential_decay_time_shifted( + time_since_last_pre, TAU_PLUS_TIME_SHIFT, exp_cos_lookup); +// int32_t multiplier = STDP_FIXED_MUL_16X16(last_pre_trace, +// maths_lut_exponential_decay(time_since_last_pre, exp_cos_lookup)); if (print_plasticity){ io_printf(IO_BUF, "multiplier: %k (fixed = %u)\n", multiplier << 4, multiplier); diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c index 36e66e91952..061a6e8e24b 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c @@ -4,8 +4,8 @@ // Globals //--------------------------------------- // Exponential lookup-tables -int16_t exp_sin_lookup[EXP_SIN_LUT_SIZE]; -//int16_lut *exp_sin_lookup; +//int16_t exp_sin_lookup[EXP_SIN_LUT_SIZE]; +int16_lut *exp_sin_lookup; //--------------------------------------- // Functions @@ -16,8 +16,10 @@ address_t timing_initialise(address_t address) { io_printf(IO_BUF, "\tCerebellum PFPC rule\n"); // Copy LUTs from following memory - address_t lut_address = maths_copy_int16_lut_with_size(&address[0], EXP_SIN_LUT_SIZE, - &exp_sin_lookup[0]); +// address_t lut_address = maths_copy_int16_lut_with_size( +// &address[0], EXP_SIN_LUT_SIZE, &exp_sin_lookup[0]); + address_t lut_address = address; + exp_sin_lookup = maths_copy_int16_lut(&lut_address); io_printf(IO_BUF, "timing_pfpc_initialise: completed successfully\n"); diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index d9e68873a5e..b3ec2e6a7ee 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -26,9 +26,9 @@ typedef int16_t pre_trace_t; #define EXP_SIN_LUT_SIZE 256 // Helper macros for looking up decays -#define EXP_SIN_LOOKUP(time) \ - maths_lut_exponential_decay_time_shifted( \ - time, TAU_PLUS_TIME_SHIFT, EXP_SIN_LUT_SIZE, exp_sin_lookup) +//#define EXP_SIN_LOOKUP(time) maths_lut_exponential_decay(time, exp_sin_lookup) +// maths_lut_exponential_decay_time_shifted( \ +// time, TAU_PLUS_TIME_SHIFT, EXP_SIN_LUT_SIZE, exp_sin_lookup) //#define DECAY_LOOKUP_TAU_MINUS(time) \ // maths_lut_exponential_decay( \ // time, TAU_MINUS_TIME_SHIFT, TAU_MINUS_SIZE, tau_minus_lookup) @@ -36,16 +36,27 @@ typedef int16_t pre_trace_t; //--------------------------------------- // Externals //--------------------------------------- -extern int16_t exp_sin_lookup[EXP_SIN_LUT_SIZE]; +//extern int16_t exp_sin_lookup[EXP_SIN_LUT_SIZE]; //extern int16_lut *exp_sin_lookup; //--------------------------------------- // Timing dependence inline functions //--------------------------------------- -static inline post_trace_t timing_get_initial_post_trace() { +static inline post_trace_t timing_get_initial_post_trace(void) { return 0; } +static inline post_trace_t timing_decay_post( + uint32_t time, uint32_t last_time, post_trace_t last_trace) { + extern int16_lut *exp_sin_lookup; + // Get time since last spike + uint32_t delta_time = time - last_time; + + // Decay previous o1 and o2 traces + return (post_trace_t) STDP_FIXED_MUL_16X16(last_trace, + maths_lut_exponential_decay(delta_time, exp_sin_lookup)); +} + //--------------------------------------- static inline post_trace_t timing_add_post_spike( uint32_t time, uint32_t last_time, post_trace_t last_trace) { @@ -141,6 +152,7 @@ static inline update_state_t timing_apply_post_spike( use(last_post_time); use(&last_pre_trace); use(&last_post_trace); + extern int16_lut *exp_sin_lookup; @@ -155,7 +167,14 @@ static inline update_state_t timing_apply_post_spike( if (time_since_last_pre < 255){ - uint32_t multiplier = EXP_SIN_LOOKUP(time_since_last_pre); +// int32_t multiplier = EXP_SIN_LOOKUP(time_since_last_pre); +// int32_t multiplier = STDP_FIXED_MUL_16X16(last_pre_trace, +// maths_lut_exponential_decay_time_shifted( +// time_since_last_pre, TAU_PLUS_TIME_SHIFT, exp_sin_lookup)); + int32_t multiplier = maths_lut_exponential_decay_time_shifted( + time_since_last_pre, TAU_PLUS_TIME_SHIFT, exp_sin_lookup); +// int32_t multiplier = STDP_FIXED_MUL_16X16(last_pre_trace, +// maths_lut_exponential_decay(time_since_last_pre, exp_sin_lookup)); if (print_plasticity){ io_printf(IO_BUF, "multiplier: %k (fixed = %u)\n", multiplier << 4, multiplier); @@ -181,7 +200,7 @@ static inline update_state_t timing_apply_post_spike( // // Apply potentiation to state (which is a weight_state) // return weight_one_term_apply_potentiation(previous_state, decayed_r1); // } else { - return previous_state; + return previous_state; //} } diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c index d94b161dfdf..caf01124c5b 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c @@ -1,26 +1,32 @@ -#include "weight_multiplicative_impl.h" +#include "weight_mfvn_impl.h" //--------------------------------------- // Globals //--------------------------------------- // Global plasticity parameter data plasticity_weight_region_data_t *plasticity_weight_region_data; -uint32_t *weight_multiply_right_shift; +uint32_t *weight_shift; + +typedef struct { + accum min_weight; + accum max_weight; + accum a2_plus; + accum a2_minus; +} mfvn_config_t; //--------------------------------------- // Functions //--------------------------------------- -uint32_t *weight_initialise(uint32_t *address, uint32_t n_synapse_types, - uint32_t *ring_buffer_to_input_buffer_left_shifts) { +address_t weight_initialise( + address_t address, uint32_t n_synapse_types, + uint32_t *ring_buffer_to_input_buffer_left_shifts) { io_printf(IO_BUF, "mfvn weight_initialise: starting\n"); io_printf(IO_BUF, "\tSTDP mfvn weight dependence\n"); // Copy plasticity region data from address // **NOTE** this seems somewhat safer than relying on sizeof - int32_t *plasticity_word = (int32_t*) address; - - plasticity_weight_region_data = (plasticity_weight_region_data_t *) + plasticity_weight_region_data_t *dtcm_copy = plasticity_weight_region_data = spin1_malloc(sizeof(plasticity_weight_region_data_t) * n_synapse_types); if (plasticity_weight_region_data == NULL) { @@ -28,36 +34,33 @@ uint32_t *weight_initialise(uint32_t *address, uint32_t n_synapse_types, return NULL; } - weight_multiply_right_shift = (uint32_t *) - spin1_malloc(sizeof(uint32_t) * n_synapse_types); + weight_shift = spin1_malloc(sizeof(uint32_t) * n_synapse_types); - if (weight_multiply_right_shift == NULL) { + if (weight_shift == NULL) { log_error("Could not initialise weight region data"); return NULL; } + + mfvn_config_t *config = (mfvn_config_t *) address; for (uint32_t s = 0; s < n_synapse_types; s++) { // Copy parameters - plasticity_weight_region_data[s].min_weight = *plasticity_word++; - plasticity_weight_region_data[s].max_weight = *plasticity_word++; - plasticity_weight_region_data[s].a2_plus = *plasticity_word++; - plasticity_weight_region_data[s].a2_minus = *plasticity_word++; + dtcm_copy[s].min_weight = config->min_weight; + dtcm_copy[s].max_weight = config->max_weight; + dtcm_copy[s].a2_plus = config->a2_plus; + dtcm_copy[s].a2_minus = config->a2_minus; - // Calculate the right shift required to fixed-point multiply weights - weight_multiply_right_shift[s] = - 16 - (ring_buffer_to_input_buffer_left_shifts[s] + 1); + // Get the weight shift for switching from int16 to accum + weight_shift[s] = ring_buffer_to_input_buffer_left_shifts[s]; io_printf(IO_BUF, "\tSynapse type %u: Min weight:%d, Max weight:%d, A2+:%d, A2-:%d," " Weight multiply right shift:%u\n", - s, plasticity_weight_region_data[s].min_weight, - plasticity_weight_region_data[s].max_weight, - plasticity_weight_region_data[s].a2_plus, - plasticity_weight_region_data[s].a2_minus, - weight_multiply_right_shift[s]); + s, dtcm_copy[s].min_weight, dtcm_copy[s].max_weight, + dtcm_copy[s].a2_plus, dtcm_copy[s].a2_minus, weight_shift[s]); } io_printf(IO_BUF, "mfvn weight initialisation: completed successfully\n"); // Return end address of region - return (address_t) plasticity_word; + return (address_t) config; } diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h index 559e91ff477..07e90c2d15a 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h @@ -12,40 +12,42 @@ // Structures //--------------------------------------- typedef struct { - int32_t min_weight; - int32_t max_weight; + accum min_weight; + accum max_weight; - int32_t a2_plus; - int32_t a2_minus; + accum a2_plus; // Note: this value is pot_alpha from the python side + accum a2_minus; } plasticity_weight_region_data_t; typedef struct { - int32_t weight; + accum weight; - int32_t a2_plus; - int32_t a2_minus; +// int32_t a2_plus; +// int32_t a2_minus; - uint32_t weight_multiply_right_shift; + uint32_t weight_shift; const plasticity_weight_region_data_t *weight_region; } weight_state_t; #include "weight_one_term.h" -//--------------------------------------- -// Externals -//--------------------------------------- -extern plasticity_weight_region_data_t *plasticity_weight_region_data; -extern uint32_t *weight_multiply_right_shift; //--------------------------------------- // Weight dependance functions //--------------------------------------- static inline weight_state_t weight_get_initial(weight_t weight, index_t synapse_type) { + //--------------------------------------- + // Externals + //--------------------------------------- + extern plasticity_weight_region_data_t *plasticity_weight_region_data; + extern uint32_t *weight_shift; + + accum s1615_weight = kbits(weight << weight_shift[synapse_type]); + return (weight_state_t ) { - .weight = (int32_t) weight, - .weight_multiply_right_shift = - weight_multiply_right_shift[synapse_type], + .weight = s1615_weight, + .weight_shift = weight_shift[synapse_type], .weight_region = &plasticity_weight_region_data[synapse_type] }; } @@ -69,7 +71,9 @@ static inline weight_state_t weight_one_term_apply_depression( // Multiply scale by depression and subtract // **NOTE** using standard STDP fixed-point format handles format conversion - state.weight -= STDP_FIXED_MUL_16X16(state.weight, depression_multiplier); +// state.weight -= STDP_FIXED_MUL_16X16(state.weight, depression_multiplier); + state.weight -= mul_accum_fixed(state.weight, depression_multiplier); + state.weight = kbits(MAX(bitsk(state.weight), bitsk(state.weight_region->min_weight))); if (print_plasticity){ io_printf(IO_BUF, " Weight after depression: %u\n\n", @@ -80,7 +84,7 @@ static inline weight_state_t weight_one_term_apply_depression( } //--------------------------------------- static inline weight_state_t weight_one_term_apply_potentiation( - weight_state_t state, int32_t potentiation) { + weight_state_t state, int32_t a2_plus) { // add fixed amount if (print_plasticity){ @@ -89,7 +93,9 @@ static inline weight_state_t weight_one_term_apply_potentiation( state.weight_region->a2_plus); } - state.a2_plus += state.weight_region->a2_plus; +// state.a2_plus += state.weight_region->a2_plus; + state.weight += state.weight_region->a2_plus; // mul_accum_fixed(state.weight_region->a2_plus, a2_plus); + state.weight = kbits(MIN(bitsk(state.weight), bitsk(state.weight_region->max_weight))); return state; @@ -107,22 +113,32 @@ static inline weight_t weight_get_final(weight_state_t new_state) { // new_state.a2_plus, new_state.weight_region->a2_plus); - // Apply all terms to initial weight - int32_t new_weight = new_state.weight + new_state.a2_plus; - // - scaled_a2_minus; - - // Clamp new weight - new_weight = MIN(new_state.weight_region->max_weight, - new_weight); +// // Apply all terms to initial weight +// int32_t new_weight = new_state.weight + new_state.a2_plus; +// // - scaled_a2_minus; +// +// // Clamp new weight +// new_weight = MIN(new_state.weight_region->max_weight, +// new_weight); +// +// if (print_plasticity){ +// io_printf(IO_BUF, " old weight: %u, new weight: %u\n", +// new_state.weight, new_weight); +// } +// +// new_state.weight = new_weight; +// +// return (weight_t) new_state.weight; + return (weight_t) (bitsk(new_state.weight) >> new_state.weight_shift); - if (print_plasticity){ - io_printf(IO_BUF, " old weight: %u, new weight: %u\n", - new_state.weight, new_weight); - } +} - new_state.weight = new_weight; +static inline void weight_decay(weight_state_t *state, int32_t decay) { + state->weight = mul_accum_fixed(state->weight, decay); +} - return (weight_t) new_state.weight; +static inline accum weight_get_update(weight_state_t state) { + return state.weight; } #endif // _WEIGHT_MFVN_IMPL_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c index 82de61ad065..0903de8b072 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c @@ -1,63 +1,65 @@ -#include "weight_multiplicative_impl.h" +#include "weight_pfpc_impl.h" //--------------------------------------- // Globals //--------------------------------------- // Global plasticity parameter data plasticity_weight_region_data_t *plasticity_weight_region_data; -uint32_t *weight_multiply_right_shift; +uint32_t *weight_shift; + +typedef struct { + accum min_weight; + accum max_weight; + accum a2_plus; + accum a2_minus; +} pfpc_config_t; //--------------------------------------- // Functions //--------------------------------------- -uint32_t *weight_initialise(uint32_t *address, uint32_t n_synapse_types, - uint32_t *ring_buffer_to_input_buffer_left_shifts) { +address_t weight_initialise( + address_t address, uint32_t n_synapse_types, + uint32_t *ring_buffer_to_input_buffer_left_shifts) { io_printf(IO_BUF, "PFPC weight_initialise: starting\n"); io_printf(IO_BUF, "\tSTDP multiplicative weight dependence\n"); // Copy plasticity region data from address // **NOTE** this seems somewhat safer than relying on sizeof - int32_t *plasticity_word = (int32_t*) address; - plasticity_weight_region_data = (plasticity_weight_region_data_t *) + plasticity_weight_region_data_t *dtcm_copy = plasticity_weight_region_data = spin1_malloc(sizeof(plasticity_weight_region_data_t) * n_synapse_types); - if (plasticity_weight_region_data == NULL) { + if (dtcm_copy == NULL) { log_error("Could not initialise weight region data"); return NULL; } - weight_multiply_right_shift = (uint32_t *) - spin1_malloc(sizeof(uint32_t) * n_synapse_types); - - if (weight_multiply_right_shift == NULL) { + weight_shift = spin1_malloc(sizeof(uint32_t) * n_synapse_types); + if (weight_shift == NULL) { log_error("Could not initialise weight region data"); return NULL; } + + pfpc_config_t *config = (pfpc_config_t *) address; for (uint32_t s = 0; s < n_synapse_types; s++) { // Copy parameters - plasticity_weight_region_data[s].min_weight = *plasticity_word++; - plasticity_weight_region_data[s].max_weight = *plasticity_word++; - plasticity_weight_region_data[s].a2_plus = *plasticity_word++; - plasticity_weight_region_data[s].a2_minus = *plasticity_word++; - - // Calculate the right shift required to fixed-point multiply weights - weight_multiply_right_shift[s] = - 16 - (ring_buffer_to_input_buffer_left_shifts[s] + 1); + dtcm_copy[s].min_weight = config->min_weight; + dtcm_copy[s].max_weight = config->max_weight; + dtcm_copy[s].a2_plus = config->a2_plus; + dtcm_copy[s].a2_minus = config->a2_minus; + // Get the weight shift for switching from int16 to accum + weight_shift[s] = ring_buffer_to_input_buffer_left_shifts[s]; io_printf(IO_BUF, "\tSynapse type %u: Min weight:%d, Max weight:%d, A2+:%d, A2-:%d," " Weight multiply right shift:%u\n", - s, plasticity_weight_region_data[s].min_weight, - plasticity_weight_region_data[s].max_weight, - plasticity_weight_region_data[s].a2_plus, - plasticity_weight_region_data[s].a2_minus, - weight_multiply_right_shift[s]); + s, dtcm_copy[s].min_weight, dtcm_copy[s].max_weight, + dtcm_copy[s].a2_plus, dtcm_copy[s].a2_minus, weight_shift[s]); } io_printf(IO_BUF, "PFPC weight_initialise: completed successfully"); // Return end address of region - return (address_t) plasticity_word; + return (address_t) config; } diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h index 6085da0aefd..ec72d000706 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h @@ -1,5 +1,5 @@ -#ifndef _WEIGHT_MULTIPLICATIVE_IMPL_H_ -#define _WEIGHT_MULTIPLICATIVE_IMPL_H_ +#ifndef _WEIGHT_PFPC_IMPL_H_ +#define _WEIGHT_PFPC_IMPL_H_ // Include generic plasticity maths functions #include @@ -12,40 +12,39 @@ // Structures //--------------------------------------- typedef struct { - int32_t min_weight; - int32_t max_weight; + accum min_weight; + accum max_weight; - int32_t a2_plus; - int32_t a2_minus; + accum a2_plus; + accum a2_minus; } plasticity_weight_region_data_t; typedef struct { - int32_t weight; + accum weight; - int32_t a2_plus; - int32_t a2_minus; +// int32_t a2_plus; +// int32_t a2_minus; - uint32_t weight_multiply_right_shift; + uint32_t weight_shift; const plasticity_weight_region_data_t *weight_region; } weight_state_t; #include "weight_one_term.h" -//--------------------------------------- -// Externals -//--------------------------------------- -extern plasticity_weight_region_data_t *plasticity_weight_region_data; -extern uint32_t *weight_multiply_right_shift; //--------------------------------------- // Weight dependance functions //--------------------------------------- static inline weight_state_t weight_get_initial(weight_t weight, index_t synapse_type) { + extern plasticity_weight_region_data_t *plasticity_weight_region_data; + extern uint32_t *weight_shift; + + accum s1615_weight = kbits(weight << weight_shift[synapse_type]); + return (weight_state_t ) { - .weight = (int32_t) weight, - .weight_multiply_right_shift = - weight_multiply_right_shift[synapse_type], + .weight = s1615_weight, + .weight_shift = weight_shift[synapse_type], .weight_region = &plasticity_weight_region_data[synapse_type] }; } @@ -70,7 +69,8 @@ static inline weight_state_t weight_one_term_apply_depression( // Multiply scale by depression and subtract // **NOTE** using standard STDP fixed-point format handles format conversion - state.weight -= STDP_FIXED_MUL_16X16(state.weight, depression_multiplier); + state.weight -= mul_accum_fixed(state.weight, depression_multiplier); + state.weight = kbits(MAX(bitsk(state.weight), bitsk(state.weight_region->min_weight))); if (print_plasticity){ io_printf(IO_BUF, " Weight after depression: %u\n\n",state.weight); @@ -82,9 +82,10 @@ static inline weight_state_t weight_one_term_apply_depression( static inline weight_state_t weight_one_term_apply_potentiation( weight_state_t state, int32_t potentiation) { use(potentiation); - // add fixed amount - state.a2_plus += state.weight_region->a2_plus; +// state.a2_plus += state.weight_region->a2_plus; + state.weight += state.weight_region->a2_plus; //mul_accum_fixed(state.weight_region->a2_plus, a2_plus); + state.weight = kbits(MIN(bitsk(state.weight), bitsk(state.weight_region->max_weight))); return state; @@ -102,20 +103,30 @@ static inline weight_t weight_get_final(weight_state_t new_state) { // Apply all terms to initial weight - int32_t new_weight = new_state.weight + new_state.a2_plus; +// int32_t new_weight = new_state.weight + new_state.a2_plus; // - scaled_a2_minus; - if (print_plasticity){ - io_printf(IO_BUF, " old weight: %u, new weight: %u\n", - new_state.weight, new_weight); - } +// if (print_plasticity){ +// io_printf(IO_BUF, " old weight: %u, new weight: %u\n", +// new_state.weight, new_weight); +// } // Clamp new weight - new_weight = MIN(new_state.weight_region->max_weight, - new_weight); +// new_weight = MIN(new_state.weight_region->max_weight, +// new_weight); +// +// new_state.weight = new_weight; + +// return (weight_t) new_state.weight; + return (weight_t) (bitsk(new_state.weight) >> new_state.weight_shift); - new_state.weight = new_weight; +} + +static inline void weight_decay(weight_state_t *state, int32_t decay) { + state->weight = mul_accum_fixed(state->weight, decay); +} - return (weight_t) new_state.weight; +static inline accum weight_get_update(weight_state_t state) { + return state.weight; } -#endif // _WEIGHT_MULTIPLICATIVE_IMPL_H_ +#endif // _WEIGHT_PFPC_IMPL_H_ diff --git a/neural_modelling/src/neuron/send_spike.h b/neural_modelling/src/neuron/send_spike.h index 41a176ad899..1871b73a071 100644 --- a/neural_modelling/src/neuron/send_spike.h +++ b/neural_modelling/src/neuron/send_spike.h @@ -61,7 +61,7 @@ static inline void send_spike_mc(uint32_t key) { //! \param[in] timer_count The global timer count when the time step started //! \param[in] time The current time step //! \param[in] The neuron index to send -static inline void send_spike(UNUSED uint32_t timer_count, uint32_t time, +static inline void send_spike(UNUSED uint32_t timer_count, UNUSED uint32_t time, uint32_t neuron_index) { // Do any required synapse processing // synapse_dynamics_process_post_synaptic_event(time, neuron_index); diff --git a/neural_modelling/src/neuron/spike_processing.c b/neural_modelling/src/neuron/spike_processing.c index e0f66d0ae53..ba73aa775d9 100644 --- a/neural_modelling/src/neuron/spike_processing.c +++ b/neural_modelling/src/neuron/spike_processing.c @@ -121,7 +121,7 @@ static struct { uint32_t time; uint32_t packets_this_time_step; uint32_t dmas_this_time_step; - uint32_t pipeline_restarts;s + uint32_t pipeline_restarts; } p_per_ts_struct; //! the region to record the packets per timestep in @@ -498,8 +498,7 @@ bool spike_processing_initialise( // EXPORTED i, dma_buffers[i].row); } dma_busy = false; - clear_input_buffers_of_late_packets = - false; + clear_input_buffers_of_late_packets = clear_input_buffers_of_late_packets_init; next_buffer_to_fill = 0; buffer_being_read = N_DMA_BUFFERS; p_per_ts_region = packets_per_timestep_region; @@ -549,19 +548,19 @@ bool spike_processing_do_rewiring(int number_of_rewires) { } // Custom provenance from SpiNNCer -void spike_processing_get_and_reset_spikes_this_tick(){ +void spike_processing_get_and_reset_spikes_this_tick(void ) { if (p_per_ts_struct.packets_this_time_step > max_spikes_in_a_tick) { max_spikes_in_a_tick = p_per_ts_struct.packets_this_time_step; } } -void spike_processing_get_and_reset_dmas_this_tick(){ +void spike_processing_get_and_reset_dmas_this_tick(void) { if (p_per_ts_struct.dmas_this_time_step > max_dmas_in_a_tick){ max_dmas_in_a_tick = p_per_ts_struct.dmas_this_time_step; } } -void spike_processing_get_and_reset_pipeline_restarts_this_tick(){ +void spike_processing_get_and_reset_pipeline_restarts_this_tick(void) { if (p_per_ts_struct.pipeline_restarts > max_pipeline_restarts) { max_pipeline_restarts = p_per_ts_struct.pipeline_restarts; } diff --git a/neural_modelling/src/neuron/spike_processing.h b/neural_modelling/src/neuron/spike_processing.h index 35938bdd5a6..1ecb4eb032f 100644 --- a/neural_modelling/src/neuron/spike_processing.h +++ b/neural_modelling/src/neuron/spike_processing.h @@ -89,28 +89,28 @@ void spike_processing_clear_input_buffer(timer_t time); //! \brief get number of spikes received since last timer event //! \return uint32_t number of spikes -uint32_t spike_processing_get_and_reset_spikes_this_tick(); +void spike_processing_get_and_reset_spikes_this_tick(void); //! \brief get number of dmas completed since last timer event //! \return uint32_t number of DMAs -uint32_t spike_processing_get_and_reset_dmas_this_tick(); +void spike_processing_get_and_reset_dmas_this_tick(void); //! \brief get number of time pipeline was restarted since last timer event //! \return uint32_t number of pipeline restarts -uint32_t spike_processing_get_and_reset_pipeline_restarts_this_tick(); +void spike_processing_get_and_reset_pipeline_restarts_this_tick(void); -//! \brief get time from T1 clock at which spike pipeline completed -//! \return uint32_t pipeline deactivation time -uint32_t spike_processing_get_pipeline_deactivation_time(); - -// FLUSH SPIKES -//! \brief returns the total unprocessed spikes from a simulation -//! \return total unprocessed spikes -uint32_t spike_processing_get_total_flushed_spikes(); - -//! \brief returns the maximum unprocessed spikes from a single -//! simulation timestep. -//! \return maximum unprocessed spikes from a single timestep. -uint32_t spike_processing_get_max_flushed_spikes(); +////! \brief get time from T1 clock at which spike pipeline completed +////! \return uint32_t pipeline deactivation time +//uint32_t spike_processing_get_pipeline_deactivation_time(); +// +//// FLUSH SPIKES +////! \brief returns the total unprocessed spikes from a simulation +////! \return total unprocessed spikes +//uint32_t spike_processing_get_total_flushed_spikes(); +// +////! \brief returns the maximum unprocessed spikes from a single +////! simulation timestep. +////! \return maximum unprocessed spikes from a single timestep. +//uint32_t spike_processing_get_max_flushed_spikes(); #endif // _SPIKE_PROCESSING_H_ diff --git a/neural_modelling/src/neuron/synapses.c b/neural_modelling/src/neuron/synapses.c index 9c9806ea3c8..2afe5182062 100644 --- a/neural_modelling/src/neuron/synapses.c +++ b/neural_modelling/src/neuron/synapses.c @@ -211,8 +211,6 @@ static inline bool process_fixed_synapses( // overflow into the weight at worst but can't affect the lower bits. uint32_t ring_buffer_index = (synaptic_word + masked_time) & ring_buffer_mask; uint32_t weight = synapse_row_sparse_weight(synaptic_word); - uint32_t combined_synapse_neuron_index = synapse_row_sparse_type_index( - synaptic_word, synapse_type_index_mask); // *********************************** // For Cerebellum plasticity @@ -225,14 +223,8 @@ static inline bool process_fixed_synapses( // io_printf(IO_BUF, "\nSpike on type: %u at time: %u\n", type, time); synapse_dynamics_process_post_synaptic_event(time, neuron_index); } - // *********************************** - // Convert into ring buffer offset - uint32_t ring_buffer_index = synapses_get_ring_buffer_index_combined( - delay + time, combined_synapse_neuron_index, - synapse_type_index_bits); - // Add weight to current ring buffer value uint32_t accumulation = ring_buffers[ring_buffer_index] + weight; diff --git a/spynnaker/pyNN/models/neural_projections/projection_application_edge.py b/spynnaker/pyNN/models/neural_projections/projection_application_edge.py index cd9c31a7094..72353885318 100644 --- a/spynnaker/pyNN/models/neural_projections/projection_application_edge.py +++ b/spynnaker/pyNN/models/neural_projections/projection_application_edge.py @@ -254,3 +254,5 @@ def post_slices(self): def get_local_provenance_data(self): for synapse_info in self.synapse_information: synapse_info.connector.get_provenance_data(synapse_info) + if are_dynamics_stdp(synapse_info.synapse_dynamics): + synapse_info.synapse_dynamics.get_provenance_data(synapse_info) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py index de93392b35a..23ca7c405ec 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py @@ -17,7 +17,7 @@ import numpy import matplotlib.pyplot as plt from data_specification.enums import DataType -from spinn_front_end_common.utilities.utility_objs import ProvenanceDataItem +# from spinn_front_end_common.utilities.utility_objs import ProvenanceDataItem # Default value of fixed-point one for STDP STDP_FIXED_POINT_ONE = (1 << 11) @@ -34,25 +34,25 @@ def float_to_fixed(value, fixed_point_one): return int(round(float(value) * float(fixed_point_one))) -def get_lut_provenance( - pre_population_label, post_population_label, rule_name, entry_name, - param_name, last_entry): - # pylint: disable=too-many-arguments - top_level_name = "{}_{}_STDP_{}".format( - pre_population_label, post_population_label, rule_name) - report = False - if last_entry is not None: - report = last_entry > 0 - return ProvenanceDataItem( - [top_level_name, entry_name], last_entry, report=report, - message=( - "The last entry in the STDP exponential lookup table for the {}" - " parameter of the {} between {} and {} was {} rather than 0," - " indicating that the lookup table was not big enough at this" - " timestep and value. Try reducing the parameter value, or" - " increasing the timestep".format( - param_name, rule_name, pre_population_label, - post_population_label, last_entry))) +# def get_lut_provenance( +# pre_population_label, post_population_label, rule_name, entry_name, +# param_name, last_entry): +# # pylint: disable=too-many-arguments +# top_level_name = "{}_{}_STDP_{}".format( +# pre_population_label, post_population_label, rule_name) +# report = False +# if last_entry is not None: +# report = last_entry > 0 +# return ProvenanceDataItem( +# [top_level_name, entry_name], last_entry, report=report, +# message=( +# "The last entry in the STDP exponential lookup table for the {}" +# " parameter of the {} between {} and {} was {} rather than 0," +# " indicating that the lookup table was not big enough at this" +# " timestep and value. Try reducing the parameter value, or" +# " increasing the timestep".format( +# param_name, rule_name, pre_population_label, +# post_population_label, last_entry))) def get_exp_lut_array(time_step, time_constant, shift=0): @@ -113,7 +113,8 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, exp_float = 0 else: # Evaluate kernel - exp_float = (math.exp(-value) * math.sin(value) ** sin_pwr / kernel_peak_value) * kernel_scaling + exp_float = (math.exp(-value) * math.sin(value) ** + sin_pwr / kernel_peak_value) * kernel_scaling # Convert to fixed-point exp_fix = float_to_fixed(exp_float, fixed_point_one) @@ -151,12 +152,22 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, 99, 115, 135, 140, 150]) print("LUT VALUES TO COMPARE TO SPINNAKER:") print("TIME DELTAS | FIXED MULTIPLIERS | FLOAT MULTIPLIERS") - for x, y, z, in zip(compare_t_values, out_fixed[compare_t_values], out_float[compare_t_values]): + for x, y, z, in zip(compare_t_values, out_fixed[compare_t_values], + out_float[compare_t_values]): print("{:8} | {:8} | {:8.4f}".format(x, y, z)) return t, out_float else: - spec.write_array(final_exp_fix, data_type=DataType.INT16) + header = numpy.array([len(final_exp_fix), shift], dtype="uint16") + array_to_write = numpy.concatenate(( + header, + numpy.array(final_exp_fix).astype("uint16"))).view("uint32") + # + # spec.write_array(array_to_write) + print("pfpc_lut: ", array_to_write) + print("header: ", header) + return array_to_write + # spec.write_array(final_exp_fix, data_type=DataType.INT16) def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, @@ -190,7 +201,8 @@ def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, exp_float = 0 else: # Evaluate kernel - exp_float = (math.exp(-abs(value * beta)) * math.cos(value) ** cos_pwr / kernel_peak_value) * kernel_scaling + exp_float = (math.exp(-abs(value * beta)) * math.cos(value) ** + cos_pwr / kernel_peak_value) * kernel_scaling # Convert to fixed-point exp_fix = float_to_fixed(exp_float, fixed_point_one) @@ -222,9 +234,17 @@ def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, 99, 115, 135, 140, 150]) print("LUT VALUES TO COMPARE TO SPINNAKER:") print("TIME DELTAS | FIXED MULTIPLIERS | FLOAT MULTIPLIERS") - for x, y, z, in zip(compare_t_values, out_fixed[compare_t_values], out_float[compare_t_values]): + for x, y, z, in zip(compare_t_values, out_fixed[compare_t_values], + out_float[compare_t_values]): print("{:8} | {:8} | {:8.4f}".format(x, y, z)) # plt.show() return plot_times, out_float else: - spec.write_array(final_exp_fix, data_type=DataType.INT16) + header = numpy.array([len(final_exp_fix), shift], dtype="uint16") + array_to_write = numpy.concatenate(( + header, + numpy.array(final_exp_fix).astype("uint16"))).view("uint32") + spec.write_array(array_to_write) + print("mfvn_lut: ", array_to_write) + print("header: ", header) + # spec.write_array(final_exp_fix, data_type=DataType.INT16) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/abstract_timing_dependence.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/abstract_timing_dependence.py index 463ad2d04fc..f6fdc9c27a1 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/abstract_timing_dependence.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/abstract_timing_dependence.py @@ -84,3 +84,9 @@ def get_parameter_names(self): :rtype: iterable(str) """ + + def get_provenance_data(self, synapse_info): + """ Get any provenance data + :param SynapseInformation synapse_info + """ + # pylint: disable=unused-argument diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py index 29c160f42f8..a34d087b303 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py @@ -1,6 +1,10 @@ from spinn_utilities.overrides import overrides +from spinn_front_end_common.interface.provenance import ProvenanceWriter +from spinn_front_end_common.utilities.globals_variables import ( + machine_time_step_ms) +from spinn_front_end_common.utilities.constants import BYTES_PER_WORD from spynnaker.pyNN.models.neuron.plasticity.stdp.common \ - import write_mfvn_lut, get_lut_provenance + import write_mfvn_lut from .abstract_timing_dependence import AbstractTimingDependence from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure\ import SynapseStructureWeightOnly @@ -18,14 +22,21 @@ class TimingDependenceMFVN(AbstractTimingDependence): "_tau_minus_last_entry", "_tau_plus", "_tau_plus_last_entry", + "__a_plus", + "__a_minus", "_beta", "_sigma", "_kernel_scaling" ] - def __init__(self, tau_plus=20.0, tau_minus=20.0, beta=10, sigma=200, kernel_scaling=1.0): + def __init__(self, tau_plus=20.0, tau_minus=20.0, A_plus=0.01, + A_minus=0.01, beta=10, sigma=200, kernel_scaling=1.0): self._tau_plus = tau_plus self._tau_minus = tau_minus + + self.__a_plus = A_plus + self.__a_minus = A_minus + self._kernel_scaling = kernel_scaling self._synapse_structure = SynapseStructureWeightOnly() @@ -45,6 +56,30 @@ def tau_plus(self): def tau_minus(self): return self._tau_minus + @property + def A_plus(self): + r""" :math:`A^+` + + :rtype: float + """ + return self.__a_plus + + @A_plus.setter + def A_plus(self, new_value): + self.__a_plus = new_value + + @property + def A_minus(self): + r""" :math:`A^-` + + :rtype: float + """ + return self.__a_minus + + @A_minus.setter + def A_minus(self, new_value): + self.__a_minus = new_value + @property def beta(self): return self._beta @@ -72,16 +107,18 @@ def pre_trace_n_bytes(self): @overrides(AbstractTimingDependence.get_parameters_sdram_usage_in_bytes) def get_parameters_sdram_usage_in_bytes(self): - return 2 * LUT_SIZE #in bytes: 256 * 16 bit values + return BYTES_PER_WORD * LUT_SIZE #in bytes: 256 * 16 bit values @property def n_weight_terms(self): return 1 @overrides(AbstractTimingDependence.write_parameters) - def write_parameters(self, spec, machine_time_step, weight_scales): + def write_parameters( + self, spec, global_weight_scale, synapse_weight_scales): # Check timestep is valid - if machine_time_step != 1000: + machine_time_step = machine_time_step_ms() + if machine_time_step != 1: raise NotImplementedError( "exp cos LUT generation currently only supports 1ms timesteps") @@ -100,15 +137,52 @@ def synaptic_structure(self): return self._synapse_structure @overrides(AbstractTimingDependence.get_provenance_data) - def get_provenance_data(self, pre_population_label, post_population_label): - prov_data = list() - prov_data.append(get_lut_provenance( - pre_population_label, post_population_label, "MFVNRule", - "tau_plus_last_entry", "tau_plus", self._tau_plus_last_entry)) - prov_data.append(get_lut_provenance( - pre_population_label, post_population_label, "MFVNRule", - "tau_minus_last_entry", "tau_minus", self._tau_minus_last_entry)) - return prov_data + def get_provenance_data(self, synapse_info): + tauplus = self._tau_plus_last_entry + tauminus = self._tau_minus_last_entry + with ProvenanceWriter() as db: + db.insert_lut( + synapse_info.pre_population.label, + synapse_info.post_population.label, + self.__class__.__name__, "tau_plus_last_entry", + tauplus) + if tauplus is not None: + if tauplus > 0: + db.insert_report( + f"The last entry in the STDP exponential lookup table " + f"for the tau_plus parameter of the" + f"{self.__class__.__name} between " + f"{synapse_info.pre_population.label} and " + f"{synapse_info.post_population.label} was {tauplus} " + f"rather than 0, indicating that the lookup table was " + f"not big enough at this timestep and value. Try " + f"reducing the parameter value, or increasing the " + f"timestep.") + db.insert_lut( + synapse_info.pre_population.label, + synapse_info.post_population.label, + self.__class__.__name__, "tau_minus_last_entry", + tauminus) + if tauminus is not None: + if tauminus > 0: + db.insert_report( + f"The last entry in the STDP exponential lookup table " + f"for the tau_minus parameter of the " + f"{self.__class__.__name} between " + f"{synapse_info.pre_population.label} and " + f"{synapse_info.post_population.label} was {tauminus} " + f"rather than 0, indicating that the lookup table was " + f"not big enough at this timestep and value. Try " + f"reducing the parameter value, or increasing the " + f"timestep.") + # prov_data = list() + # prov_data.append(get_lut_provenance( + # pre_population_label, post_population_label, "MFVNRule", + # "tau_plus_last_entry", "tau_plus", self._tau_plus_last_entry)) + # prov_data.append(get_lut_provenance( + # pre_population_label, post_population_label, "MFVNRule", + # "tau_minus_last_entry", "tau_minus", self._tau_minus_last_entry)) + # return prov_data @overrides(AbstractTimingDependence.get_parameter_names) def get_parameter_names(self): diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index 1027beaac79..2eae912ad93 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -1,6 +1,11 @@ from spinn_utilities.overrides import overrides +from spinn_front_end_common.interface.provenance import ProvenanceWriter +from spinn_front_end_common.utilities.globals_variables import ( + machine_time_step_ms) +from spinn_front_end_common.utilities.constants import ( + BYTES_PER_SHORT, BYTES_PER_WORD) from spynnaker.pyNN.models.neuron.plasticity.stdp.common \ - import write_pfpc_lut, get_lut_provenance + import write_pfpc_lut from .abstract_timing_dependence import AbstractTimingDependence from spynnaker.pyNN.models.neuron.plasticity.stdp.synapse_structure \ import SynapseStructureWeightOnly @@ -16,24 +21,34 @@ class TimingDependencePFPC(AbstractTimingDependence): __slots__ = [ "_synapse_structure", "_tau_minus", - "_tau_minus_last_entry", + "_tau_minus_data", "_tau_plus", - "_tau_plus_last_entry", + "_tau_plus_data", + "__a_plus", + "__a_minus", "_t_peak", "_kernel_scaling"] - def __init__(self, tau_plus=20.0, tau_minus=20.0, - t_peak=100, kernel_scaling=1.0): + def __init__(self, tau_plus=20.0, tau_minus=20.0, A_plus=0.01, + A_minus=0.01, t_peak=100, kernel_scaling=1.0): self._tau_plus = tau_plus self._tau_minus = tau_minus + + self.__a_plus = A_plus + self.__a_minus = A_minus + self._t_peak = t_peak self._kernel_scaling = kernel_scaling self._synapse_structure = SynapseStructureWeightOnly() # provenance data - self._tau_plus_last_entry = None - self._tau_minus_last_entry = None + dummy_spec = [] + self._tau_plus_data = write_pfpc_lut( + dummy_spec, peak_time=self._t_peak, + time_probe=None, lut_size=LUT_SIZE, + shift=0, kernel_scaling=self._kernel_scaling) + self._tau_minus_data = None @property def tau_plus(self): @@ -43,6 +58,30 @@ def tau_plus(self): def tau_minus(self): return self._tau_minus + @property + def A_plus(self): + r""" :math:`A^+` + + :rtype: float + """ + return self.__a_plus + + @A_plus.setter + def A_plus(self, new_value): + self.__a_plus = new_value + + @property + def A_minus(self): + r""" :math:`A^-` + + :rtype: float + """ + return self.__a_minus + + @A_minus.setter + def A_minus(self, new_value): + self.__a_minus = new_value + @property def t_peak(self): return self._t_peak @@ -61,48 +100,109 @@ def vertex_executable_suffix(self): @property def pre_trace_n_bytes(self): - # Here we will record the last 16 spikes, these will be 32-bit quantities, - return (16 * 4) + (2 * 16) # 16 4-byte entries, plus one counter for the number of spikes + # Here we will record the last 16 spikes: + # these will be 32-bit quantities, 16 4-byte entries, + # plus one counter for the number of spikes + return (16 * 4) + (2 * 16) @overrides(AbstractTimingDependence.get_parameters_sdram_usage_in_bytes) def get_parameters_sdram_usage_in_bytes(self): - return 2 * LUT_SIZE # in bytes: 256 * 16 bit values + # in bytes: 256 * 16 bit values ? + return BYTES_PER_WORD * len(self._tau_plus_data) @property def n_weight_terms(self): return 1 + # @overrides(AbstractTimingDependence.write_parameters) + # def write_parameters(self, spec, machine_time_step, weight_scales): + # # Check timestep is valid + # if machine_time_step != 1000: + # raise NotImplementedError( + # "exp_sin LUT generation currently only supports 1ms timesteps") + # + # # Write exp_sin lookup table + # self._tau_plus_last_entry = write_pfpc_lut( + # spec, + # peak_time=self._t_peak, + # time_probe=None, + # lut_size=LUT_SIZE, + # shift=0, + # kernel_scaling=self._kernel_scaling + # ) + @overrides(AbstractTimingDependence.write_parameters) - def write_parameters(self, spec, machine_time_step, weight_scales): + def write_parameters( + self, spec, global_weight_scale, synapse_weight_scales): # Check timestep is valid - if machine_time_step != 1000: + machine_time_step = machine_time_step_ms() + if machine_time_step != 1: raise NotImplementedError( "exp_sin LUT generation currently only supports 1ms timesteps") # Write exp_sin lookup table - self._tau_plus_last_entry = write_pfpc_lut( - spec, - peak_time=self._t_peak, - time_probe=None, - lut_size=LUT_SIZE, - shift=0, - kernel_scaling=self._kernel_scaling - ) + print("check, tau_plus_data: ", self._tau_plus_data) + spec.write_array(self._tau_plus_data) + # self._tau_plus_last_entry = write_pfpc_lut( + # spec, + # peak_time=self._t_peak, + # time_probe=None, + # lut_size=LUT_SIZE, + # shift=0, + # kernel_scaling=self._kernel_scaling + # ) @property def synaptic_structure(self): return self._synapse_structure @overrides(AbstractTimingDependence.get_provenance_data) - def get_provenance_data(self, pre_population_label, post_population_label): - prov_data = list() - prov_data.append(get_lut_provenance( - pre_population_label, post_population_label, "PFPCRule", - "tau_plus_last_entry", "tau_plus", self._tau_plus_last_entry)) - prov_data.append(get_lut_provenance( - pre_population_label, post_population_label, "PFPCRule", - "tau_minus_last_entry", "tau_minus", self._tau_minus_last_entry)) - return prov_data + def get_provenance_data(self, synapse_info): + tauplus = self._tau_plus_data[-1] + tauminus = self._tau_minus_data + with ProvenanceWriter() as db: + db.insert_lut( + synapse_info.pre_population.label, + synapse_info.post_population.label, + self.__class__.__name__, "tau_plus_last_entry", + tauplus) + if tauplus is not None: + if tauplus > 0: + db.insert_report( + f"The last entry in the STDP exponential lookup table " + f"for the tau_plus parameter of the" + f"{self.__class__.__name} between " + f"{synapse_info.pre_population.label} and " + f"{synapse_info.post_population.label} was {tauplus} " + f"rather than 0, indicating that the lookup table was " + f"not big enough at this timestep and value. Try " + f"reducing the parameter value, or increasing the " + f"timestep.") + db.insert_lut( + synapse_info.pre_population.label, + synapse_info.post_population.label, + self.__class__.__name__, "tau_minus_last_entry", + tauminus) + if tauminus is not None: + if tauminus > 0: + db.insert_report( + f"The last entry in the STDP exponential lookup table " + f"for the tau_minus parameter of the " + f"{self.__class__.__name} between " + f"{synapse_info.pre_population.label} and " + f"{synapse_info.post_population.label} was {tauminus} " + f"rather than 0, indicating that the lookup table was " + f"not big enough at this timestep and value. Try " + f"reducing the parameter value, or increasing the " + f"timestep.") + # prov_data = list() + # prov_data.append(get_lut_provenance( + # pre_population_label, post_population_label, "PFPCRule", + # "tau_plus_last_entry", "tau_plus", self._tau_plus_last_entry)) + # prov_data.append(get_lut_provenance( + # pre_population_label, post_population_label, "PFPCRule", + # "tau_minus_last_entry", "tau_minus", self._tau_minus_last_entry)) + # return prov_data @overrides(AbstractTimingDependence.get_parameter_names) def get_parameter_names(self): diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py index 89a6400857e..c6f675e971a 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py @@ -141,7 +141,9 @@ def write_parameters( self, spec, global_weight_scale, synapse_weight_scales): # Write lookup tables + print("LUT tau plus ", self.__tau_plus_data) spec.write_array(self.__tau_plus_data) + print("LUT tau minus ", self.__tau_minus_data) spec.write_array(self.__tau_minus_data) @property diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py index 73d6b8fdb40..4ee17b23456 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py @@ -7,33 +7,33 @@ class WeightDependenceMFVN( AbstractHasAPlusAMinus, AbstractWeightDependence): __slots__ = [ - "_w_max", - "_w_min", - "_pot_alpha" + "__w_max", + "__w_min", + "__pot_alpha" ] # noinspection PyPep8Naming def __init__(self, w_min=0.0, w_max=1.0, pot_alpha=0.01): super(WeightDependenceMFVN, self).__init__() - self._w_min = w_min - self._w_max = w_max - self._pot_alpha = pot_alpha + self.__w_min = w_min + self.__w_max = w_max + self.__pot_alpha = pot_alpha @property def w_min(self): - return self._w_min + return self.__w_min @property def w_max(self): - return self._w_max + return self.__w_max @property def pot_alpha(self): - return self._pot_alpha - + return self.__pot_alpha + @pot_alpha.setter def pot_alpha(self, new_value): - self._pot_alpha = new_value + self.__pot_alpha = new_value @overrides(AbstractWeightDependence.is_same_as) def is_same_as(self, weight_dependence): @@ -59,29 +59,36 @@ def get_parameters_sdram_usage_in_bytes( @overrides(AbstractWeightDependence.write_parameters) def write_parameters( - self, spec, machine_time_step, weight_scales, n_weight_terms): + self, spec, global_weight_scale, synapse_weight_scales, + n_weight_terms): # Loop through each synapse type's weight scale - for w in weight_scales: + for _ in synapse_weight_scales: # Scale the weights spec.write_value( - data=int(round(self._w_min * w)), data_type=DataType.INT32) + data=self.__w_min * global_weight_scale, + data_type=DataType.S1615) spec.write_value( - data=int(round(self._w_max * w)), data_type=DataType.INT32) + data=self.__w_max * global_weight_scale, + data_type=DataType.S1615) - # Pre-multiply weight parameters by Wmax + # Pre-multiply weight parameters by Wmax? + # I don't know what's going on here, this is weird + # If this works the parameter needs renaming on the C side + # otherwise it's just confusing spec.write_value( - data=int(round(self._pot_alpha * w)), - data_type=DataType.INT32) + data=self.__pot_alpha * global_weight_scale, + data_type=DataType.S1615) # This parameter is actually currently unused + # (I'm not convinced that's true...) spec.write_value( - data=int(round(self.A_minus * w)), - data_type=DataType.INT32) + data=self.A_minus * global_weight_scale, + data_type=DataType.S1615) @property def weight_maximum(self): - return self._w_max + return self.__w_max @overrides(AbstractWeightDependence.get_parameter_names) def get_parameter_names(self): diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py index ce0c2c76ccd..043abf46ee2 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py @@ -7,33 +7,33 @@ class WeightDependencePFPC( AbstractHasAPlusAMinus, AbstractWeightDependence): __slots__ = [ - "_w_max", - "_w_min", - "_pot_alpha" + "__w_max", + "__w_min", + "__pot_alpha" ] # noinspection PyPep8Naming def __init__(self, w_min=0.0, w_max=1.0, pot_alpha=0.01): super(WeightDependencePFPC, self).__init__() - self._w_min = w_min - self._w_max = w_max - self._pot_alpha = pot_alpha + self.__w_min = w_min + self.__w_max = w_max + self.__pot_alpha = pot_alpha @property def w_min(self): - return self._w_min + return self.__w_min @property def w_max(self): - return self._w_max + return self.__w_max @property def pot_alpha(self): - return self._pot_alpha - + return self.__pot_alpha + @pot_alpha.setter def pot_alpha(self, new_value): - self._pot_alpha = new_value + self.__pot_alpha = new_value @overrides(AbstractWeightDependence.is_same_as) def is_same_as(self, weight_dependence): @@ -59,29 +59,39 @@ def get_parameters_sdram_usage_in_bytes( @overrides(AbstractWeightDependence.write_parameters) def write_parameters( - self, spec, machine_time_step, weight_scales, n_weight_terms): + self, spec, global_weight_scale, synapse_weight_scales, + n_weight_terms): # Loop through each synapse type's weight scale - for w in weight_scales: + for _ in synapse_weight_scales: + + print("PFPC, writing values min, max, pot_alpha, A_minus ", + self.__w_min, self.__w_max, self.__pot_alpha, self.A_minus) # Scale the weights spec.write_value( - data=int(round(self._w_min * w)), data_type=DataType.INT32) + data=self.__w_min * global_weight_scale, + data_type=DataType.S1615) spec.write_value( - data=int(round(self._w_max * w)), data_type=DataType.INT32) + data=self.__w_max * global_weight_scale, + data_type=DataType.S1615) - # Pre-multiply weight parameters by Wmax + # Pre-multiply weight parameters by Wmax? + # I don't know what's going on here, this is weird + # If this works the parameter needs renaming on the C side + # otherwise it's just confusing spec.write_value( - data=int(round(self._pot_alpha * w)), - data_type=DataType.INT32) + data=self.__pot_alpha * global_weight_scale, + data_type=DataType.S1615) # This parameter is actually currently unused + # (I'm not convinced that's true...) spec.write_value( - data=int(round(self.A_minus * w)), - data_type=DataType.INT32) + data=self.A_minus * global_weight_scale, + data_type=DataType.S1615) @property def weight_maximum(self): - return self._w_max + return self.__w_max @overrides(AbstractWeightDependence.get_parameter_names) def get_parameter_names(self): diff --git a/spynnaker/pyNN/models/neuron/population_machine_synapses_provenance.py b/spynnaker/pyNN/models/neuron/population_machine_synapses_provenance.py index db37b6db593..3a42c3a222e 100644 --- a/spynnaker/pyNN/models/neuron/population_machine_synapses_provenance.py +++ b/spynnaker/pyNN/models/neuron/population_machine_synapses_provenance.py @@ -35,16 +35,20 @@ class SynapseProvenance(ctypes.LittleEndianStructure): ("n_invalid_pop_table_hits", ctypes.c_uint32), # The number of spikes that didn't transfer empty rows ("n_filtered_by_bitfield", ctypes.c_uint32), - # Custom provenance from SpiNNCer + # Custom provenance from SpiNNCer - max spikes in a tick ("max_spikes_in_a_tick", ctypes.c_uint32), - ("max_dmas_in_a tick", ctypes.c_uint32), + # max dmas in a tick + ("max_dmas_in_a_tick", ctypes.c_uint32), + # max pipeline restarts ("max_pipeline_restarts", ctypes.c_uint32), - ("timer_callback_completed", ctype.c_uint32), - ("spikes_pipeline_activated", ctype.c_uint32), + # timer callback completed? + ("timer_callback_completed", ctypes.c_uint32), + # spikes pipeline activated? + ("spikes_pipeline_activated", ctypes.c_uint32), # Max flushed spikes in a timestep - ("max_flushed_spikes", ctype.c_uint32), + ("max_flushed_spikes", ctypes.c_uint32), # Total flushed spikes - ("total_flushed_spikes", ctype.c_uint32) + ("total_flushed_spikes", ctypes.c_uint32) ] N_ITEMS = len(_fields_) @@ -152,7 +156,7 @@ def _parse_synapse_provenance(self, label, x, y, p, provenance_data): # SpiNNCer db.insert_core( x, y, p, self.MAX_SPIKES_IN_A_TICK, - synpase_prov.max_spikes_in_a_tick) + synapse_prov.max_spikes_in_a_tick) if synapse_prov.max_spikes_in_a_tick > 200: db.insert_report( f"Max number of spikes for {label} was " diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py index b0f3438849f..4f9fdcb5b6d 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py @@ -609,3 +609,7 @@ def set_delay(self, delay): @overrides(AbstractPlasticSynapseDynamics.pad_to_length) def pad_to_length(self): return self.__pad_to_length + + def get_provenance_data(self, synapse_info): + self.__timing_dependence.get_provenance_data(synapse_info) + # self.__weight_dependence.get_provenance_data(synapse_info) diff --git a/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_mfvn.py b/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_mfvn.py index 06b461b6f43..aa31162a51b 100644 --- a/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_mfvn.py +++ b/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_mfvn.py @@ -43,4 +43,4 @@ def __init__( "timing_dependence.TimingDependenceMFVN") super(TimingDependenceMFVN, self).__init__( tau_plus=tau_plus, tau_minus=tau_minus, A_plus=A_plus, - A_minus=A_minus, beta=beta, sigma=sigma, alpha=alpha) + A_minus=A_minus, beta=beta, sigma=sigma, kernel_scaling=alpha) diff --git a/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_pfpc.py b/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_pfpc.py index 3f335315d3a..fa1c5caf3f3 100644 --- a/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_pfpc.py @@ -30,14 +30,14 @@ class TimingDependencePFPC(_BaseClass): def __init__( self, tau_plus=20.0, tau_minus=20.0, A_plus=0.01, A_minus=0.01, - t_peak=100, alpha=1.0): + t_peak=100, kernel_scaling=1.0): r""" :param float tau_plus: :math:`\tau_+` :param float tau_minus: :math:`\tau_-` :param float A_plus: :math:`A^+` :param float A_minus: :math:`A^-` :param float t_peak: :math:`t_\mathrm{peak}` - :param float alpha: :math:`alpha' + :param float kernel_scaling: """ moved_in_v6("spynnaker8.models.synapse_dynamics.timing_dependence." "TimingDependencePFPC", @@ -45,4 +45,4 @@ def __init__( "timing_dependence.TimingDependencePFPC") super(TimingDependencePFPC, self).__init__( tau_plus=tau_plus, tau_minus=tau_minus, A_plus=A_plus, - A_minus=A_minus, t_peak=t_peak, alpha=alpha) + A_minus=A_minus, t_peak=t_peak, kernel_scaling=kernel_scaling) diff --git a/spynnaker8/models/synapse_dynamics/weight_dependence/__init__.py b/spynnaker8/models/synapse_dynamics/weight_dependence/__init__.py index b1620dbc3c7..7d2ecf47187 100644 --- a/spynnaker8/models/synapse_dynamics/weight_dependence/__init__.py +++ b/spynnaker8/models/synapse_dynamics/weight_dependence/__init__.py @@ -24,7 +24,7 @@ from .weight_dependence_multiplicative import WeightDependenceMultiplicative from .weight_dependence_additive_triplet import WeightDependenceAdditiveTriplet from .weight_dependence_pfpc import WeightDependencePFPC -from .weight_dependence_mfvn import import WeightDependenceMFVN +from .weight_dependence_mfvn import WeightDependenceMFVN __all__ = ["WeightDependenceAdditive", "WeightDependenceMultiplicative", "WeightDependenceAdditiveTriplet", "WeightDependencePFPC", From 0534e0d8387b5b63596452959da72fdcd608a03d Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 18 Nov 2021 12:06:38 +0000 Subject: [PATCH 048/108] Tidy up C code (vera) --- .../synapse_dynamics_stdp_mad_mfvn_impl.c | 10 ++++--- .../synapse_dynamics_stdp_mad_pfpc_impl.c | 4 +-- .../stdp/timing_dependence/timing_mfvn_impl.h | 28 +++---------------- .../stdp/timing_dependence/timing_pfpc_impl.h | 24 +--------------- .../stdp/weight_dependence/weight_mfvn_impl.h | 5 ++-- .../stdp/weight_dependence/weight_pfpc_impl.h | 9 +++--- 6 files changed, 19 insertions(+), 61 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c index a15d6d51f7f..a9ef5e967c9 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c @@ -41,12 +41,13 @@ struct synapse_row_plastic_data_t { void _print_pre_event_history(pre_event_history_t pre_eve_hist){ io_printf(IO_BUF, "\n\n************************\n\n"); - io_printf(IO_BUF, "Number recorded MF spikes: %u\n", pre_eve_hist.num_recorded_mf_spikes_minus_one); + io_printf(IO_BUF, "Number recorded MF spikes: %u\n", + pre_eve_hist.num_recorded_mf_spikes_minus_one); io_printf(IO_BUF, "Prev time: %u\n", pre_eve_hist.mf_times[pre_eve_hist.num_recorded_mf_spikes_minus_one]); - for (int i =0; i < NUM_MF_SPIKES_TO_RECORD; i ++){ - io_printf(IO_BUF, " Entry %u: %u\n", i ,pre_eve_hist.mf_times[i]); + for (int i = 0; i < NUM_MF_SPIKES_TO_RECORD; i++){ + io_printf(IO_BUF, " Entry %u: %u\n", i , pre_eve_hist.mf_times[i]); } } @@ -161,10 +162,11 @@ static inline final_state_t plasticity_update_synapse( ); } + // Some of these variables aren't used current_state = timing_apply_post_spike( delayed_mf_time, *fwd_post_window.next_trace, (time+delay_dendritic - delayed_mf_time), - last_pre_trace, fwd_post_window.prev_time, fwd_post_window.prev_trace, // these variables aren't used + last_pre_trace, fwd_post_window.prev_time, fwd_post_window.prev_trace, current_state); fwd_post_window = post_events_next_delayed(fwd_post_window, delayed_mf_time); diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c index 212f51dcef2..7b7848134a9 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c @@ -54,8 +54,8 @@ void _print_pre_event_history(pre_event_history_t pre_eve_hist){ io_printf(IO_BUF, "Prev time: %u\n", pre_eve_hist.pf_times[pre_eve_hist.num_recorded_pf_spikes_minus_one]); - for (int i =0; i < NUM_PF_SPIKES_TO_RECORD; i ++){ - io_printf(IO_BUF, " Entry %u: %u\n", i ,pre_eve_hist.pf_times[i]); + for (int i = 0; i < NUM_PF_SPIKES_TO_RECORD; i ++){ + io_printf(IO_BUF, " Entry %u: %u\n", i, pre_eve_hist.pf_times[i]); } } diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h index e45292418e7..b1b754b4946 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h @@ -23,21 +23,7 @@ typedef int16_t pre_trace_t; //--------------------------------------- // Exponential decay lookup parameters #define TAU_PLUS_TIME_SHIFT 0 -#define EXP_COS_LUT_SIZE 256 - -// Helper macros for looking up decays -//#define EXP_COS_LOOKUP(time) maths_lut_exponential_decay(time, exp_cos_lookup) -// maths_lut_exponential_decay_time_shifted( \ -// time, TAU_PLUS_TIME_SHIFT, EXP_COS_LUT_SIZE, exp_cos_lookup) -//#define DECAY_LOOKUP_TAU_MINUS(time) \ -// maths_lut_exponential_decay( \ -// time, TAU_MINUS_TIME_SHIFT, TAU_MINUS_SIZE, tau_minus_lookup) - -//--------------------------------------- -// Externals -//--------------------------------------- -//extern int16_t exp_cos_lookup[EXP_COS_LUT_SIZE]; -//extern int16_lut *exp_cos_lookup; +//#define EXP_COS_LUT_SIZE 256 //--------------------------------------- // Timing dependence inline functions @@ -65,7 +51,7 @@ static inline post_trace_t timing_add_post_spike( use(&last_trace); if (print_plasticity){ - io_printf(IO_BUF, "Adding pre spike to event history (from purkinje cell)\n"); + io_printf(IO_BUF, "Adding pre spike to event history (from vestibular nuclei)\n"); } // // Get time since last spike // uint32_t delta_time = time - last_time; @@ -114,7 +100,6 @@ static inline update_state_t timing_apply_pre_spike( } return weight_one_term_apply_potentiation(previous_state, 0); - } //--------------------------------------- @@ -130,10 +115,9 @@ static inline update_state_t timing_apply_post_spike( use(&last_post_trace); extern int16_lut *exp_cos_lookup; - // // This is where we lookup the value of e^(-bx) * cos(x)^2 + // This is where we lookup the value of e^(-bx) * cos(x)^2 -// -// // Get time of event relative to last pre-synaptic event + // Get time of event relative to last pre-synaptic event uint32_t time_since_last_pre = last_pre_time; //time - last_pre_time; if (print_plasticity){ @@ -141,8 +125,6 @@ static inline update_state_t timing_apply_post_spike( } if (time_since_last_pre < 255){ - - // int32_t multiplier = EXP_COS_LOOKUP(time_since_last_pre); // int32_t multiplier = STDP_FIXED_MUL_16X16(last_pre_trace, // maths_lut_exponential_decay_time_shifted( @@ -157,8 +139,6 @@ static inline update_state_t timing_apply_post_spike( } return weight_one_term_apply_depression(previous_state, multiplier); - - } if (print_plasticity){ diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index b3ec2e6a7ee..d353deef6f9 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -23,21 +23,7 @@ typedef int16_t pre_trace_t; //--------------------------------------- // Exponential decay lookup parameters #define TAU_PLUS_TIME_SHIFT 0 -#define EXP_SIN_LUT_SIZE 256 - -// Helper macros for looking up decays -//#define EXP_SIN_LOOKUP(time) maths_lut_exponential_decay(time, exp_sin_lookup) -// maths_lut_exponential_decay_time_shifted( \ -// time, TAU_PLUS_TIME_SHIFT, EXP_SIN_LUT_SIZE, exp_sin_lookup) -//#define DECAY_LOOKUP_TAU_MINUS(time) \ -// maths_lut_exponential_decay( \ -// time, TAU_MINUS_TIME_SHIFT, TAU_MINUS_SIZE, tau_minus_lookup) - -//--------------------------------------- -// Externals -//--------------------------------------- -//extern int16_t exp_sin_lookup[EXP_SIN_LUT_SIZE]; -//extern int16_lut *exp_sin_lookup; +//#define EXP_SIN_LUT_SIZE 256 //--------------------------------------- // Timing dependence inline functions @@ -114,9 +100,6 @@ static inline update_state_t timing_apply_pre_spike( } return weight_one_term_apply_potentiation(previous_state, 0); - - - // // // Get time of event relative to last post-synaptic event // uint32_t time_since_last_post = time - last_post_time; @@ -154,8 +137,6 @@ static inline update_state_t timing_apply_post_spike( use(&last_post_trace); extern int16_lut *exp_sin_lookup; - - // This is where we lookup the value of e^(-x) * sin(x)^20 // Get time of event relative to last pre-synaptic event @@ -166,7 +147,6 @@ static inline update_state_t timing_apply_post_spike( } if (time_since_last_pre < 255){ - // int32_t multiplier = EXP_SIN_LOOKUP(time_since_last_pre); // int32_t multiplier = STDP_FIXED_MUL_16X16(last_pre_trace, // maths_lut_exponential_decay_time_shifted( @@ -181,8 +161,6 @@ static inline update_state_t timing_apply_post_spike( } return weight_one_term_apply_depression(previous_state, multiplier); - - } if (print_plasticity){ diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h index 07e90c2d15a..8295104d162 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h @@ -57,7 +57,7 @@ static inline weight_state_t weight_one_term_apply_depression( weight_state_t state, int32_t depression_multiplier) { if (print_plasticity){ io_printf(IO_BUF, "\n Do Depression\n"); - io_printf(IO_BUF, " Weight prior to depression: %u\n",state.weight); + io_printf(IO_BUF, " Weight prior to depression: %u\n", state.weight); } // Calculate scale @@ -94,7 +94,7 @@ static inline weight_state_t weight_one_term_apply_potentiation( } // state.a2_plus += state.weight_region->a2_plus; - state.weight += state.weight_region->a2_plus; // mul_accum_fixed(state.weight_region->a2_plus, a2_plus); + state.weight += state.weight_region->a2_plus; state.weight = kbits(MIN(bitsk(state.weight), bitsk(state.weight_region->max_weight))); return state; @@ -107,7 +107,6 @@ static inline weight_t weight_get_final(weight_state_t new_state) { // first do Depression (as this would have happened first) - // // Now do potentiation (check against lower limit) // int32_t scaled_a2_plus = STDP_FIXED_MUL_16X16( // new_state.a2_plus, new_state.weight_region->a2_plus); diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h index ec72d000706..2377582bf0d 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h @@ -15,7 +15,7 @@ typedef struct { accum min_weight; accum max_weight; - accum a2_plus; + accum a2_plus; // Note: this value is pot_alpha from the python side accum a2_minus; } plasticity_weight_region_data_t; @@ -55,7 +55,7 @@ static inline weight_state_t weight_one_term_apply_depression( if (print_plasticity){ io_printf(IO_BUF, "\n Do Depression\n"); - io_printf(IO_BUF, " Weight prior to depression: %u\n",state.weight); + io_printf(IO_BUF, " Weight prior to depression: %u\n", state.weight); } // Calculate scale @@ -73,7 +73,7 @@ static inline weight_state_t weight_one_term_apply_depression( state.weight = kbits(MAX(bitsk(state.weight), bitsk(state.weight_region->min_weight))); if (print_plasticity){ - io_printf(IO_BUF, " Weight after depression: %u\n\n",state.weight); + io_printf(IO_BUF, " Weight after depression: %u\n\n", state.weight); } return state; @@ -84,7 +84,7 @@ static inline weight_state_t weight_one_term_apply_potentiation( use(potentiation); // add fixed amount // state.a2_plus += state.weight_region->a2_plus; - state.weight += state.weight_region->a2_plus; //mul_accum_fixed(state.weight_region->a2_plus, a2_plus); + state.weight += state.weight_region->a2_plus; state.weight = kbits(MIN(bitsk(state.weight), bitsk(state.weight_region->max_weight))); return state; @@ -96,7 +96,6 @@ static inline weight_t weight_get_final(weight_state_t new_state) { // first do Depression (as this would have happened first) - // // Now do potentiation (check against lower limit) // int32_t scaled_a2_plus = STDP_FIXED_MUL_16X16( // new_state.a2_plus, new_state.weight_region->a2_plus); From 89650406f821e4ac8f9a2e4b6d87f3beb9700778 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 18 Nov 2021 12:13:29 +0000 Subject: [PATCH 049/108] more tidying (vera) --- neural_modelling/src/neuron/c_main.c | 2 +- .../plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/neural_modelling/src/neuron/c_main.c b/neural_modelling/src/neuron/c_main.c index a756d27bb6c..1315b5bb343 100644 --- a/neural_modelling/src/neuron/c_main.c +++ b/neural_modelling/src/neuron/c_main.c @@ -197,7 +197,7 @@ void timer_callback(uint timer_count, UNUSED uint unused) { spike_processing_get_and_reset_pipeline_restarts_this_tick(); // cache and flush spike counters - // /localhome/mbax3pb2/py3_venv/spinnaker/sPyNNaker/neural_modelling/src/neuron/spike_profiling.h + // functions in file neural_modelling/src/neuron/spike_profiling.h spike_profiling_cache_and_flush_spike_holder(&spike_counter, &spike_cache); spike_profiling_cache_and_flush_spike_holder(&spike_counter_inh, diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c index a9ef5e967c9..2b2a21063fa 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c @@ -47,7 +47,7 @@ void _print_pre_event_history(pre_event_history_t pre_eve_hist){ pre_eve_hist.mf_times[pre_eve_hist.num_recorded_mf_spikes_minus_one]); for (int i = 0; i < NUM_MF_SPIKES_TO_RECORD; i++){ - io_printf(IO_BUF, " Entry %u: %u\n", i , pre_eve_hist.mf_times[i]); + io_printf(IO_BUF, " Entry %u: %u\n", i, pre_eve_hist.mf_times[i]); } } From 5be7fa45e2b40ef9054c341ecb6a90ff9aa11055 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 18 Nov 2021 16:26:08 +0000 Subject: [PATCH 050/108] Add pandas to requirements here too? --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 87d016ab957..ef5a0bcfec4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -33,5 +33,6 @@ pynn >= 0.9.1, < 0.10 lazyarray >= 0.2.9, <= 0.4.0 appdirs >= 1.4.2 , < 2.0.0 neo >= 0.5.2, < 0.10.0 +pandas # csa # needed but excluded due to readthedocs # spinnaker_tools From ab90b4f4433c436fe9d45346faefd6421ebe6776 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 18 Nov 2021 16:32:26 +0000 Subject: [PATCH 051/108] unused parameter --- .../pyNN/models/spike_source/spike_source_poisson_vertex.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py index d8d3d44d6eb..bcb331834fe 100644 --- a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py +++ b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py @@ -135,7 +135,7 @@ def __init__( # check for changes parameters self.__change_requires_mapping = False #True - self.__change_requires_neuron_parameters_reload = False +# self.__change_requires_neuron_parameters_reload = False self.__spike_recorder = MultiSpikeRecorder() From 3292e75adc1b2fe70b86f97ba356e3897ef2c908 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 18 Nov 2021 16:51:43 +0000 Subject: [PATCH 052/108] flake8 various --- .../neuron/builds/if_cond_exp_cerebellum.py | 16 ++++++++- ...n_model_leaky_integrate_and_fire_t_last.py | 2 +- .../models/neuron/plasticity/stdp/common.py | 14 ++++---- .../timing_dependence_mfvn.py | 24 ++++++++++--- .../timing_dependence_pfpc.py | 35 ++++++++----------- .../neuron/population_machine_vertex.py | 1 + .../spike_source_poisson_vertex.py | 2 +- 7 files changed, 59 insertions(+), 35 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py b/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py index 4b5313f022d..efe53996223 100644 --- a/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py +++ b/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py @@ -1,3 +1,17 @@ +# Copyright (c) 2017-2019 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . from spynnaker.pyNN.models.neuron import AbstractPyNNNeuronModelStandard from spynnaker.pyNN.models.defaults import default_initial_values from spynnaker.pyNN.models.neuron.neuron_models \ @@ -8,6 +22,7 @@ MAX_ATOMS_PER_CORE = 128 + class IFCondExpCerebellum(AbstractPyNNNeuronModelStandard): """ Leaky integrate and fire neuron with an exponentially decaying \ conductance input. Also includes ability to record last spike down @@ -28,7 +43,6 @@ def __init__( input_type = InputTypeConductance(e_rev_E, e_rev_I) threshold_type = ThresholdTypeStatic(v_thresh) - super(IFCondExpCerebellum, self).set_model_max_atoms_per_core( n_atoms=MAX_ATOMS_PER_CORE) diff --git a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py index 804e49fcd63..95446c89dff 100644 --- a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py +++ b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py @@ -127,7 +127,7 @@ def update_values(self, values, parameters, state_variables): # Copy the changed data only state_variables[V] = v state_variables[COUNT_REFRAC] = count_refrac - state_varaibles[T_LAST] = t_last + state_variables[T_LAST] = t_last @property def v_init(self): diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py index 23ca7c405ec..277d90f0b4b 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py @@ -16,8 +16,6 @@ import math import numpy import matplotlib.pyplot as plt -from data_specification.enums import DataType -# from spinn_front_end_common.utilities.utility_objs import ProvenanceDataItem # Default value of fixed-point one for STDP STDP_FIXED_POINT_ONE = (1 << 11) @@ -83,15 +81,15 @@ def get_exp_lut_array(time_step, time_constant, shift=0): def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, fixed_point_one=STDP_FIXED_POINT_ONE, kernel_scaling=1.0): # Add this to function arguments in the future - machine_time_step = 1.0 + # machine_time_step = 1.0 sin_pwr = 20 # Calculate required time constant time_constant = peak_time / math.atan(sin_pwr) inv_tau = (1.0 / float(time_constant)) # * (machine_time_step / 1000.0) - # # calculate time of peak (from differentiating kernel and setting to zero) - # kernel_peak_time = math.atan(20) / inv_tau + # calculate time of peak (from differentiating kernel and setting to zero) + # kernel_peak_time = math.atan(20) / inv_tau # evaluate peak value of kernel to normalise LUT kernel_peak_value = (math.exp(-peak_time * inv_tau) * @@ -114,7 +112,7 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, else: # Evaluate kernel exp_float = (math.exp(-value) * math.sin(value) ** - sin_pwr / kernel_peak_value) * kernel_scaling + sin_pwr / kernel_peak_value) * kernel_scaling # Convert to fixed-point exp_fix = float_to_fixed(exp_float, fixed_point_one) @@ -173,7 +171,7 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, fixed_point_one=STDP_FIXED_POINT_ONE, kernel_scaling=1.0): # Add this to function arguments in the future - machine_time_step = 1.0 + # machine_time_step = 1.0 cos_pwr = 2 # Calculate required time constant @@ -202,7 +200,7 @@ def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, else: # Evaluate kernel exp_float = (math.exp(-abs(value * beta)) * math.cos(value) ** - cos_pwr / kernel_peak_value) * kernel_scaling + cos_pwr / kernel_peak_value) * kernel_scaling # Convert to fixed-point exp_fix = float_to_fixed(exp_float, fixed_point_one) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py index a34d087b303..11cb5bc4243 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py @@ -1,3 +1,17 @@ +# Copyright (c) 2017-2019 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . from spinn_utilities.overrides import overrides from spinn_front_end_common.interface.provenance import ProvenanceWriter from spinn_front_end_common.utilities.globals_variables import ( @@ -15,6 +29,7 @@ LUT_SIZE = 256 + class TimingDependenceMFVN(AbstractTimingDependence): __slots__ = [ "_synapse_structure", @@ -101,13 +116,14 @@ def vertex_executable_suffix(self): @property def pre_trace_n_bytes(self): - - # Here we will record the last 16 spikes, these will be 32-bit quantities, - return (16 * 4) + (2 * 16) # 16 4-byte entries, plus one counter for the number of spikes + # Here we will record the last 16 spikes, + # these will be 32-bit quantities, + # 16 4-byte entries, plus one counter for the number of spikes + return (16 * 4) + (2 * 16) @overrides(AbstractTimingDependence.get_parameters_sdram_usage_in_bytes) def get_parameters_sdram_usage_in_bytes(self): - return BYTES_PER_WORD * LUT_SIZE #in bytes: 256 * 16 bit values + return BYTES_PER_WORD * LUT_SIZE @property def n_weight_terms(self): diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index 2eae912ad93..b4af47d29a0 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -1,9 +1,22 @@ +# Copyright (c) 2017-2019 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . from spinn_utilities.overrides import overrides from spinn_front_end_common.interface.provenance import ProvenanceWriter from spinn_front_end_common.utilities.globals_variables import ( machine_time_step_ms) -from spinn_front_end_common.utilities.constants import ( - BYTES_PER_SHORT, BYTES_PER_WORD) +from spinn_front_end_common.utilities.constants import BYTES_PER_WORD from spynnaker.pyNN.models.neuron.plasticity.stdp.common \ import write_pfpc_lut from .abstract_timing_dependence import AbstractTimingDependence @@ -107,30 +120,12 @@ def pre_trace_n_bytes(self): @overrides(AbstractTimingDependence.get_parameters_sdram_usage_in_bytes) def get_parameters_sdram_usage_in_bytes(self): - # in bytes: 256 * 16 bit values ? return BYTES_PER_WORD * len(self._tau_plus_data) @property def n_weight_terms(self): return 1 - # @overrides(AbstractTimingDependence.write_parameters) - # def write_parameters(self, spec, machine_time_step, weight_scales): - # # Check timestep is valid - # if machine_time_step != 1000: - # raise NotImplementedError( - # "exp_sin LUT generation currently only supports 1ms timesteps") - # - # # Write exp_sin lookup table - # self._tau_plus_last_entry = write_pfpc_lut( - # spec, - # peak_time=self._t_peak, - # time_probe=None, - # lut_size=LUT_SIZE, - # shift=0, - # kernel_scaling=self._kernel_scaling - # ) - @overrides(AbstractTimingDependence.write_parameters) def write_parameters( self, spec, global_weight_scale, synapse_weight_scales): diff --git a/spynnaker/pyNN/models/neuron/population_machine_vertex.py b/spynnaker/pyNN/models/neuron/population_machine_vertex.py index 53dbd44d3a9..cfca3bf112c 100644 --- a/spynnaker/pyNN/models/neuron/population_machine_vertex.py +++ b/spynnaker/pyNN/models/neuron/population_machine_vertex.py @@ -224,6 +224,7 @@ def __get_binary_file_name(app_vertex): # Reunite title and extension and return return name + app_vertex.synapse_executable_suffix + ext + @overrides(PopulationMachineCommon.parse_extra_provenance_items) def parse_extra_provenance_items( self, label, x, y, p, provenance_data): diff --git a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py index bcb331834fe..f5e5e7a42e2 100644 --- a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py +++ b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py @@ -134,7 +134,7 @@ def __init__( self.__n_data_specs = 0 # check for changes parameters - self.__change_requires_mapping = False #True + self.__change_requires_mapping = False # True # self.__change_requires_neuron_parameters_reload = False self.__spike_recorder = MultiSpikeRecorder() From 21f9ab73ccb5ffdda9199f6c575fad06ac8a5189 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 19 Nov 2021 10:28:10 +0000 Subject: [PATCH 053/108] pylint various --- ...n_model_leaky_integrate_and_fire_t_last.py | 4 ++-- .../models/neuron/plasticity/stdp/common.py | 20 +++++++++---------- .../timing_dependence_mfvn.py | 4 ++-- .../timing_dependence_pfpc.py | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py index 95446c89dff..25d334f6245 100644 --- a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py +++ b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py @@ -131,11 +131,11 @@ def update_values(self, values, parameters, state_variables): @property def v_init(self): - return self._v + return self._v_init @v_init.setter def v_init(self, v_init): - self._v = v_init + self._v_init = v_init @property def v_rest(self): diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py index 277d90f0b4b..c6c29ff4871 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py @@ -21,15 +21,15 @@ STDP_FIXED_POINT_ONE = (1 << 11) -# def float_to_fixed(value): -# """ -# :param float value: -# :rtype: int -# """ -# return int(round(float(value) * STDP_FIXED_POINT_ONE)) +def float_to_fixed(value): + """ + :param float value: + :rtype: int + """ + return int(round(float(value) * STDP_FIXED_POINT_ONE)) -def float_to_fixed(value, fixed_point_one): - return int(round(float(value) * float(fixed_point_one))) +# def float_to_fixed(value, fixed_point_one): +# return int(round(float(value) * float(fixed_point_one))) # def get_lut_provenance( @@ -115,7 +115,7 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, sin_pwr / kernel_peak_value) * kernel_scaling # Convert to fixed-point - exp_fix = float_to_fixed(exp_float, fixed_point_one) + exp_fix = float_to_fixed(exp_float) if spec is None: # in testing mode so print out_float.append(exp_float) @@ -203,7 +203,7 @@ def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, cos_pwr / kernel_peak_value) * kernel_scaling # Convert to fixed-point - exp_fix = float_to_fixed(exp_float, fixed_point_one) + exp_fix = float_to_fixed(exp_float) if spec is None: # in testing mode so print out_float.append(exp_float) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py index 11cb5bc4243..919285a3622 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py @@ -167,7 +167,7 @@ def get_provenance_data(self, synapse_info): db.insert_report( f"The last entry in the STDP exponential lookup table " f"for the tau_plus parameter of the" - f"{self.__class__.__name} between " + f"{self.__class__.__name__} between " f"{synapse_info.pre_population.label} and " f"{synapse_info.post_population.label} was {tauplus} " f"rather than 0, indicating that the lookup table was " @@ -184,7 +184,7 @@ def get_provenance_data(self, synapse_info): db.insert_report( f"The last entry in the STDP exponential lookup table " f"for the tau_minus parameter of the " - f"{self.__class__.__name} between " + f"{self.__class__.__name__} between " f"{synapse_info.pre_population.label} and " f"{synapse_info.post_population.label} was {tauminus} " f"rather than 0, indicating that the lookup table was " diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index b4af47d29a0..d55730457a7 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -166,7 +166,7 @@ def get_provenance_data(self, synapse_info): db.insert_report( f"The last entry in the STDP exponential lookup table " f"for the tau_plus parameter of the" - f"{self.__class__.__name} between " + f"{self.__class__.__name__} between " f"{synapse_info.pre_population.label} and " f"{synapse_info.post_population.label} was {tauplus} " f"rather than 0, indicating that the lookup table was " @@ -183,7 +183,7 @@ def get_provenance_data(self, synapse_info): db.insert_report( f"The last entry in the STDP exponential lookup table " f"for the tau_minus parameter of the " - f"{self.__class__.__name} between " + f"{self.__class__.__name__} between " f"{synapse_info.pre_population.label} and " f"{synapse_info.post_population.label} was {tauminus} " f"rather than 0, indicating that the lookup table was " From e60e84fca20e7deb097339ad366f3fd27a0d89fa Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 19 Nov 2021 10:49:20 +0000 Subject: [PATCH 054/108] Add copyright statements to new files --- .../neuron/IF_cond_exp_cerebellum/Makefile | 15 +++++++++++++++ .../Makefile | 15 +++++++++++++++ .../Makefile | 15 +++++++++++++++ .../models/neuron_model_lif_t_last_impl.c | 17 +++++++++++++++++ .../models/neuron_model_lif_t_last_impl.h | 17 +++++++++++++++++ .../stdp/timing_dependence/timing_mfvn_impl.c | 17 +++++++++++++++++ .../stdp/timing_dependence/timing_mfvn_impl.h | 17 +++++++++++++++++ .../stdp/timing_dependence/timing_pfpc_impl.c | 17 +++++++++++++++++ .../stdp/timing_dependence/timing_pfpc_impl.h | 17 +++++++++++++++++ .../stdp/weight_dependence/weight_mfvn_impl.c | 17 +++++++++++++++++ .../stdp/weight_dependence/weight_mfvn_impl.h | 17 +++++++++++++++++ .../stdp/weight_dependence/weight_pfpc_impl.c | 17 +++++++++++++++++ .../stdp/weight_dependence/weight_pfpc_impl.h | 17 +++++++++++++++++ neural_modelling/src/neuron/spike_profiling.h | 17 +++++++++++++++++ ...ron_model_leaky_integrate_and_fire_t_last.py | 15 +++++++++++++++ .../weight_dependence/weight_dependence_mfvn.py | 15 +++++++++++++++ .../weight_dependence/weight_dependence_pfpc.py | 15 +++++++++++++++ 17 files changed, 277 insertions(+) diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile index 211b47d1a0b..99e98fd76a6 100644 --- a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile +++ b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile @@ -1,3 +1,18 @@ +# Copyright (c) 2017-2021 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + APP = $(notdir $(CURDIR)) NEURON_MODEL = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.c diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile index fd777befbd8..2950e0c0f2c 100644 --- a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile +++ b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile @@ -1,3 +1,18 @@ +# Copyright (c) 2017-2021 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + APP = $(notdir $(CURDIR)) NEURON_MODEL = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.c diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile index 6af8b14cabf..74ff6896efb 100644 --- a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile +++ b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile @@ -1,3 +1,18 @@ +# Copyright (c) 2017-2021 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + APP = $(notdir $(CURDIR)) NEURON_MODEL = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.c diff --git a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.c b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.c index 04d9ef3be3b..88305c2b010 100644 --- a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.c +++ b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2017-2021 The University of Manchester + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "neuron_model_lif_t_last_impl.h" #include diff --git a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h index 68cb436a255..6bf34874373 100644 --- a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h +++ b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2017-2021 The University of Manchester + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #ifndef _NEURON_MODEL_LIF_CURR_T_LAST_IMPL_H_ #define _NEURON_MODEL_LIF_CURR_T_LAST_IMPL_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c index 696944da982..379ba032c24 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2017-2021 The University of Manchester + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "timing_mfvn_impl.h" //--------------------------------------- diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h index b1b754b4946..322092b5edd 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2017-2021 The University of Manchester + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #ifndef _TIMING_MFVN_IMPL_H_ #define _TIMING_MFVN_IMPL_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c index 061a6e8e24b..d94161400db 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2017-2021 The University of Manchester + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "timing_pfpc_impl.h" //--------------------------------------- diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index d353deef6f9..d2306d3430f 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2017-2021 The University of Manchester + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #ifndef _TIMING_PFPC_IMPL_H_ #define _TIMING_PFPC_IMPL_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c index caf01124c5b..97e003876e8 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2017-2021 The University of Manchester + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "weight_mfvn_impl.h" //--------------------------------------- diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h index 8295104d162..5ac3a4c5e41 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2017-2021 The University of Manchester + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #ifndef _WEIGHT_MFVN_IMPL_H_ #define _WEIGHT_MFVN_IMPL_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c index 0903de8b072..8ac98967299 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2017-2021 The University of Manchester + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "weight_pfpc_impl.h" //--------------------------------------- diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h index 2377582bf0d..b8514e789e1 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2017-2021 The University of Manchester + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #ifndef _WEIGHT_PFPC_IMPL_H_ #define _WEIGHT_PFPC_IMPL_H_ diff --git a/neural_modelling/src/neuron/spike_profiling.h b/neural_modelling/src/neuron/spike_profiling.h index 7b21687caf7..e8f2752ca30 100644 --- a/neural_modelling/src/neuron/spike_profiling.h +++ b/neural_modelling/src/neuron/spike_profiling.h @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2017-2021 The University of Manchester + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include typedef struct spike_holder_t { diff --git a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py index 25d334f6245..e0941140a31 100644 --- a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py +++ b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py @@ -1,3 +1,18 @@ +# Copyright (c) 2017-2021 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + from spinn_utilities.overrides import overrides from pacman.executor.injection_decorator import inject_items from .abstract_neuron_model import AbstractNeuronModel diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py index 4ee17b23456..a288bf948bf 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py @@ -1,3 +1,18 @@ +# Copyright (c) 2017-2021 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + from data_specification.enums import DataType from spinn_utilities.overrides import overrides from .abstract_has_a_plus_a_minus import AbstractHasAPlusAMinus diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py index 043abf46ee2..57e93af785b 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py @@ -1,3 +1,18 @@ +# Copyright (c) 2017-2021 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + from data_specification.enums import DataType from spinn_utilities.overrides import overrides from .abstract_has_a_plus_a_minus import AbstractHasAPlusAMinus From c8648abc72842db61871e81ed867e01b61bd671a Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Tue, 23 Nov 2021 17:16:05 +0000 Subject: [PATCH 055/108] Reinstate user-specified ring buffer left shifts --- .../external_device_lif_control.py | 4 ++-- .../models/neuron/abstract_population_vertex.py | 17 ++++++++++++++++- .../models/neuron/abstract_pynn_neuron_model.py | 6 +++--- .../abstract_pynn_neuron_model_standard.py | 5 +++-- spynnaker/pyNN/models/populations/population.py | 2 +- .../timing_dependence/timing_dependence_pfpc.py | 4 ++-- 6 files changed, 27 insertions(+), 11 deletions(-) diff --git a/spynnaker/pyNN/external_devices_models/external_device_lif_control.py b/spynnaker/pyNN/external_devices_models/external_device_lif_control.py index ecc1c4aa400..59a170a87ef 100644 --- a/spynnaker/pyNN/external_devices_models/external_device_lif_control.py +++ b/spynnaker/pyNN/external_devices_models/external_device_lif_control.py @@ -97,7 +97,7 @@ def __init__( def create_vertex( self, n_neurons, label, constraints, spikes_per_second, ring_buffer_sigma, incoming_spike_buffer_size, - n_steps_per_timestep, drop_late_spikes, splitter): + n_steps_per_timestep, drop_late_spikes, splitter, rb_left_shifts): if n_neurons != len(self._devices): raise ConfigurationException( "Number of neurons does not match number of devices in {}" @@ -108,4 +108,4 @@ def create_vertex( self._devices, self._create_edges, max_atoms, self._model, self, self._translator, spikes_per_second, label, ring_buffer_sigma, incoming_spike_buffer_size, constraints, - drop_late_spikes, splitter) + drop_late_spikes, splitter, rb_left_shifts) diff --git a/spynnaker/pyNN/models/neuron/abstract_population_vertex.py b/spynnaker/pyNN/models/neuron/abstract_population_vertex.py index 4528cb77d94..1f6d95ffa19 100644 --- a/spynnaker/pyNN/models/neuron/abstract_population_vertex.py +++ b/spynnaker/pyNN/models/neuron/abstract_population_vertex.py @@ -111,6 +111,7 @@ class AbstractPopulationVertex( "__ring_buffer_sigma", "__spikes_per_second", "__drop_late_spikes", + "__rb_left_shifts", "__incoming_projections", "__synapse_dynamics", "__max_row_info", @@ -138,7 +139,8 @@ class AbstractPopulationVertex( def __init__( self, n_neurons, label, constraints, max_atoms_per_core, spikes_per_second, ring_buffer_sigma, incoming_spike_buffer_size, - neuron_impl, pynn_model, drop_late_spikes, splitter): + neuron_impl, pynn_model, drop_late_spikes, splitter, + rb_left_shifts): """ :param int n_neurons: The number of neurons in the population :param str label: The label on the population @@ -196,6 +198,8 @@ def __init__( self.__drop_late_spikes = get_config_bool( "Simulation", "drop_late_spikes") + self.__rb_left_shifts = rb_left_shifts + self.__neuron_impl = neuron_impl self.__pynn_model = pynn_model self._parameters = SpynnakerRangeDictionary(n_neurons) @@ -370,6 +374,17 @@ def drop_late_spikes(self): """ return self.__drop_late_spikes + @property + def rb_left_shifts(self): + """ ring buffer left shifts (for use by user) + + :rtype: bool + """ + return self.__rb_left_shifts + + def set_rb_left_shifts(self, rb_left_shifts): + self.__rb_left_shifts = rb_left_shifts + def set_has_run(self): """ Set the flag has run so initialize only affects state variables diff --git a/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py b/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py index df17ddfea1b..970842ce24c 100644 --- a/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py +++ b/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py @@ -25,7 +25,7 @@ _population_parameters = { "spikes_per_second": None, "ring_buffer_sigma": None, "incoming_spike_buffer_size": None, "drop_late_spikes": None, - "splitter": None + "splitter": None, "rb_left_shifts": None } @@ -59,10 +59,10 @@ def get_max_atoms_per_core(cls): def create_vertex( self, n_neurons, label, constraints, spikes_per_second, ring_buffer_sigma, incoming_spike_buffer_size, drop_late_spikes, - splitter): + splitter, rb_left_shifts): # pylint: disable=arguments-differ max_atoms = self.get_max_atoms_per_core() return AbstractPopulationVertex( n_neurons, label, constraints, max_atoms, spikes_per_second, ring_buffer_sigma, incoming_spike_buffer_size, self.__model, - self, drop_late_spikes, splitter) + self, drop_late_spikes, splitter, rb_left_shifts) diff --git a/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model_standard.py b/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model_standard.py index 96ed0dcd69a..9878389b0d1 100644 --- a/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model_standard.py +++ b/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model_standard.py @@ -56,10 +56,11 @@ def __init__( def create_vertex( self, n_neurons, label, constraints, spikes_per_second, ring_buffer_sigma, incoming_spike_buffer_size, - n_steps_per_timestep, drop_late_spikes, splitter): + n_steps_per_timestep, drop_late_spikes, splitter, + rb_left_shifts): # pylint: disable=arguments-differ self._model.n_steps_per_timestep = n_steps_per_timestep return super().create_vertex( n_neurons, label, constraints, spikes_per_second, ring_buffer_sigma, incoming_spike_buffer_size, drop_late_spikes, - splitter) + splitter, rb_left_shifts) diff --git a/spynnaker/pyNN/models/populations/population.py b/spynnaker/pyNN/models/populations/population.py index 64b332743cd..443268164b3 100644 --- a/spynnaker/pyNN/models/populations/population.py +++ b/spynnaker/pyNN/models/populations/population.py @@ -1130,7 +1130,7 @@ def __create_vertex( # Setting custom RB LS if rb_left_shifts is not None: - self.__vertex.rb_left_shifts = rb_left_shifts + self.__vertex.set_rb_left_shifts(rb_left_shifts) # Introspect properties of the vertex self.__vertex_population_settable = \ isinstance(self.__vertex, AbstractPopulationSettable) diff --git a/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_pfpc.py b/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_pfpc.py index fa1c5caf3f3..d7ad24e4b86 100644 --- a/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_pfpc.py @@ -30,7 +30,7 @@ class TimingDependencePFPC(_BaseClass): def __init__( self, tau_plus=20.0, tau_minus=20.0, A_plus=0.01, A_minus=0.01, - t_peak=100, kernel_scaling=1.0): + t_peak=100, alpha=1.0): r""" :param float tau_plus: :math:`\tau_+` :param float tau_minus: :math:`\tau_-` @@ -45,4 +45,4 @@ def __init__( "timing_dependence.TimingDependencePFPC") super(TimingDependencePFPC, self).__init__( tau_plus=tau_plus, tau_minus=tau_minus, A_plus=A_plus, - A_minus=A_minus, t_peak=t_peak, kernel_scaling=kernel_scaling) + A_minus=A_minus, t_peak=t_peak, kernel_scaling=alpha) From 62ae442a1ca772aa3cf39752f27e40240c926b18 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Wed, 24 Nov 2021 12:06:02 +0000 Subject: [PATCH 056/108] Turn off plasticity printing --- neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h b/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h index f279b333f77..393e21f1403 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h +++ b/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h @@ -38,7 +38,7 @@ //! \return The product #define STDP_FIXED_MUL_16X16(a, b) maths_fixed_mul16(a, b, STDP_FIXED_POINT) -#define print_plasticity true // false +#define print_plasticity false // true //! The amount of right shift required to take a weight from s1615 format //! to STDP_FIXED_POINT format (s4,11) From 99df1e06c3a64e26b5404948e3d82957536c27d7 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Wed, 24 Nov 2021 12:13:57 +0000 Subject: [PATCH 057/108] Add rb_left_shifts argument in tests --- .../model_tests/neuron/test_synaptic_manager.py | 12 ++++++++---- unittests/test_populations/test_vertex.py | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/unittests/model_tests/neuron/test_synaptic_manager.py b/unittests/model_tests/neuron/test_synaptic_manager.py index 44d89d2a039..7cd65b2de56 100644 --- a/unittests/model_tests/neuron/test_synaptic_manager.py +++ b/unittests/model_tests/neuron/test_synaptic_manager.py @@ -218,7 +218,8 @@ def test_set_synapse_dynamics(): post_app_vertex = post_app_model.create_vertex( n_neurons=10, label="post", constraints=None, spikes_per_second=None, ring_buffer_sigma=None, incoming_spike_buffer_size=None, - n_steps_per_timestep=1, drop_late_spikes=True, splitter=None) + n_steps_per_timestep=1, drop_late_spikes=True, splitter=None, + rb_left_shifts=None) static = SynapseDynamicsStatic() stdp = SynapseDynamicsSTDP( @@ -328,7 +329,8 @@ def test_set_synapse_dynamics(): post_app_vertex = post_app_model.create_vertex( n_neurons=10, label="post", constraints=None, spikes_per_second=None, ring_buffer_sigma=None, incoming_spike_buffer_size=None, - n_steps_per_timestep=1, drop_late_spikes=True, splitter=None) + n_steps_per_timestep=1, drop_late_spikes=True, splitter=None, + rb_left_shifts=None) # STDP followed by structural STDP should result in Structural STDP post_app_vertex.synapse_dynamics = stdp @@ -350,7 +352,8 @@ def test_set_synapse_dynamics(): post_app_vertex = post_app_model.create_vertex( n_neurons=10, label="post", constraints=None, spikes_per_second=None, ring_buffer_sigma=None, incoming_spike_buffer_size=None, - n_steps_per_timestep=1, drop_late_spikes=True, splitter=None) + n_steps_per_timestep=1, drop_late_spikes=True, splitter=None, + rb_left_shifts=None) # Static followed by static structural should result in static # structural @@ -387,7 +390,8 @@ def test_set_synapse_dynamics(): post_app_vertex = post_app_model.create_vertex( n_neurons=10, label="post", constraints=None, spikes_per_second=None, ring_buffer_sigma=None, incoming_spike_buffer_size=None, - n_steps_per_timestep=1, drop_late_spikes=True, splitter=None) + n_steps_per_timestep=1, drop_late_spikes=True, splitter=None, + rb_left_shifts=None) post_app_vertex.synapse_dynamics = static_struct post_app_vertex.synapse_dynamics = stdp_struct diff --git a/unittests/test_populations/test_vertex.py b/unittests/test_populations/test_vertex.py index d16aa4e1531..9bc553cb681 100644 --- a/unittests/test_populations/test_vertex.py +++ b/unittests/test_populations/test_vertex.py @@ -112,7 +112,7 @@ def __init__(self): max_atoms_per_core=None, spikes_per_second=None, ring_buffer_sigma=None, incoming_spike_buffer_size=None, neuron_impl=foo_bar.model, pynn_model=foo_bar, - drop_late_spikes=True, splitter=None) + drop_late_spikes=True, splitter=None, rb_left_shifts=None) def test_initializable(): From 01528069a17b97605a2adf1f680121373a9108d8 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Wed, 24 Nov 2021 12:31:26 +0000 Subject: [PATCH 058/108] Missed adding rb_left_shifts in this vertex --- .../external_device_lif_control_vertex.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/spynnaker/pyNN/external_devices_models/external_device_lif_control_vertex.py b/spynnaker/pyNN/external_devices_models/external_device_lif_control_vertex.py index 778adcc78fc..ab5c2847a80 100644 --- a/spynnaker/pyNN/external_devices_models/external_device_lif_control_vertex.py +++ b/spynnaker/pyNN/external_devices_models/external_device_lif_control_vertex.py @@ -49,7 +49,8 @@ def __init__( self, devices, create_edges, max_atoms_per_core, neuron_impl, pynn_model, translator=None, spikes_per_second=None, label=None, ring_buffer_sigma=None, incoming_spike_buffer_size=None, - drop_late_spikes=None, constraints=None, splitter=None): + drop_late_spikes=None, constraints=None, splitter=None, + rb_left_shifts=None): """ :param list(AbstractMulticastControllableDevice) devices: The AbstractMulticastControllableDevice instances to be controlled @@ -105,7 +106,8 @@ def __init__( super().__init__( len(devices), label, constraints, max_atoms_per_core, spikes_per_second, ring_buffer_sigma, incoming_spike_buffer_size, - neuron_impl, pynn_model, drop_late_spikes, splitter) + neuron_impl, pynn_model, drop_late_spikes, splitter, + rb_left_shifts) def routing_key_partition_atom_mapping(self, routing_info, partition): # pylint: disable=arguments-differ From 04f58e784e25ed92252b9e065fb4ab73bb807a1b Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 25 Nov 2021 10:50:22 +0000 Subject: [PATCH 059/108] Move to use spynnaker rather than spynnaker8 locations for imports --- .../timing_dependence_mfvn.py | 8 +++---- .../timing_dependence_pfpc.py | 8 +++---- spynnaker8/extra_models/__init__.py | 24 ++++++++----------- .../timing_dependence_mfvn.py | 2 +- .../timing_dependence_pfpc.py | 2 +- 5 files changed, 20 insertions(+), 24 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py index 919285a3622..72cab0ff5ef 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py @@ -41,18 +41,18 @@ class TimingDependenceMFVN(AbstractTimingDependence): "__a_minus", "_beta", "_sigma", - "_kernel_scaling" + "_alpha" ] def __init__(self, tau_plus=20.0, tau_minus=20.0, A_plus=0.01, - A_minus=0.01, beta=10, sigma=200, kernel_scaling=1.0): + A_minus=0.01, beta=10, sigma=200, alpha=1.0): self._tau_plus = tau_plus self._tau_minus = tau_minus self.__a_plus = A_plus self.__a_minus = A_minus - self._kernel_scaling = kernel_scaling + self._alpha = alpha self._synapse_structure = SynapseStructureWeightOnly() @@ -146,7 +146,7 @@ def write_parameters( time_probe=None, lut_size=LUT_SIZE, shift=0, - kernel_scaling=self._kernel_scaling) + kernel_scaling=self._alpha) @property def synaptic_structure(self): diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index d55730457a7..783e697757e 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -40,10 +40,10 @@ class TimingDependencePFPC(AbstractTimingDependence): "__a_plus", "__a_minus", "_t_peak", - "_kernel_scaling"] + "_alpha"] def __init__(self, tau_plus=20.0, tau_minus=20.0, A_plus=0.01, - A_minus=0.01, t_peak=100, kernel_scaling=1.0): + A_minus=0.01, t_peak=100, alpha=1.0): self._tau_plus = tau_plus self._tau_minus = tau_minus @@ -51,7 +51,7 @@ def __init__(self, tau_plus=20.0, tau_minus=20.0, A_plus=0.01, self.__a_minus = A_minus self._t_peak = t_peak - self._kernel_scaling = kernel_scaling + self._alpha = alpha self._synapse_structure = SynapseStructureWeightOnly() @@ -60,7 +60,7 @@ def __init__(self, tau_plus=20.0, tau_minus=20.0, A_plus=0.01, self._tau_plus_data = write_pfpc_lut( dummy_spec, peak_time=self._t_peak, time_probe=None, lut_size=LUT_SIZE, - shift=0, kernel_scaling=self._kernel_scaling) + shift=0, kernel_scaling=self._alpha) self._tau_minus_data = None @property diff --git a/spynnaker8/extra_models/__init__.py b/spynnaker8/extra_models/__init__.py index 6b5a10cbadb..504dbe16f90 100644 --- a/spynnaker8/extra_models/__init__.py +++ b/spynnaker8/extra_models/__init__.py @@ -13,14 +13,14 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from spynnaker8.models.synapse_dynamics.timing_dependence import ( +from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence import ( TimingDependenceRecurrent as RecurrentRule, TimingDependenceSpikeNearestPair as SpikeNearestPairRule, TimingDependenceVogels2011 as Vogels2011Rule, TimingDependencePfisterSpikeTriplet as PfisterSpikeTriplet) from spynnaker.pyNN.models.neuron.synapse_dynamics import ( SynapseDynamicsNeuromodulation as Neuromodulation) -from spynnaker8.models.synapse_dynamics.weight_dependence import ( +from spynnaker.pyNN.models.neuron.plasticity.stdp.weight_dependence import ( WeightDependenceAdditiveTriplet) from spynnaker.pyNN.models.neuron.builds import ( IFCondExpStoc, @@ -37,18 +37,14 @@ from spynnaker.pyNN.models.neuron.builds.if_cond_exp_cerebellum import \ IFCondExpCerebellum # Cerebellum Plasticity -from spynnaker8.models.synapse_dynamics.timing_dependence\ - .timing_dependence_pfpc import TimingDependencePFPC as \ - TimingDependencePFPC -from spynnaker8.models.synapse_dynamics.timing_dependence\ - .timing_dependence_mfvn import TimingDependenceMFVN as \ - TimingDependenceMFVN -from spynnaker8.models.synapse_dynamics.weight_dependence\ - .weight_dependence_mfvn import \ - WeightDependenceMFVN as WeightDependenceMFVN -from spynnaker8.models.synapse_dynamics.weight_dependence\ - .weight_dependence_pfpc import \ - WeightDependencePFPC as WeightDependencePFPC +from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence import ( + TimingDependencePFPC as TimingDependencePFPC) +from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence import ( + TimingDependenceMFVN as TimingDependenceMFVN) +from spynnaker.pyNN.models.neuron.plasticity.stdp.weight_dependence import ( + WeightDependenceMFVN as WeightDependenceMFVN) +from spynnaker.pyNN.models.neuron.plasticity.stdp.weight_dependence import ( + WeightDependencePFPC as WeightDependencePFPC) __all__ = [ # sPyNNaker 8 models diff --git a/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_mfvn.py b/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_mfvn.py index aa31162a51b..06b461b6f43 100644 --- a/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_mfvn.py +++ b/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_mfvn.py @@ -43,4 +43,4 @@ def __init__( "timing_dependence.TimingDependenceMFVN") super(TimingDependenceMFVN, self).__init__( tau_plus=tau_plus, tau_minus=tau_minus, A_plus=A_plus, - A_minus=A_minus, beta=beta, sigma=sigma, kernel_scaling=alpha) + A_minus=A_minus, beta=beta, sigma=sigma, alpha=alpha) diff --git a/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_pfpc.py b/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_pfpc.py index d7ad24e4b86..ec8a1b84231 100644 --- a/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_pfpc.py @@ -45,4 +45,4 @@ def __init__( "timing_dependence.TimingDependencePFPC") super(TimingDependencePFPC, self).__init__( tau_plus=tau_plus, tau_minus=tau_minus, A_plus=A_plus, - A_minus=A_minus, t_peak=t_peak, kernel_scaling=alpha) + A_minus=A_minus, t_peak=t_peak, alpha=alpha) From caa7c39817a5240532cdaacbd52cc14a0166e43f Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 29 Nov 2021 11:57:04 +0000 Subject: [PATCH 060/108] Don't need pandas any more --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index ef5a0bcfec4..87d016ab957 100644 --- a/requirements.txt +++ b/requirements.txt @@ -33,6 +33,5 @@ pynn >= 0.9.1, < 0.10 lazyarray >= 0.2.9, <= 0.4.0 appdirs >= 1.4.2 , < 2.0.0 neo >= 0.5.2, < 0.10.0 -pandas # csa # needed but excluded due to readthedocs # spinnaker_tools From f4e8fb24d8872903b4d9fb7636169cdf8571f3fe Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 29 Nov 2021 14:21:42 +0000 Subject: [PATCH 061/108] Fix to make packets-per-timestep recording work again; move provenance --- .../src/neuron/spike_processing.c | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/neural_modelling/src/neuron/spike_processing.c b/neural_modelling/src/neuron/spike_processing.c index ba73aa775d9..c40bf6faa65 100644 --- a/neural_modelling/src/neuron/spike_processing.c +++ b/neural_modelling/src/neuron/spike_processing.c @@ -112,6 +112,9 @@ static uint32_t dma_complete_count; static uint32_t max_pipeline_restarts; static uint32_t spike_pipeline_deactivation_time = 0; static uint32_t timer_callback_completed = 0; +static uint32_t spikes_this_time_step; // needed because packets gets reset? +static uint32_t dmas_this_time_step; +static uint32_t pipeline_restarts; static uint32_t max_flushed_spikes; static uint32_t total_flushed_spikes; @@ -120,8 +123,6 @@ static uint32_t total_flushed_spikes; static struct { uint32_t time; uint32_t packets_this_time_step; - uint32_t dmas_this_time_step; - uint32_t pipeline_restarts; } p_per_ts_struct; //! the region to record the packets per timestep in @@ -347,6 +348,7 @@ static inline void start_dma_loop(void) { //! \param[in] unused: Only specified to match API static void multicast_packet_received_callback(uint key, UNUSED uint unused) { p_per_ts_struct.packets_this_time_step += 1; + spikes_this_time_step += 1; log_debug("Received spike %x at %d, DMA Busy = %d", key, time, dma_busy); if (in_spikes_add_spike(key)) { start_dma_loop(); @@ -358,6 +360,7 @@ static void multicast_packet_received_callback(uint key, UNUSED uint unused) { //! \param[in] payload: the payload of the packet. The count. static void multicast_packet_pl_received_callback(uint key, uint payload) { p_per_ts_struct.packets_this_time_step += 1; + spikes_this_time_step += 1; log_debug("Received spike %x with payload %d at %d, DMA Busy = %d", key, payload, time, dma_busy); @@ -377,7 +380,7 @@ static void multicast_packet_pl_received_callback(uint key, uint payload) { static void dma_complete_callback(UNUSED uint unused, uint tag) { // increment the dma complete count for provenance generation - p_per_ts_struct.dmas_this_time_step += 1; + dmas_this_time_step += 1; dma_complete_count += 1; log_debug("DMA transfer complete at time %u with tag %u", time, tag); @@ -451,7 +454,7 @@ void user_event_callback(UNUSED uint unused0, UNUSED uint unused1) { dma_n_spikes = 0; // Increment counter for spike processing pipeline restarts - p_per_ts_struct.pipeline_restarts++; + pipeline_restarts++; if (buffer_being_read < N_DMA_BUFFERS) { // If the DMA buffer is full of valid data, attempt to reuse it on the @@ -549,21 +552,24 @@ bool spike_processing_do_rewiring(int number_of_rewires) { // Custom provenance from SpiNNCer void spike_processing_get_and_reset_spikes_this_tick(void ) { - if (p_per_ts_struct.packets_this_time_step > max_spikes_in_a_tick) { - max_spikes_in_a_tick = p_per_ts_struct.packets_this_time_step; + if (spikes_this_time_step > max_spikes_in_a_tick) { + max_spikes_in_a_tick = spikes_this_time_step; } + spikes_this_time_step = 0; } void spike_processing_get_and_reset_dmas_this_tick(void) { - if (p_per_ts_struct.dmas_this_time_step > max_dmas_in_a_tick){ - max_dmas_in_a_tick = p_per_ts_struct.dmas_this_time_step; + if (dmas_this_time_step > max_dmas_in_a_tick){ + max_dmas_in_a_tick = dmas_this_time_step; } + dmas_this_time_step = 0; } void spike_processing_get_and_reset_pipeline_restarts_this_tick(void) { - if (p_per_ts_struct.pipeline_restarts > max_pipeline_restarts) { - max_pipeline_restarts = p_per_ts_struct.pipeline_restarts; + if (pipeline_restarts > max_pipeline_restarts) { + max_pipeline_restarts = pipeline_restarts; } + pipeline_restarts = 0; } //uint32_t spike_processing_get_pipeline_deactivation_time(){ From f6462af65473f7e3f97ce2a3fd3f7b8a12813bd1 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 29 Nov 2021 15:05:48 +0000 Subject: [PATCH 062/108] Repeat after me: "the order in Python must be the same as in C" --- .../src/neuron/spike_processing.c | 10 +-- .../population_machine_synapses_provenance.py | 67 ------------------ .../neuron/population_machine_vertex.py | 69 ++++++++++++++++++- 3 files changed, 73 insertions(+), 73 deletions(-) diff --git a/neural_modelling/src/neuron/spike_processing.c b/neural_modelling/src/neuron/spike_processing.c index c40bf6faa65..839a11fcdac 100644 --- a/neural_modelling/src/neuron/spike_processing.c +++ b/neural_modelling/src/neuron/spike_processing.c @@ -112,12 +112,12 @@ static uint32_t dma_complete_count; static uint32_t max_pipeline_restarts; static uint32_t spike_pipeline_deactivation_time = 0; static uint32_t timer_callback_completed = 0; -static uint32_t spikes_this_time_step; // needed because packets gets reset? -static uint32_t dmas_this_time_step; -static uint32_t pipeline_restarts; +static uint32_t spikes_this_time_step = 0; // needed because packets gets reset? +static uint32_t dmas_this_time_step = 0; +static uint32_t pipeline_restarts = 0; -static uint32_t max_flushed_spikes; -static uint32_t total_flushed_spikes; +static uint32_t max_flushed_spikes = 0; +static uint32_t total_flushed_spikes = 0; //! the number of packets received this time step static struct { diff --git a/spynnaker/pyNN/models/neuron/population_machine_synapses_provenance.py b/spynnaker/pyNN/models/neuron/population_machine_synapses_provenance.py index 3a42c3a222e..eca7a054f8d 100644 --- a/spynnaker/pyNN/models/neuron/population_machine_synapses_provenance.py +++ b/spynnaker/pyNN/models/neuron/population_machine_synapses_provenance.py @@ -35,20 +35,6 @@ class SynapseProvenance(ctypes.LittleEndianStructure): ("n_invalid_pop_table_hits", ctypes.c_uint32), # The number of spikes that didn't transfer empty rows ("n_filtered_by_bitfield", ctypes.c_uint32), - # Custom provenance from SpiNNCer - max spikes in a tick - ("max_spikes_in_a_tick", ctypes.c_uint32), - # max dmas in a tick - ("max_dmas_in_a_tick", ctypes.c_uint32), - # max pipeline restarts - ("max_pipeline_restarts", ctypes.c_uint32), - # timer callback completed? - ("timer_callback_completed", ctypes.c_uint32), - # spikes pipeline activated? - ("spikes_pipeline_activated", ctypes.c_uint32), - # Max flushed spikes in a timestep - ("max_flushed_spikes", ctypes.c_uint32), - # Total flushed spikes - ("total_flushed_spikes", ctypes.c_uint32) ] N_ITEMS = len(_fields_) @@ -70,15 +56,6 @@ class PopulationMachineSynapsesProvenance(object): INVALID_MASTER_POP_HITS = "Invalid Master Pop hits" BIT_FIELD_FILTERED_PACKETS = \ "How many packets were filtered by the bitfield filterer." - # Custom provenance from SpiNNCer - MAX_SPIKES_IN_A_TICK = "Maximum number of spikes in a timer tick" - MAX_DMAS_IN_A_TICK = "Maximum number of DMAs in a timer tick" - MAX_PIPELINE_RESTARTS = "Maximum pipeline restarts" - TIMER_CALLBACK_COMPLETED = "Was the timer callback completed?" - SPIKES_PIPELINE_ACTIVATED = "Was the spikes pipeline activated?" - # Flushed spikes - MAX_FLUSHED_SPIKES = "Maximum number of spikes flushed in a timer tick" - TOTAL_FLUSHED_SPIKES = "Total number of spikes flushed" @abstractproperty def _app_vertex(self): @@ -152,47 +129,3 @@ def _parse_synapse_provenance(self, label, x, y, p, provenance_data): db.insert_core( x, y, p, self.BIT_FIELD_FILTERED_PACKETS, synapse_prov.n_filtered_by_bitfield) - - # SpiNNCer - db.insert_core( - x, y, p, self.MAX_SPIKES_IN_A_TICK, - synapse_prov.max_spikes_in_a_tick) - if synapse_prov.max_spikes_in_a_tick > 200: - db.insert_report( - f"Max number of spikes for {label} was " - f"{synapse_prov.max_spikes_in_a_tick}. Empirically, we " - f"can deal with ~200 for real time performance using a " - f"1.0 ms timestep.") - - db.insert_core( - x, y, p, self.MAX_DMAS_IN_A_TICK, - synapse_prov.max_dmas_in_a_tick) - - db.insert_core( - x, y, p, self.MAX_PIPELINE_RESTARTS, - synapse_prov.max_pipeline_restarts) - - db.insert_core( - x, y, p, self.TIMER_CALLBACK_COMPLETED, - synapse_prov.timer_callback_completed) - - db.insert_core( - x, y, p, self.SPIKES_PIPELINE_ACTIVATED, - synapse_prov.spikes_pipeline_activated) - - # FLUSHED SPIKES - db.insert_core( - x, y, p, self.MAX_FLUSHED_SPIKES, - synapse_prov.max_flushed_spikes) - if synapse_prov.max_flushed_spikes > 0: - db.insert_report( - f"Max number of flushed spikes for {label} was " - f"was {synapse_prov.max_flushed_spikes}.") - - db.insert_core( - x, y, p, self.TOTAL_FLUSHED_SPIKES, - synapse_prov.total_flushed_spikes) - if synapse_prov.total_flushed_spikes > 0: - db.insert_report( - f"Total number of flushed spikes for {label} was " - f"{synapse_prov.total_flushed_spikes}.") diff --git a/spynnaker/pyNN/models/neuron/population_machine_vertex.py b/spynnaker/pyNN/models/neuron/population_machine_vertex.py index cfca3bf112c..bc29a9393eb 100644 --- a/spynnaker/pyNN/models/neuron/population_machine_vertex.py +++ b/spynnaker/pyNN/models/neuron/population_machine_vertex.py @@ -43,7 +43,21 @@ class SpikeProcessingProvenance(ctypes.LittleEndianStructure): # The number of packets that were dropped due to being late ("n_late_packets", ctypes.c_uint32), # The maximum size of the spike input buffer during simulation - ("max_size_input_buffer", ctypes.c_uint32) + ("max_size_input_buffer", ctypes.c_uint32), + # Custom provenance from SpiNNCer - max spikes in a tick + ("max_spikes_in_a_tick", ctypes.c_uint32), + # max dmas in a tick + ("max_dmas_in_a_tick", ctypes.c_uint32), + # max pipeline restarts + ("max_pipeline_restarts", ctypes.c_uint32), + # timer callback completed? + ("timer_callback_completed", ctypes.c_uint32), + # spikes pipeline activated? + ("spikes_pipeline_activated", ctypes.c_uint32), + # Max flushed spikes in a timestep + ("max_flushed_spikes", ctypes.c_uint32), + # Total flushed spikes + ("total_flushed_spikes", ctypes.c_uint32) ] N_ITEMS = len(_fields_) @@ -89,6 +103,15 @@ class PopulationMachineVertex( MAX_FILLED_SIZE_OF_INPUT_BUFFER_NAME = "Max_filled_size_input_buffer" BACKGROUND_OVERLOADS_NAME = "Times_the_background_queue_overloaded" BACKGROUND_MAX_QUEUED_NAME = "Max_backgrounds_queued" + # Custom provenance from SpiNNCer + MAX_SPIKES_IN_A_TICK = "Maximum number of spikes in a timer tick" + MAX_DMAS_IN_A_TICK = "Maximum number of DMAs in a timer tick" + MAX_PIPELINE_RESTARTS = "Maximum pipeline restarts" + TIMER_CALLBACK_COMPLETED = "Was the timer callback completed?" + SPIKES_PIPELINE_ACTIVATED = "Was the spikes pipeline activated?" + # Flushed spikes + MAX_FLUSHED_SPIKES = "Maximum number of spikes flushed in a timer tick" + TOTAL_FLUSHED_SPIKES = "Total number of spikes flushed" class REGIONS(Enum): """Regions for populations.""" @@ -381,3 +404,47 @@ def _parse_spike_processing_provenance( db.insert_core( x, y, p, self.MAX_FILLED_SIZE_OF_INPUT_BUFFER_NAME, prov.max_size_input_buffer) + + # SpiNNCer + db.insert_core( + x, y, p, self.MAX_SPIKES_IN_A_TICK, + prov.max_spikes_in_a_tick) + if prov.max_spikes_in_a_tick > 200: + db.insert_report( + f"Max number of spikes for {label} was " + f"{prov.max_spikes_in_a_tick}. Empirically, we " + f"can deal with ~200 for real time performance using a " + f"1.0 ms timestep.") + + db.insert_core( + x, y, p, self.MAX_DMAS_IN_A_TICK, + prov.max_dmas_in_a_tick) + + db.insert_core( + x, y, p, self.MAX_PIPELINE_RESTARTS, + prov.max_pipeline_restarts) + + db.insert_core( + x, y, p, self.TIMER_CALLBACK_COMPLETED, + prov.timer_callback_completed) + + db.insert_core( + x, y, p, self.SPIKES_PIPELINE_ACTIVATED, + prov.spikes_pipeline_activated) + + # FLUSHED SPIKES + db.insert_core( + x, y, p, self.MAX_FLUSHED_SPIKES, + prov.max_flushed_spikes) + if prov.max_flushed_spikes > 0: + db.insert_report( + f"Max number of flushed spikes for {label} was " + f"was {prov.max_flushed_spikes}.") + + db.insert_core( + x, y, p, self.TOTAL_FLUSHED_SPIKES, + prov.total_flushed_spikes) + if prov.total_flushed_spikes > 0: + db.insert_report( + f"Total number of flushed spikes for {label} was " + f"{prov.total_flushed_spikes}.") From 90941d95836e945269a44abfb0875c9828e75c1a Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 4 Feb 2022 15:13:47 +0000 Subject: [PATCH 063/108] Reinstate all binaries; remove model-specific hacking --- neural_modelling/makefiles/neuron/Makefile | 13 +++-- neural_modelling/src/neuron/send_spike.h | 2 +- .../src/neuron/spike_processing.c | 54 +++++++++---------- neural_modelling/src/neuron/synapses.c | 24 ++++----- 4 files changed, 46 insertions(+), 47 deletions(-) diff --git a/neural_modelling/makefiles/neuron/Makefile b/neural_modelling/makefiles/neuron/Makefile index 89e11feaceb..a005f95f838 100644 --- a/neural_modelling/makefiles/neuron/Makefile +++ b/neural_modelling/makefiles/neuron/Makefile @@ -13,17 +13,16 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -MODELS = IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc \ - IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn \ - IF_curr_exp \ +MODELS = IF_curr_exp \ IF_cond_exp \ IZK_curr_exp \ IZK_cond_exp \ IF_curr_exp_dual \ IF_curr_exp_stdp_mad_pair_additive \ - #IF_curr_exp_stdp_mad_pair_multiplicative \ + IF_curr_exp_stdp_mad_pair_multiplicative \ IF_cond_exp_stdp_mad_pair_additive \ external_device_lif_control \ + IF_cond_exp_stoc \ IF_curr_exp_stdp_mad_recurrent_pre_stochastic_multiplicative \ IF_curr_exp_stdp_mad_recurrent_dual_fsm_multiplicative \ IF_curr_exp_stdp_mad_vogels_2011_additive \ @@ -40,8 +39,6 @@ MODELS = IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc \ IF_curr_exp_structural_last_neuron_distance_weight \ IF_curr_exp_structural_random_distance_weight \ IF_curr_exp_sEMD \ - #IF_cond_exp_stoc \ - IF_curr_exp_sEMD \ IZK_curr_exp_stdp_mad_pair_additive \ IZK_cond_exp_stdp_mad_pair_additive \ IF_curr_exp_stdp_izhikevich_neuromodulation_pair_additive \ @@ -56,7 +53,9 @@ MODELS = IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc \ IF_curr_exp_stdp_mad_pair_additive_structural_random_distance_weight \ IF_cond_exp_stdp_mad_nearest_pair_additive_structural_last_neuron_distance_weight \ IF_cond_exp_stdp_mad_pair_additive_structural_last_neuron_distance_weight \ - IF_cond_exp_stdp_mad_pair_additive_structural_random_distance_weight + IF_cond_exp_stdp_mad_pair_additive_structural_random_distance_weight \ + IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc \ + IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn all: for d in $(MODELS); do $(MAKE) -C $$d || exit $$?; done diff --git a/neural_modelling/src/neuron/send_spike.h b/neural_modelling/src/neuron/send_spike.h index 1871b73a071..4f81d4c95ef 100644 --- a/neural_modelling/src/neuron/send_spike.h +++ b/neural_modelling/src/neuron/send_spike.h @@ -64,7 +64,7 @@ static inline void send_spike_mc(uint32_t key) { static inline void send_spike(UNUSED uint32_t timer_count, UNUSED uint32_t time, uint32_t neuron_index) { // Do any required synapse processing -// synapse_dynamics_process_post_synaptic_event(time, neuron_index); + synapse_dynamics_process_post_synaptic_event(time, neuron_index); if (use_key) { send_spike_mc(key | neuron_index); diff --git a/neural_modelling/src/neuron/spike_processing.c b/neural_modelling/src/neuron/spike_processing.c index 839a11fcdac..c3363028816 100644 --- a/neural_modelling/src/neuron/spike_processing.c +++ b/neural_modelling/src/neuron/spike_processing.c @@ -321,26 +321,26 @@ static inline void start_dma_loop(void) { } // if timer is getting low, don't do next DMA and instead flush spike buffer - // originally 6657 clock cycles from the end of the interval was used -// if (tc[T1_COUNT] < 6657){//6657){ -// uint cpsr = spin1_int_disable(); -// uint32_t spikes_remaining = in_spikes_flush_buffer(); -// timer_callback_active = true; -// spin1_mode_restore(cpsr); -// -// if (spikes_remaining > 0){ -// total_flushed_spikes += spikes_remaining; -// -// if (spikes_remaining > max_flushed_spikes){ -// max_flushed_spikes = spikes_remaining; -// } -// -//// log_info("--------At time: %u, flushed spikes: %u", time, spikes_remaining); -// -// //io_printf(IO_BUF, "At time: %u, flushed spikes: %u\n", -// // time, spikes_remaining); -// } -// } + // originally 6657 clock cycles from the end of the interval was used + if (tc[T1_COUNT] < 6657){//6657){ + uint cpsr = spin1_int_disable(); + uint32_t spikes_remaining = in_spikes_flush_buffer(); + timer_callback_active = true; + spin1_mode_restore(cpsr); + + if (spikes_remaining > 0){ + total_flushed_spikes += spikes_remaining; + + if (spikes_remaining > max_flushed_spikes){ + max_flushed_spikes = spikes_remaining; + } + +// log_info("--------At time: %u, flushed spikes: %u", time, spikes_remaining); + + //io_printf(IO_BUF, "At time: %u, flushed spikes: %u\n", + // time, spikes_remaining); + } + } } //! \brief Called when a multicast packet is received @@ -404,13 +404,13 @@ static void dma_complete_callback(UNUSED uint unused, uint tag) { bool plastic_only = true; // If rewiring, do rewiring first -// for (uint32_t i = n_rewires; i > 0; i--) { -// if (synaptogenesis_row_restructure(time, current_buffer->row)) { -// write_back = true; -// plastic_only = false; -// n_successful_rewires++; -// } -// } + for (uint32_t i = n_rewires; i > 0; i--) { + if (synaptogenesis_row_restructure(time, current_buffer->row)) { + write_back = true; + plastic_only = false; + n_successful_rewires++; + } + } // Process synaptic row repeatedly for any upcoming spikes while (n_spikes > 0) { diff --git a/neural_modelling/src/neuron/synapses.c b/neural_modelling/src/neuron/synapses.c index 2afe5182062..9e83a56ef0e 100644 --- a/neural_modelling/src/neuron/synapses.c +++ b/neural_modelling/src/neuron/synapses.c @@ -212,18 +212,18 @@ static inline bool process_fixed_synapses( uint32_t ring_buffer_index = (synaptic_word + masked_time) & ring_buffer_mask; uint32_t weight = synapse_row_sparse_weight(synaptic_word); - // *********************************** - // For Cerebellum plasticity - uint32_t type = synapse_row_sparse_type(synaptic_word, - synapse_index_bits, synapse_type_mask); - - if (type == 0){ - index_t neuron_index = synapse_row_sparse_index(synaptic_word, synapse_index_mask); - - // io_printf(IO_BUF, "\nSpike on type: %u at time: %u\n", type, time); - synapse_dynamics_process_post_synaptic_event(time, neuron_index); - } - // *********************************** +// // *********************************** +// // For Cerebellum plasticity +// uint32_t type = synapse_row_sparse_type(synaptic_word, +// synapse_index_bits, synapse_type_mask); +// +// if (type == 0){ +// index_t neuron_index = synapse_row_sparse_index(synaptic_word, synapse_index_mask); +// +// // io_printf(IO_BUF, "\nSpike on type: %u at time: %u\n", type, time); +// synapse_dynamics_process_post_synaptic_event(time, neuron_index); +// } +// // *********************************** // Add weight to current ring buffer value uint32_t accumulation = ring_buffers[ring_buffer_index] + weight; From ffdcc40a169d41cd8101b2839e2a0c2d446e4c71 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 10 Feb 2022 11:32:18 +0000 Subject: [PATCH 064/108] Actually use the neuron model that includes t_last --- .../neuron/IF_cond_exp_cerebellum/Makefile | 4 +- .../Makefile | 4 +- .../Makefile | 4 +- neural_modelling/makefiles/neuron/Makefile | 1 + .../models/neuron_model_lif_t_last_impl.c | 65 +------ .../models/neuron_model_lif_t_last_impl.h | 83 +++++++++ .../neuron/builds/if_cond_exp_cerebellum.py | 4 +- ...n_model_leaky_integrate_and_fire_t_last.py | 159 ++++++++++-------- 8 files changed, 188 insertions(+), 136 deletions(-) diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile index 99e98fd76a6..c624ba32c72 100644 --- a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile +++ b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile @@ -15,8 +15,8 @@ APP = $(notdir $(CURDIR)) -NEURON_MODEL = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.c -NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.h +NEURON_MODEL = $(NEURON_DIR)/neuron/models/neuron_model_lif_t_last_impl.c +NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_t_last_impl.h INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_conductance.h NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile index 2950e0c0f2c..6b3983181a6 100644 --- a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile +++ b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile @@ -15,8 +15,8 @@ APP = $(notdir $(CURDIR)) -NEURON_MODEL = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.c -NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.h +NEURON_MODEL = $(NEURON_DIR)/neuron/models/neuron_model_lif_t_last_impl.c +NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_t_last_impl.h INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_conductance.h NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile index 74ff6896efb..219a1d41eb6 100644 --- a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile +++ b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile @@ -15,8 +15,8 @@ APP = $(notdir $(CURDIR)) -NEURON_MODEL = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.c -NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.h +NEURON_MODEL = $(NEURON_DIR)/neuron/models/neuron_model_lif_t_last_impl.c +NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_t_last_impl.h INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_conductance.h NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h diff --git a/neural_modelling/makefiles/neuron/Makefile b/neural_modelling/makefiles/neuron/Makefile index a005f95f838..c9ce287f29e 100644 --- a/neural_modelling/makefiles/neuron/Makefile +++ b/neural_modelling/makefiles/neuron/Makefile @@ -54,6 +54,7 @@ MODELS = IF_curr_exp \ IF_cond_exp_stdp_mad_nearest_pair_additive_structural_last_neuron_distance_weight \ IF_cond_exp_stdp_mad_pair_additive_structural_last_neuron_distance_weight \ IF_cond_exp_stdp_mad_pair_additive_structural_random_distance_weight \ + IF_cond_exp_cerebellum \ IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc \ IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn diff --git a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.c b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.c index 88305c2b010..ca487f5a8db 100644 --- a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.c +++ b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.c @@ -19,75 +19,16 @@ #include -// simple Leaky I&F ODE -static inline void _lif_neuron_closed_form( - neuron_pointer_t neuron, REAL V_prev, input_t input_this_timestep) { - - REAL alpha = input_this_timestep * neuron->R_membrane + neuron->V_rest; - - // update membrane voltage - neuron->V_membrane = alpha - (neuron->exp_TC * (alpha - V_prev)); -} - void neuron_model_set_global_neuron_params( - global_neuron_params_pointer_t params) { - use(params); - + UNUSED const global_neuron_params_t *params) { // Does Nothing - no params } -state_t neuron_model_state_update( - uint16_t num_excitatory_inputs, input_t* exc_input, - uint16_t num_inhibitory_inputs, input_t* inh_input, - input_t external_bias, neuron_pointer_t neuron) { - - log_debug("Exc 1: %12.6k, Exc 2: %12.6k", exc_input[0], exc_input[1]); - log_debug("Inh 1: %12.6k, Inh 2: %12.6k", inh_input[0], inh_input[1]); - - - // If outside of the refractory period - if (neuron->refract_timer <= 0) { - REAL total_exc = 0; - REAL total_inh = 0; - - for (int i=0; i < num_excitatory_inputs; i++){ - total_exc += exc_input[i]; - } - for (int i=0; i< num_inhibitory_inputs; i++){ - total_inh += inh_input[i]; - } - // Get the input in nA - input_t input_this_timestep = - total_exc - total_inh + external_bias + neuron->I_offset; - - _lif_neuron_closed_form( - neuron, neuron->V_membrane, input_this_timestep); - } else { - - // countdown refractory timer - neuron->refract_timer -= 1; - } - return neuron->V_membrane; -} - -void neuron_model_has_spiked(neuron_pointer_t neuron) { - - // reset membrane voltage - neuron->V_membrane = neuron->V_reset; - - // reset refractory timer - neuron->refract_timer = neuron->T_refract; -} - -state_t neuron_model_get_membrane_voltage(neuron_pointer_t neuron) { - return neuron->V_membrane; -} - -void neuron_model_print_state_variables(restrict neuron_pointer_t neuron) { +void neuron_model_print_state_variables(const neuron_t *neuron) { log_debug("V membrane = %11.4k mv", neuron->V_membrane); } -void neuron_model_print_parameters(restrict neuron_pointer_t neuron) { +void neuron_model_print_parameters(const neuron_t *neuron) { log_debug("V reset = %11.4k mv", neuron->V_reset); log_debug("V rest = %11.4k mv", neuron->V_rest); diff --git a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h index 6bf34874373..8248a4bcb64 100644 --- a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h +++ b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h @@ -20,6 +20,8 @@ #include "neuron_model.h" +#include + ///////////////////////////////////////////////////////////// // definition for LIF neuron parameters typedef struct neuron_t { @@ -55,4 +57,85 @@ typedef struct neuron_t { typedef struct global_neuron_params_t { } global_neuron_params_t; +// simple Leaky I&F ODE +//! \param[in,out] neuron: The neuron to update +//! \param[in] V_prev: previous voltage +//! \param[in] input_this_timestep: The input to apply +static inline void _lif_neuron_closed_form( + neuron_t *neuron, REAL V_prev, input_t input_this_timestep) { + REAL alpha = input_this_timestep * neuron->R_membrane + neuron->V_rest; + + // update membrane voltage + neuron->V_membrane = alpha - (neuron->exp_TC * (alpha - V_prev)); +} + +//! \brief primary function called in timer loop after synaptic updates +//! \param[in] num_excitatory_inputs: Number of excitatory receptor types. +//! \param[in] exc_input: Pointer to array of inputs per receptor type received +//! this timer tick that produce a positive reaction within the neuron in +//! terms of stimulation. +//! \param[in] num_inhibitory_inputs: Number of inhibitory receptor types. +//! \param[in] inh_input: Pointer to array of inputs per receptor type received +//! this timer tick that produce a negative reaction within the neuron in +//! terms of stimulation. +//! \param[in] external_bias: This is the intrinsic plasticity which could be +//! used for ac, noisy input etc etc. (general purpose input) +//! \param[in,out] neuron: the pointer to a neuron parameter struct which +//! contains all the parameters for a specific neuron +//! \return the value to be compared with a threshold value to determine if the +//! neuron has spiked +static state_t neuron_model_state_update( + uint16_t num_excitatory_inputs, const input_t *exc_input, + uint16_t num_inhibitory_inputs, const input_t *inh_input, + input_t external_bias, neuron_t *restrict neuron) { + + log_debug("Exc 1: %12.6k, Exc 2: %12.6k", exc_input[0], exc_input[1]); + log_debug("Inh 1: %12.6k, Inh 2: %12.6k", inh_input[0], inh_input[1]); + + + // If outside of the refractory period + if (neuron->refract_timer <= 0) { + REAL total_exc = 0; + REAL total_inh = 0; + + for (int i=0; i < num_excitatory_inputs; i++){ + total_exc += exc_input[i]; + } + for (int i=0; i< num_inhibitory_inputs; i++){ + total_inh += inh_input[i]; + } + // Get the input in nA + input_t input_this_timestep = + total_exc - total_inh + external_bias + neuron->I_offset; + + _lif_neuron_closed_form( + neuron, neuron->V_membrane, input_this_timestep); + } else { + + // countdown refractory timer + neuron->refract_timer -= 1; + } + return neuron->V_membrane; +} + +//! \brief Indicates that the neuron has spiked +//! \param[in, out] neuron pointer to a neuron parameter struct which contains +//! all the parameters for a specific neuron +static void neuron_model_has_spiked(neuron_t *restrict neuron) { + // reset membrane voltage + neuron->V_membrane = neuron->V_reset; + + // reset refractory timer + neuron->refract_timer = neuron->T_refract; +} + +//! \brief get the neuron membrane voltage for a given neuron parameter set +//! \param[in] neuron: a pointer to a neuron parameter struct which contains +//! all the parameters for a specific neuron +//! \return the membrane voltage for a given neuron with the neuron +//! parameters specified in neuron +static state_t neuron_model_get_membrane_voltage(const neuron_t *neuron) { + return neuron->V_membrane; +} + #endif // _NEURON_MODEL_LIF_CURR_T_LAST_IMPL_H_ diff --git a/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py b/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py index efe53996223..72aa1b0950d 100644 --- a/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py +++ b/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py @@ -15,7 +15,7 @@ from spynnaker.pyNN.models.neuron import AbstractPyNNNeuronModelStandard from spynnaker.pyNN.models.defaults import default_initial_values from spynnaker.pyNN.models.neuron.neuron_models \ - import NeuronModelLeakyIntegrateAndFire + import NeuronModelLeakyIntegrateAndFireTLast from spynnaker.pyNN.models.neuron.input_types import InputTypeConductance from spynnaker.pyNN.models.neuron.synapse_types import SynapseTypeExponential from spynnaker.pyNN.models.neuron.threshold_types import ThresholdTypeStatic @@ -36,7 +36,7 @@ def __init__( i_offset=0.0, e_rev_E=0.0, e_rev_I=-70.0, v=-65.0, isyn_exc=0.0, isyn_inh=0.0): # pylint: disable=too-many-arguments, too-many-locals - neuron_model = NeuronModelLeakyIntegrateAndFire( + neuron_model = NeuronModelLeakyIntegrateAndFireTLast( v, v_rest, tau_m, cm, i_offset, v_reset, tau_refrac) synapse_type = SynapseTypeExponential( tau_syn_E, tau_syn_I, isyn_exc, isyn_inh) diff --git a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py index e0941140a31..6dd5b8bd975 100644 --- a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py +++ b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py @@ -13,12 +13,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import numpy from spinn_utilities.overrides import overrides -from pacman.executor.injection_decorator import inject_items -from .abstract_neuron_model import AbstractNeuronModel from data_specification.enums import DataType - -import numpy +from .abstract_neuron_model import AbstractNeuronModel +from spynnaker.pyNN.models.neuron.implementations import ( + AbstractStandardNeuronComponent) V = "v" V_REST = "v_rest" @@ -43,19 +43,50 @@ class NeuronModelLeakyIntegrateAndFireTLast(AbstractNeuronModel): + """ Classic LIF neuron model with t_last state variable included. + """ __slots__ = [ - "_v_init", - "_v_rest", - "_tau_m", - "_cm", - "_i_offset", - "_v_reset", - "_tau_refrac" + "__v_init", + "__v_rest", + "__tau_m", + "__cm", + "__i_offset", + "__v_reset", + "__tau_refrac" ] def __init__( self, v_init, v_rest, tau_m, cm, i_offset, v_reset, tau_refrac): - super(NeuronModelLeakyIntegrateAndFireTLast, self).__init__( + r""" + :param v_init: :math:`V_{init}` + :type v_init: + float, iterable(float), ~pyNN.random.RandomDistribution or + (mapping) function + :param v_rest: :math:`V_{rest}` + :type v_rest: + float, iterable(float), ~pyNN.random.RandomDistribution or + (mapping) function + :param tau_m: :math:`\tau_{m}` + :type tau_m: + float, iterable(float), ~pyNN.random.RandomDistribution or + (mapping) function + :param cm: :math:`C_m` + :type cm: float, iterable(float), ~pyNN.random.RandomDistribution or + (mapping) function + :param i_offset: :math:`I_{offset}` + :type i_offset: + float, iterable(float), ~pyNN.random.RandomDistribution or + (mapping) function + :param v_reset: :math:`V_{reset}` + :type v_reset: + float, iterable(float), ~pyNN.random.RandomDistribution or + (mapping) function + :param tau_refrac: :math:`\tau_{refrac}` + :type tau_refrac: + float, iterable(float), ~pyNN.random.RandomDistribution or + (mapping) function + """ + super().__init__( [DataType.S1615, # v DataType.S1615, # v_rest DataType.S1615, # r_membrane (= tau_m / cm) @@ -70,13 +101,13 @@ def __init__( if v_init is None: v_init = v_rest - self._v_init = v_init - self._v_rest = v_rest - self._tau_m = tau_m - self._cm = cm - self._i_offset = i_offset - self._v_reset = v_reset - self._tau_refrac = tau_refrac + self.__v_init = v_init + self.__v_rest = v_rest + self.__tau_m = tau_m + self.__cm = cm + self.__i_offset = i_offset + self.__v_reset = v_reset + self.__tau_refrac = tau_refrac @overrides(AbstractNeuronModel.get_n_cpu_cycles) def get_n_cpu_cycles(self, n_neurons): @@ -85,16 +116,16 @@ def get_n_cpu_cycles(self, n_neurons): @overrides(AbstractNeuronModel.add_parameters) def add_parameters(self, parameters): - parameters[V_REST] = self._v_rest - parameters[TAU_M] = self._tau_m - parameters[CM] = self._cm - parameters[I_OFFSET] = self._i_offset - parameters[V_RESET] = self._v_reset - parameters[TAU_REFRAC] = self._tau_refrac + parameters[V_REST] = self.__v_rest + parameters[TAU_M] = self.__tau_m + parameters[CM] = self.__cm + parameters[I_OFFSET] = self.__i_offset + parameters[V_RESET] = self.__v_reset + parameters[TAU_REFRAC] = self.__tau_refrac @overrides(AbstractNeuronModel.add_state_variables) def add_state_variables(self, state_variables): - state_variables[V] = self._v_init + state_variables[V] = self.__v_init state_variables[COUNT_REFRAC] = 0 state_variables[T_LAST] = 0 @@ -106,9 +137,12 @@ def get_units(self, variable): def has_variable(self, variable): return variable in UNITS - @inject_items({"ts": "MachineTimeStep"}) - @overrides(AbstractNeuronModel.get_values) + @overrides(AbstractStandardNeuronComponent.get_values) def get_values(self, parameters, state_variables, vertex_slice, ts): + """ + :param int ts: machine time step + """ + # pylint: disable=arguments-differ # Add the rest of the data return [ @@ -125,19 +159,12 @@ def get_values(self, parameters, state_variables, vertex_slice, ts): state_variables[T_LAST] ] - @overrides(AbstractNeuronModel.update_values) + @overrides(AbstractStandardNeuronComponent.update_values) def update_values(self, values, parameters, state_variables): # Read the data - (v, - _v_rest, - _r_membrane, - _exp_tc, - _i_offset, - count_refrac, - _v_reset, - _tau_refrac, - t_last) = values + (v, _v_rest, _r_membrane, _exp_tc, _i_offset, count_refrac, + _v_reset, _tau_refrac, t_last) = values # Copy the changed data only state_variables[V] = v @@ -146,56 +173,56 @@ def update_values(self, values, parameters, state_variables): @property def v_init(self): - return self._v_init + """ Settable model parameter: :math:`V_{init}` - @v_init.setter - def v_init(self, v_init): - self._v_init = v_init + :rtype: float + """ + return self.__v_init @property def v_rest(self): - return self._v_rest + """ Settable model parameter: :math:`V_{rest}` - @v_rest.setter - def v_rest(self, v_rest): - self._v_rest = v_rest + :rtype: float + """ + return self.__v_rest @property def tau_m(self): - return self._tau_m + r""" Settable model parameter: :math:`\tau_{m}` - @tau_m.setter - def tau_m(self, tau_m): - self._tau_m = tau_m + :rtype: float + """ + return self.__tau_m @property def cm(self): - return self._cm + """ Settable model parameter: :math:`C_m` - @cm.setter - def cm(self, cm): - self._cm = cm + :rtype: float + """ + return self.__cm @property def i_offset(self): - return self._i_offset + """ Settable model parameter: :math:`I_{offset}` - @i_offset.setter - def i_offset(self, i_offset): - self._i_offset = i_offset + :rtype: float + """ + return self.__i_offset @property def v_reset(self): - return self._v_reset + """ Settable model parameter: :math:`V_{reset}` - @v_reset.setter - def v_reset(self, v_reset): - self._v_reset = v_reset + :rtype: float + """ + return self.__v_reset @property def tau_refrac(self): - return self._tau_refrac + r""" Settable model parameter: :math:`\tau_{refrac}` - @tau_refrac.setter - def tau_refrac(self, tau_refrac): - self._tau_refrac = tau_refrac + :rtype: float + """ + return self.__tau_refrac From b4eda9238c056f13ab70a5e7168803683a6dfde0 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 10 Feb 2022 16:20:47 +0000 Subject: [PATCH 065/108] Put the flushed spikes counters under debug flags --- .../src/neuron/spike_processing.c | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/neural_modelling/src/neuron/spike_processing.c b/neural_modelling/src/neuron/spike_processing.c index c3363028816..b5af527a342 100644 --- a/neural_modelling/src/neuron/spike_processing.c +++ b/neural_modelling/src/neuron/spike_processing.c @@ -112,7 +112,7 @@ static uint32_t dma_complete_count; static uint32_t max_pipeline_restarts; static uint32_t spike_pipeline_deactivation_time = 0; static uint32_t timer_callback_completed = 0; -static uint32_t spikes_this_time_step = 0; // needed because packets gets reset? +static uint32_t spikes_this_time_step = 0; static uint32_t dmas_this_time_step = 0; static uint32_t pipeline_restarts = 0; @@ -320,9 +320,10 @@ static inline void start_dma_loop(void) { } } +#if LOG_LEVEL >= LOG_DEBUG // if timer is getting low, don't do next DMA and instead flush spike buffer // originally 6657 clock cycles from the end of the interval was used - if (tc[T1_COUNT] < 6657){//6657){ + if (tc[T1_COUNT] < 6657) { uint cpsr = spin1_int_disable(); uint32_t spikes_remaining = in_spikes_flush_buffer(); timer_callback_active = true; @@ -335,12 +336,10 @@ static inline void start_dma_loop(void) { max_flushed_spikes = spikes_remaining; } -// log_info("--------At time: %u, flushed spikes: %u", time, spikes_remaining); - - //io_printf(IO_BUF, "At time: %u, flushed spikes: %u\n", - // time, spikes_remaining); + log_debug("--------At time: %u, flushed spikes: %u", time, spikes_remaining); } } +#endif } //! \brief Called when a multicast packet is received @@ -572,15 +571,17 @@ void spike_processing_get_and_reset_pipeline_restarts_this_tick(void) { pipeline_restarts = 0; } -//uint32_t spike_processing_get_pipeline_deactivation_time(){ -// return spike_pipeline_deactivation_time; -//} -// -//// FLUSH SPIKES -//uint32_t spike_processing_get_total_flushed_spikes(){ -// return total_flushed_spikes; -//} -// -//uint32_t spike_processing_get_max_flushed_spikes(){ -// return max_flushed_spikes; -//} +#if LOG_LEVEL >= LOG_DEBUG +uint32_t spike_processing_get_pipeline_deactivation_time(){ + return spike_pipeline_deactivation_time; +} + +// FLUSHED SPIKES +uint32_t spike_processing_get_total_flushed_spikes(){ + return total_flushed_spikes; +} + +uint32_t spike_processing_get_max_flushed_spikes(){ + return max_flushed_spikes; +} +#endif From 38ea81db525bcf1f1155b698471dd42559a63b99 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 10 Feb 2022 16:22:29 +0000 Subject: [PATCH 066/108] Spike flushing only in debug mode --- neural_modelling/src/common/in_spikes.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/neural_modelling/src/common/in_spikes.h b/neural_modelling/src/common/in_spikes.h index ca9edfd41e3..60887e58ba8 100644 --- a/neural_modelling/src/common/in_spikes.h +++ b/neural_modelling/src/common/in_spikes.h @@ -137,6 +137,7 @@ static inline spike_t in_spikes_value_at_index(uint32_t index) { return circular_buffer_value_at_index(buffer, index); } +#if LOG_LEVEL >= LOG_DEBUG // FLUSH SPIKES static inline uint32_t in_spikes_flush_buffer(void) { @@ -145,4 +146,6 @@ static inline uint32_t in_spikes_flush_buffer(void) { return num_spikes_left; } +#endif + #endif // _IN_SPIKES_H_ From 0e6e96bcd5d1b87d7e04002898da66a4b0937ef8 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 10 Feb 2022 16:44:07 +0000 Subject: [PATCH 067/108] Tidy up and add some documentation --- .../src/neuron/plasticity/stdp/maths.h | 26 ++-------- .../src/neuron/plasticity/stdp/post_events.h | 19 ++++--- .../neuron/plasticity/stdp/stdp_typedefs.h | 2 +- .../stdp/synapse_dynamics_stdp_common.h | 9 ---- .../synapse_dynamics_stdp_mad_mfvn_impl.c | 15 +----- .../synapse_dynamics_stdp_mad_pfpc_impl.c | 27 +--------- .../stdp/timing_dependence/timing_mfvn_impl.c | 4 -- .../stdp/timing_dependence/timing_mfvn_impl.h | 15 ------ .../stdp/timing_dependence/timing_pfpc_impl.c | 3 -- .../stdp/timing_dependence/timing_pfpc_impl.h | 49 ------------------- .../stdp/weight_dependence/weight_mfvn_impl.h | 41 +--------------- .../stdp/weight_dependence/weight_pfpc_impl.c | 1 - .../stdp/weight_dependence/weight_pfpc_impl.h | 37 +------------- neural_modelling/src/neuron/send_spike.h | 2 +- .../src/neuron/spike_processing.h | 28 ++++++----- 15 files changed, 35 insertions(+), 243 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/maths.h b/neural_modelling/src/neuron/plasticity/stdp/maths.h index 78a6e5dd219..51bc5e12124 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/maths.h +++ b/neural_modelling/src/neuron/plasticity/stdp/maths.h @@ -74,22 +74,6 @@ static inline int16_lut *maths_copy_int16_lut(address_t *address) { return lut; } -////--------------------------------------- -//// Plasticity maths function inline implementation -////--------------------------------------- -//static inline address_t maths_copy_int16_lut_with_size( -// address_t *start_address, uint32_t num_entries, int16_t *lut) { -// // Pad to number of words -// const uint32_t num_words = -// (num_entries / 2) + (((num_entries & 1) != 0) ? 1 : 0); -// -// // Copy entries to LUT -// spin1_memcpy(lut, start_address, sizeof(int16_t) * num_entries); -// -// // Return address after words -// return start_address + num_words; -//} - //! \brief Get value from lookup table //! \param[in] time: The time that we are mapping //! \param[in] lut: The lookup table (result of maths_copy_int16_lut()) @@ -103,17 +87,17 @@ static inline int32_t maths_lut_exponential_decay( return (lut_index < lut->size) ? lut->values[lut_index] : 0; } +//! \brief Get value from lookup table, time shifted +//! \param[in] time: The time that we are mapping +//! \param[in] time_shift: The time shift value +//! \param[in] lut: The lookup table (result of maths_copy_int16_lut()) +//! \return The value from the LUT, or zero if out of range static inline int32_t maths_lut_exponential_decay_time_shifted( const uint32_t time, const uint32_t time_shift, const int16_lut *lut) { - - // uint32_t time, const uint32_t time_shift, const uint32_t lut_size, - // const int16_t *lut) { - // Calculate lut index uint32_t lut_index = (time >> lut->shift) >> time_shift; // Return value from LUT -// return (lut_index < lut_size) ? lut[lut_index] : 0; return (lut_index < lut->size) ? lut->values[lut_index] : 0; } diff --git a/neural_modelling/src/neuron/plasticity/stdp/post_events.h b/neural_modelling/src/neuron/plasticity/stdp/post_events.h index 996b598be70..12edf6a44e1 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/post_events.h +++ b/neural_modelling/src/neuron/plasticity/stdp/post_events.h @@ -66,7 +66,7 @@ typedef struct { // Inline functions //--------------------------------------- -//#if LOG_LEVEL >= LOG_DEBUG +#if LOG_LEVEL >= LOG_DEBUG //! \brief Print a post-synaptic event history //! \param[in] events: The history static inline void print_event_history(const post_event_history_t *events) { @@ -76,7 +76,7 @@ static inline void print_event_history(const post_event_history_t *events) { i, events->times[i], events->traces[i]); } } -//#endif +#endif //! \brief Initialise an array of post-synaptic event histories //! \param[in] n_neurons: Number of neurons @@ -84,14 +84,12 @@ static inline void print_event_history(const post_event_history_t *events) { static inline post_event_history_t *post_events_init_buffers( uint32_t n_neurons) { post_event_history_t *post_event_history = - (post_event_history_t*) spin1_malloc( - n_neurons * sizeof(post_event_history_t)); + spin1_malloc(n_neurons * sizeof(post_event_history_t)); // Check allocations succeeded if (post_event_history == NULL) { - log_error( - "Unable to allocate global STDP structures - Out of DTCM: Try " - "reducing the number of neurons per core to fix this problem "); + log_error("Unable to allocate global STDP structures - Out of DTCM: Try " + "reducing the number of neurons per core to fix this problem "); return NULL; } @@ -170,8 +168,10 @@ static inline post_event_window_t post_events_next( } -// TODO This function is removed in master. Does this still serve any purpose? -//--------------------------------------- +//! \brief Advance a post-synaptic event window to the next (delayed) event +//! \param[in] window: The window to advance +//! \param[in] delayed_time: The delayed time +//! \return the advanced window static inline post_event_window_t post_events_next_delayed( post_event_window_t window, uint32_t delayed_time) { @@ -201,7 +201,6 @@ static inline void post_events_add( events->times[new_index] = time; events->traces[new_index] = trace; } else { - // Otherwise Shuffle down elements // **NOTE** 1st element is always an entry at time 0 for (uint32_t e = 2; e < MAX_POST_SYNAPTIC_EVENTS; e++) { diff --git a/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h b/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h index 393e21f1403..df98303dbb4 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h +++ b/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h @@ -38,7 +38,7 @@ //! \return The product #define STDP_FIXED_MUL_16X16(a, b) maths_fixed_mul16(a, b, STDP_FIXED_POINT) -#define print_plasticity false // true +#define print_plasticity false //! The amount of right shift required to take a weight from s1615 format //! to STDP_FIXED_POINT format (s4,11) diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_common.h b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_common.h index 99add85a5f0..cd03627f916 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_common.h +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_common.h @@ -67,15 +67,6 @@ //--------------------------------------- // Structures //--------------------------------------- -////! \brief The type of history data of pre-events -////! -////! This data is stored in SDRAM in the plastic part of the synaptic matrix -//typedef struct { -// //! The event time -// uint32_t prev_time; -// //! The event trace -// pre_trace_t prev_trace; -//} pre_event_history_t; //! The type of configuration parameters in SDRAM (written by host) typedef struct stdp_params { diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c index 2b2a21063fa..52ec565e9fd 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c @@ -81,8 +81,6 @@ static inline final_state_t plasticity_update_synapse( io_printf(IO_BUF, " Printing PC history\n"); print_event_history(post_event_history); } -// print_delayed_window_events(post_event_history, window_begin_time, -// window_end_time, delay_dendritic); if (print_plasticity){ io_printf(IO_BUF, "\n############ Phase 1 #############\n"); @@ -255,9 +253,7 @@ static inline plastic_synapse_t process_plastic_synapse( // Update the synapse state uint32_t post_delay = s.delay_dendritic; -// if (!params.backprop_delay) { -// post_delay = 0; -// } + final_state_t final_state = plasticity_update_synapse( time, last_pre_time, last_pre_trace, new_pre_trace, post_delay, s.delay_axonal, current_state, @@ -281,20 +277,12 @@ bool synapse_dynamics_process_plastic_synapses( // Extract separate arrays of plastic synapses (from plastic region), // Control words (from fixed region) and number of plastic synapses -// plastic_synapse_t *plastic_words = _plastic_synapses( -// plastic_region_address); plastic_synapse_t *plastic_words = plastic_region_address->synapses; const control_t *control_words = synapse_row_plastic_controls(fixed_region); size_t n_plastic_synapses = synapse_row_num_plastic_controls(fixed_region); num_plastic_pre_synaptic_events += n_plastic_synapses; - // Get event history from synaptic row -// pre_event_history_t *event_history = _plastic_event_history( -// plastic_region_address); -// pre_event_history_t *event_history = plastic_region_address->history; - - // Get last pre-synaptic event from event history // Get last pre-synaptic event from event history const uint32_t recorded_spikes_minus_one = plastic_region_address->history.num_recorded_mf_spikes_minus_one; @@ -304,7 +292,6 @@ bool synapse_dynamics_process_plastic_synapses( // no longer need to manage this trace const pre_trace_t last_pre_trace = 0; - // add pre spike to struct capturing pre synaptic event history // NOTE: this uses the post_event_history_t handling code post_events_add(time, &plastic_region_address->history, 0); diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c index 7b7848134a9..b7503f8617e 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c @@ -39,14 +39,6 @@ struct synapse_row_plastic_data_t { plastic_synapse_t synapses[]; }; -//--------------------------------------- -// Structures -//--------------------------------------- -//typedef struct { -// pre_trace_t prev_trace; -// uint32_t prev_time; -//} pre_event_history_t; - void _print_pre_event_history(pre_event_history_t pre_eve_hist){ io_printf(IO_BUF, "\n\n************************\n\n"); @@ -91,9 +83,6 @@ static inline final_state_t plasticity_update_synapse( print_event_history(post_event_history); } -// print_delayed_window_events(post_event_history, window_begin_time, -// window_end_time, delay_dendritic); - if (print_plasticity){ io_printf(IO_BUF, "\n Looping over climbing fibre spikes:\n"); } @@ -112,10 +101,6 @@ static inline final_state_t plasticity_update_synapse( delayed_post_time); } -// // Get window of pf events based on cf spikes -// print_delayed_window_events(pre_event_history, -// //(delayed_post_time-255) -// pf_begin_time, delayed_post_time, delay_dendritic); post_event_window_t pre_window = post_events_get_window_delayed( pre_event_history, pf_begin_time, delayed_post_time); @@ -233,9 +218,7 @@ static inline plastic_synapse_t process_plastic_synapse( // Update the synapse state uint32_t post_delay = s.delay_dendritic; -// if (!params.backprop_delay) { -// post_delay = 0; -// } + final_state_t final_state = plasticity_update_synapse( time, last_pre_time, last_pre_trace, new_pre_trace, post_delay, s.delay_axonal, current_state, @@ -255,19 +238,12 @@ bool synapse_dynamics_process_plastic_synapses( // Extract separate arrays of plastic synapses (from plastic region), // Control words (from fixed region) and number of plastic synapses -// plastic_synapse_t *plastic_words = _plastic_synapses( -// plastic_region_address); plastic_synapse_t *plastic_words = plastic_region_address->synapses; const control_t *control_words = synapse_row_plastic_controls(fixed_region); size_t n_plastic_synapses = synapse_row_num_plastic_controls(fixed_region); num_plastic_pre_synaptic_events += n_plastic_synapses; - // Get event history from synaptic row -// pre_event_history_t *event_history = plastic_region_address->history; -// _plastic_event_history( -// plastic_region_address); - // Get last pre-synaptic event from event history const uint32_t recorded_spikes_minus_one = plastic_region_address->history.num_recorded_pf_spikes_minus_one; @@ -282,7 +258,6 @@ bool synapse_dynamics_process_plastic_synapses( post_events_add(time, &plastic_region_address->history, 0); // Update pre-synaptic trace - if (print_plasticity){ io_printf(IO_BUF, "\nAdding pre-synaptic event (parallel fibre spike) at time: %u\n\n", time); } diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c index 379ba032c24..a43c1135a36 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c @@ -21,7 +21,6 @@ // Globals //--------------------------------------- // Exponential lookup-tables -//int16_t exp_cos_lookup[EXP_COS_LUT_SIZE]; int16_lut *exp_cos_lookup; //--------------------------------------- @@ -31,11 +30,8 @@ address_t timing_initialise(address_t address) { io_printf(IO_BUF, "timing_mfvn_initialise: starting\n"); io_printf(IO_BUF, "\tCerebellum MFVN rule\n"); - // **TODO** assert number of neurons is less than max // Copy LUTs from following memory -// address_t lut_address = maths_copy_int16_lut_with_size( -// &address[0], EXP_COS_LUT_SIZE, &exp_cos_lookup[0]); address_t lut_address = address; exp_cos_lookup = maths_copy_int16_lut(&lut_address); diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h index 322092b5edd..8a6765d4f57 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h @@ -40,7 +40,6 @@ typedef int16_t pre_trace_t; //--------------------------------------- // Exponential decay lookup parameters #define TAU_PLUS_TIME_SHIFT 0 -//#define EXP_COS_LUT_SIZE 256 //--------------------------------------- // Timing dependence inline functions @@ -70,19 +69,11 @@ static inline post_trace_t timing_add_post_spike( if (print_plasticity){ io_printf(IO_BUF, "Adding pre spike to event history (from vestibular nuclei)\n"); } -// // Get time since last spike -// uint32_t delta_time = time - last_time; - -// // Decay previous o1 and o2 traces -// int32_t decayed_o1_trace = STDP_FIXED_MUL_16X16(last_trace, -// DECAY_LOOKUP_TAU_MINUS(delta_time)); // Add energy caused by new spike to trace // **NOTE** o2 trace is pre-multiplied by a3_plus int32_t new_o1_trace = 0; //decayed_o1_trace + STDP_FIXED_POINT_ONE; -// log_debug("\tdelta_time=%d, o1=%d\n", delta_time, new_o1_trace); - // Return new pre- synaptic event with decayed trace values with energy // for new spike added return (post_trace_t) new_o1_trace; @@ -142,14 +133,8 @@ static inline update_state_t timing_apply_post_spike( } if (time_since_last_pre < 255){ -// int32_t multiplier = EXP_COS_LOOKUP(time_since_last_pre); -// int32_t multiplier = STDP_FIXED_MUL_16X16(last_pre_trace, -// maths_lut_exponential_decay_time_shifted( -// time_since_last_pre, TAU_PLUS_TIME_SHIFT, exp_cos_lookup)); int32_t multiplier = maths_lut_exponential_decay_time_shifted( time_since_last_pre, TAU_PLUS_TIME_SHIFT, exp_cos_lookup); -// int32_t multiplier = STDP_FIXED_MUL_16X16(last_pre_trace, -// maths_lut_exponential_decay(time_since_last_pre, exp_cos_lookup)); if (print_plasticity){ io_printf(IO_BUF, "multiplier: %k (fixed = %u)\n", multiplier << 4, multiplier); diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c index d94161400db..efbf2d764f3 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c @@ -21,7 +21,6 @@ // Globals //--------------------------------------- // Exponential lookup-tables -//int16_t exp_sin_lookup[EXP_SIN_LUT_SIZE]; int16_lut *exp_sin_lookup; //--------------------------------------- @@ -33,8 +32,6 @@ address_t timing_initialise(address_t address) { io_printf(IO_BUF, "\tCerebellum PFPC rule\n"); // Copy LUTs from following memory -// address_t lut_address = maths_copy_int16_lut_with_size( -// &address[0], EXP_SIN_LUT_SIZE, &exp_sin_lookup[0]); address_t lut_address = address; exp_sin_lookup = maths_copy_int16_lut(&lut_address); diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index d2306d3430f..81897d35c60 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -40,7 +40,6 @@ typedef int16_t pre_trace_t; //--------------------------------------- // Exponential decay lookup parameters #define TAU_PLUS_TIME_SHIFT 0 -//#define EXP_SIN_LUT_SIZE 256 //--------------------------------------- // Timing dependence inline functions @@ -71,19 +70,10 @@ static inline post_trace_t timing_add_post_spike( io_printf(IO_BUF, "Adding climbing fibre spike to post-event history (stored on neuron\n"); } -// // Get time since last spike -// uint32_t delta_time = time - last_time; - -// // Decay previous o1 and o2 traces -// int32_t decayed_o1_trace = STDP_FIXED_MUL_16X16(last_trace, -// DECAY_LOOKUP_TAU_MINUS(delta_time)); - // Add energy caused by new spike to trace // **NOTE** o2 trace is pre-multiplied by a3_plus int32_t new_o1_trace = 0; //decayed_o1_trace + STDP_FIXED_POINT_ONE; -// log_debug("\tdelta_time=%d, o1=%d\n", delta_time, new_o1_trace); - // Return new pre- synaptic event with decayed trace values with energy // for new spike added return (post_trace_t) new_o1_trace; @@ -117,28 +107,6 @@ static inline update_state_t timing_apply_pre_spike( } return weight_one_term_apply_potentiation(previous_state, 0); -// -// // Get time of event relative to last post-synaptic event -// uint32_t time_since_last_post = time - last_post_time; -// if (time_since_last_post > 0) { -// int32_t decayed_o1 = STDP_FIXED_MUL_16X16( -// last_post_trace, DECAY_LOOKUP_TAU_MINUS(time_since_last_post)); -// -// log_debug("\t\t\ttime_since_last_post_event=%u, decayed_o1=%d\n", -// time_since_last_post, decayed_o1); -// -// // Apply depression to state (which is a weight_state) -// return weight_one_term_apply_depression(previous_state, decayed_o1); -// -// -// -// -// -// -// -// } else { -// return previous_state; -// } } //--------------------------------------- @@ -164,14 +132,8 @@ static inline update_state_t timing_apply_post_spike( } if (time_since_last_pre < 255){ -// int32_t multiplier = EXP_SIN_LOOKUP(time_since_last_pre); -// int32_t multiplier = STDP_FIXED_MUL_16X16(last_pre_trace, -// maths_lut_exponential_decay_time_shifted( -// time_since_last_pre, TAU_PLUS_TIME_SHIFT, exp_sin_lookup)); int32_t multiplier = maths_lut_exponential_decay_time_shifted( time_since_last_pre, TAU_PLUS_TIME_SHIFT, exp_sin_lookup); -// int32_t multiplier = STDP_FIXED_MUL_16X16(last_pre_trace, -// maths_lut_exponential_decay(time_since_last_pre, exp_sin_lookup)); if (print_plasticity){ io_printf(IO_BUF, "multiplier: %k (fixed = %u)\n", multiplier << 4, multiplier); @@ -185,18 +147,7 @@ static inline update_state_t timing_apply_post_spike( io_printf(IO_BUF, " out of LUT range (do nothing)"); } -// if (time_since_last_pre > 0) { -// int32_t decayed_r1 = STDP_FIXED_MUL_16X16( -// last_pre_trace, DECAY_LOOKUP_TAU_PLUS(time_since_last_pre)); -// -// log_debug("\t\t\ttime_since_last_pre_event=%u, decayed_r1=%d\n", -// time_since_last_pre, decayed_r1); -// -// // Apply potentiation to state (which is a weight_state) -// return weight_one_term_apply_potentiation(previous_state, decayed_r1); -// } else { return previous_state; - //} } #endif // _TIMING_PFPC_IMPL_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h index 5ac3a4c5e41..d460026dbba 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h @@ -39,9 +39,6 @@ typedef struct { typedef struct { accum weight; -// int32_t a2_plus; -// int32_t a2_minus; - uint32_t weight_shift; const plasticity_weight_region_data_t *weight_region; } weight_state_t; @@ -77,18 +74,7 @@ static inline weight_state_t weight_one_term_apply_depression( io_printf(IO_BUF, " Weight prior to depression: %u\n", state.weight); } - // Calculate scale - // **NOTE** this calculation must be done at runtime-defined weight - // fixed-point format -// int32_t scale = maths_fixed_mul16( -// state.weight - state.weight_region->min_weight, -//// state.weight_region->a2_minus, -// depression_multiplier, -// state.weight_multiply_right_shift); - - // Multiply scale by depression and subtract - // **NOTE** using standard STDP fixed-point format handles format conversion -// state.weight -= STDP_FIXED_MUL_16X16(state.weight, depression_multiplier); + // Multiply by depression and subtract state.weight -= mul_accum_fixed(state.weight, depression_multiplier); state.weight = kbits(MAX(bitsk(state.weight), bitsk(state.weight_region->min_weight))); @@ -110,7 +96,6 @@ static inline weight_state_t weight_one_term_apply_potentiation( state.weight_region->a2_plus); } -// state.a2_plus += state.weight_region->a2_plus; state.weight += state.weight_region->a2_plus; state.weight = kbits(MIN(bitsk(state.weight), bitsk(state.weight_region->max_weight))); @@ -122,31 +107,7 @@ static inline weight_t weight_get_final(weight_state_t new_state) { log_debug("\tnew_weight:%d\n", new_state.weight); - // first do Depression (as this would have happened first) - -// // Now do potentiation (check against lower limit) -// int32_t scaled_a2_plus = STDP_FIXED_MUL_16X16( -// new_state.a2_plus, new_state.weight_region->a2_plus); - - -// // Apply all terms to initial weight -// int32_t new_weight = new_state.weight + new_state.a2_plus; -// // - scaled_a2_minus; -// -// // Clamp new weight -// new_weight = MIN(new_state.weight_region->max_weight, -// new_weight); -// -// if (print_plasticity){ -// io_printf(IO_BUF, " old weight: %u, new weight: %u\n", -// new_state.weight, new_weight); -// } -// -// new_state.weight = new_weight; -// -// return (weight_t) new_state.weight; return (weight_t) (bitsk(new_state.weight) >> new_state.weight_shift); - } static inline void weight_decay(weight_state_t *state, int32_t decay) { diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c index 8ac98967299..76f7a983a72 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c @@ -43,7 +43,6 @@ address_t weight_initialise( // Copy plasticity region data from address // **NOTE** this seems somewhat safer than relying on sizeof - plasticity_weight_region_data_t *dtcm_copy = plasticity_weight_region_data = spin1_malloc(sizeof(plasticity_weight_region_data_t) * n_synapse_types); diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h index b8514e789e1..e104d64a2ee 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h @@ -39,9 +39,6 @@ typedef struct { typedef struct { accum weight; -// int32_t a2_plus; -// int32_t a2_minus; - uint32_t weight_shift; const plasticity_weight_region_data_t *weight_region; } weight_state_t; @@ -75,16 +72,7 @@ static inline weight_state_t weight_one_term_apply_depression( io_printf(IO_BUF, " Weight prior to depression: %u\n", state.weight); } - // Calculate scale - // **NOTE** this calculation must be done at runtime-defined weight - // fixed-point format -// int32_t scale = maths_fixed_mul16( -// state.weight - state.weight_region->min_weight, -//// state.weight_region->a2_minus, -// depression_multiplier, -// state.weight_multiply_right_shift); - - // Multiply scale by depression and subtract + // Multiply by depression and subtract // **NOTE** using standard STDP fixed-point format handles format conversion state.weight -= mul_accum_fixed(state.weight, depression_multiplier); state.weight = kbits(MAX(bitsk(state.weight), bitsk(state.weight_region->min_weight))); @@ -100,7 +88,6 @@ static inline weight_state_t weight_one_term_apply_potentiation( weight_state_t state, int32_t potentiation) { use(potentiation); // add fixed amount -// state.a2_plus += state.weight_region->a2_plus; state.weight += state.weight_region->a2_plus; state.weight = kbits(MIN(bitsk(state.weight), bitsk(state.weight_region->max_weight))); @@ -111,28 +98,6 @@ static inline weight_state_t weight_one_term_apply_potentiation( static inline weight_t weight_get_final(weight_state_t new_state) { log_debug("\tnew_weight:%d\n", new_state.weight); - // first do Depression (as this would have happened first) - -// // Now do potentiation (check against lower limit) -// int32_t scaled_a2_plus = STDP_FIXED_MUL_16X16( -// new_state.a2_plus, new_state.weight_region->a2_plus); - - - // Apply all terms to initial weight -// int32_t new_weight = new_state.weight + new_state.a2_plus; - // - scaled_a2_minus; -// if (print_plasticity){ -// io_printf(IO_BUF, " old weight: %u, new weight: %u\n", -// new_state.weight, new_weight); -// } - - // Clamp new weight -// new_weight = MIN(new_state.weight_region->max_weight, -// new_weight); -// -// new_state.weight = new_weight; - -// return (weight_t) new_state.weight; return (weight_t) (bitsk(new_state.weight) >> new_state.weight_shift); } diff --git a/neural_modelling/src/neuron/send_spike.h b/neural_modelling/src/neuron/send_spike.h index 4f81d4c95ef..67bb96cac5d 100644 --- a/neural_modelling/src/neuron/send_spike.h +++ b/neural_modelling/src/neuron/send_spike.h @@ -61,7 +61,7 @@ static inline void send_spike_mc(uint32_t key) { //! \param[in] timer_count The global timer count when the time step started //! \param[in] time The current time step //! \param[in] The neuron index to send -static inline void send_spike(UNUSED uint32_t timer_count, UNUSED uint32_t time, +static inline void send_spike(UNUSED uint32_t timer_count, uint32_t time, uint32_t neuron_index) { // Do any required synapse processing synapse_dynamics_process_post_synaptic_event(time, neuron_index); diff --git a/neural_modelling/src/neuron/spike_processing.h b/neural_modelling/src/neuron/spike_processing.h index 1ecb4eb032f..1a424593e74 100644 --- a/neural_modelling/src/neuron/spike_processing.h +++ b/neural_modelling/src/neuron/spike_processing.h @@ -99,18 +99,20 @@ void spike_processing_get_and_reset_dmas_this_tick(void); //! \return uint32_t number of pipeline restarts void spike_processing_get_and_reset_pipeline_restarts_this_tick(void); -////! \brief get time from T1 clock at which spike pipeline completed -////! \return uint32_t pipeline deactivation time -//uint32_t spike_processing_get_pipeline_deactivation_time(); -// -//// FLUSH SPIKES -////! \brief returns the total unprocessed spikes from a simulation -////! \return total unprocessed spikes -//uint32_t spike_processing_get_total_flushed_spikes(); -// -////! \brief returns the maximum unprocessed spikes from a single -////! simulation timestep. -////! \return maximum unprocessed spikes from a single timestep. -//uint32_t spike_processing_get_max_flushed_spikes(); +#if LOG_LEVEL >= LOG_DEBUG +//! \brief get time from T1 clock at which spike pipeline completed +//! \return uint32_t pipeline deactivation time +uint32_t spike_processing_get_pipeline_deactivation_time(); + +// FLUSH SPIKES +//! \brief returns the total unprocessed spikes from a simulation +//! \return total unprocessed spikes +uint32_t spike_processing_get_total_flushed_spikes(); + +//! \brief returns the maximum unprocessed spikes from a single +//! simulation timestep. +//! \return maximum unprocessed spikes from a single timestep. +uint32_t spike_processing_get_max_flushed_spikes(); +#endif #endif // _SPIKE_PROCESSING_H_ From 0bf6bc88aef38c122f42922e910b5f86ff94a634 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 11 Feb 2022 14:34:27 +0000 Subject: [PATCH 068/108] Turn tdma back on again --- .../src/spike_source/poisson/spike_source_poisson.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/neural_modelling/src/spike_source/poisson/spike_source_poisson.c b/neural_modelling/src/spike_source/poisson/spike_source_poisson.c index 07ee03974a4..393acff3a9c 100644 --- a/neural_modelling/src/spike_source/poisson/spike_source_poisson.c +++ b/neural_modelling/src/spike_source/poisson/spike_source_poisson.c @@ -725,10 +725,8 @@ static void process_fast_source( if (ssp_params.has_key) { // Send spikes const uint32_t spike_key = ssp_params.key | s_id; - spin1_send_mc_packet( - spike_key, num_spikes, WITH_PAYLOAD); -// tdma_processing_send_packet( -// spike_key, num_spikes, WITH_PAYLOAD, timer_count); + tdma_processing_send_packet( + spike_key, num_spikes, WITH_PAYLOAD, timer_count); } else if (sdram_inputs->address != 0) { input_this_timestep[sdram_inputs->offset + s_id] += sdram_inputs->weights[s_id] * num_spikes; @@ -766,10 +764,8 @@ static void process_slow_source( // if no key has been given, do not send spike to fabric. if (ssp_params.has_key) { // Send package - spin1_send_mc_packet( - ssp_params.key | s_id, 0, NO_PAYLOAD); -// tdma_processing_send_packet( -// ssp_params.key | s_id, count, WITH_PAYLOAD, timer_count); + tdma_processing_send_packet( + ssp_params.key | s_id, count, WITH_PAYLOAD, timer_count); } else if (sdram_inputs->address != 0) { input_this_timestep[sdram_inputs->offset + s_id] += sdram_inputs->weights[s_id] * count; From 20836c8c57cf2eb3939fc05b83ebc09ade096183 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 11 Feb 2022 14:47:17 +0000 Subject: [PATCH 069/108] More tidying up of python code this time --- .../models/neuron/plasticity/stdp/common.py | 28 ------------------- .../timing_dependence_mfvn.py | 8 ------ .../timing_dependence_pfpc.py | 17 ----------- 3 files changed, 53 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py index c6c29ff4871..c98abafbb73 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py @@ -28,30 +28,6 @@ def float_to_fixed(value): """ return int(round(float(value) * STDP_FIXED_POINT_ONE)) -# def float_to_fixed(value, fixed_point_one): -# return int(round(float(value) * float(fixed_point_one))) - - -# def get_lut_provenance( -# pre_population_label, post_population_label, rule_name, entry_name, -# param_name, last_entry): -# # pylint: disable=too-many-arguments -# top_level_name = "{}_{}_STDP_{}".format( -# pre_population_label, post_population_label, rule_name) -# report = False -# if last_entry is not None: -# report = last_entry > 0 -# return ProvenanceDataItem( -# [top_level_name, entry_name], last_entry, report=report, -# message=( -# "The last entry in the STDP exponential lookup table for the {}" -# " parameter of the {} between {} and {} was {} rather than 0," -# " indicating that the lookup table was not big enough at this" -# " timestep and value. Try reducing the parameter value, or" -# " increasing the timestep".format( -# param_name, rule_name, pre_population_label, -# post_population_label, last_entry))) - def get_exp_lut_array(time_step, time_constant, shift=0): """ @@ -80,8 +56,6 @@ def get_exp_lut_array(time_step, time_constant, shift=0): def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, fixed_point_one=STDP_FIXED_POINT_ONE, kernel_scaling=1.0): - # Add this to function arguments in the future - # machine_time_step = 1.0 sin_pwr = 20 # Calculate required time constant @@ -170,8 +144,6 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, fixed_point_one=STDP_FIXED_POINT_ONE, kernel_scaling=1.0): - # Add this to function arguments in the future - # machine_time_step = 1.0 cos_pwr = 2 # Calculate required time constant diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py index 72cab0ff5ef..008d229d3e1 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py @@ -191,14 +191,6 @@ def get_provenance_data(self, synapse_info): f"not big enough at this timestep and value. Try " f"reducing the parameter value, or increasing the " f"timestep.") - # prov_data = list() - # prov_data.append(get_lut_provenance( - # pre_population_label, post_population_label, "MFVNRule", - # "tau_plus_last_entry", "tau_plus", self._tau_plus_last_entry)) - # prov_data.append(get_lut_provenance( - # pre_population_label, post_population_label, "MFVNRule", - # "tau_minus_last_entry", "tau_minus", self._tau_minus_last_entry)) - # return prov_data @overrides(AbstractTimingDependence.get_parameter_names) def get_parameter_names(self): diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index 783e697757e..ef1a39e7e34 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -136,16 +136,7 @@ def write_parameters( "exp_sin LUT generation currently only supports 1ms timesteps") # Write exp_sin lookup table - print("check, tau_plus_data: ", self._tau_plus_data) spec.write_array(self._tau_plus_data) - # self._tau_plus_last_entry = write_pfpc_lut( - # spec, - # peak_time=self._t_peak, - # time_probe=None, - # lut_size=LUT_SIZE, - # shift=0, - # kernel_scaling=self._kernel_scaling - # ) @property def synaptic_structure(self): @@ -190,14 +181,6 @@ def get_provenance_data(self, synapse_info): f"not big enough at this timestep and value. Try " f"reducing the parameter value, or increasing the " f"timestep.") - # prov_data = list() - # prov_data.append(get_lut_provenance( - # pre_population_label, post_population_label, "PFPCRule", - # "tau_plus_last_entry", "tau_plus", self._tau_plus_last_entry)) - # prov_data.append(get_lut_provenance( - # pre_population_label, post_population_label, "PFPCRule", - # "tau_minus_last_entry", "tau_minus", self._tau_minus_last_entry)) - # return prov_data @overrides(AbstractTimingDependence.get_parameter_names) def get_parameter_names(self): From e779fff735463389502629f6a3fbe83ea8571f56 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 25 Feb 2022 15:02:49 +0000 Subject: [PATCH 070/108] Remove unused old structural plasticity code --- .../synapse_dynamics_stdp_mad_mfvn_impl.c | 122 ------------------ .../synapse_dynamics_stdp_mad_pfpc_impl.c | 122 ------------------ 2 files changed, 244 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c index 52ec565e9fd..5c615a8d7c1 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c @@ -414,125 +414,3 @@ bool synapse_dynamics_add_neuron(uint32_t id, synaptic_row_t row, fixed_region->num_plastic++; return true; } - -#if SYNGEN_ENABLED == 1 - -//! \brief Searches the synaptic row for the the connection with the -//! specified post-synaptic ID -//! \param[in] id: the (core-local) ID of the neuron to search for in the -//! synaptic row -//! \param[in] row: the core-local address of the synaptic row -//! \param[out] sp_data: the address of a struct through which to return -//! weight, delay information -//! \return bool: was the search successful? -bool find_plastic_neuron_with_id(uint32_t id, address_t row, - structural_plasticity_data_t *sp_data){ - address_t fixed_region = synapse_row_fixed_region(row); - address_t plastic_region_address = synapse_row_plastic_region(row); - plastic_synapse_t *plastic_words = - _plastic_synapses(plastic_region_address); - control_t *control_words = synapse_row_plastic_controls(fixed_region); - int32_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); - plastic_synapse_t weight; - uint32_t delay; - - // Loop through plastic synapses - bool found = false; - for (; plastic_synapse > 0; plastic_synapse--) { - - // Get next control word (auto incrementing) - weight = *plastic_words++; - uint32_t control_word = *control_words++; - - // Check if index is the one I'm looking for - delay = synapse_row_sparse_delay(control_word, synapse_type_index_bits); - if (synapse_row_sparse_index(control_word, synapse_index_mask)==id) { - found = true; - break; - } - } - - if (found){ - sp_data -> weight = weight; - sp_data -> offset = synapse_row_num_plastic_controls(fixed_region) - - plastic_synapse; - sp_data -> delay = delay; - return true; - } - else{ - sp_data -> weight = -1; - sp_data -> offset = -1; - sp_data -> delay = -1; - return false; - } -} - -//! \brief Remove the entry at the specified offset in the synaptic row -//! \param[in] offset: the offset in the row at which to remove the entry -//! \param[in] row: the core-local address of the synaptic row -//! \return bool: was the removal successful? -bool remove_plastic_neuron_at_offset(uint32_t offset, address_t row){ - address_t fixed_region = synapse_row_fixed_region(row); - plastic_synapse_t *plastic_words = - _plastic_synapses(synapse_row_plastic_region(row)); - control_t *control_words = synapse_row_plastic_controls(fixed_region); - int32_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); - - // Delete weight at offset - plastic_words[offset] = plastic_words[plastic_synapse-1]; - plastic_words[plastic_synapse-1] = 0; - - // Delete control word at offset - control_words[offset] = control_words[plastic_synapse-1]; - control_words[plastic_synapse-1] = 0; - - // Decrement FP - fixed_region[1] = fixed_region[1] - 1; - - return true; -} - -//! ensuring the weight is of the correct type and size -static inline plastic_synapse_t _weight_conversion(uint32_t weight){ - return (plastic_synapse_t)(0xFFFF & weight); -} - -//! packing all of the information into the required plastic control word -static inline control_t _control_conversion(uint32_t id, uint32_t delay, - uint32_t type){ - control_t new_control = - ((delay & ((1<num_plastic++; return true; } - -#if SYNGEN_ENABLED == 1 - -//! \brief Searches the synaptic row for the the connection with the -//! specified post-synaptic ID -//! \param[in] id: the (core-local) ID of the neuron to search for in the -//! synaptic row -//! \param[in] row: the core-local address of the synaptic row -//! \param[out] sp_data: the address of a struct through which to return -//! weight, delay information -//! \return bool: was the search successful? -bool find_plastic_neuron_with_id(uint32_t id, address_t row, - structural_plasticity_data_t *sp_data){ - address_t fixed_region = synapse_row_fixed_region(row); - address_t plastic_region_address = synapse_row_plastic_region(row); - plastic_synapse_t *plastic_words = - _plastic_synapses(plastic_region_address); - control_t *control_words = synapse_row_plastic_controls(fixed_region); - int32_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); - plastic_synapse_t weight; - uint32_t delay; - - // Loop through plastic synapses - bool found = false; - for (; plastic_synapse > 0; plastic_synapse--) { - - // Get next control word (auto incrementing) - weight = *plastic_words++; - uint32_t control_word = *control_words++; - - // Check if index is the one I'm looking for - delay = synapse_row_sparse_delay(control_word, synapse_type_index_bits); - if (synapse_row_sparse_index(control_word, synapse_index_mask)==id) { - found = true; - break; - } - } - - if (found){ - sp_data -> weight = weight; - sp_data -> offset = synapse_row_num_plastic_controls(fixed_region) - - plastic_synapse; - sp_data -> delay = delay; - return true; - } - else{ - sp_data -> weight = -1; - sp_data -> offset = -1; - sp_data -> delay = -1; - return false; - } -} - -//! \brief Remove the entry at the specified offset in the synaptic row -//! \param[in] offset: the offset in the row at which to remove the entry -//! \param[in] row: the core-local address of the synaptic row -//! \return bool: was the removal successful? -bool remove_plastic_neuron_at_offset(uint32_t offset, address_t row){ - address_t fixed_region = synapse_row_fixed_region(row); - plastic_synapse_t *plastic_words = - _plastic_synapses(synapse_row_plastic_region(row)); - control_t *control_words = synapse_row_plastic_controls(fixed_region); - int32_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); - - // Delete weight at offset - plastic_words[offset] = plastic_words[plastic_synapse-1]; - plastic_words[plastic_synapse-1] = 0; - - // Delete control word at offset - control_words[offset] = control_words[plastic_synapse-1]; - control_words[plastic_synapse-1] = 0; - - // Decrement FP - fixed_region[1] = fixed_region[1] - 1; - - return true; -} - -//! ensuring the weight is of the correct type and size -static inline plastic_synapse_t _weight_conversion(uint32_t weight){ - return (plastic_synapse_t)(0xFFFF & weight); -} - -//! packing all of the information into the required plastic control word -static inline control_t _control_conversion(uint32_t id, uint32_t delay, - uint32_t type){ - control_t new_control = - ((delay & ((1< Date: Fri, 25 Feb 2022 15:13:39 +0000 Subject: [PATCH 071/108] No extra fields in this set of provenance any more --- .../models/neuron/population_machine_synapses_provenance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spynnaker/pyNN/models/neuron/population_machine_synapses_provenance.py b/spynnaker/pyNN/models/neuron/population_machine_synapses_provenance.py index eca7a054f8d..9419dce7b71 100644 --- a/spynnaker/pyNN/models/neuron/population_machine_synapses_provenance.py +++ b/spynnaker/pyNN/models/neuron/population_machine_synapses_provenance.py @@ -34,7 +34,7 @@ class SynapseProvenance(ctypes.LittleEndianStructure): # The number of population table hits on INVALID entries ("n_invalid_pop_table_hits", ctypes.c_uint32), # The number of spikes that didn't transfer empty rows - ("n_filtered_by_bitfield", ctypes.c_uint32), + ("n_filtered_by_bitfield", ctypes.c_uint32) ] N_ITEMS = len(_fields_) From d6ff3893401f4f0ae6d387775775823669340f2f Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 25 Feb 2022 15:16:48 +0000 Subject: [PATCH 072/108] remove unnecessary SSP changes --- spynnaker/pyNN/models/spike_source/spike_source_poisson.py | 2 +- .../pyNN/models/spike_source/spike_source_poisson_vertex.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/spynnaker/pyNN/models/spike_source/spike_source_poisson.py b/spynnaker/pyNN/models/spike_source/spike_source_poisson.py index d2bb9e61fd1..c6f084e6da5 100644 --- a/spynnaker/pyNN/models/spike_source/spike_source_poisson.py +++ b/spynnaker/pyNN/models/spike_source/spike_source_poisson.py @@ -18,7 +18,7 @@ from spinn_utilities.overrides import overrides _population_parameters = { - "seed": None, "max_rate": 1000, "splitter": None} + "seed": None, "max_rate": None, "splitter": None} # Technically, this is ~2900 in terms of DTCM, but is timescale dependent # in terms of CPU (2900 at 10 times slow down is fine, but not at diff --git a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py index f5e5e7a42e2..a5faceeb9cf 100644 --- a/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py +++ b/spynnaker/pyNN/models/spike_source/spike_source_poisson_vertex.py @@ -134,8 +134,7 @@ def __init__( self.__n_data_specs = 0 # check for changes parameters - self.__change_requires_mapping = False # True -# self.__change_requires_neuron_parameters_reload = False + self.__change_requires_mapping = True self.__spike_recorder = MultiSpikeRecorder() From 32c6516449a5e4ce9bcc498fca810635a283b153 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Wed, 2 Mar 2022 08:43:56 +0000 Subject: [PATCH 073/108] Add reference to paper for MF-VN and PF-PC implementation --- .../plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c | 4 +++- .../plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c | 5 ++++- .../plasticity/stdp/timing_dependence/timing_mfvn_impl.h | 3 +++ .../plasticity/stdp/timing_dependence/timing_pfpc_impl.h | 3 +++ .../plasticity/stdp/weight_dependence/weight_mfvn_impl.h | 3 +++ .../plasticity/stdp/weight_dependence/weight_pfpc_impl.h | 3 +++ 6 files changed, 19 insertions(+), 2 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c index 5c615a8d7c1..41e60cb91a9 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c @@ -16,7 +16,9 @@ */ //! \file -//! \brief STDP core implementation +//! \brief STDP core implementation for MF-VN STDP rules as defined by e.g. Luque et al 2019 +//! https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1006298 + #include "post_events.h" #include "synapse_dynamics_stdp_common.h" #include "stdp_typedefs.h" diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c index dbfa55f9c6a..08d8d3aa8f2 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c @@ -16,7 +16,10 @@ */ //! \file -//! \brief STDP core implementation +//! \brief STDP implementation for MF-VN STDP rules as defined by e.g. Luque et al 2019 +//! https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1006298 + + #include "post_events.h" #include "synapse_dynamics_stdp_common.h" // sPyNNaker neural modelling includes diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h index 8a6765d4f57..c5514f9e69d 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h @@ -18,6 +18,9 @@ #ifndef _TIMING_MFVN_IMPL_H_ #define _TIMING_MFVN_IMPL_H_ +// MF-VN STDP rules as defined by e.g. Luque et al 2019 +// https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1006298 + //--------------------------------------- // Typedefines //--------------------------------------- diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index 81897d35c60..e073222b0f4 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -18,6 +18,9 @@ #ifndef _TIMING_PFPC_IMPL_H_ #define _TIMING_PFPC_IMPL_H_ +// PF-PC STDP rules as defined by e.g. Luque et al 2019 +// https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1006298 + //--------------------------------------- // Typedefines //--------------------------------------- diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h index d460026dbba..11c22f811b5 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h @@ -18,6 +18,9 @@ #ifndef _WEIGHT_MFVN_IMPL_H_ #define _WEIGHT_MFVN_IMPL_H_ +// MF-VN STDP rules as defined by e.g. Luque et al 2019 +// https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1006298 + // Include generic plasticity maths functions #include #include diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h index e104d64a2ee..f22cf63899c 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h @@ -18,6 +18,9 @@ #ifndef _WEIGHT_PFPC_IMPL_H_ #define _WEIGHT_PFPC_IMPL_H_ +// PF-PC STDP rules as defined by e.g. Luque et al 2019 +// https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1006298 + // Include generic plasticity maths functions #include #include From de67a3e43d3006c26e7835a151303a1d7caa151b Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 17 Jun 2022 11:30:26 +0100 Subject: [PATCH 074/108] Add current source argument to state update; reduce large binaries --- .../Makefile | 2 +- .../Makefile | 2 +- .../src/neuron/models/neuron_model_lif_t_last_impl.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_stdp_mad_nearest_pair_additive_structural_last_neuron_distance_weight/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_stdp_mad_nearest_pair_additive_structural_last_neuron_distance_weight/Makefile index a6556cca292..1a0af504a9b 100644 --- a/neural_modelling/makefiles/neuron/IF_cond_exp_stdp_mad_nearest_pair_additive_structural_last_neuron_distance_weight/Makefile +++ b/neural_modelling/makefiles/neuron/IF_cond_exp_stdp_mad_nearest_pair_additive_structural_last_neuron_distance_weight/Makefile @@ -17,7 +17,7 @@ APP = $(notdir $(CURDIR)) NEURON_MODEL = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.c NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.h INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_conductance.h -CURRENT_SOURCE_H = $(NEURON_DIR)/neuron/current_sources/current_source_stepnoisy_impl.h +CURRENT_SOURCE_H = $(NEURON_DIR)/neuron/current_sources/current_source_step_only_impl.h NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h SYNAPSE_TYPE_H = $(NEURON_DIR)/neuron/synapse_types/synapse_types_exponential_impl.h diff --git a/neural_modelling/makefiles/neuron/IF_curr_exp_stdp_mad_pair_additive_structural_random_distance_weight/Makefile b/neural_modelling/makefiles/neuron/IF_curr_exp_stdp_mad_pair_additive_structural_random_distance_weight/Makefile index 832dda59a84..382293593d1 100644 --- a/neural_modelling/makefiles/neuron/IF_curr_exp_stdp_mad_pair_additive_structural_random_distance_weight/Makefile +++ b/neural_modelling/makefiles/neuron/IF_curr_exp_stdp_mad_pair_additive_structural_random_distance_weight/Makefile @@ -17,7 +17,7 @@ APP = $(notdir $(CURDIR)) NEURON_MODEL = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.c NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.h INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_current.h -CURRENT_SOURCE_H = $(NEURON_DIR)/neuron/current_sources/current_source_noisy_only_impl.h +CURRENT_SOURCE_H = $(NEURON_DIR)/neuron/current_sources/current_source_step_only_impl.h NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h SYNAPSE_TYPE_H = $(NEURON_DIR)/neuron/synapse_types/synapse_types_exponential_impl.h diff --git a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h index 8248a4bcb64..14807e6acb6 100644 --- a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h +++ b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h @@ -87,7 +87,7 @@ static inline void _lif_neuron_closed_form( static state_t neuron_model_state_update( uint16_t num_excitatory_inputs, const input_t *exc_input, uint16_t num_inhibitory_inputs, const input_t *inh_input, - input_t external_bias, neuron_t *restrict neuron) { + input_t external_bias, REAL current_offset, neuron_t *restrict neuron) { log_debug("Exc 1: %12.6k, Exc 2: %12.6k", exc_input[0], exc_input[1]); log_debug("Inh 1: %12.6k, Inh 2: %12.6k", inh_input[0], inh_input[1]); @@ -106,7 +106,7 @@ static state_t neuron_model_state_update( } // Get the input in nA input_t input_this_timestep = - total_exc - total_inh + external_bias + neuron->I_offset; + total_exc - total_inh + external_bias + neuron->I_offset + current_offset; _lif_neuron_closed_form( neuron, neuron->V_membrane, input_this_timestep); From c3710e9b3b0e50cb7ac9ebf4a41a5ded94fd9cf3 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 17 Jun 2022 11:42:02 +0100 Subject: [PATCH 075/108] Move models to correct location --- spynnaker/pyNN/extra_models/__init__.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/spynnaker/pyNN/extra_models/__init__.py b/spynnaker/pyNN/extra_models/__init__.py index ffd25f94566..cd9ba63b78a 100644 --- a/spynnaker/pyNN/extra_models/__init__.py +++ b/spynnaker/pyNN/extra_models/__init__.py @@ -33,10 +33,24 @@ # Variable rate poisson from spynnaker.pyNN.models.spike_source import SpikeSourcePoissonVariable +# ICub VOR imports +from spynnaker.pyNN.models.neuron.builds.if_cond_exp_cerebellum import \ + IFCondExpCerebellum +# Cerebellum Plasticity +from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence import ( + TimingDependencePFPC as TimingDependencePFPC) +from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence import ( + TimingDependenceMFVN as TimingDependenceMFVN) +from spynnaker.pyNN.models.neuron.plasticity.stdp.weight_dependence import ( + WeightDependenceMFVN as WeightDependenceMFVN) +from spynnaker.pyNN.models.neuron.plasticity.stdp.weight_dependence import ( + WeightDependencePFPC as WeightDependencePFPC) + __all__ = [ # sPyNNaker models not currently part of full pyNN 'IFCurDelta', 'IFCurrExpCa2Adaptive', 'IFCondExpStoc', 'Izhikevich_cond', 'IF_curr_dual_exp', 'IF_curr_exp_sEMD', + "IFCondExpCerebellum", # ICub VOR neuron model # Neuromodulation synapse dynamics (Mantas Mikaitis) 'Neuromodulation', @@ -46,6 +60,8 @@ 'PfisterSpikeTriplet', 'SpikeNearestPairRule', 'RecurrentRule', 'Vogels2011Rule', + "TimingDependencePFPC", "WeightDependencePFPC", # ICub VOR + 'TimingDependenceMFVN', 'WeightDependenceMFVN', # ICub VOR # Variable rate Poisson 'SpikeSourcePoissonVariable'] From ee468b4317f0f750b043a2106edf4dbcfaceaf23 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 11 Jul 2022 12:06:25 +0100 Subject: [PATCH 076/108] missed in merge --- .../splitter_components/splitter_abstract_pop_vertex_fixed.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spynnaker/pyNN/extra_algorithms/splitter_components/splitter_abstract_pop_vertex_fixed.py b/spynnaker/pyNN/extra_algorithms/splitter_components/splitter_abstract_pop_vertex_fixed.py index 02b8caf003c..dec1d640b32 100644 --- a/spynnaker/pyNN/extra_algorithms/splitter_components/splitter_abstract_pop_vertex_fixed.py +++ b/spynnaker/pyNN/extra_algorithms/splitter_components/splitter_abstract_pop_vertex_fixed.py @@ -89,14 +89,14 @@ def create_machine_vertices(self, chip_counter): print("Using given values for RB left shifts.") ring_buffer_shifts = app_vertex.rb_left_shifts print("RB left shifts for {:20}".format(app_vertex.label), - "=", self.__ring_buffer_shifts) + "=", ring_buffer_shifts) print("-" * 80) else: print("=" * 80) print("Computing RB left shifts for", app_vertex.label) ring_buffer_shifts = app_vertex.get_ring_buffer_shifts(projections) print("RB left shifts for {:20}".format(app_vertex.label), - "=", self.__ring_buffer_shifts) + "=", ring_buffer_shifts) weight_scales = app_vertex.get_weight_scales(ring_buffer_shifts) all_syn_block_sz = app_vertex.get_synapses_size( From 540e066489f0fcc85886aa8e95840eafdf4f24dd Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 11 Jul 2022 12:29:07 +0100 Subject: [PATCH 077/108] reduce binary size --- .../Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neural_modelling/makefiles/neuron/IF_curr_exp_stdp_mad_pair_additive_structural_random_distance_weight/Makefile b/neural_modelling/makefiles/neuron/IF_curr_exp_stdp_mad_pair_additive_structural_random_distance_weight/Makefile index 382293593d1..fc9ace5af26 100644 --- a/neural_modelling/makefiles/neuron/IF_curr_exp_stdp_mad_pair_additive_structural_random_distance_weight/Makefile +++ b/neural_modelling/makefiles/neuron/IF_curr_exp_stdp_mad_pair_additive_structural_random_distance_weight/Makefile @@ -17,7 +17,7 @@ APP = $(notdir $(CURDIR)) NEURON_MODEL = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.c NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.h INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_current.h -CURRENT_SOURCE_H = $(NEURON_DIR)/neuron/current_sources/current_source_step_only_impl.h +CURRENT_SOURCE_H = $(NEURON_DIR)/neuron/current_sources/current_source_dc_only_impl.h NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h SYNAPSE_TYPE_H = $(NEURON_DIR)/neuron/synapse_types/synapse_types_exponential_impl.h From 351c3f56914447da66019beaf6a7bdada155c539 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 29 Jul 2022 13:34:50 +0100 Subject: [PATCH 078/108] If SSP is being controlled from another vertex then add control edge --- spynnaker/pyNN/spynnaker_external_device_plugin_manager.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spynnaker/pyNN/spynnaker_external_device_plugin_manager.py b/spynnaker/pyNN/spynnaker_external_device_plugin_manager.py index ef5a5674412..3fbc8c62f3d 100644 --- a/spynnaker/pyNN/spynnaker_external_device_plugin_manager.py +++ b/spynnaker/pyNN/spynnaker_external_device_plugin_manager.py @@ -25,6 +25,7 @@ from spynnaker.pyNN.utilities.constants import ( LIVE_POISSON_CONTROL_PARTITION_ID, SPIKE_PARTITION_ID) from spynnaker.pyNN.models.populations import Population +from spynnaker.pyNN.models.spike_source import SpikeSourcePoissonVertex class SpynnakerExternalDevicePluginManager(object): @@ -174,8 +175,10 @@ def activate_live_output_to( # pylint: disable=protected-access if isinstance(device, Population): device_vertex = device._vertex - SpynnakerExternalDevicePluginManager.add_edge( + edge = SpynnakerExternalDevicePluginManager.add_edge( population._vertex, device_vertex, partition_id) + if isinstance(device_vertex, SpikeSourcePoissonVertex): + device_vertex.set_live_poisson_control_edge(edge) @staticmethod def update_live_packet_gather_tracker( From 96e7e75d142f076ddc719539f56e629c8ba85caa Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Wed, 3 Aug 2022 14:25:05 +0100 Subject: [PATCH 079/108] circular_buffer size is 2^n-1, not 2^n; also modify while condition --- .../src/spike_source/poisson/spike_source_poisson.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neural_modelling/src/spike_source/poisson/spike_source_poisson.c b/neural_modelling/src/spike_source/poisson/spike_source_poisson.c index 49977d9a197..55752d2ab1a 100644 --- a/neural_modelling/src/spike_source/poisson/spike_source_poisson.c +++ b/neural_modelling/src/spike_source/poisson/spike_source_poisson.c @@ -598,7 +598,7 @@ static bool initialize(void) { // Allocate buffer to allow rate change (2 ints) per source rate_change_buffer = circular_buffer_initialize( - ssp_params.n_spike_sources * 2); + (ssp_params.n_spike_sources * 2) + 1); if (rate_change_buffer == NULL) { log_error("Could not allocate rate change buffer!"); return false; @@ -860,7 +860,7 @@ static void timer_callback(uint timer_count, UNUSED uint unused) { } // Do any rate changes - while (circular_buffer_size(rate_change_buffer) >= 2) { + while (circular_buffer_size(rate_change_buffer) > 0) { uint32_t id = 0; REAL rate = 0.0k; circular_buffer_get_next(rate_change_buffer, &id); From ce0b1336681fefdc7e0b3f0190d9948aa9179d34 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 4 Aug 2022 11:31:37 +0100 Subject: [PATCH 080/108] Match changes --- .../neuron_model_leaky_integrate_and_fire_t_last.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py index 6dd5b8bd975..9392531163b 100644 --- a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py +++ b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py @@ -109,11 +109,6 @@ def __init__( self.__v_reset = v_reset self.__tau_refrac = tau_refrac - @overrides(AbstractNeuronModel.get_n_cpu_cycles) - def get_n_cpu_cycles(self, n_neurons): - # A bit of a guess - return 100 * n_neurons - @overrides(AbstractNeuronModel.add_parameters) def add_parameters(self, parameters): parameters[V_REST] = self.__v_rest From 6a308b9361dbcf28e34e3e8519680d3b82a2a9ac Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 16 Sep 2022 15:16:14 +0100 Subject: [PATCH 081/108] Try to fit standard builds into ITCM --- .../Makefile | 1 + .../makefiles/synapse_only/Makefile | 6 ++-- .../neuron/current_sources/current_source.h | 4 +-- neural_modelling/src/neuron/direct_synapses.c | 4 +-- .../implementations/neuron_impl_standard.h | 3 -- neural_modelling/src/neuron/neuron.c | 2 +- .../population_table_binary_search_impl.c | 36 +++++++++---------- .../src/neuron/spike_processing.c | 2 +- neural_modelling/src/neuron/spike_profiling.h | 24 ++++++------- neural_modelling/src/neuron/synapses.h | 3 +- 10 files changed, 41 insertions(+), 44 deletions(-) diff --git a/neural_modelling/makefiles/neuron/IF_curr_exp_structural_random_distance_weight/Makefile b/neural_modelling/makefiles/neuron/IF_curr_exp_structural_random_distance_weight/Makefile index d4f2145cd46..0e4e0ed29cc 100644 --- a/neural_modelling/makefiles/neuron/IF_curr_exp_structural_random_distance_weight/Makefile +++ b/neural_modelling/makefiles/neuron/IF_curr_exp_structural_random_distance_weight/Makefile @@ -17,6 +17,7 @@ APP = $(notdir $(CURDIR)) NEURON_MODEL = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.c NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.h INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_current.h +CURRENT_SOURCE_H = $(NEURON_DIR)/neuron/current_sources/current_source_dcstepnoisy_impl.h NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h SYNAPSE_TYPE_H = $(NEURON_DIR)/neuron/synapse_types/synapse_types_exponential_impl.h diff --git a/neural_modelling/makefiles/synapse_only/Makefile b/neural_modelling/makefiles/synapse_only/Makefile index ad425c5f558..3d7c768f2f3 100644 --- a/neural_modelling/makefiles/synapse_only/Makefile +++ b/neural_modelling/makefiles/synapse_only/Makefile @@ -23,12 +23,12 @@ MODELS = synapses\ synapses_stdp_mad_vogels_2011_additive\ synapses_structural_random_distance_weight\ synapses_structural_last_neuron_distance_weight\ - synapses_stdp_mad_pair_additive_structural_random_distance_weight\ - synapses_stdp_mad_pair_additive_structural_last_neuron_distance_weight\ synapses_stdp_izhikevich_neuromodulation_pair_additive ifneq ($(SPYNNAKER_DEBUG), DEBUG) - MODELS += synapses_stdp_izhikevich_neuromodulation_pair_additive_structural_random_distance_weight\ + MODELS += synapses_stdp_mad_pair_additive_structural_random_distance_weight\ + synapses_stdp_mad_pair_additive_structural_last_neuron_distance_weight\ + synapses_stdp_izhikevich_neuromodulation_pair_additive_structural_random_distance_weight\ synapses_stdp_izhikevich_neuromodulation_pair_additive_structural_last_neuron_distance_weight endif diff --git a/neural_modelling/src/neuron/current_sources/current_source.h b/neural_modelling/src/neuron/current_sources/current_source.h index 43af1250469..6864e7c471a 100644 --- a/neural_modelling/src/neuron/current_sources/current_source.h +++ b/neural_modelling/src/neuron/current_sources/current_source.h @@ -92,8 +92,8 @@ static bool current_source_initialise(address_t cs_address, uint32_t n_neurons) n_step_sources = (uint32_t) cs_address[next++]; n_noisy_sources = (uint32_t) cs_address[next++]; - log_debug("Check numbers of sources: AC %u DC %u STEP %u NOISY %u", - n_dc_sources, n_ac_sources, n_step_sources, n_noisy_sources); +// log_debug("Check numbers of sources: AC %u DC %u STEP %u NOISY %u", +// n_dc_sources, n_ac_sources, n_step_sources, n_noisy_sources); // Now initialise separate sources #ifdef _CURRENT_SOURCE_DC_H_ diff --git a/neural_modelling/src/neuron/direct_synapses.c b/neural_modelling/src/neuron/direct_synapses.c index 7a02d86a84f..7cb081c8fe7 100644 --- a/neural_modelling/src/neuron/direct_synapses.c +++ b/neural_modelling/src/neuron/direct_synapses.c @@ -54,8 +54,8 @@ bool direct_synapses_initialise( log_error("Not enough memory to allocate direct matrix"); return false; } - log_debug("Copying %u bytes of direct synapses to 0x%08x", - direct_matrix_size, dtcm_copy); +// log_debug("Copying %u bytes of direct synapses to 0x%08x", +// direct_matrix_size, dtcm_copy); spin1_memcpy(dtcm_copy, direct_matrix->data, direct_matrix_size); *direct_synapses_address = dtcm_copy; } diff --git a/neural_modelling/src/neuron/implementations/neuron_impl_standard.h b/neural_modelling/src/neuron/implementations/neuron_impl_standard.h index 06723e7ea17..9aeabe390a8 100644 --- a/neural_modelling/src/neuron/implementations/neuron_impl_standard.h +++ b/neural_modelling/src/neuron/implementations/neuron_impl_standard.h @@ -177,9 +177,6 @@ SOMETIMES_UNUSED // Marked unused as only used sometimes //! \param[in] n_neurons: number of neurons static void neuron_impl_load_neuron_parameters( address_t address, uint32_t next, uint32_t n_neurons) { - log_debug("reading parameters, next is %u, n_neurons is %u ", - next, n_neurons); - // Read the number of steps per timestep n_steps_per_timestep = address[next++]; if (n_steps_per_timestep > 1) { diff --git a/neural_modelling/src/neuron/neuron.c b/neural_modelling/src/neuron/neuron.c index b9ccee8effc..93e1ff7ffdd 100644 --- a/neural_modelling/src/neuron/neuron.c +++ b/neural_modelling/src/neuron/neuron.c @@ -89,7 +89,7 @@ bool neuron_resume(void) { // EXPORTED // (re)load the current source parameters current_source_load_parameters(current_source_address); - log_debug("Resume: neuron_load_neuron_parameters starting"); +// log_debug("Resume: neuron_load_neuron_parameters starting"); return neuron_load_neuron_parameters(); } diff --git a/neural_modelling/src/neuron/population_table/population_table_binary_search_impl.c b/neural_modelling/src/neuron/population_table/population_table_binary_search_impl.c index e7415674a80..94e7038597c 100644 --- a/neural_modelling/src/neuron/population_table/population_table_binary_search_impl.c +++ b/neural_modelling/src/neuron/population_table/population_table_binary_search_impl.c @@ -320,15 +320,15 @@ bool population_table_load_bitfields(filter_region_t *filter_region) { log_debug("Master pop key: 0x%08x, mask: 0x%08x", master_population_table[mp_i].key, master_population_table[mp_i].mask); -#ifdef LOG_DEBUG - // Sanity checking code; not needed in normal operation, and costs ITCM - // With both things being in key order, this should never happen... - if (bf_i < n_filters && - filters[bf_i].key < master_population_table[mp_i].key) { - log_error("Skipping bitfield %d for key 0x%08x", bf_i, filters[bf_i].key); - rt_error(RTE_SWERR); - } -#endif +//#ifdef LOG_DEBUG +// // Sanity checking code; not needed in normal operation, and costs ITCM +// // With both things being in key order, this should never happen... +// if (bf_i < n_filters && +// filters[bf_i].key < master_population_table[mp_i].key) { +// log_error("Skipping bitfield %d for key 0x%08x", bf_i, filters[bf_i].key); +// rt_error(RTE_SWERR); +// } +//#endif // While there is a match, keep track of the start and end; note this // may recheck the first entry, but there might not be a first entry if @@ -336,7 +336,7 @@ bool population_table_load_bitfields(filter_region_t *filter_region) { uint32_t start = bf_i; uint32_t n_words_total = 0; uint32_t useful = 0; - log_debug("Starting with bit field %d with key 0x%08x", bf_i, filters[bf_i].key); +// log_debug("Starting with bit field %d with key 0x%08x", bf_i, filters[bf_i].key); while (bf_i < n_filters && matches(mp_i, filters[bf_i].key)) { log_debug("Using bit field %d with key 0x%08x, merged %d, redundant %d", bf_i, filters[bf_i].key, filters[bf_i].merged, filters[bf_i].all_ones); @@ -487,12 +487,12 @@ bool population_table_get_first_address( master_population_table_entry entry = master_population_table[position]; - #if LOG_LEVEL >= LOG_DEBUG - if (entry.count == 0) { - log_debug("Spike %u (= %x): Population found in master population" - "table but count is 0", spike, spike); - } - #endif +// #if LOG_LEVEL >= LOG_DEBUG +// if (entry.count == 0) { +// log_debug("Spike %u (= %x): Population found in master population" +// "table but count is 0", spike, spike); +// } +// #endif last_spike = spike; next_item = entry.start; @@ -513,12 +513,12 @@ bool population_table_get_first_address( // neuron here. If not return false and avoid the DMA check. if (!bit_field_test( connectivity_bit_field[position], last_neuron_id)) { - log_debug("Tested and was not set"); +// log_debug("Tested and was not set"); bit_field_filtered_packets += 1; items_to_go = 0; return false; } - log_debug("Was set, carrying on"); +// log_debug("Was set, carrying on"); } else { log_debug("Bit field was not set up. " "either its due to a lack of DTCM, or because the " diff --git a/neural_modelling/src/neuron/spike_processing.c b/neural_modelling/src/neuron/spike_processing.c index b5af527a342..2e256ec5079 100644 --- a/neural_modelling/src/neuron/spike_processing.c +++ b/neural_modelling/src/neuron/spike_processing.c @@ -336,7 +336,7 @@ static inline void start_dma_loop(void) { max_flushed_spikes = spikes_remaining; } - log_debug("--------At time: %u, flushed spikes: %u", time, spikes_remaining); +// log_debug("--------At time: %u, flushed spikes: %u", time, spikes_remaining); } } #endif diff --git a/neural_modelling/src/neuron/spike_profiling.h b/neural_modelling/src/neuron/spike_profiling.h index e8f2752ca30..3a5c6b5d2cc 100644 --- a/neural_modelling/src/neuron/spike_profiling.h +++ b/neural_modelling/src/neuron/spike_profiling.h @@ -82,15 +82,15 @@ static inline accum spike_profiling_get_spike_holder_as_accum( return x.acc; } -static inline void spike_profiling_print_spikes_from_spike_holder( - struct spike_holder_t spikes_orig) { - io_printf(IO_BUF, "Spikes from input: a %u, b %u, c %u, d %u \n", - spikes_orig.spikes_a, spikes_orig.spikes_b, spikes_orig.spikes_c, - spikes_orig.spikes_d); -} - -static inline void spike_profiling_print_spikes_from_int(int32_t output) { - io_printf(IO_BUF, "Spikes from output: a %d, b %d, c %d, d %d \n", - (output & 0xFF), (output >> 8 & 0xFF), (output >> 16 & 0xFF), - (output >> 24 & 0xFF)); -} +//static inline void spike_profiling_print_spikes_from_spike_holder( +// struct spike_holder_t spikes_orig) { +// io_printf(IO_BUF, "Spikes from input: a %u, b %u, c %u, d %u \n", +// spikes_orig.spikes_a, spikes_orig.spikes_b, spikes_orig.spikes_c, +// spikes_orig.spikes_d); +//} +// +//static inline void spike_profiling_print_spikes_from_int(int32_t output) { +// io_printf(IO_BUF, "Spikes from output: a %d, b %d, c %d, d %d \n", +// (output & 0xFF), (output >> 8 & 0xFF), (output >> 16 & 0xFF), +// (output >> 24 & 0xFF)); +//} diff --git a/neural_modelling/src/neuron/synapses.h b/neural_modelling/src/neuron/synapses.h index 5408c583e66..25ba234f95b 100644 --- a/neural_modelling/src/neuron/synapses.h +++ b/neural_modelling/src/neuron/synapses.h @@ -52,13 +52,12 @@ extern uint32_t synapse_delay_mask; //! Count of the number of times the synapses have saturated their weights. extern uint32_t synapses_saturation_count; - //! \brief Print the weight of a synapse //! \param[in] weight: the weight to print in synapse-row form //! \param[in] left_shift: the shift to use when decoding static inline void synapses_print_weight( weight_t weight, uint32_t left_shift) { - if (weight != 0) { + if (weight != 0) { io_printf(IO_BUF, "%12.6k", synapse_row_convert_weight_to_input(weight, left_shift)); } else { From 836b5c9b61016a9ef610605be11f87d05478049a Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Tue, 20 Sep 2022 09:20:54 +0100 Subject: [PATCH 082/108] Use a current source impl that exists.. --- .../IF_curr_exp_structural_random_distance_weight/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neural_modelling/makefiles/neuron/IF_curr_exp_structural_random_distance_weight/Makefile b/neural_modelling/makefiles/neuron/IF_curr_exp_structural_random_distance_weight/Makefile index 0e4e0ed29cc..d67c57adfbe 100644 --- a/neural_modelling/makefiles/neuron/IF_curr_exp_structural_random_distance_weight/Makefile +++ b/neural_modelling/makefiles/neuron/IF_curr_exp_structural_random_distance_weight/Makefile @@ -17,7 +17,7 @@ APP = $(notdir $(CURDIR)) NEURON_MODEL = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.c NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.h INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_current.h -CURRENT_SOURCE_H = $(NEURON_DIR)/neuron/current_sources/current_source_dcstepnoisy_impl.h +CURRENT_SOURCE_H = $(NEURON_DIR)/neuron/current_sources/current_source_stepnoisy_impl.h NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h SYNAPSE_TYPE_H = $(NEURON_DIR)/neuron/synapse_types/synapse_types_exponential_impl.h From da5cad3397ca930ed6c6e2df73009be20c34bcd3 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 23 Sep 2022 14:46:25 +0100 Subject: [PATCH 083/108] No argument required here --- .../splitter_abstract_pop_vertex_neurons_synapses.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spynnaker/pyNN/extra_algorithms/splitter_components/splitter_abstract_pop_vertex_neurons_synapses.py b/spynnaker/pyNN/extra_algorithms/splitter_components/splitter_abstract_pop_vertex_neurons_synapses.py index a0dcdb571c8..4b993c36cd3 100644 --- a/spynnaker/pyNN/extra_algorithms/splitter_components/splitter_abstract_pop_vertex_neurons_synapses.py +++ b/spynnaker/pyNN/extra_algorithms/splitter_components/splitter_abstract_pop_vertex_neurons_synapses.py @@ -220,8 +220,7 @@ def create_machine_vertices(self, chip_counter): else: print("=" * 80) print("Computing RB left shifts for", app_vertex.label) - rb_shifts = app_vertex.get_ring_buffer_shifts( - app_vertex.incoming_projections) + rb_shifts = app_vertex.get_ring_buffer_shifts() print("RB left shifts for {:20}".format(app_vertex.label), "=", rb_shifts) From b0502bb713379f40d5ae36f9b8ba9719c92702ee Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Wed, 28 Sep 2022 09:26:29 +0100 Subject: [PATCH 084/108] Refactor code and add test --- .../models/neuron/plasticity/stdp/common.py | 40 +++------------ .../model_tests/neuron/test_plastic_lut.py | 51 +++++++++++++++++++ 2 files changed, 59 insertions(+), 32 deletions(-) create mode 100644 unittests/model_tests/neuron/test_plastic_lut.py diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py index c98abafbb73..7f28f379cb3 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py @@ -15,7 +15,6 @@ import math import numpy -import matplotlib.pyplot as plt # Default value of fixed-point one for STDP STDP_FIXED_POINT_ONE = (1 << 11) @@ -55,7 +54,8 @@ def get_exp_lut_array(time_step, time_constant, shift=0): def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, - fixed_point_one=STDP_FIXED_POINT_ONE, kernel_scaling=1.0): + fixed_point_one=STDP_FIXED_POINT_ONE, kernel_scaling=1.0, + plot=False): sin_pwr = 20 # Calculate required time constant @@ -75,7 +75,7 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, final_exp_fix = [] - for i in range(0, lut_size): # note that i corresponds to 1 timestep!!!!!! + for i in range(0, lut_size): # note that i corresponds to 1 timestep! # Multiply by inverse of time constant value = float(i) * inv_tau @@ -108,18 +108,6 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, out_fixed = numpy.array(out_fixed) out_float = numpy.array(out_float) - plt.plot(t, out_float, label='float') - # plt.plot(t,out_fixed, label='fixed') - plt.legend() - plt.title("pf-PC LUT") - plt.savefig("figures/write_pfpc_lut.png") - - plt.plot(t, out_fixed, label='fixed int16') - plt.legend() - plt.title("pf-PC LUT") - plt.savefig("figures/write_pfpc_lut_final_exp_fix.png") - # plt.show() - compare_t_values = numpy.array([15, 20, 30, 35, 45, 47, 99, 115, 135, 140, 150]) print("LUT VALUES TO COMPARE TO SPINNAKER:") @@ -128,18 +116,15 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, out_float[compare_t_values]): print("{:8} | {:8} | {:8.4f}".format(x, y, z)) - return t, out_float + return compare_t_values, out_float, out_fixed, t else: header = numpy.array([len(final_exp_fix), shift], dtype="uint16") array_to_write = numpy.concatenate(( header, numpy.array(final_exp_fix).astype("uint16"))).view("uint32") # - # spec.write_array(array_to_write) - print("pfpc_lut: ", array_to_write) - print("header: ", header) + spec.write_array(array_to_write) return array_to_write - # spec.write_array(final_exp_fix, data_type=DataType.INT16) def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, @@ -161,7 +146,7 @@ def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, final_exp_fix = [] - for i in range(0, lut_size): # note that i corresponds to 1 timestep!!!!!! + for i in range(0, lut_size): # note that i corresponds to 1 timestep! # Multiply by inverse of time constant value = float(i) * inv_sigma @@ -187,19 +172,12 @@ def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, else: # at runtime, so write to spec final_exp_fix.append(exp_fix) - # spec.write_value(data=exp_fix, data_type=DataType.INT16) if spec is None: print("peak: time {}, value {}".format(peak_time, kernel_peak_value)) out_fixed = numpy.array(out_fixed) out_float = numpy.array(out_float) - plt.plot(plot_times, out_float, label='float') - # plt.plot(t,out_fixed, label='fixed') - plt.legend() - plt.title("mf-VN LUT") - plt.savefig("figures/write_mfvn_lut.png") - compare_t_values = numpy.array([15, 20, 30, 35, 45, 47, 99, 115, 135, 140, 150]) print("LUT VALUES TO COMPARE TO SPINNAKER:") @@ -208,13 +186,11 @@ def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, out_float[compare_t_values]): print("{:8} | {:8} | {:8.4f}".format(x, y, z)) # plt.show() - return plot_times, out_float + return compare_t_values, out_float, plot_times else: header = numpy.array([len(final_exp_fix), shift], dtype="uint16") array_to_write = numpy.concatenate(( header, numpy.array(final_exp_fix).astype("uint16"))).view("uint32") spec.write_array(array_to_write) - print("mfvn_lut: ", array_to_write) - print("header: ", header) - # spec.write_array(final_exp_fix, data_type=DataType.INT16) + return array_to_write diff --git a/unittests/model_tests/neuron/test_plastic_lut.py b/unittests/model_tests/neuron/test_plastic_lut.py new file mode 100644 index 00000000000..07e79af9b38 --- /dev/null +++ b/unittests/model_tests/neuron/test_plastic_lut.py @@ -0,0 +1,51 @@ +# Copyright (c) 2017-2019 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import numpy +import unittest +from spynnaker.pyNN.config_setup import unittest_setup +from spynnaker.pyNN.models.neuron.plasticity.stdp.common import ( + write_mfvn_lut, write_pfpc_lut) + +class TestPlasticLUT(unittest.TestCase): + + def setUp(self): + unittest_setup() + + def test_plastic_mfvn_lut(self): + t_mfvn, out_float_mfvn, _plot_times = write_mfvn_lut( + spec=None, sigma=200, beta=10, lut_size=256, shift=0, time_probe=22) + + t_compare = [15, 20, 30, 35, 45, 47, 99, 115, 135, 140, 150] + mfvn_float = [0.4697, 0.3642, 0.2181, 0.1685, 0.1002, 0.0902, 0.0055, + 0.0022, 0.0007, 0.0005, 0.0003] + print(t_mfvn, out_float_mfvn[t_mfvn], mfvn_float) + assert list(t_mfvn) == t_compare + self.assertTrue(numpy.allclose(out_float_mfvn[t_mfvn], mfvn_float, + atol=0.0001)) + + def test_plastic_pfpc_lut(self): + t_pfpc, out_float_pfpc, out_fixed_pfpc, _plot_times = write_pfpc_lut( + spec=None, peak_time=100, lut_size=256, shift=0, time_probe=100) + + t_compare = [15, 20, 30, 35, 45, 47, 99, 115, 135, 140, 150] + pfpc_fixed = [0, 0, 0, 0, 1, 1, 2043, 1215, 109, 42, 4] + pfpc_float = [0.0, 0.0, 0.0, 0.0, 0.0002, 0.0005, + 0.9977, 0.5932, 0.0534, 0.0207, 0.0019] + print(t_pfpc, out_float_pfpc[t_pfpc], out_fixed_pfpc[t_pfpc]) + assert list(t_pfpc) == t_compare + assert list(out_fixed_pfpc[t_pfpc]) == pfpc_fixed + self.assertTrue(numpy.allclose(out_float_pfpc[t_pfpc], pfpc_float, + atol=0.0001)) From f30761a072cc7c3223271e3566ea5617a72be400 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Wed, 28 Sep 2022 09:41:43 +0100 Subject: [PATCH 085/108] merge properly - no more constraints --- spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py b/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py index 3d24cbd0e5c..cec721d5135 100644 --- a/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py +++ b/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py @@ -53,6 +53,6 @@ def create_vertex( # pylint: disable=arguments-differ max_atoms = self.get_model_max_atoms_per_dimension_per_core() return AbstractPopulationVertex( - n_neurons, label, constraints, spikes_per_second, ring_buffer_sigma, + n_neurons, label, spikes_per_second, ring_buffer_sigma, incoming_spike_buffer_size, self.__model, self, drop_late_spikes, splitter, rb_left_shifts) From d669838c7e3bad50b499c6fddf38ad873a9fd850 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Wed, 28 Sep 2022 09:51:14 +0100 Subject: [PATCH 086/108] Missed an argument --- spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py b/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py index cec721d5135..c8e28d93e06 100644 --- a/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py +++ b/spynnaker/pyNN/models/neuron/abstract_pynn_neuron_model.py @@ -53,6 +53,6 @@ def create_vertex( # pylint: disable=arguments-differ max_atoms = self.get_model_max_atoms_per_dimension_per_core() return AbstractPopulationVertex( - n_neurons, label, spikes_per_second, ring_buffer_sigma, + n_neurons, label, max_atoms, spikes_per_second, ring_buffer_sigma, incoming_spike_buffer_size, self.__model, self, drop_late_spikes, splitter, rb_left_shifts) From e0c85275b9200c1ec7f813c528ac0b7686fd17e4 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Wed, 28 Sep 2022 11:18:17 +0100 Subject: [PATCH 087/108] flake8 --- unittests/model_tests/neuron/test_plastic_lut.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/unittests/model_tests/neuron/test_plastic_lut.py b/unittests/model_tests/neuron/test_plastic_lut.py index 07e79af9b38..39984a481a1 100644 --- a/unittests/model_tests/neuron/test_plastic_lut.py +++ b/unittests/model_tests/neuron/test_plastic_lut.py @@ -19,6 +19,7 @@ from spynnaker.pyNN.models.neuron.plasticity.stdp.common import ( write_mfvn_lut, write_pfpc_lut) + class TestPlasticLUT(unittest.TestCase): def setUp(self): @@ -26,7 +27,8 @@ def setUp(self): def test_plastic_mfvn_lut(self): t_mfvn, out_float_mfvn, _plot_times = write_mfvn_lut( - spec=None, sigma=200, beta=10, lut_size=256, shift=0, time_probe=22) + spec=None, sigma=200, beta=10, lut_size=256, shift=0, + time_probe=22) t_compare = [15, 20, 30, 35, 45, 47, 99, 115, 135, 140, 150] mfvn_float = [0.4697, 0.3642, 0.2181, 0.1685, 0.1002, 0.0902, 0.0055, From 114ab37b70a8f542fdeeb88a9f023ad8fcd3f8c1 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Wed, 16 Nov 2022 17:56:00 +0000 Subject: [PATCH 088/108] Update neuron model to match others --- ...n_model_leaky_integrate_and_fire_t_last.py | 99 +++++-------------- 1 file changed, 24 insertions(+), 75 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py index 9392531163b..f88b7e37696 100644 --- a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py +++ b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py @@ -13,12 +13,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import numpy from spinn_utilities.overrides import overrides from data_specification.enums import DataType -from .abstract_neuron_model import AbstractNeuronModel from spynnaker.pyNN.models.neuron.implementations import ( AbstractStandardNeuronComponent) +from spynnaker.pyNN.utilities.struct import Struct +from spynnaker.pyNN.data import SpynnakerDataView V = "v" V_REST = "v_rest" @@ -27,23 +27,12 @@ I_OFFSET = "i_offset" V_RESET = "v_reset" TAU_REFRAC = "tau_refrac" -COUNT_REFRAC = "count_refrac" +TIMESTEP = "timestep" +REFRACT_TIMER = "refract_timer" T_LAST = "t_last" -UNITS = { - V: 'mV', - V_REST: 'mV', - TAU_M: 'ms', - CM: 'nF', - I_OFFSET: 'nA', - V_RESET: 'mV', - TAU_REFRAC: 'ms', - T_LAST: "ms" -} - - -class NeuronModelLeakyIntegrateAndFireTLast(AbstractNeuronModel): - """ Classic LIF neuron model with t_last state variable included. +class NeuronModelLeakyIntegrateAndFireTLast(AbstractStandardNeuronComponent): + """ Classic leaky integrate and fire neuron model. """ __slots__ = [ "__v_init", @@ -52,8 +41,7 @@ class NeuronModelLeakyIntegrateAndFireTLast(AbstractNeuronModel): "__cm", "__i_offset", "__v_reset", - "__tau_refrac" - ] + "__tau_refrac"] def __init__( self, v_init, v_rest, tau_m, cm, i_offset, v_reset, tau_refrac): @@ -87,20 +75,22 @@ def __init__( (mapping) function """ super().__init__( - [DataType.S1615, # v - DataType.S1615, # v_rest - DataType.S1615, # r_membrane (= tau_m / cm) - DataType.S1615, # exp_tc (= e^(-ts / tau_m)) - DataType.S1615, # i_offset - DataType.INT32, # count_refrac - DataType.S1615, # v_reset - DataType.INT32, # tau_refrac - DataType.INT32 # t_last - ]) + [Struct([ + (DataType.S1615, V), + (DataType.S1615, V_REST), + (DataType.S1615, CM), + (DataType.S1615, TAU_M), + (DataType.S1615, I_OFFSET), + (DataType.S1615, V_RESET), + (DataType.S1615, TAU_REFRAC), + (DataType.INT32, T_LAST), + (DataType.INT32, REFRACT_TIMER), + (DataType.S1615, TIMESTEP)])], + {V: 'mV', V_REST: 'mV', TAU_M: 'ms', CM: 'nF', I_OFFSET: 'nA', + V_RESET: 'mV', TAU_REFRAC: 'ms', T_LAST: 'ms'}) if v_init is None: v_init = v_rest - self.__v_init = v_init self.__v_rest = v_rest self.__tau_m = tau_m @@ -109,7 +99,7 @@ def __init__( self.__v_reset = v_reset self.__tau_refrac = tau_refrac - @overrides(AbstractNeuronModel.add_parameters) + @overrides(AbstractStandardNeuronComponent.add_parameters) def add_parameters(self, parameters): parameters[V_REST] = self.__v_rest parameters[TAU_M] = self.__tau_m @@ -117,55 +107,14 @@ def add_parameters(self, parameters): parameters[I_OFFSET] = self.__i_offset parameters[V_RESET] = self.__v_reset parameters[TAU_REFRAC] = self.__tau_refrac + parameters[TIMESTEP] = SpynnakerDataView.get_simulation_time_step_ms() - @overrides(AbstractNeuronModel.add_state_variables) + @overrides(AbstractStandardNeuronComponent.add_state_variables) def add_state_variables(self, state_variables): state_variables[V] = self.__v_init - state_variables[COUNT_REFRAC] = 0 + state_variables[REFRACT_TIMER] = 0 state_variables[T_LAST] = 0 - @overrides(AbstractNeuronModel.get_units) - def get_units(self, variable): - return UNITS[variable] - - @overrides(AbstractNeuronModel.has_variable) - def has_variable(self, variable): - return variable in UNITS - - @overrides(AbstractStandardNeuronComponent.get_values) - def get_values(self, parameters, state_variables, vertex_slice, ts): - """ - :param int ts: machine time step - """ - # pylint: disable=arguments-differ - - # Add the rest of the data - return [ - state_variables[V], - parameters[V_REST], - parameters[TAU_M] / parameters[CM], - parameters[TAU_M].apply_operation( - operation=lambda x: numpy.exp(float(-ts) / (1000.0 * x))), - parameters[I_OFFSET], - state_variables[COUNT_REFRAC], - parameters[V_RESET], - parameters[TAU_REFRAC].apply_operation( - operation=lambda x: int(numpy.ceil(x / (ts / 1000.0)))), - state_variables[T_LAST] - ] - - @overrides(AbstractStandardNeuronComponent.update_values) - def update_values(self, values, parameters, state_variables): - - # Read the data - (v, _v_rest, _r_membrane, _exp_tc, _i_offset, count_refrac, - _v_reset, _tau_refrac, t_last) = values - - # Copy the changed data only - state_variables[V] = v - state_variables[COUNT_REFRAC] = count_refrac - state_variables[T_LAST] = t_last - @property def v_init(self): """ Settable model parameter: :math:`V_{init}` From 9333363e1e3f198d57766af7bbbf4305a9381999 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 17 Nov 2022 16:49:02 +0000 Subject: [PATCH 089/108] Match changes elsewhere, fix builds and runs for new plasticity rules - mfvn and pfpc now only work using split cores --- .../IF_cond_exp_cerebellum_neuron/Makefile | 24 +++ .../makefiles/neuron_only/Makefile | 1 + .../makefiles/synapse_only/Makefile | 4 +- .../synapses_stdp_mad_mfvn_mfvn/Makefile | 24 +++ .../synapses_stdp_mad_pfpc_pfpc/Makefile | 24 +++ .../models/neuron_model_lif_t_last_impl.h | 10 +- .../synapse_dynamics_stdp_mad_mfvn_impl.c | 174 +++++++++--------- .../synapse_dynamics_stdp_mad_pfpc_impl.c | 76 ++++---- .../stdp/timing_dependence/timing_mfvn_impl.c | 6 +- .../stdp/timing_dependence/timing_mfvn_impl.h | 40 ++-- .../stdp/weight_dependence/weight_mfvn_impl.c | 16 +- .../stdp/weight_dependence/weight_mfvn_impl.h | 28 +-- .../splitter_abstract_pop_vertex_fixed.py | 4 +- .../neuron/builds/if_cond_exp_cerebellum.py | 7 +- ...n_model_leaky_integrate_and_fire_t_last.py | 5 +- .../timing_dependence_mfvn.py | 4 +- .../timing_dependence_pfpc.py | 14 +- .../timing_dependence_spike_pair.py | 2 - .../synapse_dynamics/synapse_dynamics_stdp.py | 7 +- .../pyNN/models/populations/population.py | 7 - 20 files changed, 274 insertions(+), 203 deletions(-) create mode 100644 neural_modelling/makefiles/neuron_only/IF_cond_exp_cerebellum_neuron/Makefile create mode 100644 neural_modelling/makefiles/synapse_only/synapses_stdp_mad_mfvn_mfvn/Makefile create mode 100644 neural_modelling/makefiles/synapse_only/synapses_stdp_mad_pfpc_pfpc/Makefile diff --git a/neural_modelling/makefiles/neuron_only/IF_cond_exp_cerebellum_neuron/Makefile b/neural_modelling/makefiles/neuron_only/IF_cond_exp_cerebellum_neuron/Makefile new file mode 100644 index 00000000000..06b1972a50b --- /dev/null +++ b/neural_modelling/makefiles/neuron_only/IF_cond_exp_cerebellum_neuron/Makefile @@ -0,0 +1,24 @@ +# Copyright (c) 2017-2019 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +APP = $(notdir $(CURDIR)) + +NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_t_last_impl.h +INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_conductance.h +NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h +THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h +SYNAPSE_TYPE_H = $(NEURON_DIR)/neuron/synapse_types/synapse_types_exponential_impl.h + +include ../neuron_build.mk diff --git a/neural_modelling/makefiles/neuron_only/Makefile b/neural_modelling/makefiles/neuron_only/Makefile index 6c6a8d18608..8d3f469df25 100644 --- a/neural_modelling/makefiles/neuron_only/Makefile +++ b/neural_modelling/makefiles/neuron_only/Makefile @@ -23,6 +23,7 @@ MODELS = IF_curr_exp_neuron\ IF_curr_delta_neuron\ IF_curr_alpha_neuron\ IF_cond_exp_stoc_neuron\ + IF_cond_exp_cerebellum_neuron\ external_device_lif_control_neuron all: diff --git a/neural_modelling/makefiles/synapse_only/Makefile b/neural_modelling/makefiles/synapse_only/Makefile index 080c19fb98d..081bbee7aa1 100644 --- a/neural_modelling/makefiles/synapse_only/Makefile +++ b/neural_modelling/makefiles/synapse_only/Makefile @@ -26,7 +26,9 @@ MODELS = synapses\ synapses_stdp_mad_pair_additive_structural_random_distance_weight\ synapses_stdp_mad_pair_additive_structural_last_neuron_distance_weight\ synapses_stdp_mad_nearest_pair_additive_structural_random_distance_weight\ - synapses_stdp_izhikevich_neuromodulation_pair_additive + synapses_stdp_izhikevich_neuromodulation_pair_additive\ + synapses_stdp_mad_mfvn_mfvn\ + synapses_stdp_mad_pfpc_pfpc ifneq ($(SPYNNAKER_DEBUG), DEBUG) MODELS += synapses_stdp_izhikevich_neuromodulation_pair_multiplicative\ diff --git a/neural_modelling/makefiles/synapse_only/synapses_stdp_mad_mfvn_mfvn/Makefile b/neural_modelling/makefiles/synapse_only/synapses_stdp_mad_mfvn_mfvn/Makefile new file mode 100644 index 00000000000..94d6d7f89c7 --- /dev/null +++ b/neural_modelling/makefiles/synapse_only/synapses_stdp_mad_mfvn_mfvn/Makefile @@ -0,0 +1,24 @@ +# Copyright (c) 2017-2019 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +APP = $(notdir $(CURDIR)) + +SYNAPSE_DYNAMICS = $(NEURON_DIR)/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c +TIMING_DEPENDENCE = $(NEURON_DIR)/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c +TIMING_DEPENDENCE_H = $(NEURON_DIR)/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h +WEIGHT_DEPENDENCE = $(NEURON_DIR)/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c +WEIGHT_DEPENDENCE_H = $(NEURON_DIR)/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h + +include ../synapse_build.mk diff --git a/neural_modelling/makefiles/synapse_only/synapses_stdp_mad_pfpc_pfpc/Makefile b/neural_modelling/makefiles/synapse_only/synapses_stdp_mad_pfpc_pfpc/Makefile new file mode 100644 index 00000000000..e516fe5ee87 --- /dev/null +++ b/neural_modelling/makefiles/synapse_only/synapses_stdp_mad_pfpc_pfpc/Makefile @@ -0,0 +1,24 @@ +# Copyright (c) 2017-2019 The University of Manchester +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +APP = $(notdir $(CURDIR)) + +SYNAPSE_DYNAMICS = $(NEURON_DIR)/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c +TIMING_DEPENDENCE = $(NEURON_DIR)/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c +TIMING_DEPENDENCE_H = $(NEURON_DIR)/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +WEIGHT_DEPENDENCE = $(NEURON_DIR)/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c +WEIGHT_DEPENDENCE_H = $(NEURON_DIR)/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h + +include ../synapse_build.mk diff --git a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h index 0a5e75cb81f..8fa8a99388a 100644 --- a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h +++ b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h @@ -43,6 +43,9 @@ struct neuron_params_t { //! refractory time of neuron [ms] REAL T_refract_ms; + //! Time of last CF spike (saved) + int32_t t_last; + //! initial refractory timer value (saved) int32_t refract_timer_init; @@ -75,10 +78,11 @@ typedef struct neuron_t { // post-spike reset membrane voltage [mV] REAL V_reset; + // time of last CF spike + int32_t t_last; + // refractory time of neuron [timesteps] int32_t T_refract; - - int32_t t_last; // time of last CF spike } neuron_t; //! \brief Performs a ceil operation on an accum @@ -110,6 +114,7 @@ static inline void neuron_model_initialise( static inline void neuron_model_save_state(neuron_t *state, neuron_params_t *params) { params->V_init = state->V_membrane; params->refract_timer_init = state->refract_timer; + params->t_last = state->t_last; } // simple Leaky I&F ODE @@ -196,6 +201,7 @@ static state_t neuron_model_get_membrane_voltage(const neuron_t *neuron) { static inline void neuron_model_print_state_variables(const neuron_t *neuron) { log_info("V membrane = %11.4k mv", neuron->V_membrane); log_info("Refract timer = %u timesteps", neuron->refract_timer); + log_info("T_last = $u", neuron->t_last); } static inline void neuron_model_print_parameters(const neuron_t *neuron) { diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c index 41e60cb91a9..8716e10c7b4 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c @@ -21,8 +21,8 @@ #include "post_events.h" #include "synapse_dynamics_stdp_common.h" -#include "stdp_typedefs.h" -#include +//#include "stdp_typedefs.h" +//#include #define NUM_MF_SPIKES_TO_RECORD 16 @@ -40,18 +40,18 @@ struct synapse_row_plastic_data_t { plastic_synapse_t synapses[]; }; -void _print_pre_event_history(pre_event_history_t pre_eve_hist){ - - io_printf(IO_BUF, "\n\n************************\n\n"); - io_printf(IO_BUF, "Number recorded MF spikes: %u\n", - pre_eve_hist.num_recorded_mf_spikes_minus_one); - io_printf(IO_BUF, "Prev time: %u\n", - pre_eve_hist.mf_times[pre_eve_hist.num_recorded_mf_spikes_minus_one]); - - for (int i = 0; i < NUM_MF_SPIKES_TO_RECORD; i++){ - io_printf(IO_BUF, " Entry %u: %u\n", i, pre_eve_hist.mf_times[i]); - } -} +//void _print_pre_event_history(pre_event_history_t pre_eve_hist){ +// +// io_printf(IO_BUF, "\n\n************************\n\n"); +// io_printf(IO_BUF, "Number recorded MF spikes: %u\n", +// pre_eve_hist.num_recorded_mf_spikes_minus_one); +// io_printf(IO_BUF, "Prev time: %u\n", +// pre_eve_hist.mf_times[pre_eve_hist.num_recorded_mf_spikes_minus_one]); +// +// for (int i = 0; i < NUM_MF_SPIKES_TO_RECORD; i++){ +// io_printf(IO_BUF, " Entry %u: %u\n", i, pre_eve_hist.mf_times[i]); +// } +//} //--------------------------------------- // Synapse update loop @@ -79,15 +79,15 @@ static inline final_state_t plasticity_update_synapse( window_begin_time, window_end_time, post_window.prev_time, post_window.num_events); - if (print_plasticity){ - io_printf(IO_BUF, " Printing PC history\n"); - print_event_history(post_event_history); - } - - if (print_plasticity){ - io_printf(IO_BUF, "\n############ Phase 1 #############\n"); - io_printf(IO_BUF, "\n Looping over PC spikes:\n"); - } +// if (print_plasticity){ +// io_printf(IO_BUF, " Printing PC history\n"); +// print_event_history(post_event_history); +// } +// +// if (print_plasticity){ +// io_printf(IO_BUF, "\n############ Phase 1 #############\n"); +// io_printf(IO_BUF, "\n Looping over PC spikes:\n"); +// } delay_dendritic = 0; @@ -102,24 +102,24 @@ static inline final_state_t plasticity_update_synapse( post_event_window_t pre_window = post_events_get_window_delayed( pre_event_history, mf_begin_time, delayed_post_time); - if (print_plasticity){ - io_printf(IO_BUF, " Looping over MF window for this PC spike: %u \n", - delayed_post_time); - } +// if (print_plasticity){ +// io_printf(IO_BUF, " Looping over MF window for this PC spike: %u \n", +// delayed_post_time); +// } while (pre_window.num_events > 0) { const uint32_t delayed_pre_time = *pre_window.next_time + delay_dendritic; - if (print_plasticity){ - io_printf(IO_BUF, " MF Spike: %u \n", delayed_pre_time); - - io_printf(IO_BUF, " delta t = %u (delayed MF = %u, delayed PC = %u)\n", - delayed_post_time - delayed_pre_time, - delayed_pre_time, - delayed_post_time); - } +// if (print_plasticity){ +// io_printf(IO_BUF, " MF Spike: %u \n", delayed_pre_time); +// +// io_printf(IO_BUF, " delta t = %u (delayed MF = %u, delayed PC = %u)\n", +// delayed_post_time - delayed_pre_time, +// delayed_pre_time, +// delayed_post_time); +// } current_state = timing_apply_post_spike( delayed_post_time, *post_window.next_trace, @@ -145,22 +145,22 @@ static inline final_state_t plasticity_update_synapse( post_event_history, fwd_window_begin_time, window_end_time); - if (print_plasticity){ - io_printf(IO_BUF, "\n############ Phase 2 #############\n"); - io_printf(IO_BUF, - " Looping over all PC spikes and comparing to latest MF spike at: %u\n", - time+delay_dendritic); - } +// if (print_plasticity){ +// io_printf(IO_BUF, "\n############ Phase 2 #############\n"); +// io_printf(IO_BUF, +// " Looping over all PC spikes and comparing to latest MF spike at: %u\n", +// time+delay_dendritic); +// } while (fwd_post_window.num_events > 0) { const uint32_t delayed_mf_time = *fwd_post_window.next_time + delay_dendritic; - if (print_plasticity){ - io_printf(IO_BUF, " PC spike: %u, dt: %u\n", - delayed_mf_time, - (time+delay_dendritic - delayed_mf_time) - ); - } +// if (print_plasticity){ +// io_printf(IO_BUF, " PC spike: %u, dt: %u\n", +// delayed_mf_time, +// (time+delay_dendritic - delayed_mf_time) +// ); +// } // Some of these variables aren't used current_state = timing_apply_post_spike( @@ -176,10 +176,10 @@ static inline final_state_t plasticity_update_synapse( const uint32_t delayed_pre_time = time + delay_axonal; - if (print_plasticity){ - log_debug("\t\tApplying pre-synaptic event at time:%u last post time:%u\n", - delayed_pre_time, post_window.prev_time); - } +// if (print_plasticity){ +// log_debug("\t\tApplying pre-synaptic event at time:%u last post time:%u\n", +// delayed_pre_time, post_window.prev_time); +// } // Apply spike to state // **NOTE** dendritic delay is subtracted @@ -194,28 +194,28 @@ static inline final_state_t plasticity_update_synapse( //--------------------------------------- // Synaptic row plastic-region implementation //--------------------------------------- -static inline plastic_synapse_t* _plastic_synapses( - address_t plastic_region_address) { - const uint32_t pre_event_history_size_words = - sizeof(pre_event_history_t) / sizeof(uint32_t); - static_assert(pre_event_history_size_words * sizeof(uint32_t) - == sizeof(pre_event_history_t), - "Size of pre_event_history_t structure should be a multiple" - " of 32-bit words"); - - return (plastic_synapse_t*) - (&plastic_region_address[pre_event_history_size_words]); -} - -//--------------------------------------- -static inline pre_event_history_t *_plastic_event_history( - address_t plastic_region_address) { - return (pre_event_history_t*) (&plastic_region_address[0]); -} +//static inline plastic_synapse_t* _plastic_synapses( +// address_t plastic_region_address) { +// const uint32_t pre_event_history_size_words = +// sizeof(pre_event_history_t) / sizeof(uint32_t); +// static_assert(pre_event_history_size_words * sizeof(uint32_t) +// == sizeof(pre_event_history_t), +// "Size of pre_event_history_t structure should be a multiple" +// " of 32-bit words"); +// +// return (plastic_synapse_t*) +// (&plastic_region_address[pre_event_history_size_words]); +//} +// +////--------------------------------------- +//static inline pre_event_history_t *_plastic_event_history( +// address_t plastic_region_address) { +// return (pre_event_history_t*) (&plastic_region_address[0]); +//} //--------------------------------------- -static inline index_t _sparse_axonal_delay(uint32_t x) { +static inline index_t sparse_axonal_delay(uint32_t x) { #if 1 // No axonal delay, ever __use(x); @@ -273,9 +273,9 @@ bool synapse_dynamics_process_plastic_synapses( synapse_row_fixed_part_t *fixed_region, weight_t *ring_buffers, uint32_t time, bool *write_back) { - if (print_plasticity){ - io_printf(IO_BUF, "\n############ New Plasticity Update #############\n"); - } +// if (print_plasticity){ +// io_printf(IO_BUF, "\n############ New Plasticity Update #############\n"); +// } // Extract separate arrays of plastic synapses (from plastic region), // Control words (from fixed region) and number of plastic synapses @@ -292,19 +292,19 @@ bool synapse_dynamics_process_plastic_synapses( plastic_region_address->history.mf_times[recorded_spikes_minus_one]; // no longer need to manage this trace - const pre_trace_t last_pre_trace = 0; +// const pre_trace_t last_pre_trace = 0; // add pre spike to struct capturing pre synaptic event history // NOTE: this uses the post_event_history_t handling code post_events_add(time, &plastic_region_address->history, 0); // Update pre-synaptic trace - if (print_plasticity){ - io_printf(IO_BUF, - "\nAdding pre-synaptic event (mossy fibre spike) at time: %u\n\n", time); - } +// if (print_plasticity){ +// io_printf(IO_BUF, +// "\nAdding pre-synaptic event (mossy fibre spike) at time: %u\n\n", time); +// } - timing_add_pre_spike(time, last_pre_time, last_pre_trace); + timing_add_pre_spike(time, last_pre_time, 0); // last_pre_trace); // Loop through plastic synapses for (; n_plastic_synapses > 0; n_plastic_synapses--) { @@ -313,15 +313,15 @@ bool synapse_dynamics_process_plastic_synapses( uint32_t control_word = *control_words++; plastic_words[0] = process_plastic_synapse( - control_word, last_pre_time, last_pre_trace, - last_pre_trace, ring_buffers, time, + control_word, last_pre_time, 0, + 0, ring_buffers, time, plastic_words[0], &plastic_region_address->history); plastic_words++; } - if (print_plasticity){ - io_printf(IO_BUF, "\n############ Completed Plasticity Update #############\n"); - } +// if (print_plasticity){ +// io_printf(IO_BUF, "\n############ Completed Plasticity Update #############\n"); +// } *write_back = true; return true; @@ -330,9 +330,9 @@ bool synapse_dynamics_process_plastic_synapses( void synapse_dynamics_process_post_synaptic_event( uint32_t time, index_t neuron_index) { - if (print_plasticity){ - log_debug("Adding post-synaptic event (PC spike)to history at time:%u", time); - } +// if (print_plasticity){ +// log_debug("Adding post-synaptic event (PC spike)to history at time:%u", time); +// } // Add post-event post_event_history_t *history = &post_event_history[neuron_index]; diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c index 08d8d3aa8f2..87d9e288fa5 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c @@ -77,18 +77,18 @@ static inline final_state_t plasticity_update_synapse( post_event_history, window_begin_time, window_end_time); - if (print_plasticity){ - log_info("\tPerforming deferred synapse update at time:%u", time); - log_info("\t\tbegin_time:%u, end_time:%u - prev_time:%u, num_events:%u", - window_begin_time, window_end_time, post_window.prev_time, - post_window.num_events); - io_printf(IO_BUF, " Printing CF history\n"); - print_event_history(post_event_history); - } - - if (print_plasticity){ - io_printf(IO_BUF, "\n Looping over climbing fibre spikes:\n"); - } +// if (print_plasticity){ +// log_info("\tPerforming deferred synapse update at time:%u", time); +// log_info("\t\tbegin_time:%u, end_time:%u - prev_time:%u, num_events:%u", +// window_begin_time, window_end_time, post_window.prev_time, +// post_window.num_events); +// io_printf(IO_BUF, " Printing CF history\n"); +// print_event_history(post_event_history); +// } + +// if (print_plasticity){ +// io_printf(IO_BUF, "\n Looping over climbing fibre spikes:\n"); +// } delay_dendritic = 0; @@ -99,32 +99,32 @@ static inline final_state_t plasticity_update_synapse( uint32_t pf_begin_time = (delayed_post_time < 255) ? 0 : (delayed_post_time - 255); - if (print_plasticity){ - io_printf(IO_BUF, " Applying post-synaptic event at delayed time:%u\n", - delayed_post_time); - } +// if (print_plasticity){ +// io_printf(IO_BUF, " Applying post-synaptic event at delayed time:%u\n", +// delayed_post_time); +// } post_event_window_t pre_window = post_events_get_window_delayed( pre_event_history, pf_begin_time, delayed_post_time); - if (print_plasticity){ - io_printf(IO_BUF, " Looping over PF window for this CF spike\n", - delayed_post_time); - } +// if (print_plasticity){ +// io_printf(IO_BUF, " Looping over PF window for this CF spike\n", +// delayed_post_time); +// } while (pre_window.num_events > 0) { const uint32_t delayed_pre_time = *pre_window.next_time + delay_dendritic; - if (print_plasticity){ - io_printf(IO_BUF, " PF Spike: %u \n", delayed_pre_time); - - io_printf(IO_BUF, " delta t = %u (delayed PF = %u, delayed CF = %u)\n", - delayed_post_time - delayed_pre_time, - delayed_pre_time, - delayed_post_time); - } +// if (print_plasticity){ +// io_printf(IO_BUF, " PF Spike: %u \n", delayed_pre_time); +// +// io_printf(IO_BUF, " delta t = %u (delayed PF = %u, delayed CF = %u)\n", +// delayed_post_time - delayed_pre_time, +// delayed_pre_time, +// delayed_post_time); +// } current_state = timing_apply_post_spike( delayed_post_time, *post_window.next_trace, @@ -142,10 +142,10 @@ static inline final_state_t plasticity_update_synapse( const uint32_t delayed_pre_time = time + delay_axonal; - if (print_plasticity){ - log_debug("\t\tApplying pre-synaptic event at time:%u last post time:%u\n", - delayed_pre_time, post_window.prev_time); - } +// if (print_plasticity){ +// log_debug("\t\tApplying pre-synaptic event at time:%u last post time:%u\n", +// delayed_pre_time, post_window.prev_time); +// } // Apply spike to state // **NOTE** dendritic delay is subtracted @@ -261,9 +261,9 @@ bool synapse_dynamics_process_plastic_synapses( post_events_add(time, &plastic_region_address->history, 0); // Update pre-synaptic trace - if (print_plasticity){ - io_printf(IO_BUF, "\nAdding pre-synaptic event (parallel fibre spike) at time: %u\n\n", time); - } +// if (print_plasticity){ +// io_printf(IO_BUF, "\nAdding pre-synaptic event (parallel fibre spike) at time: %u\n\n", time); +// } timing_add_pre_spike(time, last_pre_time, last_pre_trace); @@ -287,9 +287,9 @@ bool synapse_dynamics_process_plastic_synapses( void synapse_dynamics_process_post_synaptic_event( uint32_t time, index_t neuron_index) { - if (print_plasticity){ - log_debug("Adding post-synaptic event to trace at time:%u", time); - } +// if (print_plasticity){ +// log_debug("Adding post-synaptic event to trace at time:%u", time); +// } // Add post-event post_event_history_t *history = &post_event_history[neuron_index]; diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c index a43c1135a36..b61e6f56beb 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c @@ -28,14 +28,14 @@ int16_lut *exp_cos_lookup; //--------------------------------------- address_t timing_initialise(address_t address) { - io_printf(IO_BUF, "timing_mfvn_initialise: starting\n"); - io_printf(IO_BUF, "\tCerebellum MFVN rule\n"); +// io_printf(IO_BUF, "timing_mfvn_initialise: starting\n"); +// io_printf(IO_BUF, "\tCerebellum MFVN rule\n"); // Copy LUTs from following memory address_t lut_address = address; exp_cos_lookup = maths_copy_int16_lut(&lut_address); - io_printf(IO_BUF, "Timing_mfvn_initialise: completed successfully\n"); +// io_printf(IO_BUF, "Timing_mfvn_initialise: completed successfully\n"); return lut_address; } diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h index c5514f9e69d..e0614310045 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h @@ -69,17 +69,17 @@ static inline post_trace_t timing_add_post_spike( use(last_time); use(&last_trace); - if (print_plasticity){ - io_printf(IO_BUF, "Adding pre spike to event history (from vestibular nuclei)\n"); - } +// if (print_plasticity){ +// io_printf(IO_BUF, "Adding pre spike to event history (from vestibular nuclei)\n"); +// } // Add energy caused by new spike to trace // **NOTE** o2 trace is pre-multiplied by a3_plus - int32_t new_o1_trace = 0; //decayed_o1_trace + STDP_FIXED_POINT_ONE; +// int32_t new_o1_trace = 0; //decayed_o1_trace + STDP_FIXED_POINT_ONE; // Return new pre- synaptic event with decayed trace values with energy // for new spike added - return (post_trace_t) new_o1_trace; + return (post_trace_t) 0; } //--------------------------------------- @@ -104,11 +104,11 @@ static inline update_state_t timing_apply_pre_spike( use(&last_pre_trace); use(&last_post_trace); - // Here we will potentiate by the fixed amount alpha - if (print_plasticity){ - io_printf(IO_BUF, "\n############ Phase 3 #############"); - io_printf(IO_BUF, "\n Now do potentiation\n"); - } +// // Here we will potentiate by the fixed amount alpha +// if (print_plasticity){ +// io_printf(IO_BUF, "\n############ Phase 3 #############"); +// io_printf(IO_BUF, "\n Now do potentiation\n"); +// } return weight_one_term_apply_potentiation(previous_state, 0); } @@ -131,25 +131,25 @@ static inline update_state_t timing_apply_post_spike( // Get time of event relative to last pre-synaptic event uint32_t time_since_last_pre = last_pre_time; //time - last_pre_time; - if (print_plasticity){ - io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); - } +// if (print_plasticity){ +// io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); +// } if (time_since_last_pre < 255){ int32_t multiplier = maths_lut_exponential_decay_time_shifted( time_since_last_pre, TAU_PLUS_TIME_SHIFT, exp_cos_lookup); - if (print_plasticity){ - io_printf(IO_BUF, "multiplier: %k (fixed = %u)\n", multiplier << 4, multiplier); - } +// if (print_plasticity){ +// io_printf(IO_BUF, "multiplier: %k (fixed = %u)\n", multiplier << 4, multiplier); +// } return weight_one_term_apply_depression(previous_state, multiplier); } - if (print_plasticity){ - io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); - io_printf(IO_BUF, " out of LUT range - do nothing"); - } +// if (print_plasticity){ +// io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); +// io_printf(IO_BUF, " out of LUT range - do nothing"); +// } return previous_state; } diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c index 97e003876e8..8b5456c457e 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c @@ -38,8 +38,8 @@ address_t weight_initialise( address_t address, uint32_t n_synapse_types, uint32_t *ring_buffer_to_input_buffer_left_shifts) { - io_printf(IO_BUF, "mfvn weight_initialise: starting\n"); - io_printf(IO_BUF, "\tSTDP mfvn weight dependence\n"); +// io_printf(IO_BUF, "mfvn weight_initialise: starting\n"); +// io_printf(IO_BUF, "\tSTDP mfvn weight dependence\n"); // Copy plasticity region data from address // **NOTE** this seems somewhat safer than relying on sizeof @@ -69,14 +69,14 @@ address_t weight_initialise( // Get the weight shift for switching from int16 to accum weight_shift[s] = ring_buffer_to_input_buffer_left_shifts[s]; - io_printf(IO_BUF, - "\tSynapse type %u: Min weight:%d, Max weight:%d, A2+:%d, A2-:%d," - " Weight multiply right shift:%u\n", - s, dtcm_copy[s].min_weight, dtcm_copy[s].max_weight, - dtcm_copy[s].a2_plus, dtcm_copy[s].a2_minus, weight_shift[s]); +// io_printf(IO_BUF, +// "\tSynapse type %u: Min weight:%d, Max weight:%d, A2+:%d, A2-:%d," +// " Weight multiply right shift:%u\n", +// s, dtcm_copy[s].min_weight, dtcm_copy[s].max_weight, +// dtcm_copy[s].a2_plus, dtcm_copy[s].a2_minus, weight_shift[s]); } - io_printf(IO_BUF, "mfvn weight initialisation: completed successfully\n"); +// io_printf(IO_BUF, "mfvn weight initialisation: completed successfully\n"); // Return end address of region return (address_t) config; diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h index 11c22f811b5..bb2e040e1ca 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h @@ -72,19 +72,19 @@ static inline weight_state_t weight_get_initial(weight_t weight, //--------------------------------------- static inline weight_state_t weight_one_term_apply_depression( weight_state_t state, int32_t depression_multiplier) { - if (print_plasticity){ - io_printf(IO_BUF, "\n Do Depression\n"); - io_printf(IO_BUF, " Weight prior to depression: %u\n", state.weight); - } +// if (print_plasticity){ +// io_printf(IO_BUF, "\n Do Depression\n"); +// io_printf(IO_BUF, " Weight prior to depression: %u\n", state.weight); +// } // Multiply by depression and subtract state.weight -= mul_accum_fixed(state.weight, depression_multiplier); state.weight = kbits(MAX(bitsk(state.weight), bitsk(state.weight_region->min_weight))); - if (print_plasticity){ - io_printf(IO_BUF, " Weight after depression: %u\n\n", - state.weight); - } +// if (print_plasticity){ +// io_printf(IO_BUF, " Weight after depression: %u\n\n", +// state.weight); +// } return state; } @@ -93,11 +93,11 @@ static inline weight_state_t weight_one_term_apply_potentiation( weight_state_t state, int32_t a2_plus) { // add fixed amount - if (print_plasticity){ - io_printf(IO_BUF, " Adding fixed coontribution: %k (int %u)\n", - state.weight_region->a2_plus << 4, - state.weight_region->a2_plus); - } +// if (print_plasticity){ +// io_printf(IO_BUF, " Adding fixed coontribution: %k (int %u)\n", +// state.weight_region->a2_plus << 4, +// state.weight_region->a2_plus); +// } state.weight += state.weight_region->a2_plus; state.weight = kbits(MIN(bitsk(state.weight), bitsk(state.weight_region->max_weight))); @@ -108,7 +108,7 @@ static inline weight_state_t weight_one_term_apply_potentiation( //--------------------------------------- static inline weight_t weight_get_final(weight_state_t new_state) { - log_debug("\tnew_weight:%d\n", new_state.weight); +// log_debug("\tnew_weight:%d\n", new_state.weight); return (weight_t) (bitsk(new_state.weight) >> new_state.weight_shift); } diff --git a/spynnaker/pyNN/extra_algorithms/splitter_components/splitter_abstract_pop_vertex_fixed.py b/spynnaker/pyNN/extra_algorithms/splitter_components/splitter_abstract_pop_vertex_fixed.py index 52f32f86cf6..ab77d640f89 100644 --- a/spynnaker/pyNN/extra_algorithms/splitter_components/splitter_abstract_pop_vertex_fixed.py +++ b/spynnaker/pyNN/extra_algorithms/splitter_components/splitter_abstract_pop_vertex_fixed.py @@ -87,14 +87,14 @@ def create_machine_vertices(self, chip_counter): print("Using given values for RB left shifts.") ring_buffer_shifts = app_vertex.rb_left_shifts print("RB left shifts for {:20}".format(app_vertex.label), - "=", self.__ring_buffer_shifts) + "=", ring_buffer_shifts) print("-" * 80) else: print("=" * 80) print("Computing RB left shifts for", app_vertex.label) ring_buffer_shifts = app_vertex.get_ring_buffer_shifts() print("RB left shifts for {:20}".format(app_vertex.label), - "=", self.__ring_buffer_shifts) + "=", ring_buffer_shifts) weight_scales = app_vertex.get_weight_scales(ring_buffer_shifts) all_syn_block_sz = app_vertex.get_synapses_size( diff --git a/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py b/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py index f65a2192548..0043b7398a4 100644 --- a/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py +++ b/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py @@ -20,14 +20,13 @@ from spynnaker.pyNN.models.neuron.synapse_types import SynapseTypeExponential from spynnaker.pyNN.models.neuron.threshold_types import ThresholdTypeStatic -MAX_ATOMS_PER_CORE = 128 - class IFCondExpCerebellum(AbstractPyNNNeuronModelStandard): """ Leaky integrate and fire neuron with an exponentially decaying \ conductance input. Also includes ability to record last spike down a particular receptor """ + __slots__ = [] @default_initial_values({"v", "isyn_exc", "isyn_inh"}) def __init__( @@ -43,10 +42,6 @@ def __init__( input_type = InputTypeConductance(e_rev_E, e_rev_I) threshold_type = ThresholdTypeStatic(v_thresh) - super(IFCondExpCerebellum, - self).set_model_max_atoms_per_dimension_per_core( - n_atoms=MAX_ATOMS_PER_CORE) - super(IFCondExpCerebellum, self).__init__( model_name="IF_cond_exp_cerebellum", binary="IF_cond_exp_cerebellum.aplx", diff --git a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py index f88b7e37696..f74b5653f09 100644 --- a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py +++ b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py @@ -31,8 +31,9 @@ REFRACT_TIMER = "refract_timer" T_LAST = "t_last" + class NeuronModelLeakyIntegrateAndFireTLast(AbstractStandardNeuronComponent): - """ Classic leaky integrate and fire neuron model. + """ Classic leaky integrate and fire neuron model, including last T. """ __slots__ = [ "__v_init", @@ -87,7 +88,7 @@ def __init__( (DataType.INT32, REFRACT_TIMER), (DataType.S1615, TIMESTEP)])], {V: 'mV', V_REST: 'mV', TAU_M: 'ms', CM: 'nF', I_OFFSET: 'nA', - V_RESET: 'mV', TAU_REFRAC: 'ms', T_LAST: 'ms'}) + V_RESET: 'mV', TAU_REFRAC: 'ms'}) if v_init is None: v_init = v_rest diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py index 2df3eb4f4f1..a99d2e9fe29 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py @@ -162,7 +162,7 @@ def get_provenance_data(self, synapse_info): self.__class__.__name__, "tau_plus_last_entry", tauplus) if tauplus is not None: - if tauplus > 0: + if tauplus[-1] > 0: db.insert_report( f"The last entry in the STDP exponential lookup table " f"for the tau_plus parameter of the" @@ -179,7 +179,7 @@ def get_provenance_data(self, synapse_info): self.__class__.__name__, "tau_minus_last_entry", tauminus) if tauminus is not None: - if tauminus > 0: + if tauminus[-1] > 0: db.insert_report( f"The last entry in the STDP exponential lookup table " f"for the tau_minus parameter of the " diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index 56b6bee97aa..4cf288a78b4 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -54,12 +54,7 @@ def __init__(self, tau_plus=20.0, tau_minus=20.0, A_plus=0.01, self._synapse_structure = SynapseStructureWeightOnly() - # provenance data - dummy_spec = [] - self._tau_plus_data = write_pfpc_lut( - dummy_spec, peak_time=self._t_peak, - time_probe=None, lut_size=LUT_SIZE, - shift=0, kernel_scaling=self._alpha) + self._tau_plus_data = None self._tau_minus_data = None @property @@ -119,7 +114,7 @@ def pre_trace_n_bytes(self): @overrides(AbstractTimingDependence.get_parameters_sdram_usage_in_bytes) def get_parameters_sdram_usage_in_bytes(self): - return BYTES_PER_WORD * len(self._tau_plus_data) + return BYTES_PER_WORD * LUT_SIZE @property def n_weight_terms(self): @@ -135,7 +130,10 @@ def write_parameters( "exp_sin LUT generation currently only supports 1ms timesteps") # Write exp_sin lookup table - spec.write_array(self._tau_plus_data) + self._tau_plus_data = write_pfpc_lut( + spec, peak_time=self._t_peak, + time_probe=None, lut_size=LUT_SIZE, + shift=0, kernel_scaling=self._alpha) @property def synaptic_structure(self): diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py index 9827e602e4a..8010c42d9f3 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_spike_pair.py @@ -140,9 +140,7 @@ def write_parameters( self, spec, global_weight_scale, synapse_weight_scales): # Write lookup tables - print("LUT tau plus ", self.__tau_plus_data) spec.write_array(self.__tau_plus_data) - print("LUT tau minus ", self.__tau_minus_data) spec.write_array(self.__tau_minus_data) @property diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py index 7a1c082ab73..3260607594c 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py @@ -591,7 +591,12 @@ def delay(self): @property @overrides(AbstractPlasticSynapseDynamics.is_combined_core_capable) def is_combined_core_capable(self): - return self.__neuromodulation is None + timing_suffix = self.__timing_dependence.vertex_executable_suffix + weight_suffix = self.__weight_dependence.vertex_executable_suffix + + return ((self.__neuromodulation is None) and + (timing_suffix != "mfvn") and (timing_suffix != "pfpc") and + (weight_suffix != "mfvn") and (weight_suffix != "pfpc")) @property @overrides(AbstractPlasticSynapseDynamics.pad_to_length) diff --git a/spynnaker/pyNN/models/populations/population.py b/spynnaker/pyNN/models/populations/population.py index 447a67eae05..78de5b158eb 100644 --- a/spynnaker/pyNN/models/populations/population.py +++ b/spynnaker/pyNN/models/populations/population.py @@ -827,13 +827,6 @@ def __create_vertex( # Setting custom RB LS if rb_left_shifts is not None: self.__vertex.set_rb_left_shifts(rb_left_shifts) - # Introspect properties of the vertex - self.__vertex_population_settable = \ - isinstance(self.__vertex, AbstractPopulationSettable) - self.__vertex_population_initializable = \ - isinstance(self.__vertex, AbstractPopulationInitializable) - self.__vertex_contains_units = \ - isinstance(self.__vertex, AbstractContainsUnits) @staticmethod def create(cellclass, cellparams=None, n=1): From 60de6f42f47ebc9b96bfd5bb3ba38dc8a7df1e48 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 18 Nov 2022 10:07:09 +0000 Subject: [PATCH 090/108] pylint, vera --- .../plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c | 3 ++- .../stdp/timing_dependence/timing_dependence_mfvn.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c index 0370556a978..5bb7920c644 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c @@ -267,7 +267,8 @@ bool synapse_dynamics_process_plastic_synapses( // Update pre-synaptic trace // if (print_plasticity){ -// io_printf(IO_BUF, "\nAdding pre-synaptic event (parallel fibre spike) at time: %u\n\n", time); +// io_printf(IO_BUF, +// "\nAdding pre-synaptic event (parallel fibre spike) at time: %u\n\n", time); // } timing_add_pre_spike(time - colour_delay, last_pre_time, last_pre_trace); diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py index a99d2e9fe29..17cfe4fcb29 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py @@ -179,7 +179,7 @@ def get_provenance_data(self, synapse_info): self.__class__.__name__, "tau_minus_last_entry", tauminus) if tauminus is not None: - if tauminus[-1] > 0: + if tauminus > 0: db.insert_report( f"The last entry in the STDP exponential lookup table " f"for the tau_minus parameter of the " From 55963acb9b9e7a3eaf09381dc24aed8525de2bff Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 18 Nov 2022 14:39:52 +0000 Subject: [PATCH 091/108] Move new provenance to split models only --- neural_modelling/src/neuron/c_main.c | 26 +--- neural_modelling/src/neuron/c_main_synapses.c | 21 ++- .../src/neuron/models/neuron_model_lif_impl.h | 16 +-- .../models/neuron_model_lif_t_last_impl.h | 18 +-- .../neuron/plasticity/stdp/stdp_typedefs.h | 2 +- .../stdp/timing_dependence/timing_pfpc_impl.h | 33 ++--- .../weight_additive_one_term_impl.h | 2 +- .../weight_additive_two_term_impl.h | 2 +- .../stdp/weight_dependence/weight_pfpc_impl.h | 14 +- .../src/neuron/spike_processing.c | 78 ++--------- .../src/neuron/spike_processing.h | 62 +++----- .../src/neuron/spike_processing_fast.c | 68 +++++++++ .../src/neuron/spike_processing_fast.h | 47 +++++++ .../neuron/population_machine_vertex.py | 132 +++++++++--------- ...pulation_synapses_machine_vertex_common.py | 70 +++++++++- 15 files changed, 352 insertions(+), 239 deletions(-) diff --git a/neural_modelling/src/neuron/c_main.c b/neural_modelling/src/neuron/c_main.c index 2181e180468..af9ada90a31 100644 --- a/neural_modelling/src/neuron/c_main.c +++ b/neural_modelling/src/neuron/c_main.c @@ -38,17 +38,11 @@ #include "c_main_common.h" #include "regions.h" #include "profile_tags.h" -#include "spike_profiling.h" #include "spike_processing.h" -struct spike_holder_t spike_counter; -struct spike_holder_t spike_cache; -struct spike_holder_t spike_counter_inh; -struct spike_holder_t spike_cache_inh; - // FLUSH SPIKES -bool timer_callback_active = false; -extern volatile bool dma_busy; +//bool timer_callback_active = false; +//extern volatile bool dma_busy; //! The combined provenance from synapses and neurons struct combined_provenance { @@ -190,17 +184,10 @@ void background_callback(uint timer_count, uint local_time) { //! executed since start of simulation //! \param[in] unused: unused parameter kept for API consistency void timer_callback(uint timer_count, UNUSED uint unused) { - // Get number of spikes in last tick, and reset spike counter - spike_processing_get_and_reset_spikes_this_tick(); - spike_processing_get_and_reset_dmas_this_tick(); - spike_processing_get_and_reset_pipeline_restarts_this_tick(); - - // cache and flush spike counters - // functions in file neural_modelling/src/neuron/spike_profiling.h - spike_profiling_cache_and_flush_spike_holder(&spike_counter, - &spike_cache); - spike_profiling_cache_and_flush_spike_holder(&spike_counter_inh, - &spike_cache_inh); +// // Get number of spikes in last tick, and reset spike counter +// spike_processing_get_and_reset_spikes_this_tick(); +// spike_processing_get_and_reset_dmas_this_tick(); +// spike_processing_get_and_reset_pipeline_restarts_this_tick(); // Disable interrupts to stop DMAs and MC getting in the way of this bit uint32_t state = spin1_int_disable(); @@ -283,7 +270,6 @@ static bool initialise(void) { &clear_input_buffer_of_late_packets, &n_rec_regions_used)) { return false; } - clear_input_buffer_of_late_packets = false; // Setup spike processing if (!spike_processing_initialise( diff --git a/neural_modelling/src/neuron/c_main_synapses.c b/neural_modelling/src/neuron/c_main_synapses.c index 811e2976f45..c60cf0aac11 100644 --- a/neural_modelling/src/neuron/c_main_synapses.c +++ b/neural_modelling/src/neuron/c_main_synapses.c @@ -36,6 +36,7 @@ #include "c_main_synapse_common.h" #include "c_main_common.h" #include "spike_processing_fast.h" +#include "spike_profiling.h" #include "structural_plasticity/synaptogenesis_dynamics.h" #include @@ -91,6 +92,12 @@ const struct synapse_regions SYNAPSE_REGIONS = { .bitfield_filter = BIT_FIELD_FILTER_REGION }; +//! spike profiling +struct spike_holder_t spike_counter; +struct spike_holder_t spike_cache; +struct spike_holder_t spike_counter_inh; +struct spike_holder_t spike_cache_inh; + //! The current timer tick value. // the timer tick callback returning the same value. uint32_t time; @@ -130,7 +137,19 @@ void resume_callback(void) { //! \param[in] unused0: unused //! \param[in] unused1: unused void timer_callback(UNUSED uint unused0, UNUSED uint unused1) { - time++; + // Get number of spikes in last tick, and reset spike counter + spike_processing_get_and_reset_spikes_this_tick(); + spike_processing_get_and_reset_dmas_this_tick(); + spike_processing_get_and_reset_pipeline_restarts_this_tick(); + + // cache and flush spike counters + // functions in file neural_modelling/src/neuron/spike_profiling.h + spike_profiling_cache_and_flush_spike_holder(&spike_counter, + &spike_cache); + spike_profiling_cache_and_flush_spike_holder(&spike_counter_inh, + &spike_cache_inh); + + time++; if (simulation_is_finished()) { // Enter pause and resume state to avoid another tick simulation_handle_pause_resume(resume_callback); diff --git a/neural_modelling/src/neuron/models/neuron_model_lif_impl.h b/neural_modelling/src/neuron/models/neuron_model_lif_impl.h index 8f1eacc0438..15ae448ff93 100644 --- a/neural_modelling/src/neuron/models/neuron_model_lif_impl.h +++ b/neural_modelling/src/neuron/models/neuron_model_lif_impl.h @@ -190,20 +190,20 @@ static inline state_t neuron_model_get_membrane_voltage(const neuron_t *neuron) } static inline void neuron_model_print_state_variables(const neuron_t *neuron) { - log_info("V membrane = %11.4k mv", neuron->V_membrane); - log_info("Refract timer = %u timesteps", neuron->refract_timer); + log_debug("V membrane = %11.4k mv", neuron->V_membrane); + log_debug("Refract timer = %u timesteps", neuron->refract_timer); } static inline void neuron_model_print_parameters(const neuron_t *neuron) { - log_info("V reset = %11.4k mv", neuron->V_reset); - log_info("V rest = %11.4k mv", neuron->V_rest); + log_debug("V reset = %11.4k mv", neuron->V_reset); + log_debug("V rest = %11.4k mv", neuron->V_rest); - log_info("I offset = %11.4k nA", neuron->I_offset); - log_info("R membrane = %11.4k Mohm", neuron->R_membrane); + log_debug("I offset = %11.4k nA", neuron->I_offset); + log_debug("R membrane = %11.4k Mohm", neuron->R_membrane); - log_info("exp(-ms/(RC)) = %11.4k [.]", neuron->exp_TC); + log_debug("exp(-ms/(RC)) = %11.4k [.]", neuron->exp_TC); - log_info("T refract = %u timesteps", neuron->T_refract); + log_debug("T refract = %u timesteps", neuron->T_refract); } diff --git a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h index 8fa8a99388a..bd6833d4b00 100644 --- a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h +++ b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h @@ -199,21 +199,21 @@ static state_t neuron_model_get_membrane_voltage(const neuron_t *neuron) { } static inline void neuron_model_print_state_variables(const neuron_t *neuron) { - log_info("V membrane = %11.4k mv", neuron->V_membrane); - log_info("Refract timer = %u timesteps", neuron->refract_timer); - log_info("T_last = $u", neuron->t_last); + log_debug("V membrane = %11.4k mv", neuron->V_membrane); + log_debug("Refract timer = %u timesteps", neuron->refract_timer); + log_debug("T_last = $u", neuron->t_last); } static inline void neuron_model_print_parameters(const neuron_t *neuron) { - log_info("V reset = %11.4k mv", neuron->V_reset); - log_info("V rest = %11.4k mv", neuron->V_rest); + log_debug("V reset = %11.4k mv", neuron->V_reset); + log_debug("V rest = %11.4k mv", neuron->V_rest); - log_info("I offset = %11.4k nA", neuron->I_offset); - log_info("R membrane = %11.4k Mohm", neuron->R_membrane); + log_debug("I offset = %11.4k nA", neuron->I_offset); + log_debug("R membrane = %11.4k Mohm", neuron->R_membrane); - log_info("exp(-ms/(RC)) = %11.4k [.]", neuron->exp_TC); + log_debug("exp(-ms/(RC)) = %11.4k [.]", neuron->exp_TC); - log_info("T refract = %u timesteps", neuron->T_refract); + log_debug("T refract = %u timesteps", neuron->T_refract); } diff --git a/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h b/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h index df98303dbb4..6cca8998a5d 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h +++ b/neural_modelling/src/neuron/plasticity/stdp/stdp_typedefs.h @@ -38,7 +38,7 @@ //! \return The product #define STDP_FIXED_MUL_16X16(a, b) maths_fixed_mul16(a, b, STDP_FIXED_POINT) -#define print_plasticity false +//#define print_plasticity false //! The amount of right shift required to take a weight from s1615 format //! to STDP_FIXED_POINT format (s4,11) diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index e073222b0f4..e1a4429278a 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -69,9 +69,10 @@ static inline post_trace_t timing_add_post_spike( use(last_time); use(&last_trace); - if (print_plasticity){ - io_printf(IO_BUF, "Adding climbing fibre spike to post-event history (stored on neuron\n"); - } +// if (print_plasticity){ +// io_printf(IO_BUF, +// "Adding climbing fibre spike to post-event history (stored on neuron\n"); +// } // Add energy caused by new spike to trace // **NOTE** o2 trace is pre-multiplied by a3_plus @@ -105,9 +106,9 @@ static inline update_state_t timing_apply_pre_spike( use(&last_post_trace); // Here we will potentiate by the fixed amount alpha - if (print_plasticity){ - io_printf(IO_BUF, " This is where we'll do potentiation\n"); - } +// if (print_plasticity){ +// io_printf(IO_BUF, " This is where we'll do potentiation\n"); +// } return weight_one_term_apply_potentiation(previous_state, 0); } @@ -130,25 +131,25 @@ static inline update_state_t timing_apply_post_spike( // Get time of event relative to last pre-synaptic event uint32_t time_since_last_pre = last_pre_time; //time - last_pre_time; - if (print_plasticity){ - io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); - } +// if (print_plasticity){ +// io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); +// } if (time_since_last_pre < 255){ int32_t multiplier = maths_lut_exponential_decay_time_shifted( time_since_last_pre, TAU_PLUS_TIME_SHIFT, exp_sin_lookup); - if (print_plasticity){ - io_printf(IO_BUF, "multiplier: %k (fixed = %u)\n", multiplier << 4, multiplier); - } +// if (print_plasticity){ +// io_printf(IO_BUF, "multiplier: %k (fixed = %u)\n", multiplier << 4, multiplier); +// } return weight_one_term_apply_depression(previous_state, multiplier); } - if (print_plasticity){ - io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); - io_printf(IO_BUF, " out of LUT range (do nothing)"); - } +// if (print_plasticity){ +// io_printf(IO_BUF, " delta t = %u, ", time_since_last_pre); +// io_printf(IO_BUF, " out of LUT range (do nothing)"); +// } return previous_state; } diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_additive_one_term_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_additive_one_term_impl.h index 3d9e73c75f2..778d1cf735d 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_additive_one_term_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_additive_one_term_impl.h @@ -25,7 +25,7 @@ #include #include -#include +//#include //--------------------------------------- // Structures diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_additive_two_term_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_additive_two_term_impl.h index 5b549345699..c7553227fda 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_additive_two_term_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_additive_two_term_impl.h @@ -25,7 +25,7 @@ #include #include -#include +//#include //--------------------------------------- // Structures diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h index f22cf63899c..bf13ec57763 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h @@ -70,19 +70,19 @@ static inline weight_state_t weight_get_initial(weight_t weight, static inline weight_state_t weight_one_term_apply_depression( weight_state_t state, int32_t depression_multiplier) { - if (print_plasticity){ - io_printf(IO_BUF, "\n Do Depression\n"); - io_printf(IO_BUF, " Weight prior to depression: %u\n", state.weight); - } +// if (print_plasticity){ +// io_printf(IO_BUF, "\n Do Depression\n"); +// io_printf(IO_BUF, " Weight prior to depression: %u\n", state.weight); +// } // Multiply by depression and subtract // **NOTE** using standard STDP fixed-point format handles format conversion state.weight -= mul_accum_fixed(state.weight, depression_multiplier); state.weight = kbits(MAX(bitsk(state.weight), bitsk(state.weight_region->min_weight))); - if (print_plasticity){ - io_printf(IO_BUF, " Weight after depression: %u\n\n", state.weight); - } +// if (print_plasticity){ +// io_printf(IO_BUF, " Weight after depression: %u\n\n", state.weight); +// } return state; } diff --git a/neural_modelling/src/neuron/spike_processing.c b/neural_modelling/src/neuron/spike_processing.c index c84d0544d0c..b27e08ab074 100644 --- a/neural_modelling/src/neuron/spike_processing.c +++ b/neural_modelling/src/neuron/spike_processing.c @@ -111,19 +111,6 @@ static uint32_t biggest_fill_size_of_input_buffer; //! end of a timer tick. static bool clear_input_buffers_of_late_packets; -static uint32_t max_spikes_in_a_tick; -static uint32_t max_dmas_in_a_tick; -static uint32_t dma_complete_count; -static uint32_t max_pipeline_restarts; -static uint32_t spike_pipeline_deactivation_time = 0; -static uint32_t timer_callback_completed = 0; -static uint32_t spikes_this_time_step = 0; -static uint32_t dmas_this_time_step = 0; -static uint32_t pipeline_restarts = 0; - -static uint32_t max_flushed_spikes = 0; -static uint32_t total_flushed_spikes = 0; - //! the number of packets received this time step static struct { uint32_t time; @@ -337,7 +324,7 @@ static inline void start_dma_loop(void) { //! \param[in] unused: Only specified to match API static void multicast_packet_received_callback(uint key, UNUSED uint unused) { p_per_ts_struct.packets_this_time_step += 1; - spikes_this_time_step += 1; +// spikes_this_time_step += 1; if (in_spikes_add_spike(key)) { start_dma_loop(); } @@ -348,7 +335,7 @@ static void multicast_packet_received_callback(uint key, UNUSED uint unused) { //! \param[in] payload: the payload of the packet. The count. static void multicast_packet_pl_received_callback(uint key, uint payload) { p_per_ts_struct.packets_this_time_step += 1; - spikes_this_time_step += 1; +// spikes_this_time_step += 1; // cycle through the packet insertion bool added = false; @@ -366,8 +353,8 @@ static void multicast_packet_pl_received_callback(uint key, uint payload) { static void dma_complete_callback(UNUSED uint unused, UNUSED uint tag) { // increment the dma complete count for provenance generation - dmas_this_time_step += 1; - dma_complete_count += 1; +// dmas_this_time_step++; + dma_complete_count++; // Get pointer to current buffer uint32_t current_buffer_index = buffer_being_read; @@ -439,7 +426,7 @@ void user_event_callback(UNUSED uint unused0, UNUSED uint unused1) { dma_n_spikes = 0; // Increment counter for spike processing pipeline restarts - pipeline_restarts++; +// pipeline_restarts++; if (buffer_being_read < N_DMA_BUFFERS) { // If the DMA buffer is full of valid data, attempt to reuse it on the @@ -491,7 +478,7 @@ bool spike_processing_initialise( // EXPORTED // Allocate incoming spike buffer if (!in_spikes_initialize_spike_buffer(incoming_spike_buffer_size)) { - io_printf(IO_BUF, "Spike buffer failed to initialise - insufficient DTCM \n"); + log_error("Spike buffer failed to initialise - insufficient DTCM \n"); return false; } @@ -514,13 +501,15 @@ void spike_processing_store_provenance(struct spike_processing_provenance *prov) prov->n_rewires = n_successful_rewires; prov->n_packets_dropped_from_lateness = count_input_buffer_packets_late; prov->max_filled_input_buffer_size = biggest_fill_size_of_input_buffer; - prov->max_spikes_in_a_tick = max_spikes_in_a_tick; - prov->max_dmas_in_a_tick = max_dmas_in_a_tick; - prov->max_pipeline_restarts = max_pipeline_restarts; - prov->timer_callback_completed = timer_callback_completed; - prov->spike_pipeline_deactivated = spike_pipeline_deactivation_time; - prov->max_flushed_spikes = max_flushed_spikes; - prov->total_flushed_spikes = total_flushed_spikes; +// prov->max_spikes_in_a_tick = max_spikes_in_a_tick; +// prov->max_dmas_in_a_tick = max_dmas_in_a_tick; +// prov->max_pipeline_restarts = max_pipeline_restarts; +// prov->timer_callback_completed = timer_callback_completed; +//#if LOG_LEVEL >= LOG_DEBUG +// prov->spike_pipeline_deactivated = spike_pipeline_deactivation_time; +// prov->max_flushed_spikes = max_flushed_spikes; +// prov->total_flushed_spikes = total_flushed_spikes; +//#endif } bool spike_processing_do_rewiring(int number_of_rewires) { @@ -532,40 +521,3 @@ bool spike_processing_do_rewiring(int number_of_rewires) { spin1_mode_restore(cpsr); return true; } - -// Custom provenance from SpiNNCer -void spike_processing_get_and_reset_spikes_this_tick(void ) { - if (spikes_this_time_step > max_spikes_in_a_tick) { - max_spikes_in_a_tick = spikes_this_time_step; - } - spikes_this_time_step = 0; -} - -void spike_processing_get_and_reset_dmas_this_tick(void) { - if (dmas_this_time_step > max_dmas_in_a_tick){ - max_dmas_in_a_tick = dmas_this_time_step; - } - dmas_this_time_step = 0; -} - -void spike_processing_get_and_reset_pipeline_restarts_this_tick(void) { - if (pipeline_restarts > max_pipeline_restarts) { - max_pipeline_restarts = pipeline_restarts; - } - pipeline_restarts = 0; -} - -#if LOG_LEVEL >= LOG_DEBUG -uint32_t spike_processing_get_pipeline_deactivation_time(){ - return spike_pipeline_deactivation_time; -} - -// FLUSHED SPIKES -uint32_t spike_processing_get_total_flushed_spikes(){ - return total_flushed_spikes; -} - -uint32_t spike_processing_get_max_flushed_spikes(){ - return max_flushed_spikes; -} -#endif diff --git a/neural_modelling/src/neuron/spike_processing.h b/neural_modelling/src/neuron/spike_processing.h index 1a424593e74..a8e9e604782 100644 --- a/neural_modelling/src/neuron/spike_processing.h +++ b/neural_modelling/src/neuron/spike_processing.h @@ -38,21 +38,23 @@ struct spike_processing_provenance { uint32_t n_packets_dropped_from_lateness; //! The maximum size of the input buffer uint32_t max_filled_input_buffer_size; - //! SpiNNCer-related provenance - //! The maximum number of spikes in a tick - uint32_t max_spikes_in_a_tick; - //! The maximum number of DMAs in a tick - uint32_t max_dmas_in_a_tick; - //! The maximum number of pipeline restarts - uint32_t max_pipeline_restarts; - //! Was the timer callback completed? - uint32_t timer_callback_completed; - //! Was the spike pipeline deactivated? - uint32_t spike_pipeline_deactivated; - //! The maximum number of flushed spikes in one step - uint32_t max_flushed_spikes; - //! Thet total number of flushed spikes - uint32_t total_flushed_spikes; +// //! SpiNNCer-related provenance +// //! The maximum number of spikes in a tick +// uint32_t max_spikes_in_a_tick; +// //! The maximum number of DMAs in a tick +// uint32_t max_dmas_in_a_tick; +// //! The maximum number of pipeline restarts +// uint32_t max_pipeline_restarts; +// //! Was the timer callback completed? +// uint32_t timer_callback_completed; +//#if LOG_LEVEL >= LOG_DEBUG +// //! Was the spike pipeline deactivated? +// uint32_t spike_pipeline_deactivated; +// //! The maximum number of flushed spikes in one step +// uint32_t max_flushed_spikes; +// //! Thet total number of flushed spikes +// uint32_t total_flushed_spikes; +//#endif }; //! \brief Initialise the spike processing system @@ -85,34 +87,4 @@ bool spike_processing_do_rewiring(int number_of_rewires); //! \param[in] time: The current timestep void spike_processing_clear_input_buffer(timer_t time); -// Custom provenance from SpiNNCer - -//! \brief get number of spikes received since last timer event -//! \return uint32_t number of spikes -void spike_processing_get_and_reset_spikes_this_tick(void); - -//! \brief get number of dmas completed since last timer event -//! \return uint32_t number of DMAs -void spike_processing_get_and_reset_dmas_this_tick(void); - -//! \brief get number of time pipeline was restarted since last timer event -//! \return uint32_t number of pipeline restarts -void spike_processing_get_and_reset_pipeline_restarts_this_tick(void); - -#if LOG_LEVEL >= LOG_DEBUG -//! \brief get time from T1 clock at which spike pipeline completed -//! \return uint32_t pipeline deactivation time -uint32_t spike_processing_get_pipeline_deactivation_time(); - -// FLUSH SPIKES -//! \brief returns the total unprocessed spikes from a simulation -//! \return total unprocessed spikes -uint32_t spike_processing_get_total_flushed_spikes(); - -//! \brief returns the maximum unprocessed spikes from a single -//! simulation timestep. -//! \return maximum unprocessed spikes from a single timestep. -uint32_t spike_processing_get_max_flushed_spikes(); -#endif - #endif // _SPIKE_PROCESSING_H_ diff --git a/neural_modelling/src/neuron/spike_processing_fast.c b/neural_modelling/src/neuron/spike_processing_fast.c index a668ae23bc6..608b58705d9 100644 --- a/neural_modelling/src/neuron/spike_processing_fast.c +++ b/neural_modelling/src/neuron/spike_processing_fast.c @@ -115,6 +115,21 @@ static uint32_t earliest_spike_received_time = 0; //! The maximum number of spikes left at the end of a time step static uint32_t max_spikes_overflow = 0; +static uint32_t max_spikes_in_a_tick; +static uint32_t max_dmas_in_a_tick; +//static uint32_t dma_complete_count; +static uint32_t max_pipeline_restarts; +static uint32_t timer_callback_completed = 0; +static uint32_t spikes_this_time_step = 0; +static uint32_t dmas_this_time_step = 0; +static uint32_t pipeline_restarts = 0; + +#if LOG_LEVEL >= LOG_DEBUG +static uint32_t spike_pipeline_deactivation_time = 0; +static uint32_t max_flushed_spikes = 0; +static uint32_t total_flushed_spikes = 0; +#endif + //! The number of packets received this time step for recording static struct { uint32_t time; @@ -551,6 +566,7 @@ void spike_processing_fast_time_step_loop(uint32_t time, uint32_t n_rewires) { break; } dma_complete_count++; + dmas_this_time_step++; if (dma_in_progress) { read_synaptic_row(spike, &result); } @@ -558,6 +574,9 @@ void spike_processing_fast_time_step_loop(uint32_t time, uint32_t n_rewires) { // Process the row we already have while the DMA progresses process_current_row(time, dma_in_progress); + // Increment counter for spike processing pipeline restarts + pipeline_restarts++; + } } @@ -579,6 +598,7 @@ static inline void check_times(void) { void multicast_packet_received_callback(uint key, UNUSED uint unused) { log_debug("Received spike %x", key); p_per_ts_struct.packets_this_time_step++; + spikes_this_time_step += 1; in_spikes_add_spike(key); check_times(); } @@ -589,6 +609,7 @@ void multicast_packet_received_callback(uint key, UNUSED uint unused) { void multicast_packet_pl_received_callback(uint key, uint payload) { log_debug("Received spike %x with payload %d", key, payload); p_per_ts_struct.packets_this_time_step++; + spikes_this_time_step += 1; // cycle through the packet insertion for (uint count = payload; count > 0; count--) { @@ -657,4 +678,51 @@ void spike_processing_fast_store_provenance( prov->earliest_receive = earliest_spike_received_time; prov->latest_receive = latest_spike_received_time; prov->max_spikes_overflow = max_spikes_overflow; + prov->max_spikes_in_a_tick = max_spikes_in_a_tick; + prov->max_dmas_in_a_tick = max_dmas_in_a_tick; + prov->max_pipeline_restarts = max_pipeline_restarts; + prov->timer_callback_completed = timer_callback_completed; +#if LOG_LEVEL >= LOG_DEBUG + prov->spike_pipeline_deactivated = spike_pipeline_deactivation_time; + prov->max_flushed_spikes = max_flushed_spikes; + prov->total_flushed_spikes = total_flushed_spikes; +#endif +} + +// Custom provenance from SpiNNCer +void spike_processing_get_and_reset_spikes_this_tick(void ) { + if (spikes_this_time_step > max_spikes_in_a_tick) { + max_spikes_in_a_tick = spikes_this_time_step; + } + spikes_this_time_step = 0; +} + +void spike_processing_get_and_reset_dmas_this_tick(void) { + if (dmas_this_time_step > max_dmas_in_a_tick){ + max_dmas_in_a_tick = dmas_this_time_step; + } + dmas_this_time_step = 0; } + +void spike_processing_get_and_reset_pipeline_restarts_this_tick(void) { + if (pipeline_restarts > max_pipeline_restarts) { + max_pipeline_restarts = pipeline_restarts; + } + pipeline_restarts = 0; +} + +#if LOG_LEVEL >= LOG_DEBUG +uint32_t spike_processing_get_pipeline_deactivation_time(){ + return spike_pipeline_deactivation_time; +} + +// FLUSHED SPIKES +uint32_t spike_processing_get_total_flushed_spikes(){ + return total_flushed_spikes; +} + +uint32_t spike_processing_get_max_flushed_spikes(){ + return max_flushed_spikes; +} +#endif + diff --git a/neural_modelling/src/neuron/spike_processing_fast.h b/neural_modelling/src/neuron/spike_processing_fast.h index 3ee096cd9a6..51fc8684f5c 100644 --- a/neural_modelling/src/neuron/spike_processing_fast.h +++ b/neural_modelling/src/neuron/spike_processing_fast.h @@ -80,6 +80,23 @@ struct spike_processing_fast_provenance { uint32_t latest_receive; //! The most spikes left at the end of any time step uint32_t max_spikes_overflow; + //! SpiNNCer-related provenance + //! The maximum number of spikes in a tick + uint32_t max_spikes_in_a_tick; + //! The maximum number of DMAs in a tick + uint32_t max_dmas_in_a_tick; + //! The maximum number of pipeline restarts + uint32_t max_pipeline_restarts; + //! Was the timer callback completed? + uint32_t timer_callback_completed; +#if LOG_LEVEL >= LOG_DEBUG + //! Was the spike pipeline deactivated? + uint32_t spike_pipeline_deactivated; + //! The maximum number of flushed spikes in one step + uint32_t max_flushed_spikes; + //! Thet total number of flushed spikes + uint32_t total_flushed_spikes; +#endif }; //! \brief Set up spike processing @@ -113,4 +130,34 @@ void spike_processing_fast_time_step_loop(uint32_t time, uint32_t n_rewires); void spike_processing_fast_store_provenance( struct spike_processing_fast_provenance *prov); +// Custom provenance from SpiNNCer + +//! \brief get number of spikes received since last timer event +//! \return uint32_t number of spikes +void spike_processing_get_and_reset_spikes_this_tick(void); + +//! \brief get number of dmas completed since last timer event +//! \return uint32_t number of DMAs +void spike_processing_get_and_reset_dmas_this_tick(void); + +//! \brief get number of time pipeline was restarted since last timer event +//! \return uint32_t number of pipeline restarts +void spike_processing_get_and_reset_pipeline_restarts_this_tick(void); + +#if LOG_LEVEL >= LOG_DEBUG +//! \brief get time from T1 clock at which spike pipeline completed +//! \return uint32_t pipeline deactivation time +uint32_t spike_processing_get_pipeline_deactivation_time(); + +// FLUSH SPIKES +//! \brief returns the total unprocessed spikes from a simulation +//! \return total unprocessed spikes +uint32_t spike_processing_get_total_flushed_spikes(); + +//! \brief returns the maximum unprocessed spikes from a single +//! simulation timestep. +//! \return maximum unprocessed spikes from a single timestep. +uint32_t spike_processing_get_max_flushed_spikes(); +#endif + #endif // _SPIKE_PROCESSING_FAST_H_ diff --git a/spynnaker/pyNN/models/neuron/population_machine_vertex.py b/spynnaker/pyNN/models/neuron/population_machine_vertex.py index b25a6414007..1e95c5a7f40 100644 --- a/spynnaker/pyNN/models/neuron/population_machine_vertex.py +++ b/spynnaker/pyNN/models/neuron/population_machine_vertex.py @@ -43,20 +43,20 @@ class SpikeProcessingProvenance(ctypes.LittleEndianStructure): ("n_late_packets", ctypes.c_uint32), # The maximum size of the spike input buffer during simulation ("max_size_input_buffer", ctypes.c_uint32), - # Custom provenance from SpiNNCer - max spikes in a tick - ("max_spikes_in_a_tick", ctypes.c_uint32), - # max dmas in a tick - ("max_dmas_in_a_tick", ctypes.c_uint32), - # max pipeline restarts - ("max_pipeline_restarts", ctypes.c_uint32), - # timer callback completed? - ("timer_callback_completed", ctypes.c_uint32), - # spikes pipeline activated? - ("spikes_pipeline_activated", ctypes.c_uint32), - # Max flushed spikes in a timestep - ("max_flushed_spikes", ctypes.c_uint32), - # Total flushed spikes - ("total_flushed_spikes", ctypes.c_uint32) + # # Custom provenance from SpiNNCer - max spikes in a tick + # ("max_spikes_in_a_tick", ctypes.c_uint32), + # # max dmas in a tick + # ("max_dmas_in_a_tick", ctypes.c_uint32), + # # max pipeline restarts + # ("max_pipeline_restarts", ctypes.c_uint32), + # # timer callback completed? + # ("timer_callback_completed", ctypes.c_uint32), + # # spikes pipeline activated? + # ("spikes_pipeline_activated", ctypes.c_uint32), + # # Max flushed spikes in a timestep + # ("max_flushed_spikes", ctypes.c_uint32), + # # Total flushed spikes + # ("total_flushed_spikes", ctypes.c_uint32) ] N_ITEMS = len(_fields_) @@ -104,15 +104,15 @@ class PopulationMachineVertex( MAX_FILLED_SIZE_OF_INPUT_BUFFER_NAME = "Max_filled_size_input_buffer" BACKGROUND_OVERLOADS_NAME = "Times_the_background_queue_overloaded" BACKGROUND_MAX_QUEUED_NAME = "Max_backgrounds_queued" - # Custom provenance from SpiNNCer - MAX_SPIKES_IN_A_TICK = "Maximum number of spikes in a timer tick" - MAX_DMAS_IN_A_TICK = "Maximum number of DMAs in a timer tick" - MAX_PIPELINE_RESTARTS = "Maximum pipeline restarts" - TIMER_CALLBACK_COMPLETED = "Was the timer callback completed?" - SPIKES_PIPELINE_ACTIVATED = "Was the spikes pipeline activated?" - # Flushed spikes - MAX_FLUSHED_SPIKES = "Maximum number of spikes flushed in a timer tick" - TOTAL_FLUSHED_SPIKES = "Total number of spikes flushed" + # # Custom provenance from SpiNNCer + # MAX_SPIKES_IN_A_TICK = "Maximum number of spikes in a timer tick" + # MAX_DMAS_IN_A_TICK = "Maximum number of DMAs in a timer tick" + # MAX_PIPELINE_RESTARTS = "Maximum pipeline restarts" + # TIMER_CALLBACK_COMPLETED = "Was the timer callback completed?" + # SPIKES_PIPELINE_ACTIVATED = "Was the spikes pipeline activated?" + # # Flushed spikes + # MAX_FLUSHED_SPIKES = "Maximum number of spikes flushed in a timer tick" + # TOTAL_FLUSHED_SPIKES = "Total number of spikes flushed" class REGIONS(Enum): """Regions for populations.""" @@ -412,49 +412,49 @@ def _parse_spike_processing_provenance( x, y, p, self.MAX_FILLED_SIZE_OF_INPUT_BUFFER_NAME, prov.max_size_input_buffer) - # SpiNNCer - db.insert_core( - x, y, p, self.MAX_SPIKES_IN_A_TICK, - prov.max_spikes_in_a_tick) - if prov.max_spikes_in_a_tick > 200: - db.insert_report( - f"Max number of spikes for {label} was " - f"{prov.max_spikes_in_a_tick}. Empirically, we " - f"can deal with ~200 for real time performance using a " - f"1.0 ms timestep.") - - db.insert_core( - x, y, p, self.MAX_DMAS_IN_A_TICK, - prov.max_dmas_in_a_tick) - - db.insert_core( - x, y, p, self.MAX_PIPELINE_RESTARTS, - prov.max_pipeline_restarts) - - db.insert_core( - x, y, p, self.TIMER_CALLBACK_COMPLETED, - prov.timer_callback_completed) - - db.insert_core( - x, y, p, self.SPIKES_PIPELINE_ACTIVATED, - prov.spikes_pipeline_activated) - - # FLUSHED SPIKES - db.insert_core( - x, y, p, self.MAX_FLUSHED_SPIKES, - prov.max_flushed_spikes) - if prov.max_flushed_spikes > 0: - db.insert_report( - f"Max number of flushed spikes for {label} was " - f"was {prov.max_flushed_spikes}.") - - db.insert_core( - x, y, p, self.TOTAL_FLUSHED_SPIKES, - prov.total_flushed_spikes) - if prov.total_flushed_spikes > 0: - db.insert_report( - f"Total number of flushed spikes for {label} was " - f"{prov.total_flushed_spikes}.") + # # SpiNNCer + # db.insert_core( + # x, y, p, self.MAX_SPIKES_IN_A_TICK, + # prov.max_spikes_in_a_tick) + # if prov.max_spikes_in_a_tick > 200: + # db.insert_report( + # f"Max number of spikes for {label} was " + # f"{prov.max_spikes_in_a_tick}. Empirically, we " + # f"can deal with ~200 for real time performance using a " + # f"1.0 ms timestep.") + # + # db.insert_core( + # x, y, p, self.MAX_DMAS_IN_A_TICK, + # prov.max_dmas_in_a_tick) + # + # db.insert_core( + # x, y, p, self.MAX_PIPELINE_RESTARTS, + # prov.max_pipeline_restarts) + # + # db.insert_core( + # x, y, p, self.TIMER_CALLBACK_COMPLETED, + # prov.timer_callback_completed) + # + # db.insert_core( + # x, y, p, self.SPIKES_PIPELINE_ACTIVATED, + # prov.spikes_pipeline_activated) + # + # # FLUSHED SPIKES + # db.insert_core( + # x, y, p, self.MAX_FLUSHED_SPIKES, + # prov.max_flushed_spikes) + # if prov.max_flushed_spikes > 0: + # db.insert_report( + # f"Max number of flushed spikes for {label} was " + # f"was {prov.max_flushed_spikes}.") + # + # db.insert_core( + # x, y, p, self.TOTAL_FLUSHED_SPIKES, + # prov.total_flushed_spikes) + # if prov.total_flushed_spikes > 0: + # db.insert_report( + # f"Total number of flushed spikes for {label} was " + # f"{prov.total_flushed_spikes}.") @overrides(PopulationMachineNeurons.set_do_neuron_regeneration) def set_do_neuron_regeneration(self): diff --git a/spynnaker/pyNN/models/neuron/population_synapses_machine_vertex_common.py b/spynnaker/pyNN/models/neuron/population_synapses_machine_vertex_common.py index 6ffef53a08e..3bea68e030a 100644 --- a/spynnaker/pyNN/models/neuron/population_synapses_machine_vertex_common.py +++ b/spynnaker/pyNN/models/neuron/population_synapses_machine_vertex_common.py @@ -68,7 +68,21 @@ class SpikeProcessingFastProvenance(ctypes.LittleEndianStructure): # The latest time a spike was received ("latest_receive", ctypes.c_uint32), # The maximum overflow of spikes in a time step - ("max_spikes_overflow", ctypes.c_uint32) + ("max_spikes_overflow", ctypes.c_uint32), + # Custom provenance from SpiNNCer - max spikes in a tick + ("max_spikes_in_a_tick", ctypes.c_uint32), + # max dmas in a tick + ("max_dmas_in_a_tick", ctypes.c_uint32), + # max pipeline restarts + ("max_pipeline_restarts", ctypes.c_uint32), + # timer callback completed? + ("timer_callback_completed", ctypes.c_uint32), + # spikes pipeline activated? + ("spikes_pipeline_activated", ctypes.c_uint32), + # Max flushed spikes in a timestep + ("max_flushed_spikes", ctypes.c_uint32), + # Total flushed spikes + ("total_flushed_spikes", ctypes.c_uint32) ] N_ITEMS = len(_fields_) @@ -95,6 +109,16 @@ class PopulationSynapsesMachineVertexCommon( LATEST_RECEIVE = "Latest_receive_time" MAX_SPIKE_OVERFLOW = "Max_spike_overflow_in_time_step" + # Custom provenance from SpiNNCer + MAX_SPIKES_IN_A_TICK = "Maximum number of spikes in a timer tick" + MAX_DMAS_IN_A_TICK = "Maximum number of DMAs in a timer tick" + MAX_PIPELINE_RESTARTS = "Maximum pipeline restarts" + TIMER_CALLBACK_COMPLETED = "Was the timer callback completed?" + SPIKES_PIPELINE_ACTIVATED = "Was the spikes pipeline activated?" + # Flushed spikes + MAX_FLUSHED_SPIKES = "Maximum number of spikes flushed in a timer tick" + TOTAL_FLUSHED_SPIKES = "Total number of spikes flushed" + __slots__ = [ "__sdram_partition", "__neuron_vertex", @@ -369,3 +393,47 @@ def _parse_spike_processing_fast_provenance( x, y, p, self.LATEST_RECEIVE, prov.latest_receive) db.insert_core( x, y, p, self.MAX_SPIKE_OVERFLOW, prov.max_spikes_overflow) + + # SpiNNCer + db.insert_core( + x, y, p, self.MAX_SPIKES_IN_A_TICK, + prov.max_spikes_in_a_tick) + if prov.max_spikes_in_a_tick > 200: + db.insert_report( + f"Max number of spikes for {label} was " + f"{prov.max_spikes_in_a_tick}. Empirically, we " + f"can deal with ~200 for real time performance using a " + f"1.0 ms timestep.") + + db.insert_core( + x, y, p, self.MAX_DMAS_IN_A_TICK, + prov.max_dmas_in_a_tick) + + db.insert_core( + x, y, p, self.MAX_PIPELINE_RESTARTS, + prov.max_pipeline_restarts) + + db.insert_core( + x, y, p, self.TIMER_CALLBACK_COMPLETED, + prov.timer_callback_completed) + + db.insert_core( + x, y, p, self.SPIKES_PIPELINE_ACTIVATED, + prov.spikes_pipeline_activated) + + # FLUSHED SPIKES + db.insert_core( + x, y, p, self.MAX_FLUSHED_SPIKES, + prov.max_flushed_spikes) + if prov.max_flushed_spikes > 0: + db.insert_report( + f"Max number of flushed spikes for {label} was " + f"was {prov.max_flushed_spikes}.") + + db.insert_core( + x, y, p, self.TOTAL_FLUSHED_SPIKES, + prov.total_flushed_spikes) + if prov.total_flushed_spikes > 0: + db.insert_report( + f"Total number of flushed spikes for {label} was " + f"{prov.total_flushed_spikes}.") From 6eaebd3bf5582fa579ca6a881f65451d56cd1b0f Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 18 Nov 2022 14:44:23 +0000 Subject: [PATCH 092/108] vera remove empty line --- neural_modelling/src/neuron/spike_processing_fast.c | 1 - 1 file changed, 1 deletion(-) diff --git a/neural_modelling/src/neuron/spike_processing_fast.c b/neural_modelling/src/neuron/spike_processing_fast.c index 608b58705d9..ff22eb46940 100644 --- a/neural_modelling/src/neuron/spike_processing_fast.c +++ b/neural_modelling/src/neuron/spike_processing_fast.c @@ -725,4 +725,3 @@ uint32_t spike_processing_get_max_flushed_spikes(){ return max_flushed_spikes; } #endif - From a0122e3b2bdd69425aeec1c5290ebca2bbe4016f Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Fri, 18 Nov 2022 15:07:42 +0000 Subject: [PATCH 093/108] Actually copy everything across properly --- neural_modelling/src/neuron/c_main_synapses.c | 4 ++ .../src/neuron/spike_processing.c | 42 +++++++++---------- .../src/neuron/spike_processing_fast.c | 20 +++++++++ 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/neural_modelling/src/neuron/c_main_synapses.c b/neural_modelling/src/neuron/c_main_synapses.c index c60cf0aac11..c73e5abab93 100644 --- a/neural_modelling/src/neuron/c_main_synapses.c +++ b/neural_modelling/src/neuron/c_main_synapses.c @@ -40,6 +40,10 @@ #include "structural_plasticity/synaptogenesis_dynamics.h" #include +// FLUSH SPIKES +bool timer_callback_active = false; +extern volatile bool dma_busy; + //! values for the priority for each callback typedef enum callback_priorities { MC = -1, DMA = -2, TIMER = 0, SDP = 0 diff --git a/neural_modelling/src/neuron/spike_processing.c b/neural_modelling/src/neuron/spike_processing.c index b27e08ab074..6edc6dfce21 100644 --- a/neural_modelling/src/neuron/spike_processing.c +++ b/neural_modelling/src/neuron/spike_processing.c @@ -27,7 +27,7 @@ #include #include -extern bool timer_callback_active; +//extern bool timer_callback_active; //! DMA buffer structure combines the row read from SDRAM with information //! about the read. @@ -297,26 +297,26 @@ static inline void start_dma_loop(void) { } } -#if LOG_LEVEL >= LOG_DEBUG - // if timer is getting low, don't do next DMA and instead flush spike buffer - // originally 6657 clock cycles from the end of the interval was used - if (tc[T1_COUNT] < 6657) { - uint cpsr = spin1_int_disable(); - uint32_t spikes_remaining = in_spikes_flush_buffer(); - timer_callback_active = true; - spin1_mode_restore(cpsr); - - if (spikes_remaining > 0){ - total_flushed_spikes += spikes_remaining; - - if (spikes_remaining > max_flushed_spikes){ - max_flushed_spikes = spikes_remaining; - } - -// log_debug("--------At time: %u, flushed spikes: %u", time, spikes_remaining); - } - } -#endif +//#if LOG_LEVEL >= LOG_DEBUG +// // if timer is getting low, don't do next DMA and instead flush spike buffer +// // originally 6657 clock cycles from the end of the interval was used +// if (tc[T1_COUNT] < 6657) { +// uint cpsr = spin1_int_disable(); +// uint32_t spikes_remaining = in_spikes_flush_buffer(); +// timer_callback_active = true; +// spin1_mode_restore(cpsr); +// +// if (spikes_remaining > 0){ +// total_flushed_spikes += spikes_remaining; +// +// if (spikes_remaining > max_flushed_spikes){ +// max_flushed_spikes = spikes_remaining; +// } +// +//// log_debug("--------At time: %u, flushed spikes: %u", time, spikes_remaining); +// } +// } +//#endif } //! \brief Called when a multicast packet is received diff --git a/neural_modelling/src/neuron/spike_processing_fast.c b/neural_modelling/src/neuron/spike_processing_fast.c index ff22eb46940..9444bb5df26 100644 --- a/neural_modelling/src/neuron/spike_processing_fast.c +++ b/neural_modelling/src/neuron/spike_processing_fast.c @@ -27,6 +27,8 @@ #include #include +extern bool timer_callback_active; + //! DMA buffer structure combines the row read from SDRAM with information //! about the read. typedef struct dma_buffer { @@ -538,6 +540,24 @@ void spike_processing_fast_time_step_loop(uint32_t time, uint32_t n_rewires) { // wait_for_interrupt(); } +#if LOG_LEVEL >= LOG_DEBUG + // if timer is getting low, don't do next DMA and instead flush spike buffer + // originally 6657 clock cycles from the end of the interval was used + if (tc[T1_COUNT] < 6657) { + uint cpsr = spin1_int_disable(); + uint32_t spikes_remaining = in_spikes_flush_buffer(); + timer_callback_active = true; + spin1_mode_restore(cpsr); + if (spikes_remaining > 0){ + total_flushed_spikes += spikes_remaining; + + if (spikes_remaining > max_flushed_spikes){ + max_flushed_spikes = spikes_remaining; + } + } + } +#endif + // If the timer has gone off, that takes precedence if (is_end_of_time_step()) { clear_end_of_time_step(); From ff03fa83cdfc1265fc8987d2df0b4e0b3b307af3 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 12 Jan 2023 17:10:21 +0000 Subject: [PATCH 094/108] pylint is now more strict --- spynnaker/pyNN/models/neuron/plasticity/stdp/common.py | 5 ++--- .../neuron/synapse_dynamics/abstract_synapse_dynamics.py | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py index 7f28f379cb3..c2890eb38c3 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/common.py @@ -54,8 +54,7 @@ def get_exp_lut_array(time_step, time_constant, shift=0): def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, - fixed_point_one=STDP_FIXED_POINT_ONE, kernel_scaling=1.0, - plot=False): + kernel_scaling=1.0): sin_pwr = 20 # Calculate required time constant @@ -128,7 +127,7 @@ def write_pfpc_lut(spec, peak_time, lut_size, shift, time_probe, def write_mfvn_lut(spec, sigma, beta, lut_size, shift, time_probe, - fixed_point_one=STDP_FIXED_POINT_ONE, kernel_scaling=1.0): + kernel_scaling=1.0): cos_pwr = 2 # Calculate required time constant diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics.py index db738864657..48701d8988f 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/abstract_synapse_dynamics.py @@ -172,11 +172,10 @@ def get_weight_variance(self, connector, weights, synapse_info): """ return connector.get_weight_variance(weights, synapse_info) - def get_provenance_data(self, pre_population_label, post_population_label): + def get_provenance_data(self, synapse_info): """ Get the provenance data from this synapse dynamics object - :param str pre_population_label: - :param str post_population_label: + :param SynapseInformation synapse_info: :rtype: iterable(~spinn_front_end_common.utilities.utility_objs.ProvenanceDataItem) """ From 49aba30ef78fdc03312c79d756c29ec071364430 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 6 Feb 2023 10:38:11 +0000 Subject: [PATCH 095/108] Provenance not under debug; make STDP naming more consistent --- .../src/neuron/spike_processing_fast.c | 8 +-- .../src/neuron/spike_processing_fast.h | 4 -- .../timing_dependence_mfvn.py | 68 ++++++++++--------- .../timing_dependence_pfpc.py | 54 ++++++++------- 4 files changed, 65 insertions(+), 69 deletions(-) diff --git a/neural_modelling/src/neuron/spike_processing_fast.c b/neural_modelling/src/neuron/spike_processing_fast.c index 9444bb5df26..6c9fa1ab78a 100644 --- a/neural_modelling/src/neuron/spike_processing_fast.c +++ b/neural_modelling/src/neuron/spike_processing_fast.c @@ -126,11 +126,11 @@ static uint32_t spikes_this_time_step = 0; static uint32_t dmas_this_time_step = 0; static uint32_t pipeline_restarts = 0; -#if LOG_LEVEL >= LOG_DEBUG +//#if LOG_LEVEL >= LOG_DEBUG static uint32_t spike_pipeline_deactivation_time = 0; static uint32_t max_flushed_spikes = 0; static uint32_t total_flushed_spikes = 0; -#endif +//#endif //! The number of packets received this time step for recording static struct { @@ -702,11 +702,9 @@ void spike_processing_fast_store_provenance( prov->max_dmas_in_a_tick = max_dmas_in_a_tick; prov->max_pipeline_restarts = max_pipeline_restarts; prov->timer_callback_completed = timer_callback_completed; -#if LOG_LEVEL >= LOG_DEBUG prov->spike_pipeline_deactivated = spike_pipeline_deactivation_time; prov->max_flushed_spikes = max_flushed_spikes; prov->total_flushed_spikes = total_flushed_spikes; -#endif } // Custom provenance from SpiNNCer @@ -731,7 +729,6 @@ void spike_processing_get_and_reset_pipeline_restarts_this_tick(void) { pipeline_restarts = 0; } -#if LOG_LEVEL >= LOG_DEBUG uint32_t spike_processing_get_pipeline_deactivation_time(){ return spike_pipeline_deactivation_time; } @@ -744,4 +741,3 @@ uint32_t spike_processing_get_total_flushed_spikes(){ uint32_t spike_processing_get_max_flushed_spikes(){ return max_flushed_spikes; } -#endif diff --git a/neural_modelling/src/neuron/spike_processing_fast.h b/neural_modelling/src/neuron/spike_processing_fast.h index 51fc8684f5c..20c79ff9c5b 100644 --- a/neural_modelling/src/neuron/spike_processing_fast.h +++ b/neural_modelling/src/neuron/spike_processing_fast.h @@ -89,14 +89,12 @@ struct spike_processing_fast_provenance { uint32_t max_pipeline_restarts; //! Was the timer callback completed? uint32_t timer_callback_completed; -#if LOG_LEVEL >= LOG_DEBUG //! Was the spike pipeline deactivated? uint32_t spike_pipeline_deactivated; //! The maximum number of flushed spikes in one step uint32_t max_flushed_spikes; //! Thet total number of flushed spikes uint32_t total_flushed_spikes; -#endif }; //! \brief Set up spike processing @@ -144,7 +142,6 @@ void spike_processing_get_and_reset_dmas_this_tick(void); //! \return uint32_t number of pipeline restarts void spike_processing_get_and_reset_pipeline_restarts_this_tick(void); -#if LOG_LEVEL >= LOG_DEBUG //! \brief get time from T1 clock at which spike pipeline completed //! \return uint32_t pipeline deactivation time uint32_t spike_processing_get_pipeline_deactivation_time(); @@ -158,6 +155,5 @@ uint32_t spike_processing_get_total_flushed_spikes(); //! simulation timestep. //! \return maximum unprocessed spikes from a single timestep. uint32_t spike_processing_get_max_flushed_spikes(); -#endif #endif // _SPIKE_PROCESSING_FAST_H_ diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py index 17cfe4fcb29..02f068a200c 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py @@ -33,9 +33,9 @@ class TimingDependenceMFVN(AbstractTimingDependence): __slots__ = [ "_synapse_structure", "_tau_minus", - "_tau_minus_last_entry", + "_tau_minus_data", "_tau_plus", - "_tau_plus_last_entry", + "_tau_plus_data", "__a_plus", "__a_minus", "_beta", @@ -59,8 +59,8 @@ def __init__(self, tau_plus=20.0, tau_minus=20.0, A_plus=0.01, self._sigma = sigma # provenance data - self._tau_plus_last_entry = None - self._tau_minus_last_entry = None + self._tau_plus_data = None + self._tau_minus_data = None @property def tau_plus(self): @@ -138,7 +138,7 @@ def write_parameters( "exp cos LUT generation currently only supports 1ms timesteps") # Write exp_sin lookup table - self._tau_plus_last_entry = write_mfvn_lut( + self._tau_plus_data = write_mfvn_lut( spec, sigma=self._sigma, beta=self._beta, @@ -153,43 +153,45 @@ def synaptic_structure(self): @overrides(AbstractTimingDependence.get_provenance_data) def get_provenance_data(self, synapse_info): - tauplus = self._tau_plus_last_entry - tauminus = self._tau_minus_last_entry + tauplus = 0 + if self._tau_plus_data is not None: + tauplus = self._tau_plus_data[-1] + tauminus = 0 + if self._tau_minus_data is not None: + tauminus = self._tau_minus_data[-1] with ProvenanceWriter() as db: db.insert_lut( synapse_info.pre_population.label, synapse_info.post_population.label, - self.__class__.__name__, "tau_plus_last_entry", + self.__class__.__name__, "tau_plus last_entry", tauplus) - if tauplus is not None: - if tauplus[-1] > 0: - db.insert_report( - f"The last entry in the STDP exponential lookup table " - f"for the tau_plus parameter of the" - f"{self.__class__.__name__} between " - f"{synapse_info.pre_population.label} and " - f"{synapse_info.post_population.label} was {tauplus} " - f"rather than 0, indicating that the lookup table was " - f"not big enough at this timestep and value. Try " - f"reducing the parameter value, or increasing the " - f"timestep.") + if tauplus > 0: + db.insert_report( + f"The last entry in the STDP exponential lookup table " + f"for the tau_plus parameter of the" + f"{self.__class__.__name__} between " + f"{synapse_info.pre_population.label} and " + f"{synapse_info.post_population.label} was {tauplus} " + f"rather than 0, indicating that the lookup table was " + f"not big enough at this timestep and value. Try " + f"reducing the parameter value, or increasing the " + f"timestep.") db.insert_lut( synapse_info.pre_population.label, synapse_info.post_population.label, - self.__class__.__name__, "tau_minus_last_entry", + self.__class__.__name__, "tau_minus last_entry", tauminus) - if tauminus is not None: - if tauminus > 0: - db.insert_report( - f"The last entry in the STDP exponential lookup table " - f"for the tau_minus parameter of the " - f"{self.__class__.__name__} between " - f"{synapse_info.pre_population.label} and " - f"{synapse_info.post_population.label} was {tauminus} " - f"rather than 0, indicating that the lookup table was " - f"not big enough at this timestep and value. Try " - f"reducing the parameter value, or increasing the " - f"timestep.") + if tauminus > 0: + db.insert_report( + f"The last entry in the STDP exponential lookup table " + f"for the tau_minus parameter of the " + f"{self.__class__.__name__} between " + f"{synapse_info.pre_population.label} and " + f"{synapse_info.post_population.label} was {tauminus} " + f"rather than 0, indicating that the lookup table was " + f"not big enough at this timestep and value. Try " + f"reducing the parameter value, or increasing the " + f"timestep.") @overrides(AbstractTimingDependence.get_parameter_names) def get_parameter_names(self): diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index 4cf288a78b4..423945d8e98 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -141,43 +141,45 @@ def synaptic_structure(self): @overrides(AbstractTimingDependence.get_provenance_data) def get_provenance_data(self, synapse_info): - tauplus = self._tau_plus_data[-1] - tauminus = self._tau_minus_data + tauplus = 0 + if self._tau_plus_data is not None: + tauplus = self._tau_plus_data[-1] + tauminus = 0 + if self._tau_minus_data is not None: + tauminus = self._tau_minus_data[-1] with ProvenanceWriter() as db: db.insert_lut( synapse_info.pre_population.label, synapse_info.post_population.label, self.__class__.__name__, "tau_plus_last_entry", tauplus) - if tauplus is not None: - if tauplus > 0: - db.insert_report( - f"The last entry in the STDP exponential lookup table " - f"for the tau_plus parameter of the" - f"{self.__class__.__name__} between " - f"{synapse_info.pre_population.label} and " - f"{synapse_info.post_population.label} was {tauplus} " - f"rather than 0, indicating that the lookup table was " - f"not big enough at this timestep and value. Try " - f"reducing the parameter value, or increasing the " - f"timestep.") + if tauplus > 0: + db.insert_report( + f"The last entry in the STDP exponential lookup table " + f"for the tau_plus parameter of the" + f"{self.__class__.__name__} between " + f"{synapse_info.pre_population.label} and " + f"{synapse_info.post_population.label} was {tauplus} " + f"rather than 0, indicating that the lookup table was " + f"not big enough at this timestep and value. Try " + f"reducing the parameter value, or increasing the " + f"timestep.") db.insert_lut( synapse_info.pre_population.label, synapse_info.post_population.label, self.__class__.__name__, "tau_minus_last_entry", tauminus) - if tauminus is not None: - if tauminus > 0: - db.insert_report( - f"The last entry in the STDP exponential lookup table " - f"for the tau_minus parameter of the " - f"{self.__class__.__name__} between " - f"{synapse_info.pre_population.label} and " - f"{synapse_info.post_population.label} was {tauminus} " - f"rather than 0, indicating that the lookup table was " - f"not big enough at this timestep and value. Try " - f"reducing the parameter value, or increasing the " - f"timestep.") + if tauminus > 0: + db.insert_report( + f"The last entry in the STDP exponential lookup table " + f"for the tau_minus parameter of the " + f"{self.__class__.__name__} between " + f"{synapse_info.pre_population.label} and " + f"{synapse_info.post_population.label} was {tauminus} " + f"rather than 0, indicating that the lookup table was " + f"not big enough at this timestep and value. Try " + f"reducing the parameter value, or increasing the " + f"timestep.") @overrides(AbstractTimingDependence.get_parameter_names) def get_parameter_names(self): From 741a51a191c0e94f20b61bf15cd600d0abb22182 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 20 Feb 2023 14:58:49 +0000 Subject: [PATCH 096/108] Update license on new files --- .../neuron/IF_cond_exp_cerebellum/Makefile | 19 +++++++++--------- .../Makefile | 19 +++++++++--------- .../Makefile | 19 +++++++++--------- .../IF_cond_exp_cerebellum_neuron/Makefile | 19 +++++++++--------- .../synapses_stdp_mad_mfvn_mfvn/Makefile | 19 +++++++++--------- .../synapses_stdp_mad_pfpc_pfpc/Makefile | 19 +++++++++--------- .../models/neuron_model_lif_t_last_impl.h | 19 +++++++++--------- .../synapse_dynamics_stdp_mad_mfvn_impl.c | 19 +++++++++--------- .../synapse_dynamics_stdp_mad_pfpc_impl.c | 19 +++++++++--------- .../stdp/timing_dependence/timing_mfvn_impl.c | 19 +++++++++--------- .../stdp/timing_dependence/timing_mfvn_impl.h | 19 +++++++++--------- .../stdp/timing_dependence/timing_pfpc_impl.c | 19 +++++++++--------- .../stdp/timing_dependence/timing_pfpc_impl.h | 19 +++++++++--------- .../stdp/weight_dependence/weight_mfvn_impl.c | 19 +++++++++--------- .../stdp/weight_dependence/weight_mfvn_impl.h | 19 +++++++++--------- .../stdp/weight_dependence/weight_pfpc_impl.c | 19 +++++++++--------- .../stdp/weight_dependence/weight_pfpc_impl.h | 19 +++++++++--------- .../timing_dependence_mfvn.py | 20 +++++++++---------- .../timing_dependence_pfpc.py | 20 +++++++++---------- .../weight_dependence_mfvn.py | 19 +++++++++--------- .../weight_dependence_pfpc.py | 19 +++++++++--------- 21 files changed, 191 insertions(+), 210 deletions(-) diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile index df6416258cf..a3c798bed46 100644 --- a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile +++ b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile @@ -1,17 +1,16 @@ # Copyright (c) 2017-2021 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. APP = $(notdir $(CURDIR)) diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile index a044504829b..b1e8bd400ba 100644 --- a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile +++ b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile @@ -1,17 +1,16 @@ # Copyright (c) 2017-2021 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. APP = $(notdir $(CURDIR)) diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile index 01e03552bf1..4c6d423e145 100644 --- a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile +++ b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile @@ -1,17 +1,16 @@ # Copyright (c) 2017-2021 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. APP = $(notdir $(CURDIR)) diff --git a/neural_modelling/makefiles/neuron_only/IF_cond_exp_cerebellum_neuron/Makefile b/neural_modelling/makefiles/neuron_only/IF_cond_exp_cerebellum_neuron/Makefile index 06b1972a50b..88637c90816 100644 --- a/neural_modelling/makefiles/neuron_only/IF_cond_exp_cerebellum_neuron/Makefile +++ b/neural_modelling/makefiles/neuron_only/IF_cond_exp_cerebellum_neuron/Makefile @@ -1,17 +1,16 @@ # Copyright (c) 2017-2019 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. APP = $(notdir $(CURDIR)) diff --git a/neural_modelling/makefiles/synapse_only/synapses_stdp_mad_mfvn_mfvn/Makefile b/neural_modelling/makefiles/synapse_only/synapses_stdp_mad_mfvn_mfvn/Makefile index 94d6d7f89c7..48c20e6a2ef 100644 --- a/neural_modelling/makefiles/synapse_only/synapses_stdp_mad_mfvn_mfvn/Makefile +++ b/neural_modelling/makefiles/synapse_only/synapses_stdp_mad_mfvn_mfvn/Makefile @@ -1,17 +1,16 @@ # Copyright (c) 2017-2019 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. APP = $(notdir $(CURDIR)) diff --git a/neural_modelling/makefiles/synapse_only/synapses_stdp_mad_pfpc_pfpc/Makefile b/neural_modelling/makefiles/synapse_only/synapses_stdp_mad_pfpc_pfpc/Makefile index e516fe5ee87..e6bf26ff757 100644 --- a/neural_modelling/makefiles/synapse_only/synapses_stdp_mad_pfpc_pfpc/Makefile +++ b/neural_modelling/makefiles/synapse_only/synapses_stdp_mad_pfpc_pfpc/Makefile @@ -1,17 +1,16 @@ # Copyright (c) 2017-2019 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. APP = $(notdir $(CURDIR)) diff --git a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h index bd6833d4b00..4dc9b57d401 100644 --- a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h +++ b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h @@ -1,18 +1,17 @@ /* * Copyright (c) 2017-2021 The University of Manchester * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #ifndef _NEURON_MODEL_LIF_CURR_T_LAST_IMPL_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c index b579c27feae..a229e485315 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c @@ -1,18 +1,17 @@ /* * Copyright (c) 2017-2019 The University of Manchester * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ //! \file diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c index 5bb7920c644..8d168c693e3 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c @@ -1,18 +1,17 @@ /* * Copyright (c) 2017-2019 The University of Manchester * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ //! \file diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c index b61e6f56beb..a324f6af790 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.c @@ -1,18 +1,17 @@ /* * Copyright (c) 2017-2021 The University of Manchester * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #include "timing_mfvn_impl.h" diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h index e0614310045..c90a76253ba 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_mfvn_impl.h @@ -1,18 +1,17 @@ /* * Copyright (c) 2017-2021 The University of Manchester * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #ifndef _TIMING_MFVN_IMPL_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c index efbf2d764f3..a09b986876c 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.c @@ -1,18 +1,17 @@ /* * Copyright (c) 2017-2021 The University of Manchester * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #include "timing_pfpc_impl.h" diff --git a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h index e1a4429278a..6a8b43b663b 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/timing_dependence/timing_pfpc_impl.h @@ -1,18 +1,17 @@ /* * Copyright (c) 2017-2021 The University of Manchester * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #ifndef _TIMING_PFPC_IMPL_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c index 8b5456c457e..d12e6a8f440 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.c @@ -1,18 +1,17 @@ /* * Copyright (c) 2017-2021 The University of Manchester * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #include "weight_mfvn_impl.h" diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h index bb2e040e1ca..cb71c95e7d5 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_mfvn_impl.h @@ -1,18 +1,17 @@ /* * Copyright (c) 2017-2021 The University of Manchester * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #ifndef _WEIGHT_MFVN_IMPL_H_ diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c index 76f7a983a72..ca7eabde27b 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.c @@ -1,18 +1,17 @@ /* * Copyright (c) 2017-2021 The University of Manchester * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #include "weight_pfpc_impl.h" diff --git a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h index bf13ec57763..524779bb96d 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h +++ b/neural_modelling/src/neuron/plasticity/stdp/weight_dependence/weight_pfpc_impl.h @@ -1,18 +1,17 @@ /* * Copyright (c) 2017-2021 The University of Manchester * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #ifndef _WEIGHT_PFPC_IMPL_H_ diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py index 02f068a200c..1b5643f325a 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_mfvn.py @@ -1,17 +1,17 @@ # Copyright (c) 2017-2019 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from spinn_utilities.overrides import overrides from spinn_front_end_common.interface.provenance import ProvenanceWriter from spynnaker.pyNN.data import SpynnakerDataView diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py index 423945d8e98..3073a7b1a69 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/timing_dependence/timing_dependence_pfpc.py @@ -1,17 +1,17 @@ # Copyright (c) 2017-2019 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from spinn_utilities.overrides import overrides from spinn_front_end_common.interface.provenance import ProvenanceWriter from spynnaker.pyNN.data import SpynnakerDataView diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py index a288bf948bf..382ec4f7396 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py @@ -1,17 +1,16 @@ # Copyright (c) 2017-2021 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from data_specification.enums import DataType from spinn_utilities.overrides import overrides diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py index 57e93af785b..791b3265a44 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py @@ -1,17 +1,16 @@ # Copyright (c) 2017-2021 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from data_specification.enums import DataType from spinn_utilities.overrides import overrides From f7a2d53318209aa582c9e38a13909b394b55a1de Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 20 Feb 2023 15:06:02 +0000 Subject: [PATCH 097/108] Update license --- .../neuron/builds/if_cond_exp_cerebellum.py | 20 +++++++++---------- ...n_model_leaky_integrate_and_fire_t_last.py | 19 +++++++++--------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py b/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py index 0043b7398a4..9cabff92593 100644 --- a/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py +++ b/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py @@ -1,17 +1,17 @@ # Copyright (c) 2017-2019 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from spynnaker.pyNN.models.neuron import AbstractPyNNNeuronModelStandard from spynnaker.pyNN.models.defaults import default_initial_values from spynnaker.pyNN.models.neuron.neuron_models \ diff --git a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py index f74b5653f09..4c6d44c5874 100644 --- a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py +++ b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py @@ -1,17 +1,16 @@ # Copyright (c) 2017-2021 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from spinn_utilities.overrides import overrides from data_specification.enums import DataType From bbd42f5d9169d657e0327736d386f04a8e80ec50 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 20 Feb 2023 15:17:16 +0000 Subject: [PATCH 098/108] Update license on new file --- neural_modelling/src/neuron/spike_profiling.h | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/neural_modelling/src/neuron/spike_profiling.h b/neural_modelling/src/neuron/spike_profiling.h index 3a5c6b5d2cc..8e761ef681f 100644 --- a/neural_modelling/src/neuron/spike_profiling.h +++ b/neural_modelling/src/neuron/spike_profiling.h @@ -1,18 +1,17 @@ /* - * Copyright (c) 2017-2021 The University of Manchester + * Copyright (c) 2021 The University of Manchester * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #include From f1289b0aef5fc138896522e787476f8817bbee12 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 20 Feb 2023 16:49:38 +0000 Subject: [PATCH 099/108] Update licenses --- .../timing_dependence_mfvn.py | 19 +++++++++--------- .../timing_dependence_pfpc.py | 19 +++++++++--------- .../weight_dependence_mfvn.py | 20 +++++++++---------- .../weight_dependence_pfpc.py | 20 +++++++++---------- .../model_tests/neuron/test_plastic_lut.py | 19 +++++++++--------- 5 files changed, 47 insertions(+), 50 deletions(-) diff --git a/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_mfvn.py b/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_mfvn.py index 06b461b6f43..d32fbcc9199 100644 --- a/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_mfvn.py +++ b/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_mfvn.py @@ -1,17 +1,16 @@ # Copyright (c) 2021 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence import ( TimingDependenceMFVN as diff --git a/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_pfpc.py b/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_pfpc.py index ec8a1b84231..84f422afe10 100644 --- a/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_pfpc.py +++ b/spynnaker8/models/synapse_dynamics/timing_dependence/timing_dependence_pfpc.py @@ -1,17 +1,16 @@ # Copyright (c) 2021 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence import ( TimingDependencePFPC as diff --git a/spynnaker8/models/synapse_dynamics/weight_dependence/weight_dependence_mfvn.py b/spynnaker8/models/synapse_dynamics/weight_dependence/weight_dependence_mfvn.py index be99af70f0f..6f88e595f08 100644 --- a/spynnaker8/models/synapse_dynamics/weight_dependence/weight_dependence_mfvn.py +++ b/spynnaker8/models/synapse_dynamics/weight_dependence/weight_dependence_mfvn.py @@ -1,17 +1,17 @@ # Copyright (c) 2021 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from spynnaker.pyNN.models.neuron.plasticity.stdp.weight_dependence import ( WeightDependenceMFVN as _BaseClass) diff --git a/spynnaker8/models/synapse_dynamics/weight_dependence/weight_dependence_pfpc.py b/spynnaker8/models/synapse_dynamics/weight_dependence/weight_dependence_pfpc.py index af28c5d7f7f..b8eadc72975 100644 --- a/spynnaker8/models/synapse_dynamics/weight_dependence/weight_dependence_pfpc.py +++ b/spynnaker8/models/synapse_dynamics/weight_dependence/weight_dependence_pfpc.py @@ -1,17 +1,17 @@ # Copyright (c) 2021 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from spynnaker.pyNN.models.neuron.plasticity.stdp.weight_dependence import ( WeightDependencePFPC as _BaseClass) diff --git a/unittests/model_tests/neuron/test_plastic_lut.py b/unittests/model_tests/neuron/test_plastic_lut.py index 39984a481a1..4104b1064d6 100644 --- a/unittests/model_tests/neuron/test_plastic_lut.py +++ b/unittests/model_tests/neuron/test_plastic_lut.py @@ -1,17 +1,16 @@ # Copyright (c) 2017-2019 The University of Manchester # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# http://www.apache.org/licenses/LICENSE-2.0 # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import numpy import unittest From cb27cfb85f715c79483468ae19a59fea5d4872fa Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 26 Jun 2023 08:43:51 +0100 Subject: [PATCH 100/108] DataType has moved --- .../neuron_model_leaky_integrate_and_fire_t_last.py | 2 +- .../plasticity/stdp/weight_dependence/weight_dependence_mfvn.py | 2 +- .../plasticity/stdp/weight_dependence/weight_dependence_pfpc.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py index 4c6d44c5874..1948848b6d9 100644 --- a/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py +++ b/spynnaker/pyNN/models/neuron/neuron_models/neuron_model_leaky_integrate_and_fire_t_last.py @@ -13,7 +13,7 @@ # limitations under the License. from spinn_utilities.overrides import overrides -from data_specification.enums import DataType +from spinn_front_end_common.interface.ds import DataType from spynnaker.pyNN.models.neuron.implementations import ( AbstractStandardNeuronComponent) from spynnaker.pyNN.utilities.struct import Struct diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py index 382ec4f7396..5c1b41cca7c 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_mfvn.py @@ -12,8 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -from data_specification.enums import DataType from spinn_utilities.overrides import overrides +from spinn_front_end_common.interface.ds import DataType from .abstract_has_a_plus_a_minus import AbstractHasAPlusAMinus from .abstract_weight_dependence import AbstractWeightDependence diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py index 791b3265a44..6fc63c2f1f9 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py @@ -12,8 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -from data_specification.enums import DataType from spinn_utilities.overrides import overrides +from spinn_front_end_common.interface.ds import DataType from .abstract_has_a_plus_a_minus import AbstractHasAPlusAMinus from .abstract_weight_dependence import AbstractWeightDependence From e9f5c853f4d0e491ab4555993f46944d819a24bf Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 26 Jun 2023 10:04:04 +0100 Subject: [PATCH 101/108] Update OS to use newer compiler --- .github/workflows/c_actions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/c_actions.yml b/.github/workflows/c_actions.yml index f6b8e70d297..dd105ac1e27 100644 --- a/.github/workflows/c_actions.yml +++ b/.github/workflows/c_actions.yml @@ -19,7 +19,7 @@ name: C Actions on: [push] jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 timeout-minutes: 10 steps: - name: Checkout From 35c3d2748ea0375cef2df281fd66a763ae4a0d4a Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 26 Jun 2023 15:01:55 +0100 Subject: [PATCH 102/108] Remove unneeded print statements --- .../stdp/weight_dependence/weight_dependence_pfpc.py | 3 --- .../models/neuron/synapse_dynamics/synapse_dynamics_utils.py | 2 -- 2 files changed, 5 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py index 6fc63c2f1f9..d09b074bd25 100644 --- a/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py +++ b/spynnaker/pyNN/models/neuron/plasticity/stdp/weight_dependence/weight_dependence_pfpc.py @@ -78,9 +78,6 @@ def write_parameters( # Loop through each synapse type's weight scale for _ in synapse_weight_scales: - print("PFPC, writing values min, max, pot_alpha, A_minus ", - self.__w_min, self.__w_max, self.__pot_alpha, self.A_minus) - # Scale the weights spec.write_value( data=self.__w_min * global_weight_scale, diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_utils.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_utils.py index 42eafcf1c36..8d036590e2a 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_utils.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_utils.py @@ -65,8 +65,6 @@ def calculate_spike_pair_additive_stdp_weight( depressions = a_minus * numpy.exp( (depression_times / tau_minus)) - print("Potentiations: ", potentiation_times, potentiations) - print("Depressions:", depression_times, depressions) return initial_weight + numpy.sum(potentiations) - numpy.sum(depressions) From 32df07acdc3245590b77da518f5fb5ed9b7f8fd6 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 20 Jul 2023 16:05:43 +0100 Subject: [PATCH 103/108] Tidy up C code --- .../src/neuron/spike_processing.c | 38 ------------------- .../src/neuron/spike_processing.h | 17 --------- .../src/neuron/spike_processing_fast.c | 10 +++-- neural_modelling/src/neuron/spike_profiling.h | 31 +++++++++------ neural_modelling/src/neuron/synapses.c | 13 ------- neural_modelling/src/neuron/synapses.h | 1 + 6 files changed, 26 insertions(+), 84 deletions(-) diff --git a/neural_modelling/src/neuron/spike_processing.c b/neural_modelling/src/neuron/spike_processing.c index 3684ad500ef..fb16b416adb 100644 --- a/neural_modelling/src/neuron/spike_processing.c +++ b/neural_modelling/src/neuron/spike_processing.c @@ -26,8 +26,6 @@ #include #include -//extern bool timer_callback_active; - //! DMA buffer structure combines the row read from SDRAM with information //! about the read. typedef struct dma_buffer { @@ -295,27 +293,6 @@ static inline void start_dma_loop(void) { dma_busy = true; } } - -//#if LOG_LEVEL >= LOG_DEBUG -// // if timer is getting low, don't do next DMA and instead flush spike buffer -// // originally 6657 clock cycles from the end of the interval was used -// if (tc[T1_COUNT] < 6657) { -// uint cpsr = spin1_int_disable(); -// uint32_t spikes_remaining = in_spikes_flush_buffer(); -// timer_callback_active = true; -// spin1_mode_restore(cpsr); -// -// if (spikes_remaining > 0){ -// total_flushed_spikes += spikes_remaining; -// -// if (spikes_remaining > max_flushed_spikes){ -// max_flushed_spikes = spikes_remaining; -// } -// -//// log_debug("--------At time: %u, flushed spikes: %u", time, spikes_remaining); -// } -// } -//#endif } //! \brief Called when a multicast packet is received @@ -323,7 +300,6 @@ static inline void start_dma_loop(void) { //! \param[in] unused: Only specified to match API static void multicast_packet_received_callback(uint key, UNUSED uint unused) { p_per_ts_struct.packets_this_time_step += 1; -// spikes_this_time_step += 1; if (in_spikes_add_spike(key)) { start_dma_loop(); } @@ -334,7 +310,6 @@ static void multicast_packet_received_callback(uint key, UNUSED uint unused) { //! \param[in] payload: the payload of the packet. The count. static void multicast_packet_pl_received_callback(uint key, uint payload) { p_per_ts_struct.packets_this_time_step += 1; -// spikes_this_time_step += 1; // cycle through the packet insertion bool added = false; @@ -352,7 +327,6 @@ static void multicast_packet_pl_received_callback(uint key, uint payload) { static void dma_complete_callback(UNUSED uint unused, UNUSED uint tag) { // increment the dma complete count for provenance generation -// dmas_this_time_step++; dma_complete_count++; // Get pointer to current buffer @@ -424,9 +398,6 @@ void user_event_callback(UNUSED uint unused0, UNUSED uint unused1) { dma_n_rewires = 0; dma_n_spikes = 0; - // Increment counter for spike processing pipeline restarts -// pipeline_restarts++; - if (buffer_being_read < N_DMA_BUFFERS) { // If the DMA buffer is full of valid data, attempt to reuse it on the // next data to be used, as this might be able to make use of the buffer @@ -500,15 +471,6 @@ void spike_processing_store_provenance(struct spike_processing_provenance *prov) prov->n_rewires = n_successful_rewires; prov->n_packets_dropped_from_lateness = count_input_buffer_packets_late; prov->max_filled_input_buffer_size = biggest_fill_size_of_input_buffer; -// prov->max_spikes_in_a_tick = max_spikes_in_a_tick; -// prov->max_dmas_in_a_tick = max_dmas_in_a_tick; -// prov->max_pipeline_restarts = max_pipeline_restarts; -// prov->timer_callback_completed = timer_callback_completed; -//#if LOG_LEVEL >= LOG_DEBUG -// prov->spike_pipeline_deactivated = spike_pipeline_deactivation_time; -// prov->max_flushed_spikes = max_flushed_spikes; -// prov->total_flushed_spikes = total_flushed_spikes; -//#endif } bool spike_processing_do_rewiring(int number_of_rewires) { diff --git a/neural_modelling/src/neuron/spike_processing.h b/neural_modelling/src/neuron/spike_processing.h index 0545566a5e5..d8fddfcacb8 100644 --- a/neural_modelling/src/neuron/spike_processing.h +++ b/neural_modelling/src/neuron/spike_processing.h @@ -37,23 +37,6 @@ struct spike_processing_provenance { uint32_t n_packets_dropped_from_lateness; //! The maximum size of the input buffer uint32_t max_filled_input_buffer_size; -// //! SpiNNCer-related provenance -// //! The maximum number of spikes in a tick -// uint32_t max_spikes_in_a_tick; -// //! The maximum number of DMAs in a tick -// uint32_t max_dmas_in_a_tick; -// //! The maximum number of pipeline restarts -// uint32_t max_pipeline_restarts; -// //! Was the timer callback completed? -// uint32_t timer_callback_completed; -//#if LOG_LEVEL >= LOG_DEBUG -// //! Was the spike pipeline deactivated? -// uint32_t spike_pipeline_deactivated; -// //! The maximum number of flushed spikes in one step -// uint32_t max_flushed_spikes; -// //! Thet total number of flushed spikes -// uint32_t total_flushed_spikes; -//#endif }; //! \brief Initialise the spike processing system diff --git a/neural_modelling/src/neuron/spike_processing_fast.c b/neural_modelling/src/neuron/spike_processing_fast.c index 8baee7b7cf4..c04c6960cbd 100644 --- a/neural_modelling/src/neuron/spike_processing_fast.c +++ b/neural_modelling/src/neuron/spike_processing_fast.c @@ -540,7 +540,9 @@ void spike_processing_fast_time_step_loop(uint32_t time, uint32_t n_rewires) { } #if LOG_LEVEL >= LOG_DEBUG - // if timer is getting low, don't do next DMA and instead flush spike buffer + // NOTE: this code is left over from previous testing; it's left + // here in case there's any interest in testing again using it + // If timer is getting low, don't do next DMA and instead flush spike buffer // originally 6657 clock cycles from the end of the interval was used if (tc[T1_COUNT] < 6657) { uint cpsr = spin1_int_disable(); @@ -728,15 +730,15 @@ void spike_processing_get_and_reset_pipeline_restarts_this_tick(void) { pipeline_restarts = 0; } -uint32_t spike_processing_get_pipeline_deactivation_time(){ +uint32_t spike_processing_get_pipeline_deactivation_time(void) { return spike_pipeline_deactivation_time; } // FLUSHED SPIKES -uint32_t spike_processing_get_total_flushed_spikes(){ +uint32_t spike_processing_get_total_flushed_spikes(void) { return total_flushed_spikes; } -uint32_t spike_processing_get_max_flushed_spikes(){ +uint32_t spike_processing_get_max_flushed_spikes(void) { return max_flushed_spikes; } diff --git a/neural_modelling/src/neuron/spike_profiling.h b/neural_modelling/src/neuron/spike_profiling.h index 8e761ef681f..07be6eaf77c 100644 --- a/neural_modelling/src/neuron/spike_profiling.h +++ b/neural_modelling/src/neuron/spike_profiling.h @@ -14,6 +14,9 @@ * limitations under the License. */ +#ifndef _SPIKE_PROFILING_H_ +#define _SPIKE_PROFILING_H_ + #include typedef struct spike_holder_t { @@ -81,15 +84,19 @@ static inline accum spike_profiling_get_spike_holder_as_accum( return x.acc; } -//static inline void spike_profiling_print_spikes_from_spike_holder( -// struct spike_holder_t spikes_orig) { -// io_printf(IO_BUF, "Spikes from input: a %u, b %u, c %u, d %u \n", -// spikes_orig.spikes_a, spikes_orig.spikes_b, spikes_orig.spikes_c, -// spikes_orig.spikes_d); -//} -// -//static inline void spike_profiling_print_spikes_from_int(int32_t output) { -// io_printf(IO_BUF, "Spikes from output: a %d, b %d, c %d, d %d \n", -// (output & 0xFF), (output >> 8 & 0xFF), (output >> 16 & 0xFF), -// (output >> 24 & 0xFF)); -//} +#if LOG_LEVEL >= LOG_DEBUG +static inline void spike_profiling_print_spikes_from_spike_holder( + struct spike_holder_t spikes_orig) { + io_printf(IO_BUF, "Spikes from input: a %u, b %u, c %u, d %u \n", + spikes_orig.spikes_a, spikes_orig.spikes_b, spikes_orig.spikes_c, + spikes_orig.spikes_d); +} + +static inline void spike_profiling_print_spikes_from_int(int32_t output) { + io_printf(IO_BUF, "Spikes from output: a %d, b %d, c %d, d %d \n", + (output & 0xFF), (output >> 8 & 0xFF), (output >> 16 & 0xFF), + (output >> 24 & 0xFF)); +} +#endif + +#endif // _SPIKE_PROFILING_H_ diff --git a/neural_modelling/src/neuron/synapses.c b/neural_modelling/src/neuron/synapses.c index 626b503724b..1b7e141505e 100644 --- a/neural_modelling/src/neuron/synapses.c +++ b/neural_modelling/src/neuron/synapses.c @@ -234,19 +234,6 @@ static inline bool process_fixed_synapses( uint32_t ring_buffer_index = (synaptic_word + masked_time) & ring_buffer_mask; uint32_t weight = synapse_row_sparse_weight(synaptic_word); -// // *********************************** -// // For Cerebellum plasticity -// uint32_t type = synapse_row_sparse_type(synaptic_word, -// synapse_index_bits, synapse_type_mask); -// -// if (type == 0){ -// index_t neuron_index = synapse_row_sparse_index(synaptic_word, synapse_index_mask); -// -// // io_printf(IO_BUF, "\nSpike on type: %u at time: %u\n", type, time); -// synapse_dynamics_process_post_synaptic_event(time, neuron_index); -// } -// // *********************************** - // Add weight to current ring buffer value uint32_t accumulation = ring_buffers[ring_buffer_index] + weight; diff --git a/neural_modelling/src/neuron/synapses.h b/neural_modelling/src/neuron/synapses.h index 64f71abcab0..e007ad5462b 100644 --- a/neural_modelling/src/neuron/synapses.h +++ b/neural_modelling/src/neuron/synapses.h @@ -61,6 +61,7 @@ extern uint32_t late_spikes; //! The maximum lateness of a spike extern uint32_t max_late_spike; + //! \brief Print the weight of a synapse //! \param[in] weight: the weight to print in synapse-row form //! \param[in] left_shift: the shift to use when decoding From 32535efc0ef3ff8bf7be9274e8c112847cfc0265 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Wed, 26 Jul 2023 15:46:58 +0100 Subject: [PATCH 104/108] Tidy up python code --- .../neuron/population_machine_vertex.py | 69 +------------------ .../synapse_dynamics/synapse_dynamics_stdp.py | 1 - .../synapse_dynamics_utils.py | 2 + 3 files changed, 3 insertions(+), 69 deletions(-) diff --git a/spynnaker/pyNN/models/neuron/population_machine_vertex.py b/spynnaker/pyNN/models/neuron/population_machine_vertex.py index c318c12d32d..5033f72e794 100644 --- a/spynnaker/pyNN/models/neuron/population_machine_vertex.py +++ b/spynnaker/pyNN/models/neuron/population_machine_vertex.py @@ -41,21 +41,7 @@ class SpikeProcessingProvenance(ctypes.LittleEndianStructure): # The number of packets that were dropped due to being late ("n_late_packets", ctypes.c_uint32), # The maximum size of the spike input buffer during simulation - ("max_size_input_buffer", ctypes.c_uint32), - # # Custom provenance from SpiNNCer - max spikes in a tick - # ("max_spikes_in_a_tick", ctypes.c_uint32), - # # max dmas in a tick - # ("max_dmas_in_a_tick", ctypes.c_uint32), - # # max pipeline restarts - # ("max_pipeline_restarts", ctypes.c_uint32), - # # timer callback completed? - # ("timer_callback_completed", ctypes.c_uint32), - # # spikes pipeline activated? - # ("spikes_pipeline_activated", ctypes.c_uint32), - # # Max flushed spikes in a timestep - # ("max_flushed_spikes", ctypes.c_uint32), - # # Total flushed spikes - # ("total_flushed_spikes", ctypes.c_uint32) + ("max_size_input_buffer", ctypes.c_uint32) ] N_ITEMS = len(_fields_) @@ -105,15 +91,6 @@ class PopulationMachineVertex( MAX_FILLED_SIZE_OF_INPUT_BUFFER_NAME = "Max_filled_size_input_buffer" BACKGROUND_OVERLOADS_NAME = "Times_the_background_queue_overloaded" BACKGROUND_MAX_QUEUED_NAME = "Max_backgrounds_queued" - # # Custom provenance from SpiNNCer - # MAX_SPIKES_IN_A_TICK = "Maximum number of spikes in a timer tick" - # MAX_DMAS_IN_A_TICK = "Maximum number of DMAs in a timer tick" - # MAX_PIPELINE_RESTARTS = "Maximum pipeline restarts" - # TIMER_CALLBACK_COMPLETED = "Was the timer callback completed?" - # SPIKES_PIPELINE_ACTIVATED = "Was the spikes pipeline activated?" - # # Flushed spikes - # MAX_FLUSHED_SPIKES = "Maximum number of spikes flushed in a timer tick" - # TOTAL_FLUSHED_SPIKES = "Total number of spikes flushed" class REGIONS(Enum): """ @@ -413,50 +390,6 @@ def _parse_spike_processing_provenance( x, y, p, self.MAX_FILLED_SIZE_OF_INPUT_BUFFER_NAME, prov.max_size_input_buffer) - # # SpiNNCer - # db.insert_core( - # x, y, p, self.MAX_SPIKES_IN_A_TICK, - # prov.max_spikes_in_a_tick) - # if prov.max_spikes_in_a_tick > 200: - # db.insert_report( - # f"Max number of spikes for {label} was " - # f"{prov.max_spikes_in_a_tick}. Empirically, we " - # f"can deal with ~200 for real time performance using a " - # f"1.0 ms timestep.") - # - # db.insert_core( - # x, y, p, self.MAX_DMAS_IN_A_TICK, - # prov.max_dmas_in_a_tick) - # - # db.insert_core( - # x, y, p, self.MAX_PIPELINE_RESTARTS, - # prov.max_pipeline_restarts) - # - # db.insert_core( - # x, y, p, self.TIMER_CALLBACK_COMPLETED, - # prov.timer_callback_completed) - # - # db.insert_core( - # x, y, p, self.SPIKES_PIPELINE_ACTIVATED, - # prov.spikes_pipeline_activated) - # - # # FLUSHED SPIKES - # db.insert_core( - # x, y, p, self.MAX_FLUSHED_SPIKES, - # prov.max_flushed_spikes) - # if prov.max_flushed_spikes > 0: - # db.insert_report( - # f"Max number of flushed spikes for {label} was " - # f"was {prov.max_flushed_spikes}.") - # - # db.insert_core( - # x, y, p, self.TOTAL_FLUSHED_SPIKES, - # prov.total_flushed_spikes) - # if prov.total_flushed_spikes > 0: - # db.insert_report( - # f"Total number of flushed spikes for {label} was " - # f"{prov.total_flushed_spikes}.") - @overrides(PopulationMachineNeurons.set_do_neuron_regeneration) def set_do_neuron_regeneration(self): self.__regenerate_neuron_data = True diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py index d4b9a40e92a..4fd30685106 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_stdp.py @@ -606,4 +606,3 @@ def pad_to_length(self): def get_provenance_data(self, synapse_info): self.__timing_dependence.get_provenance_data(synapse_info) - # self.__weight_dependence.get_provenance_data(synapse_info) diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_utils.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_utils.py index 8d036590e2a..53b3b21d536 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_utils.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_utils.py @@ -65,6 +65,8 @@ def calculate_spike_pair_additive_stdp_weight( depressions = a_minus * numpy.exp( (depression_times / tau_minus)) + print("Potentiations: ", potentation_times, potentiations) + print("Depressions: ", depression_times, depressions) return initial_weight + numpy.sum(potentiations) - numpy.sum(depressions) From 6cfe9e56100a9d046d79bf0a16e8e05b6c10684b Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Wed, 26 Jul 2023 16:15:15 +0100 Subject: [PATCH 105/108] flake8 --- .../models/neuron/synapse_dynamics/synapse_dynamics_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_utils.py b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_utils.py index 53b3b21d536..27d3c66b6d1 100644 --- a/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_utils.py +++ b/spynnaker/pyNN/models/neuron/synapse_dynamics/synapse_dynamics_utils.py @@ -65,7 +65,7 @@ def calculate_spike_pair_additive_stdp_weight( depressions = a_minus * numpy.exp( (depression_times / tau_minus)) - print("Potentiations: ", potentation_times, potentiations) + print("Potentiations: ", potentiation_times, potentiations) print("Depressions: ", depression_times, depressions) return initial_weight + numpy.sum(potentiations) - numpy.sum(depressions) From b570da678d52b8d427c48fc262fca4f241794abf Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 18 Sep 2023 15:14:53 +0100 Subject: [PATCH 106/108] Better match changes in standard STDP dynamics code --- .../src/neuron/plasticity/stdp/post_events.h | 20 ------------------- .../synapse_dynamics_stdp_mad_mfvn_impl.c | 6 +++--- .../synapse_dynamics_stdp_mad_pfpc_impl.c | 4 ++-- 3 files changed, 5 insertions(+), 25 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/post_events.h b/neural_modelling/src/neuron/plasticity/stdp/post_events.h index 47f2f5473b4..98cf280f88e 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/post_events.h +++ b/neural_modelling/src/neuron/plasticity/stdp/post_events.h @@ -166,26 +166,6 @@ static inline post_event_window_t post_events_next( return window; } - -//! \brief Advance a post-synaptic event window to the next (delayed) event -//! \param[in] window: The window to advance -//! \param[in] delayed_time: The delayed time -//! \return the advanced window -static inline post_event_window_t post_events_next_delayed( - post_event_window_t window, uint32_t delayed_time) { - - // Update previous time and increment next time - window.prev_time = delayed_time; - window.prev_trace = *window.next_trace++; - - // Go onto next event - window.next_time++; - - // Decrement remaining events - window.num_events--; - return window; -} - //--------------------------------------- //! \brief Add a post-synaptic event to the history //! \param[in] time: the time of the event diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c index a229e485315..b32f19543ad 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c @@ -126,13 +126,13 @@ static inline final_state_t plasticity_update_synapse( last_pre_trace, post_window.prev_time, post_window.prev_trace, current_state); - pre_window = post_events_next_delayed(pre_window, delayed_pre_time); + pre_window = post_events_next(pre_window); } // Go onto next event - post_window = post_events_next_delayed(post_window, delayed_post_time); + post_window = post_events_next(post_window); } // ************** @@ -168,7 +168,7 @@ static inline final_state_t plasticity_update_synapse( last_pre_trace, fwd_post_window.prev_time, fwd_post_window.prev_trace, current_state); - fwd_post_window = post_events_next_delayed(fwd_post_window, delayed_mf_time); + fwd_post_window = post_events_next(fwd_post_window); } // ************** diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c index 8d168c693e3..6f618f6744a 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c @@ -131,12 +131,12 @@ static inline final_state_t plasticity_update_synapse( last_pre_trace, post_window.prev_time, post_window.prev_trace, current_state); - pre_window = post_events_next_delayed(pre_window, delayed_pre_time); + pre_window = post_events_next(pre_window); } // Go onto next event - post_window = post_events_next_delayed(post_window, delayed_post_time); + post_window = post_events_next(post_window); } const uint32_t delayed_pre_time = time + delay_axonal; From 2451f723a3ece7f4f426ff373c544c9335ce7db1 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Mon, 18 Sep 2023 17:26:53 +0100 Subject: [PATCH 107/108] Setting delay_dendritic to zero is unnecessary --- .../synapse_dynamics_stdp_mad_mfvn_impl.c | 109 +----------------- .../synapse_dynamics_stdp_mad_pfpc_impl.c | 65 +---------- 2 files changed, 3 insertions(+), 171 deletions(-) diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c index b32f19543ad..9501c26a604 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_mfvn_impl.c @@ -39,19 +39,6 @@ struct synapse_row_plastic_data_t { plastic_synapse_t synapses[]; }; -//void _print_pre_event_history(pre_event_history_t pre_eve_hist){ -// -// io_printf(IO_BUF, "\n\n************************\n\n"); -// io_printf(IO_BUF, "Number recorded MF spikes: %u\n", -// pre_eve_hist.num_recorded_mf_spikes_minus_one); -// io_printf(IO_BUF, "Prev time: %u\n", -// pre_eve_hist.mf_times[pre_eve_hist.num_recorded_mf_spikes_minus_one]); -// -// for (int i = 0; i < NUM_MF_SPIKES_TO_RECORD; i++){ -// io_printf(IO_BUF, " Entry %u: %u\n", i, pre_eve_hist.mf_times[i]); -// } -//} - //--------------------------------------- // Synapse update loop //--------------------------------------- @@ -78,18 +65,6 @@ static inline final_state_t plasticity_update_synapse( window_begin_time, window_end_time, post_window.prev_time, post_window.num_events); -// if (print_plasticity){ -// io_printf(IO_BUF, " Printing PC history\n"); -// print_event_history(post_event_history); -// } -// -// if (print_plasticity){ -// io_printf(IO_BUF, "\n############ Phase 1 #############\n"); -// io_printf(IO_BUF, "\n Looping over PC spikes:\n"); -// } - - delay_dendritic = 0; - // Process events in post-synaptic window while (post_window.num_events > 0) { const uint32_t delayed_post_time = *post_window.next_time @@ -97,29 +72,14 @@ static inline final_state_t plasticity_update_synapse( uint32_t mf_begin_time = (delayed_post_time < 255) ? 0 : (delayed_post_time - 255); - post_event_window_t pre_window = post_events_get_window_delayed( pre_event_history, mf_begin_time, delayed_post_time); -// if (print_plasticity){ -// io_printf(IO_BUF, " Looping over MF window for this PC spike: %u \n", -// delayed_post_time); -// } - while (pre_window.num_events > 0) { const uint32_t delayed_pre_time = *pre_window.next_time + delay_dendritic; -// if (print_plasticity){ -// io_printf(IO_BUF, " MF Spike: %u \n", delayed_pre_time); -// -// io_printf(IO_BUF, " delta t = %u (delayed MF = %u, delayed PC = %u)\n", -// delayed_post_time - delayed_pre_time, -// delayed_pre_time, -// delayed_post_time); -// } - current_state = timing_apply_post_spike( delayed_post_time, *post_window.next_trace, (delayed_post_time - delayed_pre_time), @@ -127,10 +87,8 @@ static inline final_state_t plasticity_update_synapse( current_state); pre_window = post_events_next(pre_window); - } - // Go onto next event post_window = post_events_next(post_window); } @@ -143,24 +101,9 @@ static inline final_state_t plasticity_update_synapse( post_event_window_t fwd_post_window = post_events_get_window_delayed( post_event_history, fwd_window_begin_time, window_end_time); - -// if (print_plasticity){ -// io_printf(IO_BUF, "\n############ Phase 2 #############\n"); -// io_printf(IO_BUF, -// " Looping over all PC spikes and comparing to latest MF spike at: %u\n", -// time+delay_dendritic); -// } - while (fwd_post_window.num_events > 0) { const uint32_t delayed_mf_time = *fwd_post_window.next_time + delay_dendritic; -// if (print_plasticity){ -// io_printf(IO_BUF, " PC spike: %u, dt: %u\n", -// delayed_mf_time, -// (time+delay_dendritic - delayed_mf_time) -// ); -// } - // Some of these variables aren't used current_state = timing_apply_post_spike( delayed_mf_time, *fwd_post_window.next_trace, @@ -171,17 +114,10 @@ static inline final_state_t plasticity_update_synapse( fwd_post_window = post_events_next(fwd_post_window); } - // ************** - const uint32_t delayed_pre_time = time + delay_axonal; -// if (print_plasticity){ -// log_debug("\t\tApplying pre-synaptic event at time:%u last post time:%u\n", -// delayed_pre_time, post_window.prev_time); -// } - // Apply spike to state - // **NOTE** dendritic delay is subtracted + // **NOTE** dendritic delay is subtracted already current_state = timing_apply_pre_spike( delayed_pre_time, new_pre_trace, delayed_last_pre_time, last_pre_trace, post_window.prev_time, post_window.prev_trace, current_state); @@ -190,29 +126,6 @@ static inline final_state_t plasticity_update_synapse( return synapse_structure_get_final_state(current_state); } -//--------------------------------------- -// Synaptic row plastic-region implementation -//--------------------------------------- -//static inline plastic_synapse_t* _plastic_synapses( -// address_t plastic_region_address) { -// const uint32_t pre_event_history_size_words = -// sizeof(pre_event_history_t) / sizeof(uint32_t); -// static_assert(pre_event_history_size_words * sizeof(uint32_t) -// == sizeof(pre_event_history_t), -// "Size of pre_event_history_t structure should be a multiple" -// " of 32-bit words"); -// -// return (plastic_synapse_t*) -// (&plastic_region_address[pre_event_history_size_words]); -//} -// -////--------------------------------------- -//static inline pre_event_history_t *_plastic_event_history( -// address_t plastic_region_address) { -// return (pre_event_history_t*) (&plastic_region_address[0]); -//} - - //--------------------------------------- static inline index_t sparse_axonal_delay(uint32_t x) { #if 1 @@ -277,10 +190,6 @@ bool synapse_dynamics_process_plastic_synapses( weight_t *ring_buffers, uint32_t time, uint32_t colour_delay, bool *write_back) { -// if (print_plasticity){ -// io_printf(IO_BUF, "\n############ New Plasticity Update #############\n"); -// } - // Extract separate arrays of plastic synapses (from plastic region), // Control words (from fixed region) and number of plastic synapses plastic_synapse_t *plastic_words = plastic_region_address->synapses; @@ -303,12 +212,7 @@ bool synapse_dynamics_process_plastic_synapses( post_events_add(time - colour_delay, &plastic_region_address->history, 0); // Update pre-synaptic trace -// if (print_plasticity){ -// io_printf(IO_BUF, -// "\nAdding pre-synaptic event (mossy fibre spike) at time: %u\n\n", time); -// } - - timing_add_pre_spike(time - colour_delay, last_pre_time, 0); // last_pre_trace); + timing_add_pre_spike(time - colour_delay, last_pre_time, last_pre_trace); // Loop through plastic synapses for (; n_plastic_synapses > 0; n_plastic_synapses--) { @@ -323,21 +227,12 @@ bool synapse_dynamics_process_plastic_synapses( plastic_words++; } -// if (print_plasticity){ -// io_printf(IO_BUF, "\n############ Completed Plasticity Update #############\n"); -// } - *write_back = true; return true; } void synapse_dynamics_process_post_synaptic_event( uint32_t time, index_t neuron_index) { - -// if (print_plasticity){ -// log_debug("Adding post-synaptic event (PC spike)to history at time:%u", time); -// } - // Add post-event post_event_history_t *history = &post_event_history[neuron_index]; const uint32_t last_post_time = history->times[history->count_minus_one]; diff --git a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c index 6f618f6744a..972d55fd14c 100644 --- a/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c +++ b/neural_modelling/src/neuron/plasticity/stdp/synapse_dynamics_stdp_mad_pfpc_impl.c @@ -41,19 +41,6 @@ struct synapse_row_plastic_data_t { plastic_synapse_t synapses[]; }; -void _print_pre_event_history(pre_event_history_t pre_eve_hist){ - - io_printf(IO_BUF, "\n\n************************\n\n"); - io_printf(IO_BUF, "Number recorded spikes: %u\n", pre_eve_hist.num_recorded_pf_spikes_minus_one); - io_printf(IO_BUF, "Prev time: %u\n", - pre_eve_hist.pf_times[pre_eve_hist.num_recorded_pf_spikes_minus_one]); - - for (int i = 0; i < NUM_PF_SPIKES_TO_RECORD; i ++){ - io_printf(IO_BUF, " Entry %u: %u\n", i, pre_eve_hist.pf_times[i]); - } - -} - //--------------------------------------- // Synapse update loop //--------------------------------------- @@ -75,22 +62,6 @@ static inline final_state_t plasticity_update_synapse( post_event_window_t post_window = post_events_get_window_delayed( post_event_history, window_begin_time, window_end_time); - -// if (print_plasticity){ -// log_info("\tPerforming deferred synapse update at time:%u", time); -// log_info("\t\tbegin_time:%u, end_time:%u - prev_time:%u, num_events:%u", -// window_begin_time, window_end_time, post_window.prev_time, -// post_window.num_events); -// io_printf(IO_BUF, " Printing CF history\n"); -// print_event_history(post_event_history); -// } - -// if (print_plasticity){ -// io_printf(IO_BUF, "\n Looping over climbing fibre spikes:\n"); -// } - - delay_dendritic = 0; - // Process events in post-synaptic window while (post_window.num_events > 0) { const uint32_t delayed_post_time = *post_window.next_time @@ -98,33 +69,14 @@ static inline final_state_t plasticity_update_synapse( uint32_t pf_begin_time = (delayed_post_time < 255) ? 0 : (delayed_post_time - 255); -// if (print_plasticity){ -// io_printf(IO_BUF, " Applying post-synaptic event at delayed time:%u\n", -// delayed_post_time); -// } - post_event_window_t pre_window = post_events_get_window_delayed( pre_event_history, pf_begin_time, delayed_post_time); -// if (print_plasticity){ -// io_printf(IO_BUF, " Looping over PF window for this CF spike\n", -// delayed_post_time); -// } - while (pre_window.num_events > 0) { const uint32_t delayed_pre_time = *pre_window.next_time + delay_dendritic; -// if (print_plasticity){ -// io_printf(IO_BUF, " PF Spike: %u \n", delayed_pre_time); -// -// io_printf(IO_BUF, " delta t = %u (delayed PF = %u, delayed CF = %u)\n", -// delayed_post_time - delayed_pre_time, -// delayed_pre_time, -// delayed_post_time); -// } - current_state = timing_apply_post_spike( delayed_post_time, *post_window.next_trace, (delayed_post_time - delayed_pre_time), @@ -141,13 +93,8 @@ static inline final_state_t plasticity_update_synapse( const uint32_t delayed_pre_time = time + delay_axonal; -// if (print_plasticity){ -// log_debug("\t\tApplying pre-synaptic event at time:%u last post time:%u\n", -// delayed_pre_time, post_window.prev_time); -// } - // Apply spike to state - // **NOTE** dendritic delay is subtracted + // **NOTE** dendritic delay is subtracted already current_state = timing_apply_pre_spike( delayed_pre_time, new_pre_trace, delayed_last_pre_time, last_pre_trace, post_window.prev_time, post_window.prev_trace, current_state); @@ -265,11 +212,6 @@ bool synapse_dynamics_process_plastic_synapses( post_events_add(time - colour_delay, &plastic_region_address->history, 0); // Update pre-synaptic trace -// if (print_plasticity){ -// io_printf(IO_BUF, -// "\nAdding pre-synaptic event (parallel fibre spike) at time: %u\n\n", time); -// } - timing_add_pre_spike(time - colour_delay, last_pre_time, last_pre_trace); // Loop through plastic synapses @@ -291,11 +233,6 @@ bool synapse_dynamics_process_plastic_synapses( void synapse_dynamics_process_post_synaptic_event( uint32_t time, index_t neuron_index) { - -// if (print_plasticity){ -// log_debug("Adding post-synaptic event to trace at time:%u", time); -// } - // Add post-event post_event_history_t *history = &post_event_history[neuron_index]; const uint32_t last_post_time = history->times[history->count_minus_one]; From e75c1f88a297eac11e29c55974b8ac119605a5c4 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Tue, 19 Sep 2023 16:58:59 +0100 Subject: [PATCH 108/108] Remove model no longer needed and tidy up code --- .../neuron/IF_cond_exp_cerebellum/Makefile | 24 -- .../Makefile | 2 +- .../Makefile | 2 +- neural_modelling/makefiles/neuron/Makefile | 1 - .../IF_cond_exp_cerebellum_neuron/Makefile | 23 -- .../makefiles/neuron_only/Makefile | 1 - .../models/neuron_model_lif_t_last_impl.h | 219 ------------------ spynnaker/pyNN/extra_models/__init__.py | 8 +- .../neuron/builds/if_cond_exp_cerebellum.py | 49 ---- spynnaker8/extra_models/__init__.py | 6 +- 10 files changed, 4 insertions(+), 331 deletions(-) delete mode 100644 neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile rename neural_modelling/makefiles/neuron/{IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn => IF_cond_exp_stdp_mad_mfvn_mfvn}/Makefile (95%) rename neural_modelling/makefiles/neuron/{IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc => IF_cond_exp_stdp_mad_pfpc_pfpc}/Makefile (95%) delete mode 100644 neural_modelling/makefiles/neuron_only/IF_cond_exp_cerebellum_neuron/Makefile delete mode 100644 neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h delete mode 100644 spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile deleted file mode 100644 index a3c798bed46..00000000000 --- a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) 2017-2021 The University of Manchester -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -APP = $(notdir $(CURDIR)) - -NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_t_last_impl.h -INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_conductance.h -NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h -THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h -SYNAPSE_TYPE_H = $(NEURON_DIR)/neuron/synapse_types/synapse_types_exponential_impl.h -SYNAPSE_DYNAMICS = $(NEURON_DIR)/neuron/plasticity/synapse_dynamics_static_impl.c - -include ../neural_build.mk diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_stdp_mad_mfvn_mfvn/Makefile similarity index 95% rename from neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile rename to neural_modelling/makefiles/neuron/IF_cond_exp_stdp_mad_mfvn_mfvn/Makefile index b1e8bd400ba..2613796a29d 100644 --- a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_mfvn_mfvn/Makefile +++ b/neural_modelling/makefiles/neuron/IF_cond_exp_stdp_mad_mfvn_mfvn/Makefile @@ -14,7 +14,7 @@ APP = $(notdir $(CURDIR)) -NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_t_last_impl.h +NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.h INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_conductance.h NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h diff --git a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile b/neural_modelling/makefiles/neuron/IF_cond_exp_stdp_mad_pfpc_pfpc/Makefile similarity index 95% rename from neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile rename to neural_modelling/makefiles/neuron/IF_cond_exp_stdp_mad_pfpc_pfpc/Makefile index 4c6d423e145..eec66be7dbb 100644 --- a/neural_modelling/makefiles/neuron/IF_cond_exp_cerebellum_stdp_mad_pfpc_pfpc/Makefile +++ b/neural_modelling/makefiles/neuron/IF_cond_exp_stdp_mad_pfpc_pfpc/Makefile @@ -14,7 +14,7 @@ APP = $(notdir $(CURDIR)) -NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_t_last_impl.h +NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_impl.h INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_conductance.h NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h diff --git a/neural_modelling/makefiles/neuron/Makefile b/neural_modelling/makefiles/neuron/Makefile index 46a15cafa97..d9b72886d0c 100644 --- a/neural_modelling/makefiles/neuron/Makefile +++ b/neural_modelling/makefiles/neuron/Makefile @@ -19,7 +19,6 @@ MODELS = IF_curr_exp \ IF_curr_exp_dual \ IZK_cond_exp_dual \ IF_curr_delta \ - IF_cond_exp_cerebellum \ IF_curr_exp_ca2_adaptive ifneq ($(SPYNNAKER_DEBUG), DEBUG) diff --git a/neural_modelling/makefiles/neuron_only/IF_cond_exp_cerebellum_neuron/Makefile b/neural_modelling/makefiles/neuron_only/IF_cond_exp_cerebellum_neuron/Makefile deleted file mode 100644 index 88637c90816..00000000000 --- a/neural_modelling/makefiles/neuron_only/IF_cond_exp_cerebellum_neuron/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2017-2019 The University of Manchester -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -APP = $(notdir $(CURDIR)) - -NEURON_MODEL_H = $(NEURON_DIR)/neuron/models/neuron_model_lif_t_last_impl.h -INPUT_TYPE_H = $(NEURON_DIR)/neuron/input_types/input_type_conductance.h -NEURON_IMPL_H = $(NEURON_DIR)/neuron/implementations/neuron_impl_standard.h -THRESHOLD_TYPE_H = $(NEURON_DIR)/neuron/threshold_types/threshold_type_static.h -SYNAPSE_TYPE_H = $(NEURON_DIR)/neuron/synapse_types/synapse_types_exponential_impl.h - -include ../neuron_build.mk diff --git a/neural_modelling/makefiles/neuron_only/Makefile b/neural_modelling/makefiles/neuron_only/Makefile index eba5727c65a..a360e3a2194 100644 --- a/neural_modelling/makefiles/neuron_only/Makefile +++ b/neural_modelling/makefiles/neuron_only/Makefile @@ -23,7 +23,6 @@ MODELS = IF_curr_exp_neuron\ IF_curr_delta_neuron\ IF_curr_alpha_neuron\ IF_cond_exp_stoc_neuron\ - IF_cond_exp_cerebellum_neuron\ external_device_lif_control_neuron all: diff --git a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h b/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h deleted file mode 100644 index 4dc9b57d401..00000000000 --- a/neural_modelling/src/neuron/models/neuron_model_lif_t_last_impl.h +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (c) 2017-2021 The University of Manchester - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _NEURON_MODEL_LIF_CURR_T_LAST_IMPL_H_ -#define _NEURON_MODEL_LIF_CURR_T_LAST_IMPL_H_ - -#include "neuron_model.h" - -//! definition for LIF neuron parameters -struct neuron_params_t { - //! membrane voltage [mV] - REAL V_init; - - //! membrane resting voltage [mV] - REAL V_rest; - - //! membrane capacitance [nF] - REAL c_m; - - //! membrane decay time constant - REAL tau_m; - - //! offset current [nA] - REAL I_offset; - - //! post-spike reset membrane voltage [mV] - REAL V_reset; - - //! refractory time of neuron [ms] - REAL T_refract_ms; - - //! Time of last CF spike (saved) - int32_t t_last; - - //! initial refractory timer value (saved) - int32_t refract_timer_init; - - //! The time step in milliseconds - REAL time_step; -}; - -// definition for LIF neuron state -typedef struct neuron_t { - // membrane voltage [mV] - REAL V_membrane; - - // membrane resting voltage [mV] - REAL V_rest; - - // membrane resistance [MOhm] - REAL R_membrane; - - // 'fixed' computation parameter - time constant multiplier for - // closed-form solution - // exp(-(machine time step in ms)/(R * C)) [.] - REAL exp_TC; - - // offset current [nA] - REAL I_offset; - - // countdown to end of next refractory period [timesteps] - int32_t refract_timer; - - // post-spike reset membrane voltage [mV] - REAL V_reset; - - // time of last CF spike - int32_t t_last; - - // refractory time of neuron [timesteps] - int32_t T_refract; -} neuron_t; - -//! \brief Performs a ceil operation on an accum -//! \param[in] value The value to ceil -//! \return The ceil of the value -static inline int32_t lif_ceil_accum(REAL value) { - int32_t bits = bitsk(value); - int32_t integer = bits >> 15; - int32_t fraction = bits & 0x7FFF; - if (fraction > 0) { - return integer + 1; - } - return integer; -} - -static inline void neuron_model_initialise( - neuron_t *state, neuron_params_t *params, uint32_t n_steps_per_timestep) { - REAL ts = kdivui(params->time_step, n_steps_per_timestep); - state->V_membrane = params->V_init; - state->V_rest = params->V_rest; - state->R_membrane = kdivk(params->tau_m, params->c_m); - state->exp_TC = expk(-kdivk(ts, params->tau_m)); - state->I_offset = params->I_offset; - state->refract_timer = params->refract_timer_init; - state->V_reset = params->V_reset; - state->T_refract = lif_ceil_accum(kdivk(params->T_refract_ms, ts)); -} - -static inline void neuron_model_save_state(neuron_t *state, neuron_params_t *params) { - params->V_init = state->V_membrane; - params->refract_timer_init = state->refract_timer; - params->t_last = state->t_last; -} - -// simple Leaky I&F ODE -//! \param[in,out] neuron: The neuron to update -//! \param[in] V_prev: previous voltage -//! \param[in] input_this_timestep: The input to apply -static inline void _lif_neuron_closed_form( - neuron_t *neuron, REAL V_prev, input_t input_this_timestep) { - REAL alpha = input_this_timestep * neuron->R_membrane + neuron->V_rest; - - // update membrane voltage - neuron->V_membrane = alpha - (neuron->exp_TC * (alpha - V_prev)); -} - -//! \brief primary function called in timer loop after synaptic updates -//! \param[in] num_excitatory_inputs: Number of excitatory receptor types. -//! \param[in] exc_input: Pointer to array of inputs per receptor type received -//! this timer tick that produce a positive reaction within the neuron in -//! terms of stimulation. -//! \param[in] num_inhibitory_inputs: Number of inhibitory receptor types. -//! \param[in] inh_input: Pointer to array of inputs per receptor type received -//! this timer tick that produce a negative reaction within the neuron in -//! terms of stimulation. -//! \param[in] external_bias: This is the intrinsic plasticity which could be -//! used for ac, noisy input etc etc. (general purpose input) -//! \param[in,out] neuron: the pointer to a neuron parameter struct which -//! contains all the parameters for a specific neuron -//! \return the value to be compared with a threshold value to determine if the -//! neuron has spiked -static state_t neuron_model_state_update( - uint16_t num_excitatory_inputs, const input_t *exc_input, - uint16_t num_inhibitory_inputs, const input_t *inh_input, - input_t external_bias, REAL current_offset, neuron_t *restrict neuron) { - - log_debug("Exc 1: %12.6k, Exc 2: %12.6k", exc_input[0], exc_input[1]); - log_debug("Inh 1: %12.6k, Inh 2: %12.6k", inh_input[0], inh_input[1]); - - - // If outside of the refractory period - if (neuron->refract_timer <= 0) { - REAL total_exc = 0; - REAL total_inh = 0; - - for (int i=0; i < num_excitatory_inputs; i++){ - total_exc += exc_input[i]; - } - for (int i=0; i< num_inhibitory_inputs; i++){ - total_inh += inh_input[i]; - } - // Get the input in nA - input_t input_this_timestep = - total_exc - total_inh + external_bias + neuron->I_offset + current_offset; - - _lif_neuron_closed_form( - neuron, neuron->V_membrane, input_this_timestep); - } else { - - // countdown refractory timer - neuron->refract_timer -= 1; - } - return neuron->V_membrane; -} - -//! \brief Indicates that the neuron has spiked -//! \param[in, out] neuron pointer to a neuron parameter struct which contains -//! all the parameters for a specific neuron -static void neuron_model_has_spiked(neuron_t *restrict neuron) { - // reset membrane voltage - neuron->V_membrane = neuron->V_reset; - - // reset refractory timer - neuron->refract_timer = neuron->T_refract; -} - -//! \brief get the neuron membrane voltage for a given neuron parameter set -//! \param[in] neuron: a pointer to a neuron parameter struct which contains -//! all the parameters for a specific neuron -//! \return the membrane voltage for a given neuron with the neuron -//! parameters specified in neuron -static state_t neuron_model_get_membrane_voltage(const neuron_t *neuron) { - return neuron->V_membrane; -} - -static inline void neuron_model_print_state_variables(const neuron_t *neuron) { - log_debug("V membrane = %11.4k mv", neuron->V_membrane); - log_debug("Refract timer = %u timesteps", neuron->refract_timer); - log_debug("T_last = $u", neuron->t_last); -} - -static inline void neuron_model_print_parameters(const neuron_t *neuron) { - log_debug("V reset = %11.4k mv", neuron->V_reset); - log_debug("V rest = %11.4k mv", neuron->V_rest); - - log_debug("I offset = %11.4k nA", neuron->I_offset); - log_debug("R membrane = %11.4k Mohm", neuron->R_membrane); - - log_debug("exp(-ms/(RC)) = %11.4k [.]", neuron->exp_TC); - - log_debug("T refract = %u timesteps", neuron->T_refract); -} - - -#endif // _NEURON_MODEL_LIF_CURR_T_LAST_IMPL_H_ diff --git a/spynnaker/pyNN/extra_models/__init__.py b/spynnaker/pyNN/extra_models/__init__.py index 8f28c021884..b52c4296875 100644 --- a/spynnaker/pyNN/extra_models/__init__.py +++ b/spynnaker/pyNN/extra_models/__init__.py @@ -33,10 +33,7 @@ # Variable rate poisson from spynnaker.pyNN.models.spike_source import SpikeSourcePoissonVariable -# ICub VOR imports -from spynnaker.pyNN.models.neuron.builds.if_cond_exp_cerebellum import \ - IFCondExpCerebellum -# Cerebellum Plasticity +# ICub VOR imports - Cerebellum Plasticity from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence import ( TimingDependencePFPC as TimingDependencePFPC) from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence import ( @@ -52,9 +49,6 @@ 'Izhikevich_cond', 'IF_curr_dual_exp', 'IF_curr_exp_sEMD', 'Izhikevich_cond_dual', - # ICub VOR neuron model - "IFCondExpCerebellum", - # Neuromodulation synapse dynamics (Mantas Mikaitis) 'Neuromodulation', diff --git a/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py b/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py deleted file mode 100644 index 9cabff92593..00000000000 --- a/spynnaker/pyNN/models/neuron/builds/if_cond_exp_cerebellum.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (c) 2017-2019 The University of Manchester -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from spynnaker.pyNN.models.neuron import AbstractPyNNNeuronModelStandard -from spynnaker.pyNN.models.defaults import default_initial_values -from spynnaker.pyNN.models.neuron.neuron_models \ - import NeuronModelLeakyIntegrateAndFireTLast -from spynnaker.pyNN.models.neuron.input_types import InputTypeConductance -from spynnaker.pyNN.models.neuron.synapse_types import SynapseTypeExponential -from spynnaker.pyNN.models.neuron.threshold_types import ThresholdTypeStatic - - -class IFCondExpCerebellum(AbstractPyNNNeuronModelStandard): - """ Leaky integrate and fire neuron with an exponentially decaying \ - conductance input. Also includes ability to record last spike down - a particular receptor - """ - __slots__ = [] - - @default_initial_values({"v", "isyn_exc", "isyn_inh"}) - def __init__( - self, tau_m=20.0, cm=1.0, v_rest=-65.0, v_reset=-65.0, - v_thresh=-50.0, tau_syn_E=5.0, tau_syn_I=5.0, tau_refrac=0.1, - i_offset=0.0, e_rev_E=0.0, e_rev_I=-70.0, v=-65.0, - isyn_exc=0.0, isyn_inh=0.0): - # pylint: disable=too-many-arguments, too-many-locals - neuron_model = NeuronModelLeakyIntegrateAndFireTLast( - v, v_rest, tau_m, cm, i_offset, v_reset, tau_refrac) - synapse_type = SynapseTypeExponential( - tau_syn_E, tau_syn_I, isyn_exc, isyn_inh) - input_type = InputTypeConductance(e_rev_E, e_rev_I) - threshold_type = ThresholdTypeStatic(v_thresh) - - super(IFCondExpCerebellum, self).__init__( - model_name="IF_cond_exp_cerebellum", - binary="IF_cond_exp_cerebellum.aplx", - neuron_model=neuron_model, input_type=input_type, - synapse_type=synapse_type, threshold_type=threshold_type) diff --git a/spynnaker8/extra_models/__init__.py b/spynnaker8/extra_models/__init__.py index ccaf2a6256d..2bcacb9ac1a 100644 --- a/spynnaker8/extra_models/__init__.py +++ b/spynnaker8/extra_models/__init__.py @@ -33,10 +33,7 @@ from spynnaker.pyNN.models.spike_source import SpikeSourcePoissonVariable from spynnaker.pyNN.utilities.utility_calls import moved_in_v7 -# ICub VOR imports -from spynnaker.pyNN.models.neuron.builds.if_cond_exp_cerebellum import \ - IFCondExpCerebellum -# Cerebellum Plasticity +# ICub VOR imports - Cerebellum Plasticity from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence import ( TimingDependencePFPC as TimingDependencePFPC) from spynnaker.pyNN.models.neuron.plasticity.stdp.timing_dependence import ( @@ -50,7 +47,6 @@ # sPyNNaker 8 models 'IFCurDelta', 'IFCurrExpCa2Adaptive', 'IFCondExpStoc', 'Izhikevich_cond', 'IF_curr_dual_exp', 'IF_curr_exp_sEMD', - "IFCondExpCerebellum", # ICub VOR neuron model # Neuromodulation synapse dynamics (Mantas Mikaitis) 'Neuromodulation',