SpiNNFrontEndCommon 7.1.1
Common support code for user-facing front end systems.
Loading...
Searching...
No Matches
simulation.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014 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
22#include "simulation.h"
23
24#include <stdbool.h>
25#include <debug.h>
26#include <spin1_api_params.h>
27#include <spin1_api.h>
28#include <wfi.h>
29
30// Import things from spin1_api that are not explicitly exposed //
31
34extern uint resume_wait(void);
35
38
40static uint32_t *pointer_to_infinite_run;
41
43static uint32_t *pointer_to_current_time;
44
47
50
53
56
59
62
65
67static bool uses_timer = true;
68
70static uint32_t n_sync_steps;
71
73static uint32_t next_sync_step;
74
80
81 // store the data into the provenance data region
82 prov->transmission_event_overflow = diagnostics.tx_packet_queue_full;
83 prov->callback_queue_overloads = diagnostics.task_queue_full;
84 prov->dma_queue_overloads = diagnostics.dma_queue_full;
85 prov->user_queue_overloads = diagnostics.user_event_queue_full;
86 prov->timer_tic_has_overrun =
88 prov->max_num_timer_tic_overrun =
90 return prov->provenance_data_elements;
91}
92
94static void execute_provenance_storage(void) {
95 if (prov != NULL) {
96 log_info("Starting basic provenance gathering");
97 void *address_to_start_with = simulation_store_provenance_data();
99 log_info("running other provenance gathering");
100 stored_provenance_function(address_to_start_with);
101 }
102 }
103}
104
105void simulation_run(void) {
106 // go into spin1 API start, but paused (no SYNC yet)
108}
109
111 // Pause the simulation
112 if (uses_timer) {
113 spin1_pause();
114 }
115
117
118 // Store provenance data as required
120}
121
127
131
134static void send_ok_response(sdp_msg_t *msg) {
135 msg->cmd_rc = RC_OK;
136 msg->length = 12;
137 uint dest_port = msg->dest_port;
138 uint dest_addr = msg->dest_addr;
139 msg->dest_port = msg->srce_port;
140 msg->srce_port = dest_port;
141 msg->dest_addr = msg->srce_addr;
142 msg->srce_addr = dest_addr;
143 spin1_send_sdp_msg(msg, 10);
144}
145
149static inline void wait_before_run(bool reset_event) {
150 while (resume_wait()) {
152 }
153 if (reset_event) {
154 event.wait ^= 1;
155 }
157}
158
162static void synchronise_start(uint unused0, uint unused1) {
163 // If we are not using the timer, no-one else resets the event, so do it now
164 // (event comes from sark.h - this is how SARK knows whether to wait for a
165 // SYNC0 or SYNC1 message)
168}
169
171static inline void set_cpu_wait_state() {
172 if (event.wait) {
174 } else {
176 }
177}
178
184static void simulation_control_scp_callback(uint mailbox, UNUSED uint port) {
185 sdp_msg_t *msg = (sdp_msg_t *) mailbox;
186 uint16_t length = msg->length;
187
188 switch (msg->cmd_rc) {
189 case CMD_STOP:
190 log_info("Received exit signal. Program complete.");
191
192 // free the message to stop overload
193 spin1_msg_free(msg);
194
195 // call any stored exit callbacks
196 if (stored_exit_function != NULL) {
197 log_info("Calling pre-exit function");
199 }
200 log_info("Exiting");
201 spin1_exit(0);
202 break;
203
204 case CMD_RUNTIME:
205 log_info("Setting the runtime of this model to %d starting at %d",
206 msg->arg1, msg->arg3);
207 log_info("Setting the flag of infinite run for this model to %d",
208 msg->arg2);
209
210 // resetting the simulation time pointer
213 // We start at time - 1 because the first thing models do is
214 // increment a time counter
215 *pointer_to_current_time = (msg->arg3 - 1);
216 uint32_t *data = (uint32_t *) msg->data;
217 n_sync_steps = data[0];
218 if (n_sync_steps > 0) {
219 // Add one to make the sync happen *after* n_sync_steps
221 } else {
222 next_sync_step = 0;
223 }
224
226 log_info("Calling pre-resume function");
229 }
230
233 }
234 if (uses_timer) {
235 log_info("Resuming");
237 } else {
239 }
240 send_ok_response(msg);
241
242 // free the message to stop overload
243 spin1_msg_free(msg);
244 break;
245
247 log_info("Forced provenance gathering");
248
249 // force provenance to be executed and then exit
251
252 // call any stored exit callbacks
253 if (stored_exit_function != NULL) {
254 log_info("Calling pre-exit function");
256 }
257 spin1_msg_free(msg);
258 spin1_exit(1);
259 break;
260
261 case IOBUF_CLEAR:
262 // run clear iobuf code
264
265 // If we are told to send a response, send it now
266 if (msg->arg3 == 1) {
267 send_ok_response(msg);
268 }
269
270 // free the message to stop overload
271 spin1_msg_free(msg);
272 break;
273
274 default:
275 // should never get here
276 log_error("received packet with unknown command code %d",
277 msg->cmd_rc);
278 spin1_msg_free(msg);
279 }
280}
281
285static void simulation_sdp_callback_handler(uint mailbox, uint port) {
286 if (sdp_callback[port] != NULL) {
287 // if a callback is associated with the port, process it
288 sdp_callback[port](mailbox, port);
289 } else {
290 // if no callback is associated, dump the received packet
291 sdp_msg_t *msg = (sdp_msg_t *) mailbox;
292 sark_msg_free(msg);
293 }
294}
295
296bool simulation_sdp_callback_on(uint sdp_port, callback_t callback) {
297 if (sdp_callback[sdp_port] != NULL) {
298 log_error("Cannot allocate SDP callback on port %d as its already "
299 "been allocated.", sdp_port);
300 return false;
301 }
302 sdp_callback[sdp_port] = callback;
303 return true;
304}
305
307 sdp_callback[sdp_port] = NULL;
308}
309
314 if (tag < MAX_DMA_CALLBACK_TAG && dma_complete_callbacks[tag] != NULL) {
315 dma_complete_callbacks[tag](unused, tag);
316 }
317}
318
319bool simulation_dma_transfer_done_callback_on(uint tag, callback_t callback) {
320 // ensure that tag being allocated is less than max tag
321 if (tag >= MAX_DMA_CALLBACK_TAG) {
322 log_error("Cannot handle tag value above %d, please reduce the tag "
323 "value accordingly.", MAX_DMA_CALLBACK_TAG - 1);
324 return false;
325 }
326
327 // allocate tag callback if not already allocated
328 if (dma_complete_callbacks[tag] != NULL) {
329 // if allocated already, raise error
330 log_error("Cannot allocate DMA transfer callback on tag %d as its "
331 "already been allocated.", tag);
332 return false;
333 }
334
336 return true;
337}
338
342
344 address_t address, uint32_t expected_app_magic_number,
345 uint32_t* timer_period, uint32_t *simulation_ticks_pointer,
346 uint32_t *infinite_run_pointer, uint32_t *time_pointer,
347 int sdp_packet_callback_priority,
348 int dma_transfer_done_callback_priority) {
349 struct simulation_config *config = (void *) address;
350
351 // handle the timing reading
352 if (config->application_magic_number != expected_app_magic_number) {
353 log_error("Unexpected magic number 0x%08x instead of 0x%08x at 0x%08x",
354 config->application_magic_number, expected_app_magic_number,
355 &config->application_magic_number);
356 return false;
357 }
358
359 if (sdp_packet_callback_priority < -1) {
360 log_error("The SDP callback priority should be set to a number greater "
361 "than or equal to -1. It is currently set to %d",
362 sdp_packet_callback_priority);
363 return false;
364 }
365
366 // transfer data to pointers for end user usage
367 *timer_period = config->timer_period;
368
369 // handle the SDP callback for the simulation
370 pointer_to_simulation_time = simulation_ticks_pointer;
371 pointer_to_infinite_run = infinite_run_pointer;
372 pointer_to_current_time = time_pointer;
373
375 sdp_packet_callback_priority);
376 simulation_sdp_callback_on(config->control_sdp_port,
378 if (dma_transfer_done_callback_priority >= -1) {
380 dma_transfer_done_callback_priority);
381 }
382
383 // if all simulation initialisation complete return true,
384 return true;
385}
386
388 prov = (void *) provenance_data_address;
389}
390
392 prov_callback_t provenance_function,
393 address_t provenance_data_address) {
394 stored_provenance_function = provenance_function;
395 prov = (void *) provenance_data_address;
396}
397
399 stored_exit_function = exit_function;
400}
401
403 stored_start_function = start_function;
404}
405
406void simulation_set_uses_timer(bool sim_uses_timer) {
407 uses_timer = sim_uses_timer;
408}
409
410void simulation_set_sync_steps(uint32_t n_steps) {
411 n_sync_steps = n_steps;
412 if (n_steps > 0) {
414 }
415}
416
418 bool finished = ((*pointer_to_infinite_run != TRUE) &&
420 // If we are finished, or not running synchronized, return finished
421 if (finished || !n_sync_steps) {
422 return finished;
423 }
424 // If we are synchronized, check if this is a sync step (or should have been)
426 log_debug("Sync at %d", next_sync_step);
427
428 // If using the timer, pause the timer
429 if (uses_timer) {
430 log_debug("Pausing");
431 spin1_pause();
432 }
433
434 // Wait for synchronisation to happen
435 log_debug("Waiting for sync");
437 wait_before_run(true);
439 log_debug("Sync done, next sync at %d", next_sync_step);
440
441 // If using the timer, start it again
442 if (uses_timer) {
444 }
445 }
446 return false;
447}
uint32_t * address_t
A generic pointer to a word.
static uint32_t data[ITEMS_PER_DATA_PACKET]
SpiNNaker debug header file.
void log_error(const char *message,...)
This function logs errors. Errors usually indicate a serious fault in the program,...
void log_debug(const char *message,...)
This function logs debugging messages. This level of message is normally not printed except when the ...
void log_info(const char *message,...)
This function logs informational messages. This is the lowest level of message normally printed.
The configuration parameters for the application.
uchar data[SDP_BUF_SIZE]
uchar dest_port
ushort cmd_rc
#define NUM_SDP_PORTS
uchar srce_port
CPU_STATE_RUN
CPU_STATE_SYNC1
CPU_STATE_SYNC0
CPU_STATE_WAIT
RC_OK
SYNC_WAIT
SYNC_NOWAIT
void sark_msg_free(sdp_msg_t *msg)
void sark_cpu_state(cpu_state state)
ushort length
ushort dest_addr
ushort srce_addr
event_data_t event
void sark_io_buf_reset(void)
void simulation_handle_pause_resume(resume_callback_t callback)
cleans up the house keeping, falls into a sync state and handles the resetting up of states as requir...
Definition simulation.c:110
void simulation_set_provenance_function(prov_callback_t provenance_function, address_t provenance_data_address)
Set an additional callback function to store extra provenance data.
Definition simulation.c:391
void simulation_set_provenance_data_address(address_t provenance_data_address)
Set the address of the data region where provenance data is to be stored.
Definition simulation.c:387
static uint32_t n_sync_steps
The number of steps to run before synchronisation.
Definition simulation.c:70
static void wait_before_run(bool reset_event)
wait for a signal before running
Definition simulation.c:149
static callback_t sdp_callback[NUM_SDP_PORTS]
the list of SDP callbacks for ports
Definition simulation.c:61
static void * simulation_store_provenance_data(void)
Store basic provenance data.
Definition simulation.c:77
static void simulation_control_scp_callback(uint mailbox, uint port)
Handle the new commands needed to resume the binary with a new runtime counter, as well as switching ...
Definition simulation.c:184
void simulation_exit(void)
Exit the application.
Definition simulation.c:124
void simulation_set_start_function(start_callback_t start_function)
Set an additional function to call before starting the binary.
Definition simulation.c:402
void simulation_set_uses_timer(bool sim_uses_timer)
set whether the simulation uses the timer. By default it will be assumed that simulations use the tim...
Definition simulation.c:406
static void simulation_sdp_callback_handler(uint mailbox, uint port)
handles the SDP callbacks interface.
Definition simulation.c:285
static uint32_t * pointer_to_infinite_run
the pointer to the flag for if it is a infinite run
Definition simulation.c:40
void simulation_set_exit_function(exit_callback_t exit_function)
Set an additional function to call before exiting the binary when running without a fixed duration of...
Definition simulation.c:398
static void execute_provenance_storage(void)
Run the provenance data storage.
Definition simulation.c:94
static exit_callback_t stored_exit_function
the function call to run when received a exit command.
Definition simulation.c:49
static callback_t dma_complete_callbacks[MAX_DMA_CALLBACK_TAG]
the list of DMA callbacks for DMA complete callbacks
Definition simulation.c:64
bool simulation_is_finished(void)
determine if the simulation is finished. Will also pause the simulation for resynchronisation if requ...
Definition simulation.c:417
static void set_cpu_wait_state()
Set the CPU state depending on the event wait state.
Definition simulation.c:171
bool simulation_initialise(address_t address, uint32_t expected_app_magic_number, uint32_t *timer_period, uint32_t *simulation_ticks_pointer, uint32_t *infinite_run_pointer, uint32_t *time_pointer, int sdp_packet_callback_priority, int dma_transfer_done_callback_priority)
initialises the simulation interface which involves:
Definition simulation.c:343
static uint32_t next_sync_step
The number simulation timestep at the next synchronisation.
Definition simulation.c:73
static void send_ok_response(sdp_msg_t *msg)
Send an OK response to the host when a command message is received.
Definition simulation.c:134
static uint32_t * pointer_to_current_time
the pointer to the current simulation time
Definition simulation.c:43
bool simulation_dma_transfer_done_callback_on(uint tag, callback_t callback)
registers a DMA transfer callback to the simulation system
Definition simulation.c:319
void simulation_ready_to_read(void)
Indicates that all data has been written and the core is going idle, so any data can now be read.
Definition simulation.c:128
static start_callback_t stored_start_function
the function call to run at the start of simulation
Definition simulation.c:55
static struct simulation_provenance * prov
the region ID for storing provenance data from the chip
Definition simulation.c:58
static prov_callback_t stored_provenance_function
the function call to run when extracting provenance data from the chip
Definition simulation.c:46
static void simulation_dma_transfer_done_callback(uint unused, uint tag)
handles the DMA transfer done callbacks interface.
Definition simulation.c:313
void simulation_sdp_callback_off(uint sdp_port)
disables SDP callbacks on the given port
Definition simulation.c:306
void simulation_set_sync_steps(uint32_t n_steps)
sets the simulation to enter a synchronisation barrier repeatedly during the simulation....
Definition simulation.c:410
bool simulation_sdp_callback_on(uint sdp_port, callback_t callback)
Registers an additional SDP callback on a given SDP port. This is required when using simulation_regi...
Definition simulation.c:296
uint resume_wait(void)
Indicate whether the SYNC signal has been received.
static resume_callback_t stored_resume_function
the function call to run just before resuming a simulation
Definition simulation.c:52
static void synchronise_start(uint unused0, uint unused1)
Callback when starting after synchronise.
Definition simulation.c:162
static bool uses_timer
Whether the simulation uses the timer or not (default true)
Definition simulation.c:67
void simulation_dma_transfer_done_callback_off(uint tag)
turns off a registered callback for a given DMA transfer done tag
Definition simulation.c:339
void simulation_run(void)
Starts the simulation running, returning when it is complete,.
Definition simulation.c:105
static uint32_t * pointer_to_simulation_time
the pointer to the simulation time used by application models
Definition simulation.c:37
Simulation Functions Header File.
void(* resume_callback_t)(void)
the definition of the callback used by pause and resume
Definition simulation.h:73
void(* exit_callback_t)(void)
Definition simulation.h:77
#define MAX_DMA_CALLBACK_TAG
Definition simulation.h:35
resume_callback_t start_callback_t
the definition of the callback used to call a function once at start
Definition simulation.h:80
void(* prov_callback_t)(address_t)
the definition of the callback used by provenance data functions
Definition simulation.h:70
@ CMD_STOP
Asks the simulation loop to stop as soon as possible.
Definition simulation.h:60
@ PROVENANCE_DATA_GATHERING
Asks the application to gather provenance data.
Definition simulation.h:64
@ CMD_RUNTIME
Tells the simulation loop how long to run for.
Definition simulation.h:62
@ IOBUF_CLEAR
Clears the IOBUF.
Definition simulation.h:66
the position and human readable terms for each element from the region containing the timing details.
Definition simulation.h:39
elements that are always grabbed for provenance if possible when requested
Definition simulation.h:47
SDP_PACKET_RX
DMA_TRANSFER_DONE
#define NULL
void spin1_pause(void)
uint user_event_queue_full
uint total_times_tick_tic_callback_overran
diagnostics_t diagnostics
uint tx_packet_queue_full
uint spin1_schedule_callback(callback_t cback, uint arg0, uint arg1, uint priority)
void spin1_resume(sync_bool sync)
void(* callback_t)(uint, uint)
uint largest_number_of_concurrent_timer_tic_overruns
#define TRUE
void spin1_exit(uint error)
uint task_queue_full
uint spin1_start_paused(void)
void spin1_callback_on(uint event_id, callback_t cback, int priority)
cback_t callback[NUM_EVENTS]
unsigned int uint
Wait for interrupt.
static void wait_for_interrupt(void)
Wait for any interrupt to occur.
Definition wfi.h:32