Skip to content

Commit

Permalink
Use structs to access synaptic rows
Browse files Browse the repository at this point in the history
Complicated because rows have multiple VLAs within them. Code recovered
from #857 which was becoming too unwieldy to keep up to date.
  • Loading branch information
dkfellows committed Nov 16, 2020
1 parent 265b44d commit 4da572e
Show file tree
Hide file tree
Showing 21 changed files with 350 additions and 323 deletions.
24 changes: 22 additions & 2 deletions neural_modelling/src/common/neuron-typedefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
47 changes: 28 additions & 19 deletions neural_modelling/src/neuron/direct_synapses.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,41 +21,50 @@
#include <spin1_api.h>
#include <common/neuron-typedefs.h>

//! 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;
}
4 changes: 2 additions & 2 deletions neural_modelling/src/neuron/direct_synapses.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_ */
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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
Expand All @@ -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);
Expand All @@ -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);
}
30 changes: 16 additions & 14 deletions neural_modelling/src/neuron/plasticity/synapse_dynamics.h
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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);
Expand All @@ -82,25 +84,25 @@ 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
//! \param[in] row: the core-local address of the synaptic row
//! \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
Expand All @@ -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_
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
}

Expand All @@ -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);

Expand All @@ -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;
}

Expand All @@ -151,21 +151,22 @@ 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);

// 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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand All @@ -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_
Loading

0 comments on commit 4da572e

Please sign in to comment.