sPyNNaker neural_modelling  7.4.2
bit_field_expander.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 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 <bit_field.h>
20 #include <neuron/synapse_row.h>
23 #include <filter_info.h>
24 #include <key_atom_map.h>
25 
26 /***************************************************************/
27 
28 static uint32_t master_pop_table_length;
29 static master_population_table_entry* master_pop_table;
31 
39  synaptic_row_t row_data, pop_table_lookup_result_t *result) {
40  spin1_memcpy(row_data, result->row_address, result->n_bytes_to_transfer);
41  log_debug("Process synaptic row");
42 
43  // get address of plastic region from row
44  if (synapse_row_plastic_size(row_data) > 0) {
45  log_debug("Plastic row had entries, so cant be pruned");
46  return true;
47  }
48 
49  // Get address of non-plastic region from row
50  synapse_row_fixed_part_t *fixed_region = synapse_row_fixed_region(row_data);
51  uint32_t fixed_synapse = synapse_row_num_fixed_synapses(fixed_region);
52  if (fixed_synapse == 0) {
53  log_debug("Plastic and fixed do not have entries, so can be pruned");
54  return false;
55  } else {
56  log_debug("Fixed row has entries, so cant be pruned");
57  return true;
58  }
59 }
60 
62 static inline void determine_redundancy(filter_region_t *bitfield_filters) {
63  // Semantic sugar to keep the code a little shorter
64  filter_info_t *filters = bitfield_filters->filters;
65  for (uint32_t i = 0; i < bitfield_filters->n_filters; i++) {
66  filters[i].merged = 0;
67  filters[i].all_ones = 0;
68  int i_atoms = filters[i].n_atoms;
69  int i_words = get_bit_field_size(i_atoms);
70  if (i_atoms == count_bit_field(filters[i].data, i_words)) {
71  filters[i].all_ones = 1;
72  }
73  }
74 }
75 
78 static inline bool generate_bit_field(filter_region_t *bitfield_filters,
79  uint32_t *n_atom_data, void *synaptic_matrix, void *structural_matrix,
81 
82  // Get the location just after the structs for the actual bit fields
83  uint32_t *bit_field_words_location = (uint32_t *)
84  &bitfield_filters->filters[master_pop_table_length];
85  int position = 0;
86 
87  // iterate through the master pop entries
88  log_info("Generating %u bitfields", master_pop_table_length);
89  for (uint32_t i = 0; i < master_pop_table_length; i++) {
90 
91  // determine n_neurons and bit field size
92  uint32_t n_neurons = n_atom_data[i];
93  uint32_t n_words = get_bit_field_size(n_neurons);
94 
95  // Make and clear a bit field
96  bit_field_t bit_field = bit_field_alloc(n_neurons);
97  if (bit_field == NULL) {
98  log_error("Could not allocate dtcm for bit field");
99  return false;
100  }
101  clear_bit_field(bit_field, n_words);
102 
103  master_population_table_entry mp_entry = master_pop_table[i];
104 
105  if (structural_matrix != NULL) {
106 
107  // If this is a structural entry, set all the bits
108  uint32_t dummy1 = 0, dummy2 = 0, dummy3 = 0, dummy4 = 0;
109  if (sp_structs_find_by_spike(pre_info, mp_entry.key,
110  &dummy1, &dummy2, &dummy3, &dummy4)) {
111  for (uint32_t n = 0; n < n_neurons; n++) {
112  bit_field_set(bit_field, n);
113  }
114  }
115  } else {
116 
117  // Go through the addresses of the master pop entry
118  uint32_t pos = mp_entry.start;
119  for (uint32_t j = mp_entry.count; j > 0; j--, pos++) {
120 
121  // Find the base address and row length of the address entry
122  address_list_entry entry = address_list[pos];
123 
124  // Skip invalid addresses
125  if (entry.address == INVALID_ADDRESS) {
126  continue;
127  }
128 
129  // Go through each neuron and check the row
130  for (uint32_t n = 0; n < n_neurons; n++) {
131 
132  // If this neuron is already set, skip it this round
133  if (bit_field_test(bit_field, n)) {
134  continue;
135  }
136 
138  get_row_addr_and_size(entry, (uint32_t) synaptic_matrix,
139  n, &result);
140 
141  // Check if the row is non-empty and if so set a bit
142  if (do_sdram_read_and_test(row_data, &result)) {
143  bit_field_set(bit_field, n);
144  }
145  }
146  }
147  }
148 
149  // Copy details into SDRAM
150  bitfield_filters->filters[i].key = mp_entry.key;
151  bitfield_filters->filters[i].n_atoms = n_neurons;
152  bitfield_filters->filters[i].n_atoms_per_core = mp_entry.n_neurons;
153  bitfield_filters->filters[i].core_shift = mp_entry.mask_shift;
154  spin1_memcpy(&bit_field_words_location[position], bit_field,
155  n_words * sizeof(uint32_t));
156  bitfield_filters->filters[i].data = &bit_field_words_location[position];
157 
158  // Move to the next location in SDRAM for bit fields
159  position += n_words;
160 
161  // free dtcm of bitfield.
162  log_debug("Freeing the bitfield dtcm");
163  sark_free(bit_field);
164  }
165 
166  // write how many entries (thus bitfields) have been generated into sdram
167  bitfield_filters->n_filters = master_pop_table_length;
168  return true;
169 }
170 
173  uint32_t *n_atom_data_sdram, void *master_pop,
174  void *synaptic_matrix, void *bitfield_filters, void *structural_matrix) {
175 
176  pop_table_config_t *config = (pop_table_config_t *) master_pop;
177  master_pop_table_length = config->table_length;
178 
179  if (master_pop_table_length == 0) {
180  return true;
181  }
182 
183  master_pop_table = &config->data[0];
184  address_list = (address_list_entry *) &config->data[master_pop_table_length];
185 
186  uint32_t n_atom_bytes = master_pop_table_length * sizeof(uint32_t);
187  uint32_t *n_atom_data = spin1_malloc(n_atom_bytes);
188  if (n_atom_data == NULL) {
189  log_error("Couldn't allocate memory for key_to_max_atoms");
190  rt_error(RTE_SWERR);
191  }
192  spin1_memcpy(n_atom_data, n_atom_data_sdram, n_atom_bytes);
193 
194 
195  uint32_t row_max_n_words = 0xFF + N_SYNAPSE_ROW_HEADER_WORDS;
196  synaptic_row_t row_data = spin1_malloc(row_max_n_words * sizeof(uint32_t));
197  if (row_data == NULL) {
198  log_error("Could not allocate dtcm for the row data");
199  return false;
200  }
201 
204  pre_pop_info_table_t pre_info = {0, NULL};
205  if (structural_matrix != NULL) {
207  structural_matrix, &rewiring_data, &pre_info, &post_to_pre_table);
208  }
209 
210  if (!generate_bit_field(bitfield_filters, n_atom_data, synaptic_matrix,
211  structural_matrix, &pre_info, row_data)) {
212  log_error("Failed to generate bit fields");
213  return false;
214  }
215  determine_redundancy(bitfield_filters);
216  return true;
217 }
static void determine_redundancy(filter_region_t *bitfield_filters)
Determine which bit fields are redundant.
static bool do_bitfield_generation(uint32_t *n_atom_data_sdram, void *master_pop, void *synaptic_matrix, void *bitfield_filters, void *structural_matrix)
Entry point.
static bool generate_bit_field(filter_region_t *bitfield_filters, uint32_t *n_atom_data, void *synaptic_matrix, void *structural_matrix, pre_pop_info_table_t *pre_info, synaptic_row_t row_data)
Create the bitfield for this master pop table and synaptic matrix.
static bool do_sdram_read_and_test(synaptic_row_t row_data, pop_table_lookup_result_t *result)
Read row and test if there are any synapses.
static struct local_only_config config
A local copy of the configuration.
Definition: local_only.c:43
struct synaptic_row * synaptic_row_t
The type of a synaptic row.
static uint32_t n_neurons
The number of neurons on the core.
Definition: neuron.c:45
Master pop(ulation) table API.
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.
uint32_t address
the address
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.
#define INVALID_ADDRESS
An Invalid address and row length.
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.
static address_list_entry * address_list
The array of information that points into the synaptic matrix.
Miscellaneous structures.
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 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
Entry of map from post-connection to pre-connection neural indices.
Definition: sp_structs.h:41
table of individual pre-synaptic information
Definition: sp_structs.h:70
parameters of the synaptic rewiring model
Definition: sp_structs.h:76
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.
Definition: synapse_row.h:147
static size_t synapse_row_num_fixed_synapses(const synapse_row_fixed_part_t *fixed)
Get the number of fixed synapses in the row.
Definition: synapse_row.h:156
static size_t synapse_row_plastic_size(const synaptic_row_t row)
Get the size of the plastic region.
Definition: synapse_row.h:129
#define N_SYNAPSE_ROW_HEADER_WORDS
Number of header words per synaptic row.
Definition: synapse_row.h:109
The type of the fixed part of the row. The fixed-plastic part follows.
Definition: synapse_row.h:118
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