sPyNNaker neural_modelling 7.3.1
Loading...
Searching...
No Matches
topographic_map_impl.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016 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
25
26#include <random.h>
27#include <spin1_api.h>
28#include <debug.h>
29#include <stdfix-full-iso.h>
30#include <circular_buffer.h>
31#include <recording.h>
32
33#include <neuron/synapse_row.h>
34
35#include <neuron/synapses.h>
36
37#include <common/maths-util.h>
38#include <simulation.h>
39
40// Interface for rules
43#include "formation/formation.h"
44
46enum {
50 FORM_FLAG = 1
51};
53#define ID_SHIFT 1
55#define PRE_ID_SHIFT 9
56
57//-----------------------------------------------------------------------------
58// Structures and global data |
59//-----------------------------------------------------------------------------
60
63
66
69
71static formation_params_t **formation_params;
72
74static elimination_params_t **elimination_params;
75
80
86
89
92 uint32_t time;
93 uint32_t value;
95
98
100static uint32_t last_rewiring_time = 0;
101
103 uint32_t n_elements =
104 rewiring_data.s_max * rewiring_data.machine_no_atoms;
105
106 for (uint32_t i=0; i < n_elements; i++) {
107 log_debug("index %d, pop index %d, sub pop index %d, neuron_index %d",
108 i, post_to_pre_table[i].pop_index,
109 post_to_pre_table[i].sub_pop_index,
110 post_to_pre_table[i].neuron_index);
111 }
112}
113
114//-----------------------------------------------------------------------------
115// Access helpers for circular buffers
116//-----------------------------------------------------------------------------
117static inline void _queue_state(current_state_t *state) {
118 if (__builtin_expect(
119 !circular_buffer_add(current_state_queue, (uint32_t) state), 0)) {
120 log_error("Could not add state (0x%08x) to queued states", state);
121 rt_error(RTE_SWERR);
122 }
123}
124
125static inline current_state_t *_get_state(void) {
126 current_state_t *state;
127 if (__builtin_expect(
128 !circular_buffer_get_next(current_state_queue, (uint32_t *) &state),
129 0)) {
130 log_error("Could not read a state!");
131 rt_error(RTE_SWERR);
132 }
133 return state;
134}
135
136static inline void _free_state(current_state_t *state) {
137 if (__builtin_expect(
138 !circular_buffer_add(free_states, (uint32_t) state), 0)) {
139 log_error("Could not add state (0x%08x) to free states", state);
140 rt_error(RTE_SWERR);
141 }
142}
143
144static inline current_state_t *_alloc_state(void) {
145 current_state_t *state;
146 if (__builtin_expect(
147 !circular_buffer_get_next(free_states, (uint32_t *) &state), 0)) {
148 log_error("Ran out of states!");
149 rt_error(RTE_SWERR);
150 }
151 return state;
152}
153
154//-----------------------------------------------------------------------------
155// Initialisation |
156//-----------------------------------------------------------------------------
157
159 address_t sdram_sp_address, uint32_t *recording_regions_used) {
160 uint8_t *data = sp_structs_read_in_common(
161 sdram_sp_address, &rewiring_data, &pre_info, &post_to_pre_table);
162
163 // Allocate current states
164 uint32_t n_states = 1;
165 if (rewiring_data.fast) {
166 n_states = rewiring_data.p_rew;
167 }
168 log_debug("Rewiring period %u, fast=%u, n_states=%u",
169 rewiring_data.p_rew, rewiring_data.fast, n_states);
170 // Add one to number of states as buffer wastes an entry
172 if (current_state_queue == NULL) {
173 log_error("Could not allocate current state queue");
175 }
176 // Add one to number of states as buffer wastes an entry
178 if (free_states == NULL) {
179 log_error("Could not allocate free state queue");
180 }
181 current_state_t *states = spin1_malloc(n_states * sizeof(current_state_t));
182 if (states == NULL) {
183 log_error("Could not allocate states");
185 }
186 for (uint32_t i = 0; i < n_states; i++) {
187 _free_state(&states[i]);
188 }
189
190 partner_init(&data);
191
192 formation_params = spin1_malloc(
193 rewiring_data.no_pre_pops * sizeof(struct formation_params *));
194 if (formation_params == NULL) {
195 log_error("Could not initialise formation parameters");
197 }
198 for (uint32_t i = 0; i < rewiring_data.no_pre_pops; i++) {
200 }
201
202 elimination_params = spin1_malloc(
203 rewiring_data.no_pre_pops * sizeof(struct elimination_params *));
204 if (elimination_params == NULL) {
205 log_error("Could not initialise elimination parameters");
207 }
208 for (uint32_t i = 0; i < rewiring_data.no_pre_pops; i++) {
210 }
211
212 rewiring_recording_index = *recording_regions_used;
213 *recording_regions_used = rewiring_recording_index + 1;
214
215 log_debug("The rewiring_recording_index is %u", rewiring_recording_index);
216
217 return true;
218}
219
221 uint32_t time, spike_t *spike, pop_table_lookup_result_t *result) {
222
223 // Randomly choose a postsynaptic (application neuron)
224 uint32_t post_id = rand_int(rewiring_data.app_no_atoms,
225 rewiring_data.shared_seed);
226
227 // Check if neuron is in the current machine vertex
228 if (post_id < rewiring_data.low_atom ||
229 post_id > rewiring_data.high_atom) {
230 return false;
231 }
232 post_id -= rewiring_data.low_atom;
233
234 // Select an arbitrary synaptic element for the neurons
235 uint32_t row_offset = post_id * rewiring_data.s_max;
236 uint32_t column_offset = rand_int(rewiring_data.s_max,
237 rewiring_data.local_seed);
238 uint32_t total_offset = row_offset + column_offset;
239 post_to_pre_entry entry = post_to_pre_table[total_offset];
240 uint32_t pre_app_pop = 0, pre_sub_pop = 0, m_pop_index = 0, neuron_id = 0;
241 if (entry.neuron_index == 0xFFFF) {
242 if (!potential_presynaptic_partner(time, &pre_app_pop, &pre_sub_pop,
243 &neuron_id, spike, &m_pop_index)) {
244 return false;
245 }
246 } else {
247 pre_app_pop = entry.pop_index;
248 pre_sub_pop = entry.sub_pop_index;
249 neuron_id = entry.neuron_index;
250 }
251 pre_info_t *prepop_info = pre_info.prepop_info[pre_app_pop];
252 key_atom_info_t *key_atom_info = &prepop_info->key_atom_info[pre_sub_pop];
253 if (entry.neuron_index != 0xFFFF) {
254 *spike = key_atom_info->key | (neuron_id << key_atom_info->n_colour_bits);
255 m_pop_index = key_atom_info->m_pop_index;
256 }
257
258 if (!population_table_get_first_address(*spike, result)) {
259 log_error("FAIL@key %d", *spike);
261 }
262 uint32_t index = 0;
263 while (index < m_pop_index) {
264 if (!population_table_get_next_address(spike, result)) {
265 log_error("FAIL@key %d, index %d (failed at %d)",
266 *spike, m_pop_index, index);
268 }
269 index++;
270 }
271
272 // Saving current state
273 current_state_t *current_state = _alloc_state();
274 current_state->pre_syn_id = neuron_id;
275 current_state->post_syn_id = post_id;
276 current_state->element_exists = entry.neuron_index != 0xFFFF;
277 current_state->post_to_pre_table_entry = &post_to_pre_table[total_offset];
278 current_state->pre_population_info = prepop_info;
279 current_state->key_atom_info = key_atom_info;
280 current_state->post_to_pre.neuron_index = neuron_id;
281 current_state->post_to_pre.pop_index = pre_app_pop;
282 current_state->post_to_pre.sub_pop_index = pre_sub_pop;
283 current_state->local_seed = &rewiring_data.local_seed;
284 current_state->post_low_atom = rewiring_data.low_atom;
285 current_state->with_replacement = rewiring_data.with_replacement;
286 _queue_state(current_state);
287 return true;
288}
289
290static bool do_formation(uint32_t time, synaptic_row_t restrict row,
291 current_state_t *restrict current_state) {
292 if (synaptogenesis_formation_rule(current_state,
293 formation_params[current_state->post_to_pre.pop_index], time, row)) {
294 // Create recorded value
295 // (bottom bit: add/remove, next 8: local id, remainder: pre global id)
296 uint32_t pre_id = current_state->key_atom_info->lo_atom
297 + current_state->pre_syn_id;
298 uint32_t id = current_state->post_syn_id;
299 uint32_t record_value = FORM_FLAG | (id << ID_SHIFT) |
300 (pre_id << PRE_ID_SHIFT);
302 structural_recording_values.value = record_value;
305
306 return true;
307 }
308 return false;
309}
310
317static inline bool row_restructure(
318 uint32_t time, synaptic_row_t restrict row,
319 current_state_t *restrict current_state) {
320 // the selected pre- and postsynaptic IDs are in current_state
321
322 if (current_state->element_exists) {
323 // find the offset of the neuron in the current row
325 current_state->post_syn_id, row,
326 &current_state->weight, &current_state->delay,
327 &current_state->offset, &current_state->synapse_type)) {
328 log_debug("Post neuron %u not in row", current_state->post_syn_id);
329 return false;
330 }
331
332 if (synaptogenesis_elimination_rule(current_state,
333 elimination_params[current_state->post_to_pre.pop_index],
334 time, row)) {
335 // Create recorded value
336 // (bottom bit: add/remove, next 8: local id, remainder: pre global id)
337 uint32_t pre_id = current_state->key_atom_info->lo_atom + current_state->pre_syn_id;
338 uint32_t id = current_state->post_syn_id;
339 uint32_t record_value = ELIM_FLAG | (id << ID_SHIFT) | (pre_id << PRE_ID_SHIFT);
341 structural_recording_values.value = record_value;
344
345 return true;
346 } else {
347 return false;
348 }
349
350 } else {
351 // Can't form if the row is full
352 uint32_t no_elems = synapse_dynamics_n_connections_in_row(
354 if (no_elems >= rewiring_data.s_max) {
355 return false;
356 } else {
357 if (current_state->with_replacement) {
358 // A synapse can be added anywhere on the current row, so just do it
359 return do_formation(time, row, current_state);
360 } else {
361 // A synapse cannot be added if one exists between the current pair of neurons
363 current_state->post_syn_id, row,
364 &(current_state->weight), &(current_state->delay),
365 &(current_state->offset), &(current_state->synapse_type))) {
366 return do_formation(time, row, current_state);
367 } else {
368 log_debug("Post neuron %u already in row", current_state->post_syn_id);
369 return false;
370 }
371 }
372 }
373 }
374}
375
377 current_state_t *current_state = _get_state();
378 bool return_value = row_restructure(time, row, current_state);
379 _free_state(current_state);
380 return return_value;
381}
382
383void synaptogenesis_spike_received(uint32_t time, spike_t spike) {
385}
386
388 if (rewiring_data.fast) {
389 return rewiring_data.p_rew;
390 }
391
393 if (last_rewiring_time >= rewiring_data.p_rew) {
395 return 1;
396 }
397
398 return 0;
399}
uint32_t time
The current timer tick value.
Definition c_main.c:94
circular_buffer circular_buffer_initialize(uint32_t size)
uint32_t * address_t
void log_error(const char *message,...)
void log_debug(const char *message,...)
API for synapse elimination.
elimination_params_t * synaptogenesis_elimination_init(uint8_t **data)
Read and return an elimination parameter data structure from the data stream.
static bool synaptogenesis_elimination_rule(current_state_t *current_state, const elimination_params_t *params, uint32_t time, synaptic_row_t row)
Elimination rule for synaptogenesis.
Configuration of synapse elimination rule.
API for synapse formation.
static bool synaptogenesis_formation_rule(current_state_t *current_state, const formation_params_t *params, uint32_t time, synaptic_row_t row)
Formation rule for synaptogenesis; picks what neuron in the current population will have a synapse ad...
formation_params_t * synaptogenesis_formation_init(uint8_t **data)
Read and return an formation parameter data structure from the data stream.
Configuration of synapse formation rule.
void partner_init(uint8_t **data)
Initialise the partner selection rule.
static void partner_spike_received(uint32_t time, spike_t spike)
Notifies the rule that a spike has been received.
static bool potential_presynaptic_partner(uint32_t time, uint32_t *restrict population_id, uint32_t *restrict sub_population_id, uint32_t *restrict neuron_id, spike_t *restrict spike, uint32_t *restrict m_pop_index)
Choose the potential (remote) synaptic partner.
maths-util.h - first created 7/10/2013 version 0.1
struct synaptic_row * synaptic_row_t
The type of a synaptic row.
uint32_t spike_t
The type of a spike.
Partner selection rule common API.
Master pop(ulation) table API.
bool population_table_get_next_address(spike_t *spike, pop_table_lookup_result_t *result)
Get the next row data for a previously given spike. If no spike has been given, return False.
bool population_table_get_first_address(spike_t spike, pop_table_lookup_result_t *result)
Get the first row data for the given input spike.
A structure to hold a response to a population table lookup.
bool recording_record(channel_index_t channel, void *data, size_t size_bytes)
RTE_SWERR
void rt_error(uint code,...)
uint32_t element_exists
does the connection already exist
Definition sp_structs.h:103
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
uint32_t post_low_atom
Low atom copied from rewiring data.
Definition sp_structs.h:96
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
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
#define NULL
uint32_t synapse_dynamics_n_connections_in_row(synapse_row_fixed_part_t *fixed)
Get the number of connections in the given row.
bool synapse_dynamics_find_neuron(uint32_t id, synaptic_row_t row, weight_t *weight, uint16_t *delay, uint32_t *offset, uint32_t *synapse_type)
Search the synaptic row for the the connection with the specified post-synaptic ID.
implementation for handling the processing of synapse rows.
static synapse_row_fixed_part_t * synapse_row_fixed_region(synaptic_row_t row)
Get the address of the non-plastic (or fixed) region.
Operations on synapses.
This file contains the main interface for structural plasticity.
bool synaptogenesis_dynamics_rewire(uint32_t time, spike_t *spike, pop_table_lookup_result_t *result)
Trigger the process of synaptic rewiring.
#define ID_SHIFT
How much to shift post-IDs by.
rewiring_data_t rewiring_data
the instantiation of the rewiring data
pre_pop_info_table_t pre_info
pre-population information table
uint32_t rewiring_recording_index
The recording region for the structural events.
void synaptogenesis_spike_received(uint32_t time, spike_t spike)
Indicates that a spike has been received.
static circular_buffer current_state_queue
Current states in use.
structural_recording_values_t structural_recording_values
Working buffer for the recording of structural changes.
uint32_t synaptogenesis_n_updates(void)
Number of updates to do of synaptogenesis this time step.
static formation_params_t ** formation_params
The formation parameters per pre-population.
static bool row_restructure(uint32_t time, synaptic_row_t restrict row, current_state_t *restrict current_state)
Performs the actual restructuring of a row.
static uint32_t last_rewiring_time
Timer callbacks since last rewiring.
void print_post_to_pre_entry(void)
Print a certain data object.
static elimination_params_t ** elimination_params
The elimination parameters per pre-population.
static post_to_pre_entry * post_to_pre_table
inverse of synaptic matrix
@ FORM_FLAG
Formation flag.
@ ELIM_FLAG
Elimination flag.
static circular_buffer free_states
Free current states.
#define PRE_ID_SHIFT
How much to shift pre-IDs by.
bool synaptogenesis_row_restructure(uint32_t time, synaptic_row_t row)
Perform the actual restructuring of a row.
bool synaptogenesis_dynamics_initialise(address_t sdram_sp_address, uint32_t *recording_regions_used)
Initialisation of synaptic rewiring (synaptogenesis) parameters (random seed, spread of receptive fie...
Struct for structural recording data.