sPyNNaker neural_modelling  7.4.2
c_main_neurons.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 
35 #include "c_main_neuron_common.h"
36 #include "c_main_common.h"
37 #include "profile_tags.h"
38 #include "dma_common.h"
39 #include <spin1_api_params.h>
40 
42 typedef enum callback_priorities {
43  DMA = -2, SDP = 0, TIMER = 0
45 
47 enum regions {
48  SYSTEM_REGION,
50  PROVENANCE_DATA_REGION,
51  PROFILER_REGION,
58 };
59 
61 const struct common_regions COMMON_REGIONS = {
62  .system = SYSTEM_REGION,
63  .provenance = PROVENANCE_DATA_REGION,
64  .profiler = PROFILER_REGION,
65  .recording = RECORDING_REGION
66 };
67 
69 const struct common_priorities COMMON_PRIORITIES = {
70  .sdp = SDP,
71  .dma = DMA,
72  .timer = TIMER
73 };
74 
78 const struct neuron_regions NEURON_REGIONS = {
80  .neuron_params = NEURON_PARAMS_REGION,
81  .current_source_params = CURRENT_SOURCE_PARAMS_REGION,
82  .neuron_recording = NEURON_RECORDING_REGION,
83  .initial_values = INITIAL_VALUES_REGION
84 };
85 
87 struct sdram_config {
89  uint8_t *address;
91  uint32_t size_in_bytes;
93  uint32_t n_synapse_cores;
94 };
95 
98  uint32_t n_timer_overruns;
99 };
100 
102 #define N_SYNAPTIC_BUFFERS 2
103 
105 // the timer tick callback returning the same value.
106 uint32_t time;
107 
109 static uint32_t timer_period;
110 
112 static uint32_t simulation_ticks = 0;
113 
115 static uint32_t infinite_run;
116 
118 static uint32_t recording_flags = 0;
119 
121 static struct sdram_config sdram_inputs;
122 
125 
127 static uint32_t timer_overruns = 0;
128 
130 static union {
131  uint32_t *as_int;
132  weight_t *as_weight;
134 
135 
138 static void store_provenance_data(address_t provenance_region) {
139  struct neuron_provenance *prov = (void *) provenance_region;
140  store_neuron_provenance(prov);
141  struct neurons_provenance *n_prov = (void *) &prov[1];
142  n_prov->n_timer_overruns = timer_overruns;
143 
144 }
145 
147 void resume_callback(void) {
148 
149  // Reset recording
150  recording_reset();
151 
152  // try resuming neuron
153  // NOTE: at reset, time is set to UINT_MAX ahead of timer_callback(...)
154  if (!neuron_resume(time + 1)) {
155  log_error("failed to resume neuron.");
156  rt_error(RTE_SWERR);
157  }
158 }
159 
162 static inline void sum(weight_t *syns) {
163  uint32_t n_words = sdram_inputs.size_in_bytes >> 2;
164  const uint32_t *src = (const uint32_t *) syns;
165  uint32_t *tgt = all_synaptic_contributions.as_int;
166  for (uint32_t i = n_words; i > 0; i--) {
167  *tgt++ += *src++;
168  }
169 }
170 
175 void timer_callback(uint timer_count, UNUSED uint unused) {
176 
177  profiler_write_entry_disable_irq_fiq(PROFILER_ENTER | PROFILER_TIMER);
178 
179  uint32_t start_time = tc[T1_COUNT];
180 
181  time++;
182 
183  log_debug("Timer tick %u \n", time);
184 
185  /* if a fixed number of simulation ticks that were specified at startup
186  * then do reporting for finishing */
187  if (simulation_is_finished()) {
188 
189  // Enter pause and resume state to avoid another tick
190  simulation_handle_pause_resume(resume_callback);
191 
192  // Pause neuron processing
193  neuron_pause();
194 
195  // Pause common functions
196  common_pause(recording_flags);
197 
198  profiler_write_entry_disable_irq_fiq(PROFILER_EXIT | PROFILER_TIMER);
199 
200  // Subtract 1 from the time so this tick gets done again on the next
201  // run
202  time--;
203 
204  simulation_ready_to_read();
205  return;
206  }
207 
208  // Start the transfer of the first part of the weight data
209  uint8_t *sdram = sdram_inputs.address;
210  uint32_t write_index = 0;
211  uint32_t read_index = 0;
212 
213  // Start the first DMA
214  do_fast_dma_read(sdram, synaptic_contributions[write_index],
216  write_index = !write_index;
217 
218  for (uint32_t i = 0; i < sdram_inputs.n_synapse_cores; i++) {
219  // Wait for the last DMA to complete
220  wait_for_dma_to_complete();
221 
222  // Start the next DMA if not finished
223  if (i + 1 < sdram_inputs.n_synapse_cores) {
224  sdram += sdram_inputs.size_in_bytes;
225  do_fast_dma_read(sdram, synaptic_contributions[write_index],
227  write_index = !write_index;
228  }
229 
230  // Add in the contributions from the last read item
231  sum(synaptic_contributions[read_index]);
232  read_index = !read_index;
233  }
234 
236 
237  // Now do neuron time step update
238  neuron_do_timestep_update(time, timer_count);
239 
240  uint32_t end_time = tc[T1_COUNT];
241  if (end_time > start_time) {
242  timer_overruns += 1;
243  }
244 
245  profiler_write_entry_disable_irq_fiq(PROFILER_EXIT | PROFILER_TIMER);
246 }
247 
251 static bool initialise(void) {
252  data_specification_metadata_t *ds_regions;
253  if (!initialise_common_regions(
256  COMMON_REGIONS, COMMON_PRIORITIES, &ds_regions)) {
257  return false;
258  }
259 
260  // Setup neurons
261  uint32_t n_rec_regions_used;
262  if (!initialise_neuron_regions(
263  ds_regions, NEURON_REGIONS, &n_rec_regions_used)) {
264  return false;
265  }
266 
267  // Setup for reading synaptic inputs at start of each time step
268  struct sdram_config * sdram_config = data_specification_get_region(
269  SDRAM_PARAMS_REGION, ds_regions);
270  spin1_memcpy(&sdram_inputs, sdram_config, sizeof(struct sdram_config));
271 
272  uint32_t n_words = sdram_inputs.size_in_bytes >> 2;
273  uint32_t n_weights = sdram_inputs.size_in_bytes >> 1;
274  for (uint32_t i = 0; i < N_SYNAPTIC_BUFFERS; i++) {
276  if (synaptic_contributions[i] == NULL) {
277  log_error("Could not allocate %d bytes for synaptic contributions %d",
279  return false;
280  }
281  for (uint32_t j = 0; j < n_weights; j++) {
282  synaptic_contributions[i][j] = 0;
283  }
284  }
286  if (all_synaptic_contributions.as_int == NULL) {
287  log_error("Could not allocate %d bytes for all synaptic contributions",
289  return false;
290  }
291  for (uint32_t j = 0; j < n_words; j++) {
292  all_synaptic_contributions.as_int[j] = 0;
293  }
294  uint32_t *sdram_word = (void *) sdram_inputs.address;
295  for (uint32_t i = 0; i < sdram_inputs.n_synapse_cores; i++) {
296  for (uint32_t j = 0; j < n_words; j++) {
297  *(sdram_word++) = 0;
298  }
299  }
300  // Set timer tick (in microseconds)
301  log_debug("setting timer tick callback for %d microseconds", timer_period);
302  spin1_set_timer_tick(timer_period);
303 
304  return true;
305 }
306 
308 void c_main(void) {
309 
310  // Start the time at "-1" so that the first tick will be 0
311  time = UINT32_MAX;
312 
313  // initialise the model
314  if (!initialise()) {
315  rt_error(RTE_API);
316  }
317 
318  simulation_run();
319 }
callback_priorities
Identify the priorities for all tasks.
Definition: c_main.c:54
static uint32_t simulation_ticks
The number of timer ticks to run for before being expected to exit.
void timer_callback(uint timer_count, uint unused)
Timer interrupt callback.
const struct neuron_regions NEURON_REGIONS
static void sum(weight_t *syns)
Add up all the synaptic contributions into a global buffer.
callback_priorities
values for the priority for each callback
static void store_provenance_data(address_t provenance_region)
Callback to store provenance data (format: neuron_provenance).
#define N_SYNAPTIC_BUFFERS
The number of buffers for synaptic data (one processing, one in progress)
static weight_t * synaptic_contributions[N_SYNAPTIC_BUFFERS]
The inputs from the various synapse cores.
void resume_callback(void)
the function to call when resuming a simulation
static union @7 all_synaptic_contributions
All the synaptic contributions for adding up in 2 formats.
static uint32_t recording_flags
The recording flags indicating if anything is recording.
static uint32_t infinite_run
Determines if this model should run for infinite time.
static struct sdram_config sdram_inputs
The SDRAM input configuration data.
void c_main(void)
The entry point for this model.
const struct common_priorities COMMON_PRIORITIES
Identify the priority of certain tasks.
static uint32_t timer_overruns
The timer overruns.
static bool initialise(void)
Initialises the model by reading in the regions and checking recording data.
static uint32_t timer_period
timer tick period (in microseconds)
const struct common_regions COMMON_REGIONS
From the regions, select those that are common.
uint32_t time
The current timer tick value.
Provenance for this specific core.
@ TIMER
Call timer at 0 to keep it quick.
@ DMA
DMA is not actually used.
@ SDP
SDP handling is queued.
@ PROFILER_TIMER
timer
Definition: profile_tags.h:23
void neuron_pause(void)
Perform steps needed before pausing a simulation.
Definition: neuron.c:184
bool neuron_resume(uint32_t time)
Prepare to resume simulation of the neurons.
Definition: neuron.c:93
void neuron_transfer(weight_t *syns)
Add inputs to the neurons.
Definition: neuron.c:204
void neuron_do_timestep_update(timer_t time, uint timer_count)
executes all the updates to neural parameters when a given timer period has occurred.
Definition: neuron.c:190
@ NEURON_PARAMS_REGION
neuron parameters; 2
Definition: regions.h:28
@ CORE_PARAMS_REGION
core parameters; 1
Definition: regions.h:27
@ INITIAL_VALUES_REGION
initial neuron state; 16
Definition: regions.h:42
@ RECORDING_REGION
general recording data; 15
Definition: regions.h:41
@ NEURON_RECORDING_REGION
recording; 9
Definition: regions.h:35
@ CURRENT_SOURCE_PARAMS_REGION
current source parameters; 3
Definition: regions.h:29
Tags for profiling of the spike source poisson.
uint32_t size_in_bytes
The size of the input data to be transferred per core.
@ SDRAM_PARAMS_REGION
SDRAM transfer parameters region.
uint8_t * address
The start address of the input data to be transferred.
uint32_t n_synapse_cores
The number of synapse cores feeding into here.
A region of SDRAM used to transfer synapses.
The callback priorities used by all simulation cores.
Definition: c_main_common.h:46
uint32_t sdp
The SDP callback priority.
Definition: c_main_common.h:48
The identifiers of the regions used by all simulation cores.
Definition: c_main_common.h:34
uint32_t system
Data for general simulation setup.
Definition: c_main_common.h:36
The provenance information provided by neurons.
The region IDs used by the neuron processing.
uint32_t core_params
The core parameters.