From 4da572e4f0484b2054471952dc301f7046eeecb7 Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Mon, 16 Nov 2020 16:51:48 +0000 Subject: [PATCH 1/6] Use structs to access synaptic rows Complicated because rows have multiple VLAs within them. Code recovered from #857 which was becoming too unwieldy to keep up to date. --- neural_modelling/src/common/neuron-typedefs.h | 24 +++- neural_modelling/src/neuron/direct_synapses.c | 47 +++++--- neural_modelling/src/neuron/direct_synapses.h | 4 +- .../stdp/synapse_dynamics_stdp_mad_impl.c | 31 +++-- .../src/neuron/plasticity/synapse_dynamics.h | 30 ++--- .../plasticity/synapse_dynamics_static_impl.c | 29 ++--- .../population_table/population_table.h | 9 +- .../population_table_binary_search_impl.c | 49 ++++---- .../src/neuron/spike_processing.c | 66 +++++----- .../synaptogenesis/elimination/elimination.h | 2 +- .../elimination_random_by_weight_impl.h | 2 +- .../synaptogenesis/formation/formation.h | 2 +- .../formation_distance_dependent_impl.h | 2 +- .../synaptogenesis/sp_structs.h | 4 +- .../synaptogenesis/topographic_map_impl.c | 47 ++++---- .../synaptogenesis_dynamics.h | 20 ++-- .../synaptogenesis_dynamics_static_impl.c | 4 +- neural_modelling/src/neuron/synapse_row.h | 62 ++++++---- neural_modelling/src/neuron/synapses.c | 57 ++++----- .../matrix_generator_static.h | 69 +++++------ .../matrix_generators/matrix_generator_stdp.h | 113 ++++++++---------- 21 files changed, 350 insertions(+), 323 deletions(-) diff --git a/neural_modelling/src/common/neuron-typedefs.h b/neural_modelling/src/common/neuron-typedefs.h index c148eee3a2c..2b6a3384074 100644 --- a/neural_modelling/src/common/neuron-typedefs.h +++ b/neural_modelling/src/common/neuron-typedefs.h @@ -95,8 +95,28 @@ static inline payload_t spike_payload(UNUSED spike_t s) { #endif /*SPIKES_WITH_PAYLOADS*/ #endif /*__SPIKE_T__*/ -//! The type of a synaptic row -typedef address_t synaptic_row_t; +//! \brief The type of a synaptic row. +//! \details There is no definition of `struct synaptic row` because it is a +//! form of memory structure that C cannot encode as a single `struct`. +//! +//! It's actually this, with multiple variable length arrays intermixed with +//! size counts: +//! ~~~~~~{.c} +//! struct synaptic_row { +//! uint32_t n_plastic_synapse_words; +//! uint32_t plastic_synapse_data[n_plastic_synapse_words]; // VLA +//! uint32_t n_fixed_synapse_words; +//! uint32_t n_plastic_controls; +//! uint32_t fixed_synapse_data[n_fixed_synapse_words]; // VLA +//! control_t plastic_control_data[n_plastic_controls]; // VLA +//! } +//! ~~~~~~ +//! +//! The relevant implementation structures are: +//! * ::synapse_row_plastic_part_t +//! * ::synapse_row_fixed_part_t +//! * ::single_synaptic_row_t +typedef struct synaptic_row *synaptic_row_t; //! The type of an input typedef REAL input_t; diff --git a/neural_modelling/src/neuron/direct_synapses.c b/neural_modelling/src/neuron/direct_synapses.c index bc03caddd7e..1f1db85780a 100644 --- a/neural_modelling/src/neuron/direct_synapses.c +++ b/neural_modelling/src/neuron/direct_synapses.c @@ -21,41 +21,50 @@ #include #include -//! The size of the fixed synapse buffer, in words -#define SIZE_OF_SINGLE_FIXED_SYNAPSE 4 +//! \brief The type of a singleton synaptic row. +//! \details The counts are constant. See ::synapse_row_plastic_part_t and +//! ::synapse_row_fixed_part_t for what this is a packed version of. +typedef struct single_synaptic_row_t { + const uint32_t n_plastic; //!< Number of plastic synapses. Always zero + const uint32_t n_fixed; //!< Number of fixed synapses. Always one + const uint32_t n_plastic_controls; //!< Number of plastic controls. Always zero + uint32_t synapse_datum; //!< The value of the single synapse +} single_synaptic_row_t; //! Working buffer for direct synapse access -static uint32_t single_fixed_synapse[SIZE_OF_SINGLE_FIXED_SYNAPSE]; +static single_synaptic_row_t single_fixed_synapse = {0, 1, 0, 0}; + +//! The layout of the direct matrix region +typedef struct { + const uint32_t size; //!< Size of data, _not_ number of elements + const uint32_t data[]; //!< Direct matrix data +} direct_matrix_data_t; bool direct_synapses_initialise( - address_t direct_matrix_address, address_t *direct_synapses_address) { + void *direct_matrix_address, address_t *direct_synapses_address) { + direct_matrix_data_t *direct_matrix = direct_matrix_address; // Work out the positions of the direct and indirect synaptic matrices // and copy the direct matrix to DTCM - uint32_t direct_matrix_size = direct_matrix_address[0]; + uint32_t direct_matrix_size = direct_matrix->size; log_info("Direct matrix malloc size is %d", direct_matrix_size); if (direct_matrix_size != 0) { - *direct_synapses_address = spin1_malloc(direct_matrix_size); - if (*direct_synapses_address == NULL) { + void *dtcm_copy = spin1_malloc(direct_matrix_size); + if (dtcm_copy == NULL) { 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, *direct_synapses_address); - spin1_memcpy(*direct_synapses_address, &direct_matrix_address[1], - direct_matrix_size); + direct_matrix_size, dtcm_copy); + spin1_memcpy(dtcm_copy, direct_matrix->data, direct_matrix_size); + *direct_synapses_address = dtcm_copy; } - // Set up for single fixed synapses - // (data that is consistent per direct row) - single_fixed_synapse[0] = 0; - single_fixed_synapse[1] = 1; - single_fixed_synapse[2] = 0; - return true; } -synaptic_row_t direct_synapses_get_direct_synapse(address_t row_address) { - single_fixed_synapse[3] = (uint32_t) row_address[0]; - return (synaptic_row_t) single_fixed_synapse; +synaptic_row_t direct_synapses_get_direct_synapse(void *row_address) { + uint32_t *data = row_address; + single_fixed_synapse.synapse_datum = *data; + return (synaptic_row_t) &single_fixed_synapse; } diff --git a/neural_modelling/src/neuron/direct_synapses.h b/neural_modelling/src/neuron/direct_synapses.h index 388d98da864..5ed75719933 100644 --- a/neural_modelling/src/neuron/direct_synapses.h +++ b/neural_modelling/src/neuron/direct_synapses.h @@ -27,11 +27,11 @@ //! the DTCM address for the direct matrix //! \return true if successful, false otherwise. bool direct_synapses_initialise( - address_t direct_matrix_address, address_t *direct_synapses_address); + void *direct_matrix_address, address_t *direct_synapses_address); //! \brief Get the synapse for a given direct synaptic row. //! \param[in] row_address: the row address to read. //! \return the synaptic row synapse data. -synaptic_row_t direct_synapses_get_direct_synapse(address_t row_address); +synaptic_row_t direct_synapses_get_direct_synapse(void *row_address); #endif /* _DIRECT_SYNAPSES_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 71722427486..83adf643624 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 @@ -430,11 +430,10 @@ uint32_t synapse_dynamics_get_plastic_saturation_count(void) { } bool synapse_dynamics_find_neuron( - uint32_t id, address_t row, weight_t *weight, uint16_t *delay, + uint32_t id, synaptic_row_t row, weight_t *weight, uint16_t *delay, uint32_t *offset, uint32_t *synapse_type) { - address_t fixed_region = synapse_row_fixed_region(row); - synapse_row_plastic_data_t *plastic_data = (void *) - synapse_row_plastic_region(row); + synapse_row_fixed_part_t *fixed_region = synapse_row_fixed_region(row); + synapse_row_plastic_data_t *plastic_data = 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); int32_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); @@ -458,10 +457,9 @@ bool synapse_dynamics_find_neuron( return false; } -bool synapse_dynamics_remove_neuron(uint32_t offset, address_t row) { - address_t fixed_region = synapse_row_fixed_region(row); - synapse_row_plastic_data_t *plastic_data = (void *) - synapse_row_plastic_region(row); +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 = 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); @@ -474,12 +472,11 @@ bool synapse_dynamics_remove_neuron(uint32_t offset, address_t row) { control_words[plastic_synapse - 1] = 0; // Decrement FP - fixed_region[1]--; - + fixed_region->num_plastic--; return true; } -//! \brief packing all of the information into the required plastic control word +//! \brief Pack all of the information into the required plastic control word //! \param[in] id: The spike ID //! \param[in] delay: The delay //! \param[in] type: The synapse type @@ -493,14 +490,13 @@ static inline control_t control_conversion( return new_control; } -bool synapse_dynamics_add_neuron(uint32_t id, address_t row, +bool synapse_dynamics_add_neuron(uint32_t id, synaptic_row_t row, weight_t weight, uint32_t delay, uint32_t type) { plastic_synapse_t new_weight = synapse_structure_create_synapse(weight); control_t new_control = control_conversion(id, delay, type); - address_t fixed_region = synapse_row_fixed_region(row); - synapse_row_plastic_data_t *plastic_data = (void *) - synapse_row_plastic_region(row); + 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; control_t *control_words = synapse_row_plastic_controls(fixed_region); int32_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); @@ -512,10 +508,11 @@ bool synapse_dynamics_add_neuron(uint32_t id, address_t row, control_words[plastic_synapse] = new_control; // Increment FP - fixed_region[1]++; + fixed_region->num_plastic++; return true; } -uint32_t synapse_dynamics_n_connections_in_row(address_t fixed) { +uint32_t synapse_dynamics_n_connections_in_row( + synapse_row_fixed_part_t *fixed) { return synapse_row_num_plastic_controls(fixed); } diff --git a/neural_modelling/src/neuron/plasticity/synapse_dynamics.h b/neural_modelling/src/neuron/plasticity/synapse_dynamics.h index f678072d677..c6ad87ed214 100644 --- a/neural_modelling/src/neuron/plasticity/synapse_dynamics.h +++ b/neural_modelling/src/neuron/plasticity/synapse_dynamics.h @@ -36,17 +36,18 @@ 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); -//! \brief Processes the dynamics of the synapses +//! \brief Process the dynamics of the synapses //! \param[in,out] plastic_region_address: Where the plastic data is -//! \param[in] fixed_region_address: Where the fixed data is +//! \param[in] fixed_region: Where the fixed data is //! \param[in,out] ring_buffers: The ring buffers //! \param[in] time: The current simulation time //! \return ??? bool synapse_dynamics_process_plastic_synapses( - address_t plastic_region_address, address_t fixed_region_address, + address_t plastic_region_address, + synapse_row_fixed_part_t *fixed_region, weight_t *ring_buffers, uint32_t time); -//! \brief Informs the synapses that the neuron fired +//! \brief Inform the synapses that the neuron fired //! \param[in] time: The current simulation time //! \param[in] neuron_index: Which neuron are we processing void synapse_dynamics_process_post_synaptic_event( @@ -61,19 +62,20 @@ input_t synapse_dynamics_get_intrinsic_bias( //! \brief Print the synapse dynamics //! \param[in] plastic_region_address: Where the plastic data is -//! \param[in] fixed_region_address: Where the fixed data is +//! \param[in] fixed_region: Where the fixed data is //! \param[in] ring_buffer_to_input_buffer_left_shifts: //! How to interpret the values from the ring buffers void synapse_dynamics_print_plastic_synapses( - address_t plastic_region_address, address_t fixed_region_address, + address_t plastic_region_address, + synapse_row_fixed_part_t *fixed_region, uint32_t *ring_buffer_to_input_buffer_left_shifts); -//! \brief returns the counters for plastic pre synaptic events based on (if +//! \brief Get the counters for plastic pre synaptic events based on (if //! the model was compiled with SYNAPSE_BENCHMARK parameter) or returns 0 //! \return counters for plastic pre synaptic events or 0 uint32_t synapse_dynamics_get_plastic_pre_synaptic_events(void); -//! \brief returns the number of ring buffer saturation events due to adding +//! \brief Get the number of ring buffer saturation events due to adding //! plastic weights. //! \return counter for saturation events or 0 uint32_t synapse_dynamics_get_plastic_saturation_count(void); @@ -82,7 +84,7 @@ uint32_t synapse_dynamics_get_plastic_saturation_count(void); // Synaptic rewiring functions //----------------------------------------------------------------------------- -//! \brief Searches the synaptic row for the the connection with the +//! \brief Search 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 @@ -90,17 +92,17 @@ uint32_t synapse_dynamics_get_plastic_saturation_count(void); //! \param[out] weight: address to contain the weight of the connection //! \param[out] delay: address to contain the delay of the connection //! \param[out] offset: address to contain the offset of the connection -//! \param[out] synapse_type: address to contain the synapse type of the connection +//! \param[out] synapse_type: the synapse type of the connection //! \return was the search successful? bool synapse_dynamics_find_neuron( - uint32_t id, address_t row, weight_t *weight, uint16_t *delay, + uint32_t id, synaptic_row_t row, weight_t *weight, uint16_t *delay, uint32_t *offset, uint32_t *synapse_type); //! \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 was the removal successful? -bool synapse_dynamics_remove_neuron(uint32_t offset, address_t row); +bool synapse_dynamics_remove_neuron(uint32_t offset, synaptic_row_t row); //! \brief Add an entry in the synaptic row //! \param[in] id: the (core-local) ID of the post-synaptic neuron to be added @@ -110,12 +112,12 @@ bool synapse_dynamics_remove_neuron(uint32_t offset, address_t row); //! \param[in] type: the type of the connection (e.g. inhibitory) //! \return was the addition successful? bool synapse_dynamics_add_neuron( - uint32_t id, address_t row, weight_t weight, + uint32_t id, synaptic_row_t row, weight_t weight, uint32_t delay, uint32_t type); //! \brief Get the number of connections in the given row //! \param[in] fixed: the fixed region of the synaptic row //! \return The number of connections in the row -uint32_t synapse_dynamics_n_connections_in_row(address_t fixed); +uint32_t synapse_dynamics_n_connections_in_row(synapse_row_fixed_part_t *fixed); #endif // _SYNAPSE_DYNAMICS_H_ diff --git a/neural_modelling/src/neuron/plasticity/synapse_dynamics_static_impl.c b/neural_modelling/src/neuron/plasticity/synapse_dynamics_static_impl.c index 4caabb52073..21586991023 100644 --- a/neural_modelling/src/neuron/plasticity/synapse_dynamics_static_impl.c +++ b/neural_modelling/src/neuron/plasticity/synapse_dynamics_static_impl.c @@ -71,7 +71,7 @@ void synapse_dynamics_process_post_synaptic_event( //--------------------------------------- bool synapse_dynamics_process_plastic_synapses( UNUSED address_t plastic_region_address, - UNUSED address_t fixed_region_address, + UNUSED synapse_row_fixed_part_t *fixed_region, UNUSED weight_t *ring_buffer, UNUSED uint32_t time) { log_error("There should be no plastic synapses!"); return false; @@ -85,7 +85,7 @@ input_t synapse_dynamics_get_intrinsic_bias( void synapse_dynamics_print_plastic_synapses( UNUSED address_t plastic_region_address, - UNUSED address_t fixed_region_address, + UNUSED synapse_row_fixed_part_t *fixed_region, UNUSED uint32_t *ring_buffer_to_input_left_shifts) { } @@ -98,9 +98,9 @@ uint32_t synapse_dynamics_get_plastic_saturation_count(void) { } bool synapse_dynamics_find_neuron( - uint32_t id, address_t row, weight_t *weight, uint16_t *delay, + uint32_t id, synaptic_row_t row, weight_t *weight, uint16_t *delay, uint32_t *offset, uint32_t *synapse_type) { - address_t fixed_region = synapse_row_fixed_region(row); + synapse_row_fixed_part_t *fixed_region = synapse_row_fixed_region(row); int32_t fixed_synapse = synapse_row_num_fixed_synapses(fixed_region); uint32_t *synaptic_words = synapse_row_fixed_weight_controls(fixed_region); @@ -125,16 +125,16 @@ bool synapse_dynamics_find_neuron( return false; } -bool synapse_dynamics_remove_neuron(uint32_t offset, address_t row) { - address_t fixed_region = synapse_row_fixed_region(row); +bool synapse_dynamics_remove_neuron(uint32_t offset, synaptic_row_t row) { + synapse_row_fixed_part_t *fixed_region = synapse_row_fixed_region(row); int32_t fixed_synapse = synapse_row_num_fixed_synapses(fixed_region); uint32_t *synaptic_words = synapse_row_fixed_weight_controls(fixed_region); - // Delete control word at offset (contains weight) - synaptic_words[offset] = synaptic_words[fixed_synapse-1]; + // Delete control word at offset (contains weight) + synaptic_words[offset] = synaptic_words[fixed_synapse - 1]; // Decrement FF - fixed_region[0] = fixed_region[0] - 1; + fixed_region->num_fixed--; return true; } @@ -151,9 +151,9 @@ static inline uint32_t _fixed_synapse_convert( } bool synapse_dynamics_add_neuron( - uint32_t id, address_t row, weight_t weight, + uint32_t id, synaptic_row_t row, weight_t weight, uint32_t delay, uint32_t type) { - address_t fixed_region = synapse_row_fixed_region(row); + synapse_row_fixed_part_t *fixed_region = synapse_row_fixed_region(row); int32_t fixed_synapse = synapse_row_num_fixed_synapses(fixed_region); uint32_t *synaptic_words = synapse_row_fixed_weight_controls(fixed_region); uint32_t new_synapse = _fixed_synapse_convert(id, weight, delay, type); @@ -161,11 +161,12 @@ bool synapse_dynamics_add_neuron( // Add control word at offset synaptic_words[fixed_synapse] = new_synapse; - // Increment FF - fixed_region[0] = fixed_region[0] + 1; + // Increment FF + fixed_region->num_fixed++; return true; } -uint32_t synapse_dynamics_n_connections_in_row(address_t fixed) { +uint32_t synapse_dynamics_n_connections_in_row( + synapse_row_fixed_part_t *fixed) { return synapse_row_num_fixed_synapses(fixed); } diff --git a/neural_modelling/src/neuron/population_table/population_table.h b/neural_modelling/src/neuron/population_table/population_table.h index 0570ac01fb4..963d03d680e 100644 --- a/neural_modelling/src/neuron/population_table/population_table.h +++ b/neural_modelling/src/neuron/population_table/population_table.h @@ -39,7 +39,7 @@ extern uint32_t failed_bit_field_reads; //! they don't hit anything extern uint32_t bit_field_filtered_packets; -//! \brief Sets up the table +//! \brief Set up the table //! \param[in] table_address: The address of the start of the table data //! \param[in] synapse_rows_address: The address of the start of the synapse //! data @@ -63,7 +63,8 @@ bool population_table_load_bitfields(filter_region_t *filter_region); //! \param[out] n_bytes_to_transfer: Updated with the number of bytes to read //! \return True if there is a row to read, False if not bool population_table_get_first_address( - spike_t spike, address_t* row_address, size_t* n_bytes_to_transfer); + spike_t spike, synaptic_row_t* row_address, + size_t* n_bytes_to_transfer); //! \brief Get the next row data for a previously given spike. If no spike has //! been given, return False. @@ -72,7 +73,7 @@ bool population_table_get_first_address( //! \param[out] n_bytes_to_transfer: Updated with the number of bytes to read //! \return True if there is a row to read, False if not bool population_table_get_next_address( - spike_t *spike, address_t* row_address, size_t* n_bytes_to_transfer); - + spike_t *spike, synaptic_row_t* row_address, + size_t* n_bytes_to_transfer); #endif // _POPULATION_TABLE_H_ 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 11d0ee7daea..00ce14fbfdd 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 @@ -88,6 +88,15 @@ typedef union { // delayed and undelayed tables #define INVALID_ADDRESS ((1 << N_ADDRESS_BITS) - 1) +//! \brief The memory layout in SDRAM of the first part of the population table +//! configuration. Address list data (array of ::address_and_row_length) is +//! packed on the end. +typedef struct { + uint32_t table_length; + uint32_t addr_list_length; + master_population_table_entry data[]; +} pop_table_config_t; + //! The master population table. This is sorted. static master_population_table_entry *master_population_table; @@ -143,9 +152,8 @@ static inline uint32_t get_direct_address(address_and_row_length entry) { } //! \brief Get the standard address offset out of an entry -//! -//! The address is in units of four words, so this multiplies by 16 (= up -//! shifts by 4) +//! \details The address is in units of four words, so this multiplies by 16 +//! (= up shifts by 4) //! \param[in] entry: the table entry //! \return a row address (which is an offset) static inline uint32_t get_offset(address_and_row_length entry) { @@ -226,8 +234,7 @@ static inline uint32_t get_extended_neuron_id( } //! \brief Prints the master pop table. -//! -//! For debugging +//! \details For debugging static inline void print_master_population_table(void) { log_info("Master_population\n"); for (uint32_t i = 0; i < master_population_table_length; i++) { @@ -414,14 +421,14 @@ bool population_table_initialise( address_t table_address, address_t synapse_rows_address, address_t direct_rows_address, uint32_t *row_max_n_words) { log_debug("Population_table_initialise: starting"); + pop_table_config_t *config = (pop_table_config_t *) table_address; - master_population_table_length = table_address[0]; + master_population_table_length = config->table_length; log_debug("Master pop table length is %d\n", master_population_table_length); log_debug("Master pop table entry size is %d\n", sizeof(master_population_table_entry)); uint32_t n_master_pop_bytes = master_population_table_length * sizeof(master_population_table_entry); - uint32_t n_master_pop_words = n_master_pop_bytes >> 2; log_debug("Pop table size is %d\n", n_master_pop_bytes); // only try to malloc if there's stuff to malloc. @@ -433,7 +440,7 @@ bool population_table_initialise( } } - uint32_t address_list_length = table_address[1]; + uint32_t address_list_length = config->addr_list_length; uint32_t n_address_list_bytes = address_list_length * sizeof(address_list_entry); @@ -452,9 +459,8 @@ bool population_table_initialise( address_list_length, n_address_list_bytes); // Copy the master population table - spin1_memcpy(master_population_table, &table_address[2], - n_master_pop_bytes); - spin1_memcpy(address_list, &table_address[2 + n_master_pop_words], + spin1_memcpy(master_population_table, config->data, n_master_pop_bytes); + spin1_memcpy(address_list, &config->data[master_population_table_length], n_address_list_bytes); // Store the base address @@ -472,7 +478,8 @@ bool population_table_initialise( } bool population_table_get_first_address( - spike_t spike, address_t* row_address, size_t* n_bytes_to_transfer) { + spike_t spike, synaptic_row_t *row_address, + size_t *n_bytes_to_transfer) { // locate the position in the binary search / array log_debug("Searching for key %d", spike); @@ -547,7 +554,7 @@ bool population_table_get_first_address( bool population_table_get_next_address( spike_t *spike, address_t *row_address, size_t *n_bytes_to_transfer) { // If there are no more items in the list, return false - if (items_to_go <= 0) { + if (items_to_go == 0) { return false; } @@ -559,10 +566,9 @@ bool population_table_get_next_address( // If the row is a direct row, indicate this by specifying the // n_bytes_to_transfer is 0 if (item.is_single) { - *row_address = (address_t) (get_direct_address(item) + + *row_address = (synaptic_row_t) (get_direct_address(item) + (last_neuron_id * sizeof(uint32_t))); *n_bytes_to_transfer = 0; - is_valid = true; } else { uint32_t row_length = get_row_length(item); @@ -570,16 +576,15 @@ bool population_table_get_next_address( uint32_t stride = (row_length + N_SYNAPSE_ROW_HEADER_WORDS); uint32_t neuron_offset = last_neuron_id * stride * sizeof(uint32_t); - *row_address = (address_t) (block_address + neuron_offset); + *row_address = (synaptic_row_t) (block_address + neuron_offset); *n_bytes_to_transfer = stride * sizeof(uint32_t); - log_debug( - "neuron_id = %u, block_address = 0x%.8x," - "row_length = %u, row_address = 0x%.8x, n_bytes = %u", - last_neuron_id, block_address, row_length, *row_address, - *n_bytes_to_transfer); + log_debug("neuron_id = %u, block_address = 0x%.8x, " + "row_length = %u, row_address = 0x%.8x, n_bytes = %u", + last_neuron_id, block_address, row_length, *row_address, + *n_bytes_to_transfer); *spike = last_spike; - is_valid = true; } + is_valid = true; } next_item++; diff --git a/neural_modelling/src/neuron/spike_processing.c b/neural_modelling/src/neuron/spike_processing.c index 064f7f9edbc..876b2404b68 100644 --- a/neural_modelling/src/neuron/spike_processing.c +++ b/neural_modelling/src/neuron/spike_processing.c @@ -32,7 +32,7 @@ //! about the read. typedef struct dma_buffer { //! Address in SDRAM to write back plastic region to - address_t sdram_writeback_address; + synaptic_row_t sdram_writeback_address; //! \brief Key of originating spike //! \details used to allow row data to be re-used for multiple spikes @@ -42,7 +42,7 @@ typedef struct dma_buffer { uint32_t n_bytes_transferred; //! Row data - address_t row; + synaptic_row_t row; } dma_buffer; //! The number of DMA Buffers to use @@ -74,15 +74,17 @@ static uint32_t buffer_being_read; //! Number of outstanding synaptogenic rewirings static volatile uint32_t rewires_to_do = 0; -//! The number of rewires to do when the DMA completes. When a DMA is first set -//! up, only this or dma_n_spikes can be 1 with the other being 0. +//! \brief The number of rewires to do when the DMA completes. +//! \details When a DMA is first set up, only this or ::dma_n_spikes can be 1 +//! with the other being 0. static uint32_t dma_n_rewires; -//! The number of spikes to do when the DMA completes. When a DMA is first set -//! up, only this or dma_n_rewires can be 1 with the other being 0. +//! \brief The number of spikes to do when the DMA completes. +//! \details When a DMA is first set up, only this or ::dma_n_rewires can be 1 +//! with the other being 0. static uint32_t dma_n_spikes; -//! the number of dma completes (used in provenance generation) +//! the number of DMA completes (used in provenance generation) static uint32_t dma_complete_count; //! the number of spikes that were processed (used in provenance generation) @@ -91,15 +93,15 @@ static uint32_t spike_processing_count; //! The number of successful rewires static uint32_t n_successful_rewires; -//! count how many packets were lost from the input buffer because of late -//! arrival +//! \breif How many packets were lost from the input buffer because of +//! late arrival static uint32_t count_input_buffer_packets_late; //! tracker of how full the input buffer got. static uint32_t biggest_fill_size_of_input_buffer; -//! bool that governs if we should clear packets from the input buffer at the -//! end of a timer tick. +//! \brief Whether if we should clear packets from the input buffer at the +//! end of a timer tick. static bool clear_input_buffers_of_late_packets; //! the number of packets received this time step @@ -114,15 +116,15 @@ static uint32_t p_per_ts_region; /* PRIVATE FUNCTIONS - static for inlining */ //! \brief Perform a DMA read of a synaptic row -//! \param[in] row_address: Where in SDRAM to read the row from +//! \param[in] row: Where in SDRAM to read the row from //! \param[in] n_bytes_to_transfer: The size of the synaptic row //! \param[in] spike: The spike that triggered this read static inline void do_dma_read( - address_t row_address, size_t n_bytes_to_transfer, spike_t spike) { + synaptic_row_t row, size_t n_bytes_to_transfer, spike_t spike) { // Write the SDRAM address of the plastic region and the // Key of the originating spike to the beginning of DMA buffer dma_buffer *next_buffer = &dma_buffers[next_buffer_to_fill]; - next_buffer->sdram_writeback_address = row_address; + next_buffer->sdram_writeback_address = row; next_buffer->originating_spike = spike; next_buffer->n_bytes_transferred = n_bytes_to_transfer; @@ -130,7 +132,7 @@ static inline void do_dma_read( // buffer buffer_being_read = next_buffer_to_fill; while (!spin1_dma_transfer( - DMA_TAG_READ_SYNAPTIC_ROW, row_address, next_buffer->row, DMA_READ, + DMA_TAG_READ_SYNAPTIC_ROW, row, next_buffer->row, DMA_READ, n_bytes_to_transfer)) { // Do Nothing } @@ -138,7 +140,7 @@ static inline void do_dma_read( } //! \brief Check if there is anything to do. If not, DMA is not busy -//! \param[out] row_address: +//! \param[out] row: //! The address of the synaptic row that has been processed //! \param[out] n_bytes_to_transfer: The size of the processed synaptic row //! \param[out] spike: The spike being processed @@ -146,7 +148,7 @@ static inline void do_dma_read( //! \param[in,out] n_process_spike: Accumulator of number of processed spikes //! \return True if there's something to do static inline bool is_something_to_do( - address_t *row_address, size_t *n_bytes_to_transfer, + synaptic_row_t *row, size_t *n_bytes_to_transfer, spike_t *spike, uint32_t *n_rewire, uint32_t *n_process_spike) { // Disable interrupts here as dma_busy modification is a critical section uint cpsr = spin1_int_disable(); @@ -155,7 +157,7 @@ static inline bool is_something_to_do( while (rewires_to_do) { rewires_to_do--; spin1_mode_restore(cpsr); - if (synaptogenesis_dynamics_rewire(time, spike, row_address, + if (synaptogenesis_dynamics_rewire(time, spike, row, n_bytes_to_transfer)) { *n_rewire += 1; return true; @@ -165,8 +167,7 @@ static inline bool is_something_to_do( // Is there another address in the population table? spin1_mode_restore(cpsr); - if (population_table_get_next_address( - spike, row_address, n_bytes_to_transfer)) { + if (population_table_get_next_address(spike, row, n_bytes_to_transfer)) { *n_process_spike += 1; return true; } @@ -184,7 +185,7 @@ static inline bool is_something_to_do( // as this can be slow spin1_mode_restore(cpsr); if (population_table_get_first_address( - *spike, row_address, n_bytes_to_transfer)) { + *spike, row, n_bytes_to_transfer)) { synaptogenesis_spike_received(time, *spike); *n_process_spike += 1; return true; @@ -217,7 +218,7 @@ static inline bool is_something_to_do( static void setup_synaptic_dma_read(dma_buffer *current_buffer, uint32_t *n_rewires, uint32_t *n_synapse_processes) { // Set up to store the DMA location and size to read - address_t row_address; + synaptic_row_t row; size_t n_bytes_to_transfer; spike_t spike; dma_n_spikes = 0; @@ -225,10 +226,10 @@ static void setup_synaptic_dma_read(dma_buffer *current_buffer, // Keep looking if there is something to do until a DMA can be done bool setup_done = false; - while (!setup_done && is_something_to_do(&row_address, - &n_bytes_to_transfer, &spike, &dma_n_rewires, &dma_n_spikes)) { + while (!setup_done && is_something_to_do(&row, &n_bytes_to_transfer, + &spike, &dma_n_rewires, &dma_n_spikes)) { if (current_buffer != NULL && - current_buffer->sdram_writeback_address == row_address) { + current_buffer->sdram_writeback_address == row) { // If we can reuse the row, add on what we can use it for // Note that only one of these will have a value of 1 with the // other being set to 0, but we add both as it is simple @@ -239,7 +240,7 @@ static void setup_synaptic_dma_read(dma_buffer *current_buffer, } else if (n_bytes_to_transfer == 0) { // If the row is in DTCM, process the row now synaptic_row_t single_fixed_synapse = - direct_synapses_get_direct_synapse(row_address); + direct_synapses_get_direct_synapse(row); bool write_back; synapses_process_synaptic_row( time, single_fixed_synapse, &write_back); @@ -247,7 +248,7 @@ static void setup_synaptic_dma_read(dma_buffer *current_buffer, dma_n_spikes = 0; } else { // If the row is in SDRAM, set up the transfer and we are done - do_dma_read(row_address, n_bytes_to_transfer, spike); + do_dma_read(row, n_bytes_to_transfer, spike); setup_done = true; } @@ -269,16 +270,17 @@ static inline void setup_synaptic_dma_write( // Get the number of plastic bytes and the write back address from the // synaptic row size_t write_size = buffer->n_bytes_transferred; - address_t sdram_start_address = buffer->sdram_writeback_address; - address_t dtcm_start_address = buffer->row; + void *sdram_start_address = buffer->sdram_writeback_address; + void *dtcm_start_address = buffer->row; if (plastic_only) { write_size = synapse_row_plastic_size(buffer->row) * sizeof(uint32_t); - sdram_start_address = synapse_row_plastic_region(sdram_start_address); - dtcm_start_address = synapse_row_plastic_region(dtcm_start_address); + sdram_start_address = synapse_row_plastic_region( + buffer->sdram_writeback_address); + dtcm_start_address = synapse_row_plastic_region(buffer->row); } log_debug("Writing back %u bytes of plastic region to %08x for spike %u", - write_size, sdram_start_address, buffer->originating_spike); + write_size, sdram_start_address, buffer->originating_spike); // Start transfer while (!spin1_dma_transfer(DMA_TAG_WRITE_PLASTIC_REGION, sdram_start_address, diff --git a/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/elimination/elimination.h b/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/elimination/elimination.h index 3b6bfe72a61..4e4bb21b98f 100644 --- a/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/elimination/elimination.h +++ b/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/elimination/elimination.h @@ -40,6 +40,6 @@ elimination_params_t *synaptogenesis_elimination_init(uint8_t **data); //! \return if row was modified static inline bool synaptogenesis_elimination_rule( current_state_t *current_state, const elimination_params_t *params, - uint32_t time, address_t row); + uint32_t time, synaptic_row_t row); #endif // _ELIMINATION_H_ diff --git a/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/elimination/elimination_random_by_weight_impl.h b/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/elimination/elimination_random_by_weight_impl.h index bd76cc5af27..3a6bb3d4bc2 100644 --- a/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/elimination/elimination_random_by_weight_impl.h +++ b/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/elimination/elimination_random_by_weight_impl.h @@ -42,7 +42,7 @@ struct elimination_params { static inline bool synaptogenesis_elimination_rule( current_state_t *restrict current_state, const elimination_params_t *params, - UNUSED uint32_t time, address_t restrict row) { + UNUSED uint32_t time, synaptic_row_t restrict row) { uint32_t random_number = mars_kiss64_seed(*(current_state->local_seed)); // Is weight depressed? diff --git a/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/formation/formation.h b/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/formation/formation.h index 1fed93419a5..a8f25371e9f 100644 --- a/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/formation/formation.h +++ b/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/formation/formation.h @@ -42,6 +42,6 @@ formation_params_t *synaptogenesis_formation_init(uint8_t **data); //! \return if row was modified static inline bool synaptogenesis_formation_rule( current_state_t *current_state, const formation_params_t *params, - uint32_t time, address_t row); + uint32_t time, synaptic_row_t row); #endif // _FORMATION_H_ diff --git a/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/formation/formation_distance_dependent_impl.h b/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/formation/formation_distance_dependent_impl.h index c8c71283d91..acc5ff9eca1 100644 --- a/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/formation/formation_distance_dependent_impl.h +++ b/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/formation/formation_distance_dependent_impl.h @@ -71,7 +71,7 @@ static int my_abs(int a) { //! \return if row was modified static inline bool synaptogenesis_formation_rule( current_state_t *current_state, const formation_params_t *params, - UNUSED uint32_t time, address_t row) { + UNUSED uint32_t time, synaptic_row_t row) { // Compute distances // To do this I need to take the DIV and MOD of the // post-synaptic neuron ID, of the pre-synaptic neuron ID diff --git a/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/sp_structs.h b/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/sp_structs.h index 5bcf52cc3a8..84781d0cfee 100644 --- a/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/sp_structs.h +++ b/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/sp_structs.h @@ -186,7 +186,7 @@ static inline bool sp_structs_get_sub_pop_info( //! \param[in,out] row: The row of the synaptic matrix to be updated //! \return True if the synapse was removed static inline bool sp_structs_remove_synapse( - current_state_t *restrict current_state, address_t restrict row) { + current_state_t *restrict current_state, synaptic_row_t restrict row) { if (!synapse_dynamics_remove_neuron(current_state->offset, row)) { return false; } @@ -199,7 +199,7 @@ static inline bool sp_structs_remove_synapse( //! \param[in,out] row: The row of the synaptic matrix to be updated //! \return True if the synapse was added static inline bool sp_structs_add_synapse( - current_state_t *restrict current_state, address_t restrict row) { + current_state_t *restrict current_state, synaptic_row_t restrict row) { uint32_t appr_scaled_weight = current_state->pre_population_info->weight; uint32_t actual_delay; diff --git a/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/topographic_map_impl.c b/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/topographic_map_impl.c index 99fc57caa09..ffe95b50bce 100644 --- a/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/topographic_map_impl.c +++ b/neural_modelling/src/neuron/structural_plasticity/synaptogenesis/topographic_map_impl.c @@ -187,7 +187,7 @@ bool synaptogenesis_dynamics_initialise(address_t sdram_sp_address) { } bool synaptogenesis_dynamics_rewire( - uint32_t time, spike_t *spike, address_t *synaptic_row_address, + uint32_t time, spike_t *spike, synaptic_row_t *synaptic_row, uint32_t *n_bytes) { // Randomly choose a postsynaptic (application neuron) @@ -204,7 +204,7 @@ bool synaptogenesis_dynamics_rewire( // Select an arbitrary synaptic element for the neurons uint32_t row_offset = post_id * rewiring_data.s_max; uint32_t column_offset = rand_int(rewiring_data.s_max, - rewiring_data.local_seed); + rewiring_data.local_seed); uint32_t total_offset = row_offset + column_offset; post_to_pre_entry entry = post_to_pre_table[total_offset]; uint32_t pre_app_pop = 0, pre_sub_pop = 0, m_pop_index = 0, neuron_id = 0; @@ -225,15 +225,13 @@ bool synaptogenesis_dynamics_rewire( m_pop_index = key_atom_info->m_pop_index; } - if (!population_table_get_first_address( - *spike, synaptic_row_address, n_bytes)) { + if (!population_table_get_first_address(*spike, synaptic_row, n_bytes)) { log_error("FAIL@key %d", *spike); rt_error(RTE_SWERR); } uint32_t index = 0; while (index < m_pop_index) { - if (!population_table_get_next_address( - spike, synaptic_row_address, n_bytes)) { + if (!population_table_get_next_address(spike, synaptic_row, n_bytes)) { log_error("FAIL@key %d, index %d (failed at %d)", *spike, m_pop_index, index); rt_error(RTE_SWERR); @@ -258,39 +256,46 @@ bool synaptogenesis_dynamics_rewire( return true; } -bool synaptogenesis_row_restructure(uint32_t time, address_t row) { - current_state_t *current_state = _get_state(); - +//! \brief Performs the actual restructuring of a row +//! \details Supporting function for synaptogenesis_row_restructure() +//! \param[in] time: The time of the restructure +//! \param[in] row: The row to restructure +//! \param[in] current_state: The current state of the world +//! \return True if the row was changed and needs to be written back +static inline bool row_restructure( + uint32_t time, synaptic_row_t restrict row, + current_state_t *restrict current_state) { // the selected pre- and postsynaptic IDs are in current_state - bool return_value; if (current_state->element_exists) { // find the offset of the neuron in the current row - if (synapse_dynamics_find_neuron( + if (!synapse_dynamics_find_neuron( current_state->post_syn_id, row, ¤t_state->weight, ¤t_state->delay, ¤t_state->offset, ¤t_state->synapse_type)) { - return_value = synaptogenesis_elimination_rule(current_state, - elimination_params[current_state->post_to_pre.pop_index], - time, row); - } else { log_debug("Post neuron %d not in row", current_state->post_syn_id); - return_value = false; + return false; } + return synaptogenesis_elimination_rule(current_state, + elimination_params[current_state->post_to_pre.pop_index], + time, row); } else { // Can't form if the row is full uint32_t no_elems = synapse_dynamics_n_connections_in_row( synapse_row_fixed_region(row)); if (no_elems >= rewiring_data.s_max) { log_debug("row is full"); - return_value = false; - } else { - return_value = synaptogenesis_formation_rule(current_state, - formation_params[current_state->post_to_pre.pop_index], - time, row); + return false; } + return synaptogenesis_formation_rule(current_state, + formation_params[current_state->post_to_pre.pop_index], + time, row); } +} +bool synaptogenesis_row_restructure(uint32_t time, synaptic_row_t row) { + current_state_t *current_state = _get_state(); + bool return_value = row_restructure(time, row, current_state); _free_state(current_state); return return_value; } diff --git a/neural_modelling/src/neuron/structural_plasticity/synaptogenesis_dynamics.h b/neural_modelling/src/neuron/structural_plasticity/synaptogenesis_dynamics.h index e2f1e0f579d..8edd3777b6a 100644 --- a/neural_modelling/src/neuron/structural_plasticity/synaptogenesis_dynamics.h +++ b/neural_modelling/src/neuron/structural_plasticity/synaptogenesis_dynamics.h @@ -35,40 +35,40 @@ bool synaptogenesis_dynamics_initialise( address_t sdram_sp_address); -//! \brief Function called (usually on a timer from c_main()) to -//! trigger the process of synaptic rewiring +//! \brief Trigger the process of synaptic rewiring +//! \details Usually called on a timer registered in c_main() //! \param[in] time: the current timestep //! \param[out] spike: variable to hold the spike -//! \param[out] synaptic_row_address: variable to hold the address of the row +//! \param[out] synaptic_row: variable to hold the address of the row //! \param[out] n_bytes: variable to hold the size of the row //! \return True if a row is to be transferred, false otherwise bool synaptogenesis_dynamics_rewire(uint32_t time, - spike_t *spike, address_t *synaptic_row_address, uint32_t *n_bytes); + spike_t *spike, synaptic_row_t *synaptic_row, uint32_t *n_bytes); -//! \brief Performs the actual restructuring of a row +//! \brief Perform the actual restructuring of a row //! \param[in] time: The time of the restructure //! \param[in] row: The row to restructure //! \return True if the row was changed and needs to be written back -bool synaptogenesis_row_restructure(uint32_t time, address_t row); +bool synaptogenesis_row_restructure(uint32_t time, synaptic_row_t row); -//! \brief retrieve the period of rewiring +//! \brief Get the period of rewiring //! \return Based on synaptogenesis_is_fast(), this can either be how many times //! rewiring happens in a timestep, or how many timesteps have to pass until //! rewiring happens. int32_t synaptogenesis_rewiring_period(void); -//! \brief controls whether rewiring is attempted multiple times per timestep +//! \brief Get whether rewiring is attempted multiple times per timestep //! or after a number of timesteps. //! \return true if the result of synaptogenesis_rewiring_period() is the number //! of attempts to try per timestep. bool synaptogenesis_is_fast(void); -//! Indicates that a spike has been received +//! \brief Indicates that a spike has been received //! \param[in] time: The time that the spike was received at //! \param[in] spike: The received spike void synaptogenesis_spike_received(uint32_t time, spike_t spike); -//! Prints a certain data object +//! Print a certain data object void print_post_to_pre_entry(void); #endif // _SYNAPTOGENESIS_DYNAMICS_H_ diff --git a/neural_modelling/src/neuron/structural_plasticity/synaptogenesis_dynamics_static_impl.c b/neural_modelling/src/neuron/structural_plasticity/synaptogenesis_dynamics_static_impl.c index b08404eae3f..7e188945fe0 100644 --- a/neural_modelling/src/neuron/structural_plasticity/synaptogenesis_dynamics_static_impl.c +++ b/neural_modelling/src/neuron/structural_plasticity/synaptogenesis_dynamics_static_impl.c @@ -29,12 +29,12 @@ bool synaptogenesis_dynamics_initialise(UNUSED address_t sdram_sp_address) { bool synaptogenesis_dynamics_rewire( UNUSED uint32_t time, UNUSED spike_t *spike, - UNUSED address_t *synaptic_row_address, UNUSED uint32_t *n_bytes) { + UNUSED synaptic_row_t *synaptic_row, UNUSED uint32_t *n_bytes) { return false; } bool synaptogenesis_row_restructure( - UNUSED uint32_t time, UNUSED address_t row) { + UNUSED uint32_t time, UNUSED synaptic_row_t row) { return false; } diff --git a/neural_modelling/src/neuron/synapse_row.h b/neural_modelling/src/neuron/synapse_row.h index afdf051289b..662a1c2a099 100644 --- a/neural_modelling/src/neuron/synapse_row.h +++ b/neural_modelling/src/neuron/synapse_row.h @@ -118,53 +118,75 @@ typedef uint16_t control_t; //! Number of header words per synaptic row #define N_SYNAPSE_ROW_HEADER_WORDS 3 -//! \brief Returns the size of the plastic region +//! The type of the plastic-plastic part of the row +typedef struct { + size_t size; //!< The number of plastic words in `data` + uint32_t data[]; //!< The plastic words, followed by the fixed part +} synapse_row_plastic_part_t; + +//! The type of the fixed part of the row. The fixed-plastic part follows. +typedef struct { + size_t num_fixed; //!< The number of fixed synapses in `data` + size_t num_plastic; //!< The number of plastic controls in `data` + uint32_t data[]; //!< The data, first the fixed then the plastic +} synapse_row_fixed_part_t; + +//! \brief Get the size of the plastic region //! \param[in] row: The synaptic row //! \return The size of the plastic region of the row -static inline size_t synapse_row_plastic_size(address_t row) { - return (size_t) row[0]; +static inline size_t synapse_row_plastic_size(const synaptic_row_t row) { + const synapse_row_plastic_part_t *the_row = + (const synapse_row_plastic_part_t *) row; + return the_row->size; } -//! \brief Returns the address of the plastic region +//! \brief Get the address of the plastic region //! \param[in] row: The synaptic row //! \return Address of the plastic region of the row -static inline address_t synapse_row_plastic_region(address_t row) { - return (address_t) &row[1]; +static inline void *synapse_row_plastic_region(synaptic_row_t row) { + synapse_row_plastic_part_t *the_row = (synapse_row_plastic_part_t *) row; + return the_row->data; } -//! \brief Returns the address of the non-plastic (or fixed) region +//! \brief Get the address of the non-plastic (or fixed) region //! \param[in] row: The synaptic row //! \return Address of the fixed region of the row -static inline address_t synapse_row_fixed_region(address_t row) { - return (address_t) &row[synapse_row_plastic_size(row) + 1]; +static inline synapse_row_fixed_part_t *synapse_row_fixed_region( + synaptic_row_t row) { + synapse_row_plastic_part_t *the_row = (synapse_row_plastic_part_t *) row; + return (synapse_row_fixed_part_t *) &the_row->data[the_row->size]; } -//! \brief The number of fixed synapses in the row +//! \brief Get the number of fixed synapses in the row //! \param[in] fixed: The fixed region of the synaptic row //! \return Size of the fixed region of the row (in words) -static inline size_t synapse_row_num_fixed_synapses(address_t fixed) { - return (size_t) fixed[0]; +static inline size_t synapse_row_num_fixed_synapses( + const synapse_row_fixed_part_t *fixed) { + return fixed->num_fixed; } -//! \brief The number of plastic controls in the row +//! \brief Get the number of plastic controls in the row //! \param[in] fixed: The fixed region of the synaptic row //! \return Size of the fixed-plastic region of the row (in _half_ words) -static inline size_t synapse_row_num_plastic_controls(address_t fixed) { - return (size_t) fixed[1]; +static inline size_t synapse_row_num_plastic_controls( + const synapse_row_fixed_part_t *fixed) { + return fixed->num_plastic; } -//! \brief The array of plastic controls in the row +//! \brief Get the array of plastic controls in the row //! \param[in] fixed: The fixed region of the synaptic row //! \return Address of the fixed-plastic region of the row -static inline control_t* synapse_row_plastic_controls(address_t fixed) { - return (control_t*) &fixed[2 + synapse_row_num_fixed_synapses(fixed)]; +static inline control_t *synapse_row_plastic_controls( + synapse_row_fixed_part_t *fixed) { + return (control_t *) &fixed->data[fixed->num_fixed]; } //! \brief The array of fixed weights in the row //! \param[in] fixed: The fixed region of the synaptic row //! \return Address of the fixed-fixed region of the row -static inline uint32_t *synapse_row_fixed_weight_controls(address_t fixed) { - return &fixed[2]; +static inline uint32_t *synapse_row_fixed_weight_controls( + synapse_row_fixed_part_t *fixed) { + return fixed->data; } // The following are offset calculations into the ring buffers diff --git a/neural_modelling/src/neuron/synapses.c b/neural_modelling/src/neuron/synapses.c index 939a448cb86..cf20011607f 100644 --- a/neural_modelling/src/neuron/synapses.c +++ b/neural_modelling/src/neuron/synapses.c @@ -99,26 +99,23 @@ static inline void print_synaptic_row(synaptic_row_t synaptic_row) { log_debug("----------------------------------------\n"); // Get details of fixed region - address_t fixed_region_address = synapse_row_fixed_region(synaptic_row); - address_t fixed_synapses = - synapse_row_fixed_weight_controls(fixed_region_address); - size_t n_fixed_synapses = - synapse_row_num_fixed_synapses(fixed_region_address); + synapse_row_fixed_part_t *fixed_region = + synapse_row_fixed_region(synaptic_row); + address_t fixed_synapses = synapse_row_fixed_weight_controls(fixed_region); + size_t n_fixed_synapses = synapse_row_num_fixed_synapses(fixed_region); log_debug("Fixed region %u fixed synapses (%u plastic control words):\n", - n_fixed_synapses, - synapse_row_num_plastic_controls(fixed_region_address)); + n_fixed_synapses, synapse_row_num_plastic_controls(fixed_region)); for (uint32_t i = 0; i < n_fixed_synapses; i++) { uint32_t synapse = fixed_synapses[i]; uint32_t synapse_type = synapse_row_sparse_type( synapse, synapse_index_bits, synapse_type_mask); - log_debug("%08x [%3d: (w: %5u (=", + io_printf(IO_BUF, "%08x [%3d: (w: %5u (=", synapse, i, synapse_row_sparse_weight(synapse)); synapses_print_weight(synapse_row_sparse_weight(synapse), ring_buffer_to_input_left_shifts[synapse_type]); - log_debug( - "nA) d: %2u, %s, n = %3u)] - {%08x %08x}\n", + io_printf(IO_BUF, "nA) d: %2u, %s, n = %3u)] - {%08x %08x}\n", synapse_row_sparse_delay(synapse, synapse_type_index_bits), get_type_char(synapse_type), synapse_row_sparse_index(synapse, synapse_index_mask), @@ -131,7 +128,7 @@ static inline void print_synaptic_row(synaptic_row_t synaptic_row) { address_t plastic_region_address = synapse_row_plastic_region(synaptic_row); synapse_dynamics_print_plastic_synapses( - plastic_region_address, fixed_region_address, + plastic_region_address, fixed_region, ring_buffer_to_input_left_shifts); } @@ -142,8 +139,7 @@ static inline void print_synaptic_row(synaptic_row_t synaptic_row) { } //! \brief Print the contents of the ring buffers. -//! -//! Only does anything when debugging. +//! \details Only does anything when debugging. //! \param[in] time: The current timestamp static inline void print_ring_buffers(uint32_t time) { #if LOG_LEVEL >= LOG_DEBUG @@ -181,8 +177,7 @@ static inline void print_ring_buffers(uint32_t time) { } //! \brief Print the neuron inputs. -//! -//! Only does anything when debugging. +//! \details Only does anything when debugging. static inline void print_inputs(void) { #if LOG_LEVEL >= LOG_DEBUG log_debug("Inputs\n"); @@ -191,18 +186,15 @@ static inline void print_inputs(void) { } -//! \brief This is the "inner loop" of the neural simulation. -//! -//! Every spike event could cause up to 256 different weights to -//! be put into the ring buffer. -//! \param[in] fixed_region_address: The fixed region of the synaptic matrix +//! \brief The "inner loop" of the neural simulation. +//! \details Every spike event could cause up to 256 different weights to +//! be put into the ring buffer. +//! \param[in] fixed_region: The fixed region of the synaptic matrix //! \param[in] time: The current simulation time static inline void process_fixed_synapses( - address_t fixed_region_address, uint32_t time) { - register uint32_t *synaptic_words = - synapse_row_fixed_weight_controls(fixed_region_address); - register uint32_t fixed_synapse = - synapse_row_num_fixed_synapses(fixed_region_address); + synapse_row_fixed_part_t *fixed_region, uint32_t time) { + uint32_t *synaptic_words = synapse_row_fixed_weight_controls(fixed_region); + uint32_t fixed_synapse = synapse_row_num_fixed_synapses(fixed_region); num_fixed_pre_synaptic_events += fixed_synapse; @@ -241,7 +233,7 @@ static inline void process_fixed_synapses( } } -//! private method for doing output debug data on the synapses +//! Print output debug data on the synapses static inline void print_synapse_parameters(void) { // only if the models are compiled in debug mode will this method contain // said lines. @@ -366,7 +358,7 @@ bool synapses_process_synaptic_row( uint32_t time, synaptic_row_t row, bool *write_back) { // Get address of non-plastic region from row - address_t fixed_region_address = synapse_row_fixed_region(row); + synapse_row_fixed_part_t *fixed_region = synapse_row_fixed_region(row); // **TODO** multiple optimised synaptic row formats //if (plastic_tag(row) == 0) { @@ -379,7 +371,7 @@ bool synapses_process_synaptic_row( profiler_write_entry_disable_fiq( PROFILER_ENTER | PROFILER_PROCESS_PLASTIC_SYNAPSES); if (!synapse_dynamics_process_plastic_synapses(plastic_region_address, - fixed_region_address, ring_buffers, time)) { + fixed_region, ring_buffers, time)) { return false; } profiler_write_entry_disable_fiq( @@ -393,19 +385,18 @@ bool synapses_process_synaptic_row( // **NOTE** this is done after initiating DMA in an attempt // to hide cost of DMA behind this loop to improve the chance // that the DMA controller is ready to read next synaptic row afterwards - process_fixed_synapses(fixed_region_address, time); + process_fixed_synapses(fixed_region, time); //} return true; } -//! \brief returns the number of times the synapses have saturated their -//! weights. +//! \brief Get the number of times the synapses have saturated their weights. //! \return the number of times the synapses have saturated. uint32_t synapses_get_saturation_count(void) { return saturation_count; } -//! \brief returns the counters for plastic and fixed pre synaptic events +//! \brief Get the counters for plastic and fixed pre synaptic events //! based on (if the model was compiled with SYNAPSE_BENCHMARK parameter) or //! returns 0 //! \return the counter for plastic and fixed pre synaptic events or 0 @@ -420,7 +411,7 @@ void synapses_flush_ring_buffers(void) { } } -//! \brief allows clearing of DTCM used by synapses +//! \brief Clear DTCM used by synapses //! \return true if successful bool synapses_shut_down(void) { sark_free(ring_buffer_to_input_left_shifts); diff --git a/neural_modelling/src/synapse_expander/matrix_generators/matrix_generator_static.h b/neural_modelling/src/synapse_expander/matrix_generators/matrix_generator_static.h index 8c38b6b273b..110d9511e5e 100644 --- a/neural_modelling/src/synapse_expander/matrix_generators/matrix_generator_static.h +++ b/neural_modelling/src/synapse_expander/matrix_generators/matrix_generator_static.h @@ -58,25 +58,13 @@ static void matrix_generator_static_free(UNUSED void *generator) { */ #define SYNAPSE_DELAY_MASK 0xFF -/** - * \brief The position of the plastic-plastic size within a row - */ -#define STATIC_PLASTIC_PLASTIC_SIZE 0 - -/** - * \brief The position of the fixed-plastic size within a row - */ -#define STATIC_FIXED_PLASTIC_SIZE 2 - -/** - * \brief The position of the fixed-fixed size within a row - */ -#define STATIC_FIXED_FIXED_SIZE 1 - -/** - * \brief The starting position of the fixed-fixed data within a row - */ -#define STATIC_FIXED_FIXED_OFFSET 3 +//! The layout of a purely static row of a synaptic matrix. +typedef struct { + uint32_t plastic_plastic_size; //!< the plastic-plastic size within a row + uint32_t fixed_fixed_size; //!< the fixed-fixed size within a row + uint32_t fixed_plastic_size; //!< the fixed-plastic size within a row + uint32_t fixed_fixed_data[]; //!< the fixed-fixed data within a row +} *static_row_t; /** * \brief Build a static synaptic word from components @@ -105,16 +93,16 @@ static uint32_t build_static_word( /** * \brief How to generate a row of a static synaptic matrix - * \param[in] generator: The data for the matrix generator, returned by the - * initialise function + * \param[in] generator: + * The data for the matrix generator, returned by the initialise function * \param[out] synaptic_matrix: The address of the synaptic matrix to write to - * \param[out] delayed_synaptic_matrix: The address of the synaptic matrix to - * write delayed connections to + * \param[out] delayed_synaptic_matrix: + * The address of the synaptic matrix to write delayed connections to * \param[in] n_pre_neurons: The number of pre neurons to generate for * \param[in] pre_neuron_index: The index of the first pre neuron * \param[in] max_row_n_words: The maximum number of words in a normal row - * \param[in] max_delayed_row_n_words: The maximum number of words in a - * delayed row + * \param[in] max_delayed_row_n_words: + * The maximum number of words in a delayed row * \param[in] synapse_type_bits: The number of bits used for the synapse type * \param[in] synapse_index_bits: The number of bits used for the neuron id * \param[in] synapse_type: The synapse type of each connection @@ -137,19 +125,19 @@ static void matrix_generator_static_write_row( // Row address and position for each possible delay stage (including no // delay stage) - address_t row_address[max_stage]; + static_row_t row[max_stage]; // The space available on each row uint16_t space[max_stage]; // The normal row position and space available - might be 0 if all delayed - row_address[0] = NULL; + row[0] = NULL; space[0] = max_row_n_words; if (synaptic_matrix != NULL) { - row_address[0] = + row[0] = (static_row_t) &synaptic_matrix[pre_neuron_index * (max_row_n_words + 3)]; } - log_debug("row[0] = 0x%08x", row_address[0]); + log_debug("row[0] = 0x%08x", row[0]); // The delayed row positions and space available if (delayed_synaptic_matrix != NULL) { @@ -158,28 +146,29 @@ static void matrix_generator_static_write_row( uint32_t single_matrix_size = n_pre_neurons * (max_delayed_row_n_words + 3); for (uint32_t i = 1; i < max_stage; i++) { - row_address[i] = &delayed_address[single_matrix_size * (i - 1)]; + row[i] = (static_row_t) + &delayed_address[single_matrix_size * (i - 1)]; space[i] = max_delayed_row_n_words; - log_debug("row[%u] = 0x%08x", i, row_address[i]); + log_debug("row[%u] = 0x%08x", i, row[i]); } } else { for (uint32_t i = 1; i < max_stage; i++) { - row_address[i] = NULL; + row[i] = NULL; space[i] = 0; - log_debug("row[%u] = 0x%08x", i, row_address[i]); + log_debug("row[%u] = 0x%08x", i, row[i]); } } // The address to write synapses to on each stage address_t write_address[max_stage]; for (uint32_t i = 0; i < max_stage; i++) { - if (row_address[i] != NULL) { + if (row[i] != NULL) { log_debug("Row size at 0x%08x for stage %u", - &row_address[i][STATIC_FIXED_FIXED_SIZE], i); - row_address[i][STATIC_FIXED_FIXED_SIZE] = 0; - row_address[i][STATIC_PLASTIC_PLASTIC_SIZE] = 0; - row_address[i][STATIC_FIXED_PLASTIC_SIZE] = 0; - write_address[i] = &row_address[i][STATIC_FIXED_FIXED_OFFSET]; + &row[i]->fixed_fixed_size, i); + row[i]->fixed_fixed_size = 0; + row[i]->plastic_plastic_size = 0; + row[i]->fixed_plastic_size = 0; + write_address[i] = row[i]->fixed_fixed_data; } else { write_address[i] = NULL; } @@ -222,7 +211,7 @@ static void matrix_generator_static_write_row( write_address[delay.stage] = &write_address[delay.stage][1]; // Increment the size of the current row - row_address[delay.stage][STATIC_FIXED_FIXED_SIZE]++; + row[delay.stage]->fixed_fixed_size++; space[delay.stage]--; } } diff --git a/neural_modelling/src/synapse_expander/matrix_generators/matrix_generator_stdp.h b/neural_modelling/src/synapse_expander/matrix_generators/matrix_generator_stdp.h index 12cc647979a..0256c812fef 100644 --- a/neural_modelling/src/synapse_expander/matrix_generators/matrix_generator_stdp.h +++ b/neural_modelling/src/synapse_expander/matrix_generators/matrix_generator_stdp.h @@ -33,30 +33,18 @@ */ #define SYNAPSE_DELAY_MASK 0xFF -/** - * \brief The position of the plastic-plastic size within the row - */ -#define STDP_PLASTIC_PLASTIC_SIZE 0 - -/** - * \brief The position of the plastic-plastic data within the row - */ -#define STDP_PLASTIC_PLASTIC_OFFSET 1 - -/** - * \brief The position of the fixed-fixed size within the fixed region - */ -#define STDP_FIXED_FIXED_SIZE 0 - -/** - * \brief The position of the fixed-plastic size within the fixed region - */ -#define STDP_FIXED_PLASTIC_SIZE 1 - -/** - * \brief The position of the fixed-plastic data within the fixed region - */ -#define STDP_FIXED_PLASTIC_OFFSET 2 +//! The layout of the initial plastic synapse part of the row +typedef struct { + uint32_t plastic_plastic_size; //!< the plastic-plastic size within the row + uint16_t plastic_plastic_data[]; //!< the plastic-plastic data within the row +} *row_plastic_t; + +//! The layout of the fixed synapse region of the row; the fixed-fixed region is empty +typedef struct { + uint32_t fixed_fixed_size; //!< the fixed-fixed size within the fixed region + uint32_t fixed_plastic_size; //!< the fixed-plastic size within the fixed region + uint16_t fixed_plastic_data[]; //!< the fixed-plastic data within the fixed region +} *row_fixed_t; //! Data for the generator struct matrix_generator_stdp { @@ -69,7 +57,7 @@ struct matrix_generator_stdp { }; /** - * \brief How to initialise the STDP synaptic matrix generator + * \brief Initialise the STDP synaptic matrix generator * \param[in,out] region: Region to read parameters from. Should be updated * to position just after parameters after calling. * \return A data item to be passed in to other functions later on @@ -87,7 +75,7 @@ void *matrix_generator_stdp_initialize(address_t *region) { } /** - * \brief How to free any data for the STDP synaptic matrix generator + * \brief Free any data for the STDP synaptic matrix generator * \param[in] generator: The generator to free */ void matrix_generator_stdp_free(void *generator) { @@ -95,7 +83,7 @@ void matrix_generator_stdp_free(void *generator) { } /** - * \brief Build a fixed-plastic half-word from the components + * \brief Build a fixed-plastic half-word from its components * \param[in] delay: The delay of the synapse * \param[in] type: The synapse type * \param[in] post_index: The core-relative index of the target neuron @@ -120,17 +108,17 @@ static uint16_t build_fixed_plastic_half_word( } /** - * \brief How to generate a row of a STDP synaptic matrix - * \param[in] generator: The data for the matrix generator, returned by the - * initialise function + * \brief Generate a row of a STDP synaptic matrix + * \param[in] generator: + * The data for the matrix generator, returned by the initialise function * \param[out] synaptic_matrix: The address of the synaptic matrix to write to - * \param[out] delayed_synaptic_matrix: The address of the synaptic matrix to - * write delayed connections to + * \param[out] delayed_synaptic_matrix: + * The address of the synaptic matrix to write delayed connections to * \param[in] n_pre_neurons: The number of pre neurons to generate for * \param[in] pre_neuron_index: The index of the first pre neuron * \param[in] max_row_n_words: The maximum number of words in a normal row - * \param[in] max_delayed_row_n_words: The maximum number of words in a - * delayed row + * \param[in] max_delayed_row_n_words: + * The maximum number of words in a delayed row * \param[in] synapse_type_bits: The number of bits used for the synapse type * \param[in] synapse_index_bits: The number of bits used for the neuron id * \param[in] synapse_type: The synapse type of each connection @@ -152,7 +140,7 @@ void matrix_generator_stdp_write_row( struct matrix_generator_stdp *obj = generator; // Row address for each possible delay stage (including no delay stage) - address_t row_address[max_stage]; + row_plastic_t row[max_stage]; // Space available in each row uint16_t space_half_words[max_stage]; @@ -162,10 +150,11 @@ void matrix_generator_stdp_write_row( uint32_t n_delay_row_words = max_delayed_row_n_words + 3; // The normal row position and space available - might be 0 if all delayed - row_address[0] = NULL; + row[0] = NULL; space_half_words[0] = max_row_n_words * 2; if (synaptic_matrix != NULL) { - row_address[0] = &synaptic_matrix[pre_neuron_index * n_row_words]; + row[0] = (row_plastic_t) + &synaptic_matrix[pre_neuron_index * n_row_words]; } // The delayed row positions and space available @@ -174,23 +163,23 @@ void matrix_generator_stdp_write_row( &delayed_synaptic_matrix[pre_neuron_index * n_delay_row_words]; uint32_t single_matrix_size = n_pre_neurons * n_delay_row_words; for (uint32_t i = 1; i < max_stage; i++) { - row_address[i] = &delayed_address[single_matrix_size * (i - 1)]; + row[i] = (row_plastic_t) + &delayed_address[single_matrix_size * (i - 1)]; space_half_words[i] = max_delayed_row_n_words * 2; } } else { for (uint32_t i = 1; i < max_stage; i++) { - row_address[i] = NULL; + row[i] = NULL; space_half_words[i] = 0; } } // Add the header half words (zero initialised) to each row for (uint32_t i = 0; i < max_stage; i++) { - if (row_address[i] != NULL) { - row_address[i][STDP_PLASTIC_PLASTIC_SIZE] = + if (row[i] != NULL) { + row[i]->plastic_plastic_size = obj->n_half_words_per_pp_row_header >> 1; - uint16_t *header = (uint16_t *) - &row_address[i][STDP_PLASTIC_PLASTIC_OFFSET]; + uint16_t *header = row[i]->plastic_plastic_data; for (uint32_t j = 0; j < obj->n_half_words_per_pp_row_header; j++) { header[j] = 0; @@ -205,10 +194,9 @@ void matrix_generator_stdp_write_row( uint16_t n_half_words_per_row[max_stage]; for (uint32_t i = 0; i < max_stage; i++) { n_half_words_per_row[i] = 0; - if (row_address[i] != NULL) { - pp_address[i] = (uint16_t *) &row_address[i][ - STDP_PLASTIC_PLASTIC_OFFSET + - (obj->n_half_words_per_pp_row_header >> 1)]; + if (row[i] != NULL) { + pp_address[i] = &row[i]->plastic_plastic_data[ + obj->n_half_words_per_pp_row_header]; } else { pp_address[i] = NULL; } @@ -222,7 +210,7 @@ void matrix_generator_stdp_write_row( struct delay_value delay = get_delay(delays[synapse], max_stage); // Check that the position is valid - if (pp_address[delay.stage] == NULL) { + if (delay.stage >= max_stage || pp_address[delay.stage] == NULL) { log_error("Delay stage %u has not been initialised", delay.stage); rt_error(RTE_SWERR); } @@ -243,36 +231,32 @@ void matrix_generator_stdp_write_row( weight_words[i] = 0; } weight_words[obj->weight_half_word] = weight; - n_half_words_per_row[delay.stage] += - obj->n_half_words_per_pp_synapse; + n_half_words_per_row[delay.stage] += obj->n_half_words_per_pp_synapse; space_half_words[delay.stage] -= obj->n_half_words_per_pp_synapse; } // Add padding to any rows that are not word-aligned // and set the size in words for (uint32_t i = 0; i < max_stage; i++) { - if (row_address[i] != NULL) { + if (row[i] != NULL) { if (n_half_words_per_row[i] & 0x1) { - pp_address[i][0] = 0; - pp_address[i] = &pp_address[i][1]; + *pp_address[i]++ = 0; n_half_words_per_row[i]++; } - row_address[i][STDP_PLASTIC_PLASTIC_SIZE] += - n_half_words_per_row[i] >> 1; + row[i]->plastic_plastic_size += n_half_words_per_row[i] >> 1; } } // PP address is now fixed region address // Set the fixed-fixed size to 0 and point to the fixed-plastic region - uint32_t *fixed_address[max_stage]; + row_fixed_t fixed[max_stage]; uint16_t *fp_address[max_stage]; for (uint32_t i = 0; i < max_stage; i++) { - fixed_address[i] = (uint32_t *) pp_address[i]; - if (pp_address[i] != NULL) { - fp_address[i] = (uint16_t *) - &fixed_address[i][STDP_FIXED_PLASTIC_OFFSET]; - fixed_address[i][STDP_FIXED_FIXED_SIZE] = 0; - fixed_address[i][STDP_FIXED_PLASTIC_SIZE] = 0; + fixed[i] = (row_fixed_t) pp_address[i]; + if (fixed[i] != NULL) { + fp_address[i] = fixed[i]->fixed_plastic_data; + fixed[i]->fixed_fixed_size = 0; + fixed[i]->fixed_plastic_size = 0; } else { fp_address[i] = NULL; } @@ -291,10 +275,9 @@ void matrix_generator_stdp_write_row( synapse_index_bits); // Write the half-word - fp_address[delay.stage][0] = fp_half_word; - fp_address[delay.stage] = &fp_address[delay.stage][1]; + *fp_address[delay.stage]++ = fp_half_word; // Increment the size of the current row - fixed_address[delay.stage][STDP_FIXED_PLASTIC_SIZE]++; + fixed[delay.stage]->fixed_plastic_size++; } } From 04a26649a01eb9dd155ba9a60a76ff51f613dc46 Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Mon, 16 Nov 2020 17:02:17 +0000 Subject: [PATCH 2/6] Gradually fixing the type errors introduced accidentally --- .../bit_field_expander/bit_field_expander.c | 21 +++++++++---------- .../population_table_binary_search_impl.c | 3 ++- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/neural_modelling/src/bit_field_expander/bit_field_expander.c b/neural_modelling/src/bit_field_expander/bit_field_expander.c index dbfbe6745ed..bcbea259455 100644 --- a/neural_modelling/src/bit_field_expander/bit_field_expander.c +++ b/neural_modelling/src/bit_field_expander/bit_field_expander.c @@ -83,7 +83,7 @@ uint32_t n_vertex_regions = 0; bit_field_t* fake_bit_fields; //! Holds SDRAM read row -uint32_t * row_data; +synaptic_row_t row_data; //! Says if we should run bool can_run = true; @@ -271,9 +271,8 @@ bool process_synaptic_row(synaptic_row_t row) { } // Get address of non-plastic region from row - address_t fixed_region_address = synapse_row_fixed_region(row); - uint32_t fixed_synapse = - synapse_row_num_fixed_synapses(fixed_region_address); + synapse_row_fixed_part_t *fixed_region = synapse_row_fixed_region(row); + uint32_t fixed_synapse = synapse_row_num_fixed_synapses(fixed_region); if (fixed_synapse == 0) { log_debug("Plastic and fixed do not have entries, so can be pruned"); return false; @@ -289,8 +288,8 @@ bool process_synaptic_row(synaptic_row_t row) { //! how many bytes to read to get the synaptic row //! \return Whether there is target static bool do_sdram_read_and_test( - address_t row_address, uint32_t n_bytes_to_transfer) { - spin1_memcpy(row_data, row_address, n_bytes_to_transfer); + synaptic_row_t row, uint32_t n_bytes_to_transfer) { + spin1_memcpy(row_data, row, n_bytes_to_transfer); log_debug("Process synaptic row"); return process_synaptic_row(row_data); } @@ -388,10 +387,10 @@ bool generate_bit_field(void) { // used to store the row from the master pop / synaptic matrix, // not going to be used in reality. - address_t row_address; + synaptic_row_t row; if (!bit_found) { if (population_table_get_first_address( - new_key, &row_address, &n_bytes_to_transfer)) { + new_key, &row, &n_bytes_to_transfer)) { log_debug("%d", neuron_id); // This is a direct row to process, so will have 1 target, @@ -403,11 +402,11 @@ bool generate_bit_field(void) { // sdram read (faking dma transfer) log_debug("DMA read synapse"); bit_found = do_sdram_read_and_test( - row_address, n_bytes_to_transfer); + row, n_bytes_to_transfer); } while (!bit_found && population_table_get_next_address( - &new_key, &row_address, &n_bytes_to_transfer)){ + &new_key, &row, &n_bytes_to_transfer)){ log_debug("%d", neuron_id); // This is a direct row to process, so will have 1 @@ -419,7 +418,7 @@ bool generate_bit_field(void) { // sdram read (faking dma transfer) log_debug("DMA read synapse"); bit_found = do_sdram_read_and_test( - row_address, n_bytes_to_transfer); + row, n_bytes_to_transfer); } } } 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 00ce14fbfdd..c19d8e841eb 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 @@ -552,7 +552,8 @@ bool population_table_get_first_address( } bool population_table_get_next_address( - spike_t *spike, address_t *row_address, size_t *n_bytes_to_transfer) { + spike_t *spike, synaptic_row_t *row_address, + size_t *n_bytes_to_transfer) { // If there are no more items in the list, return false if (items_to_go == 0) { return false; From e2dd5d6e9f6ebe8ca0080c50c7922558b43f4f6d Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Mon, 16 Nov 2020 17:09:32 +0000 Subject: [PATCH 3/6] There's one place where it is useful to see a row as an array of words --- neural_modelling/src/neuron/spike_processing.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/neural_modelling/src/neuron/spike_processing.c b/neural_modelling/src/neuron/spike_processing.c index 876b2404b68..1428cf89a2e 100644 --- a/neural_modelling/src/neuron/spike_processing.c +++ b/neural_modelling/src/neuron/spike_processing.c @@ -378,9 +378,10 @@ static void dma_complete_callback(UNUSED uint unused, uint tag) { current_buffer->row); // Print out the row for debugging + address_t row = (address_t) current_buffer->row; for (uint32_t i = 0; i < (current_buffer->n_bytes_transferred >> 2); i++) { - log_error("%u: 0x%.8x", i, current_buffer->row[i]); + log_error("%u: 0x%.8x", i, row[i]); } rt_error(RTE_SWERR); } From ccf82b7ec4b0a37278ab8ecb93161ed1a0a72849 Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Mon, 16 Nov 2020 17:16:38 +0000 Subject: [PATCH 4/6] Missed some type conversions --- .../stdp/synapse_dynamics_stdp_mad_impl.c | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) 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 83adf643624..d220904d8ed 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 @@ -205,10 +205,11 @@ static inline final_state_t plasticity_update_synapse( //--------------------------------------- void synapse_dynamics_print_plastic_synapses( - address_t plastic_region_address, address_t fixed_region_address, + address_t plastic_region_address, + synapse_row_fixed_part_t *fixed_region, uint32_t *ring_buffer_to_input_buffer_left_shifts) { __use(plastic_region_address); - __use(fixed_region_address); + __use(fixed_region); __use(ring_buffer_to_input_buffer_left_shifts); #if LOG_LEVEL >= LOG_DEBUG @@ -217,10 +218,8 @@ void synapse_dynamics_print_plastic_synapses( // Extract separate arrays of weights (from plastic region), // Control words (from fixed region) and number of plastic synapses const plastic_synapse_t *plastic_words = data_ptr->synapses; - 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 control_t *control_words = synapse_row_plastic_controls(fixed_region); + size_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); log_debug("Plastic region %u synapses\n", plastic_synapse); @@ -319,17 +318,16 @@ bool synapse_dynamics_initialise( } bool synapse_dynamics_process_plastic_synapses( - address_t plastic_region_address, address_t fixed_region_address, + address_t plastic_region_address, + synapse_row_fixed_part_t *fixed_region, weight_t *ring_buffers, uint32_t time) { synapse_row_plastic_data_t *plastic_data = (synapse_row_plastic_data_t *) plastic_region_address; // 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_data->synapses; - 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 control_t *control_words = synapse_row_plastic_controls(fixed_region); + size_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); num_plastic_pre_synaptic_events += plastic_synapse; From c4211deaf06243c662b285c1d6e92e47a6ea3e5f Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Tue, 8 Dec 2020 15:53:08 +0000 Subject: [PATCH 5/6] Resolving some issues --- .../src/neuron/spike_processing.c | 2 +- neural_modelling/src/neuron/synapses.c | 31 +++++++++---------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/neural_modelling/src/neuron/spike_processing.c b/neural_modelling/src/neuron/spike_processing.c index 1428cf89a2e..ec083d71374 100644 --- a/neural_modelling/src/neuron/spike_processing.c +++ b/neural_modelling/src/neuron/spike_processing.c @@ -93,7 +93,7 @@ static uint32_t spike_processing_count; //! The number of successful rewires static uint32_t n_successful_rewires; -//! \breif How many packets were lost from the input buffer because of +//! \brief How many packets were lost from the input buffer because of //! late arrival static uint32_t count_input_buffer_packets_late; diff --git a/neural_modelling/src/neuron/synapses.c b/neural_modelling/src/neuron/synapses.c index 753fe5fc317..f3fda94fc13 100644 --- a/neural_modelling/src/neuron/synapses.c +++ b/neural_modelling/src/neuron/synapses.c @@ -90,20 +90,21 @@ static inline const char *get_type_char(uint32_t synapse_type) { //! Only does anything when debugging. //! \param[in] synaptic_row: The synaptic row to print static inline void print_synaptic_row(synaptic_row_t synaptic_row) { -#if LOG_LEVEL >= LOG_DEBUG - log_debug("Synaptic row, at address %08x Num plastic words:%u\n", + log_debug("Synaptic row, at address %08x, Num plastic words:%u", (uint32_t) synaptic_row, synapse_row_plastic_size(synaptic_row)); if (synaptic_row == NULL) { return; } - log_debug("----------------------------------------\n"); +#if LOG_LEVEL >= LOG_DEBUG + io_printf(IO_BUF, "----------------------------------------\n"); // Get details of fixed region synapse_row_fixed_part_t *fixed_region = synapse_row_fixed_region(synaptic_row); address_t fixed_synapses = synapse_row_fixed_weight_controls(fixed_region); size_t n_fixed_synapses = synapse_row_num_fixed_synapses(fixed_region); - log_debug("Fixed region %u fixed synapses (%u plastic control words):\n", + io_printf(IO_BUF, + "Fixed region %u fixed synapses (%u plastic control words):\n", n_fixed_synapses, synapse_row_num_plastic_controls(fixed_region)); for (uint32_t i = 0; i < n_fixed_synapses; i++) { @@ -124,7 +125,7 @@ static inline void print_synaptic_row(synaptic_row_t synaptic_row) { // If there's a plastic region if (synapse_row_plastic_size(synaptic_row) > 0) { - log_debug("----------------------------------------\n"); + io_printf(IO_BUF, "----------------------------------------\n"); address_t plastic_region_address = synapse_row_plastic_region(synaptic_row); synapse_dynamics_print_plastic_synapses( @@ -132,9 +133,7 @@ static inline void print_synaptic_row(synaptic_row_t synaptic_row) { ring_buffer_to_input_left_shifts); } - log_debug("----------------------------------------\n"); -#else - use(synaptic_row); + io_printf(IO_BUF, "----------------------------------------\n"); #endif // LOG_LEVEL >= LOG_DEBUG } @@ -142,9 +141,9 @@ static inline void print_synaptic_row(synaptic_row_t synaptic_row) { //! \details Only does anything when debugging. //! \param[in] time: The current timestamp static inline void print_ring_buffers(uint32_t time) { + log_debug("Ring Buffer at %u", time); #if LOG_LEVEL >= LOG_DEBUG - log_debug("Ring Buffer at %u\n", time); - log_debug("----------------------------------------\n"); + io_printf(IO_BUF, "----------------------------------------\n"); for (uint32_t n = 0; n < n_neurons; n++) { for (uint32_t t = 0; t < n_synapse_types; t++) { // Determine if this row can be omitted @@ -158,21 +157,19 @@ static inline void print_ring_buffers(uint32_t time) { continue; doPrint: // Have to print the row - log_debug("%3d(%s):", n, get_type_char(t)); + io_printf(IO_BUF, "%3d(%s):", n, get_type_char(t)); for (uint32_t d = 0; d < (1 << SYNAPSE_DELAY_BITS); d++) { - log_debug(" "); + io_printf(IO_BUF, " "); uint32_t ring_buffer_index = synapses_get_ring_buffer_index( d + time, t, n, synapse_type_index_bits, synapse_index_bits); synapses_print_weight(ring_buffers[ring_buffer_index], ring_buffer_to_input_left_shifts[t]); } - log_debug("\n"); + io_printf(IO_BUF, "\n"); } } - log_debug("----------------------------------------\n"); -#else - use(time); + io_printf(IO_BUF, "----------------------------------------\n"); #endif // LOG_LEVEL >= LOG_DEBUG } @@ -180,7 +177,7 @@ static inline void print_ring_buffers(uint32_t time) { //! \details Only does anything when debugging. static inline void print_inputs(void) { #if LOG_LEVEL >= LOG_DEBUG - log_debug("Inputs\n"); + log_debug("Inputs"); neuron_print_inputs(); #endif // LOG_LEVEL >= LOG_DEBUG } From 4757171a9f444fdd34b50aa577d47936e3343155 Mon Sep 17 00:00:00 2001 From: Donal Fellows Date: Tue, 8 Dec 2020 16:13:38 +0000 Subject: [PATCH 6/6] Magic to make the typing of the plastic region of a row better --- .../stdp/synapse_dynamics_stdp_mad_impl.c | 28 ++++++++----------- .../src/neuron/plasticity/synapse_dynamics.h | 8 +++--- .../plasticity/synapse_dynamics_static_impl.c | 4 +-- neural_modelling/src/neuron/synapse_row.h | 9 ++++-- neural_modelling/src/neuron/synapses.c | 10 +++---- 5 files changed, 29 insertions(+), 30 deletions(-) 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 d220904d8ed..55bc50b4f9e 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 @@ -113,12 +113,12 @@ typedef struct { post_event_history_t *post_event_history; //! The format of the plastic data region of a synaptic row -typedef struct { +struct synapse_row_plastic_data_t { //! The pre-event history pre_event_history_t history; //! The per-synapse information plastic_synapse_t synapses[]; -} synapse_row_plastic_data_t; +}; /* PRIVATE FUNCTIONS */ @@ -205,19 +205,17 @@ static inline final_state_t plasticity_update_synapse( //--------------------------------------- void synapse_dynamics_print_plastic_synapses( - address_t plastic_region_address, + synapse_row_plastic_data_t *plastic_region_data, synapse_row_fixed_part_t *fixed_region, uint32_t *ring_buffer_to_input_buffer_left_shifts) { - __use(plastic_region_address); + __use(plastic_region_data); __use(fixed_region); __use(ring_buffer_to_input_buffer_left_shifts); #if LOG_LEVEL >= LOG_DEBUG - synapse_row_plastic_data_t *data_ptr = plastic_region_address; - // Extract separate arrays of weights (from plastic region), // Control words (from fixed region) and number of plastic synapses - const plastic_synapse_t *plastic_words = data_ptr->synapses; + const plastic_synapse_t *plastic_words = plastic_region_data->synapses; const control_t *control_words = synapse_row_plastic_controls(fixed_region); size_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); @@ -318,27 +316,25 @@ bool synapse_dynamics_initialise( } bool synapse_dynamics_process_plastic_synapses( - address_t plastic_region_address, + synapse_row_plastic_data_t *plastic_region_address, synapse_row_fixed_part_t *fixed_region, weight_t *ring_buffers, uint32_t time) { - synapse_row_plastic_data_t *plastic_data = - (synapse_row_plastic_data_t *) plastic_region_address; // 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_data->synapses; + plastic_synapse_t *plastic_words = plastic_region_address->synapses; const control_t *control_words = synapse_row_plastic_controls(fixed_region); size_t plastic_synapse = synapse_row_num_plastic_controls(fixed_region); num_plastic_pre_synaptic_events += plastic_synapse; // Get last pre-synaptic event from event history - const uint32_t last_pre_time = plastic_data->history.prev_time; - const pre_trace_t last_pre_trace = plastic_data->history.prev_trace; + const uint32_t last_pre_time = plastic_region_address->history.prev_time; + const pre_trace_t last_pre_trace = plastic_region_address->history.prev_trace; // Update pre-synaptic trace log_debug("Adding pre-synaptic event to trace at time:%u", time); - plastic_data->history.prev_time = time; - plastic_data->history.prev_trace = + plastic_region_address->history.prev_time = time; + plastic_region_address->history.prev_trace = timing_add_pre_spike(time, last_pre_time, last_pre_trace); // Loop through plastic synapses @@ -375,7 +371,7 @@ bool synapse_dynamics_process_plastic_synapses( } final_state_t final_state = plasticity_update_synapse( time, last_pre_time, last_pre_trace, - plastic_data->history.prev_trace, + plastic_region_address->history.prev_trace, post_delay, delay_axonal, current_state, &post_event_history[index]); diff --git a/neural_modelling/src/neuron/plasticity/synapse_dynamics.h b/neural_modelling/src/neuron/plasticity/synapse_dynamics.h index c6ad87ed214..b6a44b03d6a 100644 --- a/neural_modelling/src/neuron/plasticity/synapse_dynamics.h +++ b/neural_modelling/src/neuron/plasticity/synapse_dynamics.h @@ -37,13 +37,13 @@ bool synapse_dynamics_initialise( uint32_t *ring_buffer_to_input_buffer_left_shifts); //! \brief Process the dynamics of the synapses -//! \param[in,out] plastic_region_address: Where the plastic data is +//! \param[in,out] plastic_region_data: Where the plastic data is //! \param[in] fixed_region: Where the fixed data is //! \param[in,out] ring_buffers: The ring buffers //! \param[in] time: The current simulation time //! \return ??? bool synapse_dynamics_process_plastic_synapses( - address_t plastic_region_address, + synapse_row_plastic_data_t *plastic_region_data, synapse_row_fixed_part_t *fixed_region, weight_t *ring_buffers, uint32_t time); @@ -61,12 +61,12 @@ input_t synapse_dynamics_get_intrinsic_bias( uint32_t time, index_t neuron_index); //! \brief Print the synapse dynamics -//! \param[in] plastic_region_address: Where the plastic data is +//! \param[in] plastic_region_data: Where the plastic data is //! \param[in] fixed_region: Where the fixed data is //! \param[in] ring_buffer_to_input_buffer_left_shifts: //! How to interpret the values from the ring buffers void synapse_dynamics_print_plastic_synapses( - address_t plastic_region_address, + synapse_row_plastic_data_t *plastic_region_data, synapse_row_fixed_part_t *fixed_region, uint32_t *ring_buffer_to_input_buffer_left_shifts); diff --git a/neural_modelling/src/neuron/plasticity/synapse_dynamics_static_impl.c b/neural_modelling/src/neuron/plasticity/synapse_dynamics_static_impl.c index 21586991023..75eb6a6548a 100644 --- a/neural_modelling/src/neuron/plasticity/synapse_dynamics_static_impl.c +++ b/neural_modelling/src/neuron/plasticity/synapse_dynamics_static_impl.c @@ -70,7 +70,7 @@ void synapse_dynamics_process_post_synaptic_event( //--------------------------------------- bool synapse_dynamics_process_plastic_synapses( - UNUSED address_t plastic_region_address, + UNUSED synapse_row_plastic_data_t *plastic_region_data, UNUSED synapse_row_fixed_part_t *fixed_region, UNUSED weight_t *ring_buffer, UNUSED uint32_t time) { log_error("There should be no plastic synapses!"); @@ -84,7 +84,7 @@ input_t synapse_dynamics_get_intrinsic_bias( } void synapse_dynamics_print_plastic_synapses( - UNUSED address_t plastic_region_address, + UNUSED synapse_row_plastic_data_t *plastic_region_data, UNUSED synapse_row_fixed_part_t *fixed_region, UNUSED uint32_t *ring_buffer_to_input_left_shifts) { } diff --git a/neural_modelling/src/neuron/synapse_row.h b/neural_modelling/src/neuron/synapse_row.h index 662a1c2a099..979a0fbe047 100644 --- a/neural_modelling/src/neuron/synapse_row.h +++ b/neural_modelling/src/neuron/synapse_row.h @@ -131,6 +131,8 @@ typedef struct { uint32_t data[]; //!< The data, first the fixed then the plastic } synapse_row_fixed_part_t; +typedef struct synapse_row_plastic_data_t synapse_row_plastic_data_t; + //! \brief Get the size of the plastic region //! \param[in] row: The synaptic row //! \return The size of the plastic region of the row @@ -142,10 +144,11 @@ static inline size_t synapse_row_plastic_size(const synaptic_row_t row) { //! \brief Get the address of the plastic region //! \param[in] row: The synaptic row -//! \return Address of the plastic region of the row -static inline void *synapse_row_plastic_region(synaptic_row_t row) { +//! \return Pointer to the plastic region of the row +static inline synapse_row_plastic_data_t *synapse_row_plastic_region( + synaptic_row_t row) { synapse_row_plastic_part_t *the_row = (synapse_row_plastic_part_t *) row; - return the_row->data; + return (synapse_row_plastic_data_t *) the_row->data; } //! \brief Get the address of the non-plastic (or fixed) region diff --git a/neural_modelling/src/neuron/synapses.c b/neural_modelling/src/neuron/synapses.c index f3fda94fc13..d3d6f3e3e70 100644 --- a/neural_modelling/src/neuron/synapses.c +++ b/neural_modelling/src/neuron/synapses.c @@ -126,11 +126,10 @@ static inline void print_synaptic_row(synaptic_row_t synaptic_row) { // If there's a plastic region if (synapse_row_plastic_size(synaptic_row) > 0) { io_printf(IO_BUF, "----------------------------------------\n"); - address_t plastic_region_address = + synapse_row_plastic_data_t *plastic_data = synapse_row_plastic_region(synaptic_row); synapse_dynamics_print_plastic_synapses( - plastic_region_address, fixed_region, - ring_buffer_to_input_left_shifts); + plastic_data, fixed_region, ring_buffer_to_input_left_shifts); } io_printf(IO_BUF, "----------------------------------------\n"); @@ -362,12 +361,13 @@ bool synapses_process_synaptic_row( // If this row has a plastic region if (synapse_row_plastic_size(row) > 0) { // Get region's address - address_t plastic_region_address = synapse_row_plastic_region(row); + synapse_row_plastic_data_t *plastic_data = + synapse_row_plastic_region(row); // Process any plastic synapses profiler_write_entry_disable_fiq( PROFILER_ENTER | PROFILER_PROCESS_PLASTIC_SYNAPSES); - if (!synapse_dynamics_process_plastic_synapses(plastic_region_address, + if (!synapse_dynamics_process_plastic_synapses(plastic_data, fixed_region, ring_buffers, time)) { return false; }