sPyNNaker neural_modelling 7.1.1
Loading...
Searching...
No Matches
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
42typedef enum callback_priorities {
43 DMA = -2, SDP = 0, TIMER = 0
45
47enum regions {
49 CORE_PARAMS_REGION,
50 PROVENANCE_DATA_REGION,
51 PROFILER_REGION,
52 RECORDING_REGION,
53 NEURON_PARAMS_REGION,
54 CURRENT_SOURCE_PARAMS_REGION,
55 NEURON_RECORDING_REGION,
56 SDRAM_PARAMS_REGION,
57 INITIAL_VALUES_REGION
58};
59
63 .provenance = PROVENANCE_DATA_REGION,
64 .profiler = PROFILER_REGION,
65 .recording = RECORDING_REGION
66};
67
70 .sdp = SDP,
71 .dma = DMA,
72 .timer = TIMER
73};
74
79 .core_params = CORE_PARAMS_REGION,
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
89 uint8_t *address;
91 uint32_t size_in_bytes;
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.
106uint32_t time;
107
109static uint32_t timer_period;
110
112static uint32_t simulation_ticks = 0;
113
115static uint32_t infinite_run;
116
118static uint32_t recording_flags = 0;
119
122
125
127static uint32_t timer_overruns = 0;
128
130static union {
131 uint32_t *as_int;
132 weight_t *as_weight;
134
135
138static 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
147void resume_callback(void) {
148
149 // Reset recording
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.");
157 }
158}
159
162static 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
175void 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 */
188
189 // Enter pause and resume state to avoid another tick
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
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) {
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
251static bool initialise(void) {
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);
271
272 uint32_t n_words = sdram_inputs.size_in_bytes >> 2;
273 for (uint32_t i = 0; i < N_SYNAPTIC_BUFFERS; i++) {
275 if (synaptic_contributions[i] == NULL) {
276 log_error("Could not allocate %d bytes for synaptic contributions %d",
278 return false;
279 }
280 for (uint32_t j = 0; j < n_words; j++) {
281 synaptic_contributions[i][j] = 0;
282 }
283 }
285 if (all_synaptic_contributions.as_int == NULL) {
286 log_error("Could not allocate %d bytes for all synaptic contributions",
288 return false;
289 }
290 for (uint32_t j = 0; j < n_words; j++) {
291 all_synaptic_contributions.as_int[j] = 0;
292 }
293 uint32_t *sdram_word = (void *) sdram_inputs.address;
294 for (uint32_t i = 0; i < sdram_inputs.n_synapse_cores; i++) {
295 for (uint32_t j = 0; j < n_words; j++) {
296 *(sdram_word++) = 0;
297 }
298 }
299 // Set timer tick (in microseconds)
300 log_debug("setting timer tick callback for %d microseconds", timer_period);
301 spin1_set_timer_tick(timer_period);
302
303 return true;
304}
305
307void c_main(void) {
308
309 // Start the time at "-1" so that the first tick will be 0
310 time = UINT32_MAX;
311
312 // initialise the model
313 if (!initialise()) {
315 }
316
318}
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
DMA
SDP
callback_priorities
SYSTEM_REGION
uint32_t * address_t
void log_error(const char *message,...)
void log_debug(const char *message,...)
@ PROFILER_TIMER
timer
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
void recording_reset(void)
RTE_SWERR
RTE_API
void rt_error(uint code,...)
void simulation_handle_pause_resume(resume_callback_t callback)
bool simulation_is_finished(void)
void simulation_ready_to_read(void)
void simulation_run(void)
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.
#define NULL
void spin1_memcpy(void *dst, void const *src, uint len)
#define T1_COUNT
unsigned int uint
The callback priorities used by all simulation cores.
uint32_t sdp
The SDP callback priority.
The identifiers of the regions used by all simulation cores.
uint32_t system
Data for general simulation setup.
The provenance information provided by neurons.
The region IDs used by the neuron processing.
uint32_t core_params
The core parameters.