sPyNNaker neural_modelling  development
sp_structs.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 
21 #ifndef _SP_STRUCTS_H_
22 #define _SP_STRUCTS_H_
23 
25 #include <neuron/synapse_row.h>
26 #include <debug.h>
27 #include <random.h>
28 
29 // Define the formation and elimination params
30 struct elimination_params;
31 struct formation_params;
32 
34 #define IS_CONNECTION_LAT 1
35 
36 #ifndef SOMETIMES_UNUSED
37 #define SOMETIMES_UNUSED __attribute__((unused))
38 #endif // !SOMETIMES_UNUSED
39 
41 typedef struct post_to_pre_entry {
42  uint8_t pop_index;
43  uint8_t sub_pop_index;
44  uint16_t neuron_index;
46 
48 typedef struct {
49  uint32_t key;
50  uint32_t mask;
51  uint32_t n_colour_bits;
52  uint32_t n_atoms;
53  uint32_t lo_atom;
54  uint32_t m_pop_index;
56 
58 typedef struct {
59  uint16_t no_pre_vertices;
60  uint16_t sp_control;
61  uint16_t delay_lo;
62  uint16_t delay_hi;
63  uint32_t weight;
64  uint32_t connection_type;
65  uint32_t total_no_atoms;
66  key_atom_info_t key_atom_info[];
67 } pre_info_t;
68 
70 typedef struct {
71  uint32_t no_pre_pops;
72  pre_info_t **prepop_info;
74 
76 typedef struct {
77  uint32_t fast;
78  uint32_t p_rew;
79  uint32_t s_max;
80  uint32_t app_no_atoms;
81  uint32_t machine_no_atoms;
82  uint32_t low_atom;
83  uint32_t high_atom;
84  uint32_t with_replacement;
85  // the 2 seeds that are used: shared for sync, local for everything else
86  mars_kiss64_seed_t shared_seed;
87  mars_kiss64_seed_t local_seed;
88  uint32_t no_pre_pops;
90 
92 typedef struct {
94  mars_kiss64_seed_t *local_seed;
96  uint32_t post_low_atom;
97  // with_replacement copied from rewiring data
98  uint32_t with_replacement;
99  // what are the currently selecting pre- and post-synaptic neurons
100  uint32_t pre_syn_id;
101  uint32_t post_syn_id;
103  uint32_t element_exists;
104  // information extracted from the post to pre table
105  post_to_pre_entry *post_to_pre_table_entry;
106  pre_info_t *pre_population_info;
107  key_atom_info_t *key_atom_info;
108  post_to_pre_entry post_to_pre;
110  uint32_t offset;
112  uint16_t delay;
114  uint16_t weight;
116  uint32_t synapse_type;
118 
123 static inline uint32_t rand_int(uint32_t max, mars_kiss64_seed_t seed) {
124  return muliulr(max, ulrbits(mars_kiss64_seed(seed)));
125 }
126 
136 static inline bool sp_structs_find_by_spike(
137  const pre_pop_info_table_t *pre_pop_info_table, spike_t spike,
138  uint32_t *restrict neuron_id, uint32_t *restrict population_id,
139  uint32_t *restrict sub_population_id, uint32_t *restrict m_pop_index) {
140  // Amazing linear search inc.
141  // Loop over all populations
142  for (uint32_t i = 0; i < pre_pop_info_table->no_pre_pops; i++) {
143  const pre_info_t *pre_pop_info = pre_pop_info_table->prepop_info[i];
144 
145  // Loop over all sub-populations and check if the KEY matches
146  // (with neuron ID masked out)
147  for (int j = 0; j < pre_pop_info->no_pre_vertices; j++) {
148  const key_atom_info_t *kai = &pre_pop_info->key_atom_info[j];
149  if ((spike & kai->mask) == kai->key) {
150  *population_id = i;
151  *sub_population_id = j;
152  *neuron_id = (spike & ~kai->mask) >> kai->n_colour_bits;
153  *m_pop_index = kai->m_pop_index;
154  return true;
155  }
156  }
157  }
158  return false;
159 }
160 
171 static inline bool sp_structs_get_sub_pop_info(
172  const pre_pop_info_table_t *pre_pop_info_table, uint32_t population_id,
173  uint32_t pop_neuron_id, uint32_t *restrict sub_population_id,
174  uint32_t *restrict sub_pop_neuron_id, uint32_t *restrict spike) {
175  const pre_info_t *app_pop_info =
176  pre_pop_info_table->prepop_info[population_id];
177  uint32_t neuron_id = pop_neuron_id;
178  for (uint32_t i = 0; i < app_pop_info->no_pre_vertices; i++) {
179  const key_atom_info_t *kai = &app_pop_info->key_atom_info[i];
180  uint32_t n_atoms = kai->n_atoms;
181  if (neuron_id < n_atoms) {
182  *sub_population_id = i;
183  *sub_pop_neuron_id = neuron_id;
184  *spike = kai->key | (neuron_id << kai->n_colour_bits);
185  return true;
186  }
187  neuron_id -= n_atoms;
188  }
189  return false;
190 }
191 
196 static inline bool sp_structs_remove_synapse(
197  current_state_t *restrict current_state, synaptic_row_t restrict row) {
198  if (!synapse_dynamics_remove_neuron(current_state->offset, row)) {
199  return false;
200  }
201 
202  current_state->post_to_pre_table_entry->neuron_index = 0xFFFF;
203  return true;
204 }
205 
210 static inline bool sp_structs_add_synapse(
211  current_state_t *restrict current_state, synaptic_row_t restrict row) {
212  uint32_t appr_scaled_weight = current_state->pre_population_info->weight;
213 
214  uint32_t actual_delay;
215  uint32_t offset = current_state->pre_population_info->delay_hi -
216  current_state->pre_population_info->delay_lo;
217  actual_delay = rand_int(offset, *(current_state->local_seed)) +
218  current_state->pre_population_info->delay_lo;
219 
221  current_state->post_syn_id, row, appr_scaled_weight, actual_delay,
222  current_state->pre_population_info->connection_type)) {
223  return false;
224  }
225 
226  // Critical: tell the compiler that this pointer is aligned so it doesn't
227  // internally convert the assignment to a memcpy(), which is a saving of
228  // hundreds of bytes...
229  post_to_pre_entry *ppentry = __builtin_assume_aligned(
230  current_state->post_to_pre_table_entry, 4);
231  *ppentry = current_state->post_to_pre;
232  return true;
233 }
234 
246 static inline uint8_t *sp_structs_read_in_common(
247  address_t sdram_sp_address, rewiring_data_t *rewiring_data,
249  uint8_t *data = (uint8_t *) sdram_sp_address;
250  spin1_memcpy(rewiring_data, data, sizeof(rewiring_data_t));
251  data += sizeof(rewiring_data_t);
252 
253  pre_info->no_pre_pops = rewiring_data->no_pre_pops;
254  pre_info->prepop_info = spin1_malloc(
255  rewiring_data->no_pre_pops * sizeof(pre_info_t *));
256  if (pre_info->prepop_info == NULL) {
257  log_error("Could not initialise pre population info");
258  rt_error(RTE_SWERR);
259  }
260  for (uint32_t i = 0; i < rewiring_data->no_pre_pops; i++) {
261  pre_info->prepop_info[i] = (pre_info_t *) data;
262  uint32_t pre_size = (pre_info->prepop_info[i]->no_pre_vertices
263  * sizeof(key_atom_info_t)) + sizeof(pre_info_t);
264  pre_info->prepop_info[i] = spin1_malloc(pre_size);
265  if (pre_info->prepop_info[i] == NULL) {
266  log_error("Could not initialise pre population info %d", i);
267  rt_error(RTE_SWERR);
268  }
269  spin1_memcpy(pre_info->prepop_info[i], data, pre_size);
270 
271  log_debug("no_pre = %u, sp_control %u, "
272  "delay lo %u, delay hi %u, weight %d",
273  pre_info->prepop_info[i]->no_pre_vertices,
274  pre_info->prepop_info[i]->sp_control,
275  pre_info->prepop_info[i]->delay_lo,
276  pre_info->prepop_info[i]->delay_hi,
277  pre_info->prepop_info[i]->weight);
278  log_debug("connection_type = %d, total_no_atoms=%d",
279  pre_info->prepop_info[i]->connection_type,
280  pre_info->prepop_info[i]->total_no_atoms);
281  data += pre_size;
282  }
283 
285  uint32_t n_elements =
286  rewiring_data->s_max * rewiring_data->machine_no_atoms;
287 
288  for (uint32_t i=0; i < n_elements; i++){
289  log_debug("index %d, pop index %d, sub pop index %d, neuron_index %d",
290  i, (*post_to_pre_table)[i].pop_index,
291  (*post_to_pre_table)[i].sub_pop_index,
292  (*post_to_pre_table)[i].neuron_index);
293  }
294  data += n_elements * sizeof(post_to_pre_entry);
295  return (uint8_t *) data;
296 }
297 
298 #endif // _SP_STRUCTS_H_
static uint32_t key
Base multicast key for sending messages.
static uint32_t n_colour_bits
The number of colour bits (both from source and to send)
Configuration of synapse elimination rule.
Configuration of synapse formation rule.
struct synaptic_row * synaptic_row_t
The type of a synaptic row.
uint32_t spike_t
The type of a spike.
static mars_kiss64_seed_t seed
YUCK copy and pasted RNG to allow inlining and also to avoid horrific executable bloat.
Definition: random_util.h:31
uint32_t offset
offset in synaptic row (if exists)
Definition: sp_structs.h:110
uint32_t element_exists
does the connection already exist
Definition: sp_structs.h:103
uint32_t synapse_type
synapse type
Definition: sp_structs.h:116
static bool sp_structs_add_synapse(current_state_t *restrict current_state, synaptic_row_t restrict row)
Adds a synapse to the relevant structures.
Definition: sp_structs.h:210
uint32_t post_low_atom
Low atom copied from rewiring data.
Definition: sp_structs.h:96
static bool sp_structs_remove_synapse(current_state_t *restrict current_state, synaptic_row_t restrict row)
Removes a synapse from the relevant structures.
Definition: sp_structs.h:196
uint16_t weight
current weight (if exists)
Definition: sp_structs.h:114
mars_kiss64_seed_t * local_seed
Seed referenced from rewiring data.
Definition: sp_structs.h:94
static uint32_t rand_int(uint32_t max, mars_kiss64_seed_t seed)
Definition: sp_structs.h:123
uint16_t delay
current delay (if exists)
Definition: sp_structs.h:112
static bool sp_structs_find_by_spike(const pre_pop_info_table_t *pre_pop_info_table, spike_t spike, uint32_t *restrict neuron_id, uint32_t *restrict population_id, uint32_t *restrict sub_population_id, uint32_t *restrict m_pop_index)
unpack the spike into key and identifying information for the neuron; Identify pop,...
Definition: sp_structs.h:136
static bool sp_structs_get_sub_pop_info(const pre_pop_info_table_t *pre_pop_info_table, uint32_t population_id, uint32_t pop_neuron_id, uint32_t *restrict sub_population_id, uint32_t *restrict sub_pop_neuron_id, uint32_t *restrict spike)
Get the sub-population id and sub-population-based neuron id given the population id and the populati...
Definition: sp_structs.h:171
static uint8_t * sp_structs_read_in_common(address_t sdram_sp_address, rewiring_data_t *rewiring_data, pre_pop_info_table_t *pre_info, post_to_pre_entry **post_to_pre_table)
Common code for structural plasticity initialisation.
Definition: sp_structs.h:246
struct representing the current state of rewiring
Definition: sp_structs.h:92
information per atom
Definition: sp_structs.h:48
Entry of map from post-connection to pre-connection neural indices.
Definition: sp_structs.h:41
individual pre-synaptic sub-population information
Definition: sp_structs.h:58
table of individual pre-synaptic information
Definition: sp_structs.h:70
parameters of the synaptic rewiring model
Definition: sp_structs.h:76
API for synapse dynamics.
bool synapse_dynamics_add_neuron(uint32_t id, synaptic_row_t row, weight_t weight, uint32_t delay, uint32_t type)
Add an entry in the synaptic row.
bool synapse_dynamics_remove_neuron(uint32_t offset, synaptic_row_t row)
Remove the entry at the specified offset in the synaptic row.
implementation for handling the processing of synapse rows.
rewiring_data_t rewiring_data
the instantiation of the rewiring data
pre_pop_info_table_t pre_info
pre-population information table
static post_to_pre_entry * post_to_pre_table
inverse of synaptic matrix