sPyNNaker neural_modelling 7.1.1
Loading...
Searching...
No Matches
population_table_binary_search_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
19#include "population_table.h"
20#include <neuron/synapse_row.h>
21#include <debug.h>
22#include <stdbool.h>
23
24
27
30
33
36
39
41static uint32_t last_colour = 0;
42
44static uint32_t last_colour_mask = 0;
45
47static uint32_t last_neuron_id = 0;
48
50static uint16_t next_item = 0;
51
54uint16_t items_to_go = 0;
55
58
61
64
68
72
75static inline void print_master_population_table(void) {
76#if LOG_LEVEL >= LOG_DEBUG
77 log_info("Master_population\n");
78 for (uint32_t i = 0; i < master_population_table_length; i++) {
80 log_info("key: 0x%08x, mask: 0x%08x", entry.key, entry.mask);
81 int count = entry.count;
82 int start = entry.start;
83 log_info(" core_mask: 0x%08x, core_shift: %u, n_neurons: %u, n_words: %u, n_colour_bits: %u",
84 entry.core_mask, entry.mask_shift, entry.n_neurons, entry.n_words, entry.n_colour_bits);
85 for (uint16_t j = start; j < (start + count); j++) {
87 if (addr.address == INVALID_ADDRESS) {
88 log_info(" index %d: INVALID", j);
89 } else {
90 log_info(" index %d: offset: %u, address: 0x%08x, row_length: %u",
92 get_row_length(addr));
93 }
94 }
95 }
96 log_info("Population table has %u entries", master_population_table_length);
97#endif
98}
99
103static inline void print_bitfields(uint32_t mp_i, filter_info_t *filters) {
104#if LOG_LEVEL >= LOG_DEBUG
105 // print out the bit field for debug purposes
106 uint32_t n_words = get_bit_field_size(filters[mp_i].n_atoms);
107 log_info("Bit field(s) for key 0x%08x, %u words for %u atoms:",
108 master_population_table[mp_i].key, n_words, filters[mp_i].n_atoms);
109 for (uint32_t i = 0; i < n_words; i++) {
110 log_info("0x%08x", connectivity_bit_field[mp_i][i]);
111 }
112#else
113 use(mp_i);
114 use(filters);
115#endif
116}
117
119
121 return true;
122 }
123 // No filters = nothing to load
124 if (filter_region->n_filters == 0) {
125 return true;
126 }
127 // try allocating DTCM for starting array for bitfields
129 spin1_malloc(sizeof(bit_field_t) * master_population_table_length);
132 "Couldn't initialise basic bit field holder. Will end up doing"
133 " possibly more DMA's during the execution than required."
134 " We required %d bytes where %d are available",
137 failed_bit_field_reads += filter_region->n_filters;
138 return true;
139 }
140
141 // Go through the population table, and the relevant bitfield list, both
142 // of which are ordered by key...
143 if (filter_region->n_filters != master_population_table_length) {
144 log_error("The number of filters doesn't match the population table");
145 return false;
146 }
147 filter_info_t* filters = filter_region->filters;
148 for (uint32_t mp_i = 0; mp_i < master_population_table_length; mp_i++) {
150
151 // Fail if the key doesn't match
152 if (master_population_table[mp_i].key != filters[mp_i].key) {
153 log_error("Bitfield for %u keys do not match: bf=0x%08x vs mp=0x%08x",
154 mp_i, filters[mp_i].key, master_population_table[mp_i].key);
155 return false;
156 }
157 uint32_t useful = !(filters[mp_i].merged || filters[mp_i].all_ones);
158
159 if (useful) {
160 // Try to allocate all the bitfields for this entry
161 uint32_t n_words = get_bit_field_size(filters[mp_i].n_atoms);
162 uint32_t size = sizeof(bit_field_t) * n_words;
163 connectivity_bit_field[mp_i] = spin1_malloc(size);
164 if (connectivity_bit_field[mp_i] == NULL) {
165 // There might be more than one that has failed
167 } else {
168 spin1_memcpy(connectivity_bit_field[mp_i], filters[mp_i].data, size);
169 print_bitfields(mp_i, filters);
170 }
171 }
172 }
173 return true;
174}
175
181 spike_t spike, uint32_t *position) {
182 uint32_t imin = 0;
183 uint32_t imax = master_population_table_length;
184
185 while (imin < imax) {
186 uint32_t imid = (imax + imin) >> 1;
188 if ((spike & entry.mask) == entry.key) {
189 *position = imid;
190 return true;
191 } else if (entry.key < spike) {
192
193 // Entry must be in upper part of the table
194 imin = imid + 1;
195 } else {
196 // Entry must be in lower part of the table
197 imax = imid;
198 }
199 }
200 return false;
201}
202
203bool population_table_setup(address_t table_address, uint32_t *row_max_n_words,
204 uint32_t *master_pop_table_length,
205 master_population_table_entry **master_pop_table,
207 pop_table_config_t *config = (pop_table_config_t *) table_address;
208
209 *master_pop_table_length = config->table_length;
210
211 if (*master_pop_table_length == 0) {
212 return true;
213 }
214
215 uint32_t n_master_pop_bytes =
216 *master_pop_table_length * sizeof(master_population_table_entry);
217
218 // only try to malloc if there's stuff to malloc.
219 *master_pop_table = spin1_malloc(n_master_pop_bytes);
220 if (*master_pop_table == NULL) {
221 log_error("Could not allocate master population table of %u bytes",
222 n_master_pop_bytes);
223 return false;
224 }
225
226 uint32_t address_list_length = config->addr_list_length;
227 uint32_t n_address_list_bytes =
228 address_list_length * sizeof(address_list_entry);
229
230 *address_list = spin1_malloc(n_address_list_bytes);
231 if (*address_list == NULL) {
232 log_error("Could not allocate master population address list of %u bytes",
233 n_address_list_bytes);
234 return false;
235 }
236
237 // Copy the master population table
238 spin1_memcpy(*master_pop_table, config->data, n_master_pop_bytes);
239 spin1_memcpy(*address_list, &config->data[*master_pop_table_length],
240 n_address_list_bytes);
241
242 *row_max_n_words = 0xFF + N_SYNAPSE_ROW_HEADER_WORDS;
243 return true;
244}
246
249
251 address_t table_address, address_t synapse_rows_address,
252 uint32_t *row_max_n_words) {
253 population_table_setup(table_address, row_max_n_words,
256
257 // Store the base address
258 synaptic_rows_base_address = (uint32_t) synapse_rows_address;
259
261 return true;
262}
263
265
266 // check we don't have a complete miss
267 uint32_t position;
270 return false;
271 }
272
274
275 last_spike = spike;
276 next_item = entry.start;
277 items_to_go = entry.count;
278 uint32_t local_neuron_id = get_local_neuron_id(entry, spike);
279 if (entry.n_colour_bits) {
280 last_colour_mask = (1 << entry.n_colour_bits) - 1;
281 last_colour = local_neuron_id & last_colour_mask;
282 last_neuron_id = (local_neuron_id >> entry.n_colour_bits) + get_core_sum(entry, spike);
283 } else {
284 last_colour = 0;
286 last_neuron_id = local_neuron_id + get_core_sum(entry, spike);
287 }
288
289 // check we have a entry in the bit field for this (possible not to due to
290 // DTCM limitations or router table compression). If not, go to DMA check.
292 connectivity_bit_field[position] != NULL) {
293 // check that the bit flagged for this neuron id does hit a
294 // neuron here. If not return false and avoid the DMA check.
295 if (!bit_field_test(
298 items_to_go = 0;
299 return false;
300 }
301 }
302
303 // A local address is used here as the interface requires something
304 // to be passed in but using the address of an argument is odd!
305 uint32_t local_spike_id;
306 bool get_next = population_table_get_next_address(&local_spike_id, result);
307
308 // tracks surplus DMAs
309 if (!get_next) {
311 }
312 return get_next;
313}
314
316 // If there are no more items in the list, return false
317 if (items_to_go == 0) {
318 return false;
319 }
320
321 bool is_valid = false;
322 do {
324 if (item.address != INVALID_ADDRESS) {
325
327 last_neuron_id, result);
328 *spike = last_spike;
329 result->colour = last_colour;
330 result->colour_mask = last_colour_mask;
331 is_valid = true;
332 }
333
334 next_item++;
335 items_to_go--;
336 } while (!is_valid && (items_to_go > 0));
337
338 return is_valid;
339}
340
uint32_t * bit_field_t
#define use(x)
uint32_t * address_t
void log_error(const char *message,...)
void log_warning(const char *message,...)
void log_info(const char *message,...)
static uint32_t key
Base multicast key for sending messages.
uint32_t merged
filter_info_t filters[]
uint32_t all_ones
uint32_t n_filters
uint32_t spike_t
The type of a spike.
Master pop(ulation) table API.
static uint32_t get_offset(address_list_entry entry)
Get the standard address offset out of an entry.
uint32_t key
The key to match against the incoming message.
uint32_t count
The number of entries in address_list for this entry.
uint32_t n_neurons
The number of neurons per core.
static uint32_t get_address(address_list_entry entry, uint32_t addr)
Get the standard address out of an entry.
uint32_t address
the address
static uint32_t get_row_length(address_list_entry entry)
Get the length of the row from the entry.
static void get_row_addr_and_size(address_list_entry item, uint32_t synaptic_rows_base_address, uint32_t neuron_id, pop_table_lookup_result_t *result)
Get the row address and size for a given neuron.
static uint32_t get_local_neuron_id(master_population_table_entry entry, spike_t spike)
Get the neuron id of the neuron on the source core, for a spike with extra info.
uint32_t mask
The mask to select the relevant bits of key for matching.
uint32_t n_colour_bits
The number of bits of key used for colour (0 if no colour)
uint32_t n_words
The number of words for n_neurons.
#define INVALID_ADDRESS
An Invalid address and row length.
static uint32_t get_core_sum(master_population_table_entry entry, spike_t spike)
Get the total number of neurons on cores which come before this core.
uint32_t core_mask
The mask to apply to the key once shifted to get the core index.
uint32_t mask_shift
The shift to apply to the key to get the core part.
uint32_t start
The index into address_list for this entry.
A packed address and row length (note: same size as extra info)
An entry in the master population table.
The memory layout in SDRAM of the first part of the population table configuration....
A structure to hold a response to a population table lookup.
bool population_table_setup(address_t table_address, uint32_t *row_max_n_words, uint32_t *master_pop_table_length, master_population_table_entry **master_pop_table, address_list_entry **address_list)
Set up and return the table for outside use.
static uint16_t next_item
the index for the next item in the address_list
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.
static master_population_table_entry * master_population_table
The master population table. This is sorted.
static void print_bitfields(uint32_t mp_i, filter_info_t *filters)
Print bitfields for debugging.
static uint32_t last_colour
The last colour received.
static uint32_t synaptic_rows_base_address
Base address for the synaptic matrix's indirect rows.
static void print_master_population_table(void)
Prints the master pop table.
uint32_t failed_bit_field_reads
The number of bit fields which were not able to be read in due to DTCM limits.
uint32_t invalid_master_pop_hits
the number of times packet isnt in the master pop table at all!
uint32_t bit_field_filtered_packets
The number of packets dropped because the bitfield filter says they don't hit anything.
bool population_table_load_bitfields(filter_region_t *filter_region)
Initialise the bitfield filtering system.
static address_list_entry * address_list
The array of information that points into the synaptic matrix.
static uint32_t last_colour_mask
The last colour mask used.
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.
static bool population_table_position_in_the_master_pop_array(spike_t spike, uint32_t *position)
Get the position in the master population table.
static uint32_t last_neuron_id
The last neuron id for the key.
uint32_t ghost_pop_table_searches
the number of times a DMA resulted in 0 entries
static uint32_t master_population_table_length
The length of master_population_table.
bool population_table_initialise(address_t table_address, address_t synapse_rows_address, uint32_t *row_max_n_words)
Set up the table.
uint16_t items_to_go
The number of addresses from the same spike left to process.
static bit_field_t * connectivity_bit_field
The bitfield map.
static spike_t last_spike
The last spike received.
heap_t * heap
sark_data_t sark
uint sark_heap_max(heap_t *heap, uint flag)
#define NULL
void spin1_memcpy(void *dst, void const *src, uint len)
implementation for handling the processing of synapse rows.
#define N_SYNAPSE_ROW_HEADER_WORDS
Number of header words per synaptic row.