sPyNNaker neural_modelling  7.4.2
matrix_generator_stdp.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 The University of Manchester
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
23 #include <stdbool.h>
24 #include <spin1_api.h>
25 #include <debug.h>
29 #include <utils.h>
30 
32 typedef struct {
34  uint16_t plastic_plastic_data[];
36 
38 typedef struct {
39  uint32_t fixed_fixed_size;
40  uint32_t fixed_plastic_size;
41  uint16_t fixed_plastic_data[];
42 } row_fixed_t;
43 
45 typedef struct matrix_generator_stdp {
46  union {
48  uint32_t *synaptic_matrix;
50  uint32_t synaptic_matrix_offset;
51  };
52  union {
54  uint32_t *delayed_synaptic_matrix;
56  uint32_t delayed_matrix_offset;
57  };
63  uint32_t max_row_n_words;
67  uint32_t synapse_type;
73  uint32_t max_stage;
77  uint32_t delay_bits;
79  uint32_t n_pre_neurons;
87  uint32_t weight_half_word;
92  uint32_t row_offset;
94 
104 static uint32_t plastic_half_words(uint32_t n_half_words_per_pp_header,
105  uint32_t n_half_words_per_pp_synapse, uint32_t max_row_n_synapses) {
106  uint32_t n_half_words = n_half_words_per_pp_header
107  + (n_half_words_per_pp_synapse * max_row_n_synapses);
108  if (n_half_words & 0x1) {
109  n_half_words += 1;
110  }
111  return n_half_words;
112 }
113 
126  uint32_t n_half_words_per_pp_header, uint32_t n_half_words_per_pp_synapse,
127  uint32_t max_row_n_synapses) {
128  uint32_t idx_16 = plastic_half_words(n_half_words_per_pp_header,
129  n_half_words_per_pp_synapse, max_row_n_synapses);
130  return (row_fixed_t *) &(plastic_row->plastic_plastic_data[idx_16]);
131 }
132 
144 static void setup_stdp_rows(uint32_t *matrix, uint32_t n_rows,
145  uint32_t n_half_words_per_pp_header, uint32_t n_half_words_per_pp_synapse,
146  uint32_t max_row_n_synapses, uint32_t max_row_n_words,
147  uint32_t first_header_word_is_row_index, uint32_t row_offset) {
148 
149  // Set all the header half-words to 0 and set all the sizes
150  uint32_t plastic_words = plastic_half_words(n_half_words_per_pp_header,
151  n_half_words_per_pp_synapse, max_row_n_synapses) >> 1;
152  for (uint32_t i = 0; i < n_rows; i++) {
153  row_plastic_t *row = get_row(matrix, max_row_n_words, i);
154  // Use word writing for efficiency (and to write the first word)
155  uint32_t *data = (uint32_t *) &row->plastic_plastic_data[0];
156  if (first_header_word_is_row_index) {
157  data[0] = i + row_offset;
158  } else {
159  data[0] = 0;
160  }
161  for (uint32_t j = 1; j < plastic_words; j++) {
162  data[j] = 0;
163  }
164  row->plastic_plastic_size = plastic_words;
165  row_fixed_t *fixed = get_stdp_fixed_row(row, n_half_words_per_pp_header,
166  n_half_words_per_pp_synapse, max_row_n_synapses);
167  fixed->fixed_fixed_size = 0;
168  fixed->fixed_plastic_size = 0;
169  }
170 }
171 
172 
184  uint16_t delay, uint32_t type,
185  uint32_t post_index, uint32_t synapse_type_bits,
186  uint32_t synapse_index_bits, uint32_t delay_bits) {
187  uint16_t synapse_index_mask = (1 << synapse_index_bits) - 1;
188  uint16_t synapse_type_mask = (1 << synapse_type_bits) - 1;
189  uint16_t delay_mask = (1 << delay_bits) - 1;
190 
191  uint16_t wrd = post_index & synapse_index_mask;
192  wrd |= (type & synapse_type_mask) << synapse_index_bits;
193  wrd |= (delay & delay_mask) <<
195  // wrd |= (delay & SYNAPSE_DELAY_MASK) << synapse_type_bits;
196 
197  return wrd;
198 }
199 
207 void *matrix_generator_stdp_initialize(void **region, void *synaptic_matrix) {
208  // Allocate memory for the parameters
210  spin1_malloc(sizeof(matrix_generator_stdp_data_t));
211 
212  // Copy the parameters in
213  matrix_generator_stdp_data_t *params_sdram = *region;
214  *obj = *params_sdram;
215  *region = &params_sdram[1];
216 
217  // Offsets are in words
218  uint32_t *syn_mat = synaptic_matrix;
219  if (obj->synaptic_matrix_offset != 0xFFFFFFFF) {
220  obj->synaptic_matrix = &(syn_mat[obj->synaptic_matrix_offset]);
221  setup_stdp_rows(obj->synaptic_matrix, obj->n_pre_neurons,
225  obj->row_offset);
226  } else {
227  obj->synaptic_matrix = NULL;
228  }
229 
230  if (obj->delayed_matrix_offset != 0xFFFFFFFF) {
231  obj->delayed_synaptic_matrix = &(syn_mat[obj->delayed_matrix_offset]);
232  setup_stdp_rows(obj->delayed_synaptic_matrix,
233  obj->n_pre_neurons * (obj->max_stage - 1),
238  } else {
239  obj->delayed_synaptic_matrix = NULL;
240  }
241 
242  return obj;
243 }
244 
249 void matrix_generator_stdp_free(void *generator) {
250  sark_free(generator);
251 }
252 
263 static bool matrix_generator_stdp_write_synapse(void *generator,
264  uint32_t pre_index, uint16_t post_index, accum weight, uint16_t delay,
265  unsigned long accum weight_scale) {
266  matrix_generator_stdp_data_t *data = generator;
267  struct delay_value delay_and_stage = get_delay(delay, data->max_stage,
268  data->max_delay_per_stage);
269  row_plastic_t *plastic_row;
270  row_fixed_t *fixed_row;
271  uint32_t pos;
272  if (delay_and_stage.stage == 0) {
273  plastic_row = get_row(data->synaptic_matrix, data->max_row_n_words,
274  pre_index);
275  fixed_row = get_stdp_fixed_row(plastic_row,
278  pos = fixed_row->fixed_plastic_size;
279  if (pos >= data->max_row_n_synapses) {
280  log_warning("Row %u at 0x%08x, 0x%08x of matrix 0x%08x is already full (%u of %u)",
281  pre_index, plastic_row, fixed_row, data->synaptic_matrix, pos,
282  data->max_row_n_synapses);
283  return false;
284  }
285  } else {
286  plastic_row = get_delay_row(data->delayed_synaptic_matrix,
287  data->max_delayed_row_n_words, pre_index, delay_and_stage.stage,
288  data->n_pre_neurons_per_core, data->max_stage, data->n_pre_neurons);
289  fixed_row = get_stdp_fixed_row(plastic_row,
292  pos = fixed_row->fixed_plastic_size;
293  if (pos >= data->max_delayed_row_n_synapses) {
294  log_warning("Row %u at 0x%08x, 0x%08x of matrix 0x%08x is already full (%u of %u)",
295  pre_index, plastic_row, fixed_row, data->synaptic_matrix, pos,
297  return false;
298  }
299  }
300 
301  uint16_t scaled_weight = rescale_weight(weight, weight_scale);
302 
303  fixed_row->fixed_plastic_size = pos + 1;
305  delay_and_stage.delay, data->synapse_type, post_index,
306  data->synapse_type_bits, data->synapse_index_bits, data->delay_bits);
307  uint32_t plastic_pos = data->n_half_words_per_pp_row_header
308  + (data->n_half_words_per_pp_synapse * pos) + data->weight_half_word;
309  plastic_row->plastic_plastic_data[plastic_pos] = scaled_weight;
310  return true;
311 }
Declarations for delay extensions.
General types associated with generators.
static uint16_t rescale_weight(accum weight, unsigned long accum weight_scale)
Rescales a weight to account for weight granularity and type-converts it.
uint32_t synapse_index_bits
The number of bits used by just the post-neuron index.
Definition: local_only.c:77
Common functions for matrix generation.
static void * get_row(uint32_t *synaptic_matrix, uint32_t max_row_n_words, uint32_t pre_index)
Get a synaptic row for a given neuron.
static struct delay_value get_delay(uint16_t delay_value, uint32_t max_stage, uint32_t max_delay_per_stage)
Get a converted delay value and stage.
static void * get_delay_row(uint32_t *delayed_synaptic_matrix, uint32_t max_delayed_row_n_words, uint32_t pre_index, uint32_t delay_stage, uint32_t n_pre_neurons_per_core, uint32_t max_delay_stage, uint32_t n_pre_neurons)
Get a delayed synaptic row for a given neuron and delay stage.
A converted final delay value and delay stage.
void * matrix_generator_stdp_initialize(void **region, void *synaptic_matrix)
Initialise the STDP synaptic matrix generator.
uint32_t synapse_type
The matrix synapse type.
uint32_t max_stage
The maximum delay stage, including 0 for no delay stage.
uint16_t plastic_plastic_data[]
the plastic-plastic data within the row
static uint32_t plastic_half_words(uint32_t n_half_words_per_pp_header, uint32_t n_half_words_per_pp_synapse, uint32_t max_row_n_synapses)
Get the maximum number of plastic half-words in a row.
uint32_t n_pre_neurons
The number of pre-synaptic neurons.
uint32_t max_delayed_row_n_words
The maximum number of words on a delayed row.
uint32_t fixed_fixed_size
the fixed-fixed size within the fixed region
uint32_t max_row_n_synapses
The maximum number of synapses on a row.
uint16_t fixed_plastic_data[]
the fixed-plastic data within the fixed region
uint32_t delay_bits
The number of bits needed to represent the maximum delay per stage.
static row_fixed_t * get_stdp_fixed_row(row_plastic_t *plastic_row, uint32_t n_half_words_per_pp_header, uint32_t n_half_words_per_pp_synapse, uint32_t max_row_n_synapses)
Get the fixed part of a row that comes after the plastic part. Note that this assumes the max row siz...
uint32_t n_half_words_per_pp_synapse
The number of half-words in each plastic-plastic synapse.
void matrix_generator_stdp_free(void *generator)
Free any data for the STDP synaptic matrix generator.
static bool matrix_generator_stdp_write_synapse(void *generator, uint32_t pre_index, uint16_t post_index, accum weight, uint16_t delay, unsigned long accum weight_scale)
How to write a synapse to a matrix.
uint32_t n_half_words_per_pp_row_header
The number of half-words in a plastic-plastic row header.
uint32_t plastic_plastic_size
the plastic-plastic size within the row
uint32_t max_row_n_words
The maximum number of words on a row.
uint32_t n_pre_neurons_per_core
The number of pre-synaptic neurons per core.
static void setup_stdp_rows(uint32_t *matrix, uint32_t n_rows, uint32_t n_half_words_per_pp_header, uint32_t n_half_words_per_pp_synapse, uint32_t max_row_n_synapses, uint32_t max_row_n_words, uint32_t first_header_word_is_row_index, uint32_t row_offset)
Set up the rows so that they are ready for writing to.
uint32_t weight_half_word
The index of the half-word that will contain the weight.
uint32_t fixed_plastic_size
the fixed-plastic size within the fixed region
uint32_t max_delay_per_stage
The maximum delay per delay stage in time steps.
static uint16_t build_fixed_plastic_half_word(uint16_t delay, uint32_t type, uint32_t post_index, uint32_t synapse_type_bits, uint32_t synapse_index_bits, uint32_t delay_bits)
Build a fixed-plastic half-word from its components.
uint32_t max_delayed_row_n_synapses
The maximum number of synapses on a delayed row.
uint32_t synapse_type_bits
The number of bits needed to represent the synapse type.
uint32_t synapse_index_bits
The number of bits needed to represent the synapse neuron id.
uint32_t row_offset
The offset of the row index to use.
The layout of the fixed synapse region of the row; the fixed-fixed region is empty.
The layout of the initial plastic synapse part of the row.
region
spike source array region IDs in human readable form
uint32_t synapse_index_mask
Mask to pick out the synapse index.
Definition: synapses.c:69
uint32_t synapse_type_bits
Number of bits in the synapse type.
Definition: synapses.c:71
uint32_t synapse_type_mask
Mask to pick out the synapse type.
Definition: synapses.c:73