sPyNNaker neural_modelling  7.4.2
synapse_expander.c
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 "matrix_generator.h"
24 #include "connection_generator.h"
25 #include "param_generator.h"
26 #include "rng.h"
27 
28 #include <spin1_api.h>
29 #include <data_specification.h>
30 #include <debug.h>
31 #include <key_atom_map.h>
32 #include "common_mem.h"
33 #include "bit_field_expander.h"
34 
35 #define INVALID_REGION_ID 0xFFFFFFFF
36 
38 typedef struct connection_builder_config {
39  // the per-connector parameters
40  uint32_t pre_lo;
41  uint32_t pre_hi;
42  uint32_t post_lo;
43  uint32_t post_hi;
44  uint32_t synapse_type;
45  // The types of the various components
46  uint32_t matrix_type;
47  uint32_t connector_type;
48  uint32_t weight_type;
49  uint32_t delay_type;
51 
53 __attribute__((aligned(4)))
54 typedef struct expander_config {
55  uint32_t synaptic_matrix_region;
56  uint32_t master_pop_region;
57  uint32_t bitfield_filter_region;
58  uint32_t structural_region;
59  uint32_t n_in_edges;
60  uint32_t post_slice_start;
61  uint32_t post_slice_count;
62  uint32_t post_index;
63  uint32_t n_synapse_types;
64  accum timestep_per_delay;
67  unsigned long accum weight_scales[];
68 } expander_config_t;
69 
72 
89  void *synaptic_matrix, uint32_t post_slice_start,
90  uint32_t post_slice_count, uint32_t post_index,
91  unsigned long accum *weight_scales, accum timestep_per_delay) {
94  *region = &sdram_config[1];
95 
96  // Get the matrix, connector, weight and delay parameter generators
97  matrix_generator_t matrix_generator =
98  matrix_generator_init(config.matrix_type, region, synaptic_matrix);
99  connection_generator_t connection_generator =
100  connection_generator_init(config.connector_type, region);
101  param_generator_t weight_generator =
102  param_generator_init(config.weight_type, region);
103  param_generator_t delay_generator =
104  param_generator_init(config.delay_type, region);
105 
106  // If any components couldn't be created return false
107  if (matrix_generator == NULL || connection_generator == NULL
108  || delay_generator == NULL || weight_generator == NULL) {
109  return false;
110  }
111 
113  connection_generator, config.pre_lo, config.pre_hi, config.post_lo,
114  config.post_hi, post_index, post_slice_start, post_slice_count,
115  weight_scales[config.synapse_type], timestep_per_delay,
116  weight_generator, delay_generator, matrix_generator)) {
117  return false;
118  }
119 
120  // Free the neuron four!
123  param_generator_free(weight_generator);
124  param_generator_free(delay_generator);
125 
126  // Return success!
127  return true;
128 }
129 
137 static bool run_synapse_expander(data_specification_metadata_t *ds_regions,
138  void *params_address) {
139  // Read in the global parameters
140  expander_config_t *sdram_config = params_address;
141  uint32_t data_size = sizeof(expander_config_t)
142  + (sizeof(long accum) * sdram_config->n_synapse_types);
143  expander_config_t *config = spin1_malloc(data_size);
144  fast_memcpy(config, sdram_config, data_size);
145  log_info("Generating %u edges for %u atoms starting at %u",
146  config->n_in_edges, config->post_slice_count, config->post_slice_start);
147 
148  // Get the synaptic matrix region
149  void *synaptic_matrix = data_specification_get_region(
150  config->synaptic_matrix_region, ds_regions);
151 
152  // We are changing this region, so void the checksum
153  ds_regions->regions[config->synaptic_matrix_region].n_words = 0;
154  ds_regions->regions[config->synaptic_matrix_region].checksum = 0;
155 
156  // Store the RNGs
157  population_rng = &(config->population_rng);
158  core_rng = &(config->core_rng);
159 
160  log_info("Population RNG: %u %u %u %u", population_rng->seed[0],
161  population_rng->seed[1], population_rng->seed[2],
162  population_rng->seed[3]);
163 
164  log_info("Core RNG: %u %u %u %u", core_rng->seed[0],
165  core_rng->seed[1], core_rng->seed[2], core_rng->seed[3]);
166 
167 
168  // Go through each connector and generate
169  void *address = &(sdram_config->weight_scales[config->n_synapse_types]);
170  for (uint32_t edge = 0; edge < config->n_in_edges; edge++) {
172  &address, synaptic_matrix, config->post_slice_start,
173  config->post_slice_count, config->post_index,
174  config->weight_scales, config->timestep_per_delay)) {
175  return false;
176  }
177  }
178 
179  // Do bitfield generation on the whole matrix
180  uint32_t *n_atom_data_sdram = address;
181  void *master_pop = data_specification_get_region(
182  config->master_pop_region, ds_regions);
183  void *bitfield_filter = data_specification_get_region(
184  config->bitfield_filter_region, ds_regions);
185  void *structural_matrix = NULL;
186  if (config->structural_region != INVALID_REGION_ID) {
187  structural_matrix = data_specification_get_region(
188  config->structural_region, ds_regions);
189  }
190 
191  // We are changing this region, so void the checksum
192  ds_regions->regions[config->bitfield_filter_region].n_words = 0;
193  ds_regions->regions[config->bitfield_filter_region].checksum = 0;
194  log_info("Region %u set to 0 at 0x%08x and 0x%08x",
195  config->bitfield_filter_region,
196  &(ds_regions->regions[config->bitfield_filter_region].n_words),
197  &(ds_regions->regions[config->bitfield_filter_region].checksum));
198  return do_bitfield_generation(n_atom_data_sdram, master_pop,
199  synaptic_matrix, bitfield_filter, structural_matrix);
200 }
201 
203 void c_main(void) {
204  sark_cpu_state(CPU_STATE_RUN);
205 
206  log_info("Starting To Build Connectors");
207 
208  // Get pointer to 1st virtual processor info struct in SRAM and get USER1;
209  // This is the ID of the connection builder region from which to read the
210  // rest of the data
211  vcpu_t *virtual_processor_table = (vcpu_t*) SV_VCPU;
212  uint user1 = virtual_processor_table[spin1_get_core_id()].user1;
213 
214  // Get the addresses of the regions
215  data_specification_metadata_t *ds_regions =
216  data_specification_get_data_address();
217  void *params_address = data_specification_get_region(user1, ds_regions);
218  log_info("\tReading SDRAM at 0x%08x", params_address);
219 
220  // Run the expander
221  if (!run_synapse_expander(ds_regions, params_address)) {
222  log_info("!!! Error reading SDRAM data !!!");
223  rt_error(RTE_ABORT);
224  }
225 
226  log_info("Finished On Machine Connectors!");
227 }
Expands bitfields on SpiNNaker to reduce data transfer times.
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.
Utility functions for working with memory.
static void fast_memcpy(void *restrict to, const void *restrict from, size_t num_bytes)
A small and fast version of memcpy().
Definition: common_mem.h:33
connection_generator_t connection_generator_init(uint32_t hash, void **in_region)
Initialise a specific connection generator.
bool connection_generator_generate(connection_generator_t generator, uint32_t pre_lo, uint32_t pre_hi, uint32_t post_lo, uint32_t post_hi, uint32_t post_index, uint32_t post_slice_start, uint32_t post_slice_count, unsigned long accum weight_scale, accum timestep_per_delay, param_generator_t weight_generator, param_generator_t delay_generator, matrix_generator_t matrix_generator)
Generate connections with a connection generator.
void connection_generator_free(connection_generator_t generator)
Finish with a connection generator.
The data for a connection generator.
Connection Generator interface.
static struct local_only_config config
A local copy of the configuration.
Definition: local_only.c:43
matrix_generator_t matrix_generator_init(uint32_t hash, void **in_region, void *synaptic_matrix)
Initialise a specific matrix generator.
void matrix_generator_free(matrix_generator_t generator)
Finish with a matrix generator.
The data for a matrix generator.
Interface for matrix generation.
static uint32_t n_synapse_types
The number of synapse types.
Definition: neuron.c:51
void param_generator_free(param_generator_t generator)
Finish with a parameter generator.
param_generator_t param_generator_init(uint32_t hash, void **in_region)
Initialise a specific parameter generator.
Interface for parameter generator.
Random number generator interface.
The Random number generator parameters.
Definition: rng.h:30
region
spike source array region IDs in human readable form
A region of SDRAM used to transfer synapses.
static bool read_connection_builder_region(void **region, void *synaptic_matrix, uint32_t post_slice_start, uint32_t post_slice_count, uint32_t post_index, unsigned long accum *weight_scales, accum timestep_per_delay)
Generate the synapses for a single connector.
rng_t * core_rng
An RNG that is local to the current core.
void c_main(void)
Entry point.
rng_t * population_rng
An RNG that starts in the same place on every core of the Population.
static bool run_synapse_expander(data_specification_metadata_t *ds_regions, void *params_address)
Read the data for the expander.
The configuration of the connection builder.