SpiNNFrontEndCommon 7.3.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
76static bool simulation_paused = false;
77
83
84 // store the data into the provenance data region
85 prov->transmission_event_overflow = diagnostics.tx_packet_queue_full;
86 prov->callback_queue_overloads = diagnostics.task_queue_full;
87 prov->dma_queue_overloads = diagnostics.dma_queue_full;
88 prov->user_queue_overloads = diagnostics.user_event_queue_full;
89 prov->timer_tic_has_overrun =
91 prov->max_num_timer_tic_overrun =
93 return prov->provenance_data_elements;
94}
95
97static void execute_provenance_storage(void) {
98 if (prov != NULL) {
99 log_info("Starting basic provenance gathering");
100 void *address_to_start_with = simulation_store_provenance_data();
102 log_info("running other provenance gathering");
103 stored_provenance_function(address_to_start_with);
104 }
105 }
106}
107
108void simulation_run(void) {
109 // go into spin1 API start, but paused (no SYNC yet)
111}
112
114 // Pause the simulation
115 if (uses_timer) {
116 spin1_pause();
117 }
118
120
121 // Store provenance data as required
123}
124
130
134
137static void send_ok_response(sdp_msg_t *msg) {
138 msg->cmd_rc = RC_OK;
139 msg->length = 12;
140 uint dest_port = msg->dest_port;
141 uint dest_addr = msg->dest_addr;
142 msg->dest_port = msg->srce_port;
143 msg->srce_port = dest_port;
144 msg->dest_addr = msg->srce_addr;
145 msg->srce_addr = dest_addr;
146 spin1_send_sdp_msg(msg, 10);
147}
148
152static inline void wait_before_run(bool reset_event) {
153 while (resume_wait()) {
155 }
156 if (reset_event) {
157 event.wait ^= 1;
158 }
160}
161
165static void synchronise_start(uint unused0, uint unused1) {
166 // If we are not using the timer, no-one else resets the event, so do it now
167 // (event comes from sark.h - this is how SARK knows whether to wait for a
168 // SYNC0 or SYNC1 message)
171}
172
174static inline void set_cpu_wait_state() {
175 if (event.wait) {
177 } else {
179 }
180}
181
187static void simulation_control_scp_callback(uint mailbox, UNUSED uint port) {
188 sdp_msg_t *msg = (sdp_msg_t *) mailbox;
189 uint16_t length = msg->length;
190
191 switch (msg->cmd_rc) {
192 case CMD_STOP:
193 log_info("Received exit signal. Program complete.");
194
195 // free the message to stop overload
196 spin1_msg_free(msg);
197
198 // call any stored exit callbacks
199 if (stored_exit_function != NULL) {
200 log_info("Calling pre-exit function");
202 }
203 log_info("Exiting");
204 spin1_exit(0);
205 break;
206
207 case CMD_RUNTIME:
208 log_info("Setting the runtime of this model to %d starting at %d",
209 msg->arg1, msg->arg3);
210 log_info("Setting the flag of infinite run for this model to %d",
211 msg->arg2);
212
213 // resetting the simulation time pointer
216 // We start at time - 1 because the first thing models do is
217 // increment a time counter
218 *pointer_to_current_time = (msg->arg3 - 1);
219 uint32_t *data = (uint32_t *) msg->data;
220 n_sync_steps = data[0];
221 if (n_sync_steps > 0) {
222 // Add one to make the sync happen *after* n_sync_steps
224 } else {
225 next_sync_step = 0;
226 }
227
229 log_info("Calling pre-resume function");
232 }
233
236 }
237 if (uses_timer) {
238 log_info("Resuming");
240 } else {
242 }
243 send_ok_response(msg);
244
245 // free the message to stop overload
246 spin1_msg_free(msg);
247 break;
248
250 log_info("Forced provenance gathering");
251
252 // force provenance to be executed and then exit
254
255 // call any stored exit callbacks
256 if (stored_exit_function != NULL) {
257 log_info("Calling pre-exit function");
259 }
260 spin1_msg_free(msg);
261 spin1_exit(1);
262 break;
263
264 case IOBUF_CLEAR:
265 // run clear iobuf code
267
268 // If we are told to send a response, send it now
269 if (msg->arg3 == 1) {
270 send_ok_response(msg);
271 }
272
273 // free the message to stop overload
274 spin1_msg_free(msg);
275 break;
276
277 case CMD_PAUSE:
278 // pause the simulation
279 log_info("Pausing the simulation");
280 simulation_paused = true;
281 send_ok_response(msg);
282 spin1_msg_free(msg);
283 break;
284
285 case CMD_GET_TIME:
286 // send the current time back
287 msg->cmd_rc = RC_OK;
288 // The length is 12 for the header + 4 for the time (in arg1)
289 msg->length = 16;
291 uint dest_port = msg->dest_port;
292 uint dest_addr = msg->dest_addr;
293 msg->dest_port = msg->srce_port;
294 msg->srce_port = dest_port;
295 msg->dest_addr = msg->srce_addr;
296 msg->srce_addr = dest_addr;
297 spin1_send_sdp_msg(msg, 10);
298 spin1_msg_free(msg);
299 break;
300
301 default:
302 // should never get here
303 log_error("received packet with unknown command code %d",
304 msg->cmd_rc);
305 spin1_msg_free(msg);
306 }
307}
308
312static void simulation_sdp_callback_handler(uint mailbox, uint port) {
313 if (sdp_callback[port] != NULL) {
314 // if a callback is associated with the port, process it
315 sdp_callback[port](mailbox, port);
316 } else {
317 // if no callback is associated, dump the received packet
318 sdp_msg_t *msg = (sdp_msg_t *) mailbox;
319 sark_msg_free(msg);
320 }
321}
322
323bool simulation_sdp_callback_on(uint sdp_port, callback_t callback) {
324 if (sdp_callback[sdp_port] != NULL) {
325 log_error("Cannot allocate SDP callback on port %d as its already "
326 "been allocated.", sdp_port);
327 return false;
328 }
329 sdp_callback[sdp_port] = callback;
330 return true;
331}
332
334 sdp_callback[sdp_port] = NULL;
335}
336
341 if (tag < MAX_DMA_CALLBACK_TAG && dma_complete_callbacks[tag] != NULL) {
342 dma_complete_callbacks[tag](unused, tag);
343 }
344}
345
346bool simulation_dma_transfer_done_callback_on(uint tag, callback_t callback) {
347 // ensure that tag being allocated is less than max tag
348 if (tag >= MAX_DMA_CALLBACK_TAG) {
349 log_error("Cannot handle tag value above %d, please reduce the tag "
350 "value accordingly.", MAX_DMA_CALLBACK_TAG - 1);
351 return false;
352 }
353
354 // allocate tag callback if not already allocated
355 if (dma_complete_callbacks[tag] != NULL) {
356 // if allocated already, raise error
357 log_error("Cannot allocate DMA transfer callback on tag %d as its "
358 "already been allocated.", tag);
359 return false;
360 }
361
363 return true;
364}
365
369
371 address_t address, uint32_t expected_app_magic_number,
372 uint32_t* timer_period, uint32_t *simulation_ticks_pointer,
373 uint32_t *infinite_run_pointer, uint32_t *time_pointer,
374 int sdp_packet_callback_priority,
375 int dma_transfer_done_callback_priority) {
376 struct simulation_config *config = (void *) address;
377
378 // handle the timing reading
379 if (config->application_magic_number != expected_app_magic_number) {
380 log_error("Unexpected magic number 0x%08x instead of 0x%08x at 0x%08x",
381 config->application_magic_number, expected_app_magic_number,
382 &config->application_magic_number);
383 return false;
384 }
385
386 if (sdp_packet_callback_priority < -1) {
387 log_error("The SDP callback priority should be set to a number greater "
388 "than or equal to -1. It is currently set to %d",
389 sdp_packet_callback_priority);
390 return false;
391 }
392
393 // transfer data to pointers for end user usage
394 *timer_period = config->timer_period;
395
396 // handle the SDP callback for the simulation
397 pointer_to_simulation_time = simulation_ticks_pointer;
398 pointer_to_infinite_run = infinite_run_pointer;
399 pointer_to_current_time = time_pointer;
400
402 sdp_packet_callback_priority);
403 simulation_sdp_callback_on(config->control_sdp_port,
405 if (dma_transfer_done_callback_priority >= -1) {
407 dma_transfer_done_callback_priority);
408 }
409
410 // if all simulation initialisation complete return true,
411 return true;
412}
413
415 prov = (void *) provenance_data_address;
416}
417
419 prov_callback_t provenance_function,
420 address_t provenance_data_address) {
421 stored_provenance_function = provenance_function;
422 prov = (void *) provenance_data_address;
423}
424
426 stored_exit_function = exit_function;
427}
428
430 stored_start_function = start_function;
431}
432
433void simulation_set_uses_timer(bool sim_uses_timer) {
434 uses_timer = sim_uses_timer;
435}
436
437void simulation_set_sync_steps(uint32_t n_steps) {
438 n_sync_steps = n_steps;
439 if (n_steps > 0) {
441 }
442}
443
445 // If we are manually paused, report yes once, then go back to no
446 if (simulation_paused) {
447 simulation_paused = false;
448 return true;
449 }
450
451 bool finished = ((*pointer_to_infinite_run != TRUE) &&
453 // If we are finished, or not running synchronized, return finished
454 if (finished || !n_sync_steps) {
455 return finished;
456 }
457 // If we are synchronized, check if this is a sync step (or should have been)
459 log_debug("Sync at %d", next_sync_step);
460
461 // If using the timer, pause the timer
462 if (uses_timer) {
463 log_debug("Pausing");
464 spin1_pause();
465 }
466
467 // Wait for synchronisation to happen
468 log_debug("Waiting for sync");
470 wait_before_run(true);
472 log_debug("Sync done, next sync at %d", next_sync_step);
473
474 // If using the timer, start it again
475 if (uses_timer) {
477 }
478 }
479 return false;
480}
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:113
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:418
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:414
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:152
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:80
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:187
void simulation_exit(void)
Exit the application.
Definition simulation.c:127
void simulation_set_start_function(start_callback_t start_function)
Set an additional function to call before starting the binary.
Definition simulation.c:429
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:433
static void simulation_sdp_callback_handler(uint mailbox, uint port)
handles the SDP callbacks interface.
Definition simulation.c:312
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:425
static void execute_provenance_storage(void)
Run the provenance data storage.
Definition simulation.c:97
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:444
static void set_cpu_wait_state()
Set the CPU state depending on the event wait state.
Definition simulation.c:174
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:370
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:137
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:346
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:131
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 bool simulation_paused
Whether the simulation has been manually "paused".
Definition simulation.c:76
static void simulation_dma_transfer_done_callback(uint unused, uint tag)
handles the DMA transfer done callbacks interface.
Definition simulation.c:340
void simulation_sdp_callback_off(uint sdp_port)
disables SDP callbacks on the given port
Definition simulation.c:333
void simulation_set_sync_steps(uint32_t n_steps)
sets the simulation to enter a synchronisation barrier repeatedly during the simulation....
Definition simulation.c:437
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:323
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:165
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:366
void simulation_run(void)
Starts the simulation running, returning when it is complete,.
Definition simulation.c:108
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:78
void(* exit_callback_t)(void)
Definition simulation.h:82
#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:85
void(* prov_callback_t)(address_t)
the definition of the callback used by provenance data functions
Definition simulation.h:75
@ CMD_STOP
Asks the simulation loop to stop as soon as possible.
Definition simulation.h:60
@ CMD_PAUSE
Definition simulation.h:69
@ CMD_GET_TIME
Get the current simulation time.
Definition simulation.h:71
@ 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