SpiNNFrontEndCommon  development
Common support code for user-facing front end systems.
live_packet_gather.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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 
25 
26 #include <common-typedefs.h>
27 #include <circular_buffer.h>
28 #include <data_specification.h>
29 #include <debug.h>
30 #include <simulation.h>
31 #include <spin1_api.h>
32 #include <eieio.h>
33 
35 typedef struct lpg_provenance_data_t {
45 
46 typedef struct key_translation_entry {
47  // The key to check against after masking
48  uint32_t key;
49  // The mask to apply to the key
50  uint32_t mask;
51  // The atom identifier to add to the computed index
52  uint32_t lo_atom;
54 
58 struct lpg_config {
60  uint32_t apply_prefix;
62  uint32_t prefix;
64  uint32_t prefix_type;
66  uint32_t packet_type;
68  uint32_t key_right_shift;
74  uint32_t payload_prefix;
78  uint32_t sdp_tag;
80  uint32_t sdp_dest;
91 };
92 
94 enum {
95  MC_PACKET = -1,
96  SDP = 0,
97  USER = 1,
98  DMA = 2,
99  TIMER = 3
100 };
101 
103 enum {
105  CONFIGURATION_REGION,
107 };
108 
111  NO_PAYLOAD_16,
112  PAYLOAD_16,
113  NO_PAYLOAD_32,
114  PAYLOAD_32
115 };
116 
117 // Globals
119 static sdp_msg_t g_event_message;
120 
122 static uint16_t *sdp_msg_aer_header;
123 
125 static uint16_t *sdp_msg_aer_payload_prefix = NULL;
126 
128 static uint16_t *sdp_msg_aer_data;
129 
131 static uint32_t time;
132 
134 static uint32_t packets_sent;
135 
137 static uint32_t buffer_index;
138 
140 static uint16_t eieio_constant_header;
141 
143 static uint8_t event_size;
144 
146 static uint8_t sdp_msg_aer_header_len;
147 
149 static uint32_t simulation_ticks = 0;
150 
153 static uint32_t infinite_run = FALSE;
154 
156 static circular_buffer without_payload_buffer;
157 
159 static circular_buffer with_payload_buffer;
160 
162 static bool processing_events = false;
163 
166 
168 static struct lpg_config *config;
169 
171 #define FLAG_IS_SET(flags, bit) (((flags) & (bit)) != 0)
172 
174 #define CLAMP8(value) ((value) & 0xFF)
175 
177 #define CLAMP16(value) ((value) & 0xFFFF)
178 
180 #define HAVE_PAYLOAD(pkt_type) FLAG_IS_SET(pkt_type, 0x1)
181 
183 #define HAVE_WIDE_LOAD(pkt_type) FLAG_IS_SET(pkt_type, 0x2)
184 
186 #define BUFFER_CAPACITY 256
187 
189 static inline bool find_translation_entry(uint32_t key, uint32_t *index) {
190  if (!config->n_translation_entries) {
191  return false;
192  }
193 
194  uint32_t imin = 0;
195  uint32_t imax = config->n_translation_entries;
196 
197  while (imin < imax) {
198  uint32_t imid = (imax + imin) >> 1;
199  key_translation_entry entry = config->translation_table[imid];
200  if ((key & entry.mask) == entry.key) {
201  *index = imid;
202  return true;
203  } else if (entry.key < key) {
204 
205  // Entry must be in upper part of the table
206  imin = imid + 1;
207  } else {
208  // Entry must be in lower part of the table
209  imax = imid;
210  }
211  }
212  return false;
213 }
214 
215 static inline uint32_t translated_key(uint32_t key) {
216  uint32_t index = 0;
217 
218  // If there isn't an entry, don't translate
219  if (!find_translation_entry(key, &index)) {
220  return key & config->received_key_mask;
221  }
222 
223  key_translation_entry entry = config->translation_table[index];
224 
225  // Pre-shift the key as requested
226  uint32_t shifted_key = key & ~entry.mask;
227  if (config->translated_key_right_shift) {
228  shifted_key = shifted_key >> config->translated_key_right_shift;
229  }
230  return shifted_key + entry.lo_atom;
231 }
232 
239 static inline void write_word(void *base, uint32_t index, uint32_t value) {
240  uint16_t *ary = base;
241  uint32_t idx = index * 2;
242  ary[idx++] = CLAMP16(value);
243  ary[idx] = CLAMP16(value >> 16);
244 }
245 
250 static inline void write_short(void *base, uint32_t index, uint32_t value) {
251  uint16_t *ary = base;
252  ary[index] = CLAMP16(value);
253 }
254 
257 static inline uint8_t get_event_count(void) {
258  uint8_t event_count = buffer_index;
259  // If there are payloads, it takes two buffer values to encode them
260  if (HAVE_PAYLOAD(config->packet_type)) {
261  event_count >>= 1;
262  }
263  return event_count;
264 }
265 
268 static void flush_events(void) {
269  // Send the event message only if there is data
270  if ((buffer_index > 0) && (
271  (config->packets_per_timestamp == 0) ||
272  (packets_sent < config->packets_per_timestamp))) {
273  // Get the event count depending on if there is a payload or not
274  uint8_t event_count = get_event_count();
275 
276  // insert appropriate header
277  sdp_msg_aer_header[0] = eieio_constant_header | CLAMP8(event_count);
278 
279  g_event_message.length =
280  sizeof(sdp_hdr_t) + sdp_msg_aer_header_len +
281  event_count * event_size;
282 
283  // Add the timestamp if required
284  if (sdp_msg_aer_payload_prefix && config->payload_timestamp) {
285  if (!HAVE_WIDE_LOAD(config->packet_type)) {
287  } else {
289  }
290  }
291 
292  spin1_send_sdp_msg(&g_event_message, 1);
293  packets_sent++;
295  }
296 
297  // reset counter
298  buffer_index = 0;
299 }
300 
304 static void record_provenance_data(address_t provenance_region_address) {
305  lpg_provenance_data_t *sdram = (void *) provenance_region_address;
306  // Copy provenance data into SDRAM region
307  *sdram = provenance_data;
308 }
309 
310 // Callbacks
318 static void timer_callback(UNUSED uint unused0, UNUSED uint unused1) {
319  // flush the spike message and sent it over the Ethernet
320  flush_events();
321 
322  // increase time variable to keep track of current timestep
323  time++;
324  log_debug("Timer tick %u", time);
325 
326  // Reset the count of packets sent in the current timestep
327  packets_sent = 0;
328 
329  // check if the simulation has run to completion
330  if (simulation_is_finished()) {
332 
334  }
335 }
336 
341 static inline void flush_events_if_full(void) {
342  if ((get_event_count() + 1) * event_size > BUFFER_CAPACITY) {
343  flush_events();
344  }
345 }
346 
349 static void process_incoming_event(uint key) {
350  log_debug("Processing key %x", key);
351 
352  // process the received spike
353  if (!HAVE_WIDE_LOAD(config->packet_type)) {
354  // 16 bit packet
356  key >> config->key_right_shift);
357 
358  // if there is a payload to be added
359  if (HAVE_PAYLOAD(config->packet_type) && !config->payload_timestamp) {
361  } else if (HAVE_PAYLOAD(config->packet_type) && config->payload_timestamp) {
363  }
364  } else {
365  // 32 bit packet
367 
368  // if there is a payload to be added
369  if (HAVE_PAYLOAD(config->packet_type) && !config->payload_timestamp) {
371  } else if (HAVE_PAYLOAD(config->packet_type) && config->payload_timestamp) {
373  }
374  }
376 }
377 
381 static void process_incoming_event_payload(uint key, uint payload) {
382  log_debug("Processing key %x, payload %x", key, payload);
383 
384  // process the received spike
385  if (!HAVE_WIDE_LOAD(config->packet_type)) {
386  //16 bit packet
388  key >> config->key_right_shift);
389 
390  //if there is a payload to be added
391  if (HAVE_PAYLOAD(config->packet_type) && !config->payload_timestamp) {
393  payload >> config->payload_right_shift);
394  } else if (HAVE_PAYLOAD(config->packet_type) && config->payload_timestamp) {
396  }
397  } else {
398  //32 bit packet
400 
401  //if there is a payload to be added
402  if (HAVE_PAYLOAD(config->packet_type) && !config->payload_timestamp) {
404  } else if (HAVE_PAYLOAD(config->packet_type) && config->payload_timestamp) {
406  }
407  }
409 }
410 
427  UNUSED uint unused0, UNUSED uint unused1) {
428  do {
429  uint32_t key, payload;
430 
431  if (circular_buffer_get_next(without_payload_buffer, &key)) {
432  key = translated_key(key);
434  } else if (circular_buffer_get_next(with_payload_buffer, &key)
435  && circular_buffer_get_next(with_payload_buffer, &payload)) {
436  key = translated_key(key);
437  process_incoming_event_payload(key, payload);
438  } else {
439  processing_events = false;
440  break;
441  }
442 
443  // send packet if enough data is stored
445  } while (processing_events);
446 }
447 
455 static void incoming_event_callback(uint key, UNUSED uint unused) {
456  log_debug("Received key %x", key);
457 
458  if (circular_buffer_add(without_payload_buffer, key)) {
459  if (!processing_events) {
460  processing_events = true;
461  spin1_trigger_user_event(0, 0);
462  }
463  } else {
465  }
466 }
467 
475 static void incoming_event_payload_callback(uint key, uint payload) {
476  log_debug("Received key %x, payload %x", key, payload);
477 
478  if (circular_buffer_add(with_payload_buffer, key)) {
479  circular_buffer_add(with_payload_buffer, payload);
480  if (!processing_events) {
481  processing_events = true;
482  spin1_trigger_user_event(0, 0);
483  }
484  } else {
486  }
487 }
488 
494 static bool read_parameters(struct lpg_config *sdram_config) {
495  uint32_t n_bytes = sizeof(struct lpg_config) +
496  (sdram_config->n_translation_entries * sizeof(key_translation_entry));
497  config = spin1_malloc(n_bytes);
498  if (config == NULL) {
499  log_error("Could not allocate space for config!");
500  return false;
501 
502  }
503  spin1_memcpy(config, sdram_config, n_bytes);
504 
505  log_info("apply_prefix: %d", config->apply_prefix);
506  log_info("prefix: %08x", config->prefix);
507  log_info("prefix_type: %d", config->prefix_type);
508  log_info("packet_type: %d", config->packet_type);
509  log_info("key_right_shift: %d", config->key_right_shift);
510  log_info("payload_timestamp: %d", config->payload_timestamp);
511  log_info("payload_apply_prefix: %d", config->payload_apply_prefix);
512  log_info("payload_prefix: %08x", config->payload_prefix);
513  log_info("payload_right_shift: %d", config->payload_right_shift);
514  log_info("sdp_tag: %d", config->sdp_tag);
515  log_info("sdp_dest: 0x%04x", config->sdp_dest);
516  log_info("packets_per_timestamp: %d", config->packets_per_timestamp);
517  log_info("n_translation_entries: %d", config->n_translation_entries);
518  for (uint32_t i = 0; i < config->n_translation_entries; i++) {
519  key_translation_entry *entry = &config->translation_table[i];
520  log_info("key = 0x%08x, mask = 0x%08x, lo_atom = 0x%08x",
521  entry->key, entry->mask, entry->lo_atom);
522  }
523 
524  return true;
525 }
526 
531 static bool initialize(uint32_t *timer_period) {
532  // Get the address this core's DTCM data starts at from SRAM
533  data_specification_metadata_t *ds_regions =
535 
536  // Read the header
537  if (!data_specification_read_header(ds_regions)) {
538  return false;
539  }
540 
541  // Get the timing details and set up the simulation interface
544  APPLICATION_NAME_HASH, timer_period, &simulation_ticks,
545  &infinite_run, &time, SDP, DMA)) {
546  return false;
547  }
551 
552  // Fix simulation ticks to be one extra timer period to soak up last events
553  if (infinite_run != TRUE) {
555  }
556 
557  // Read the parameters
558  return read_parameters(
559  data_specification_get_region(CONFIGURATION_REGION, ds_regions));
560 }
561 
564 static bool configure_sdp_msg(void) {
565  log_debug("configure_sdp_msg");
566 
567  switch (config->packet_type) {
568  case NO_PAYLOAD_16:
569  event_size = 2;
570  break;
571  case PAYLOAD_16:
572  event_size = 4;
573  break;
574  case NO_PAYLOAD_32:
575  event_size = 4;
576  break;
577  case PAYLOAD_32:
578  event_size = 8;
579  break;
580  default:
581  log_error("unknown packet type: %d", config->packet_type);
582  return false;
583  }
584 
585  // initialise SDP header
586  g_event_message.tag = config->sdp_tag;
587  // No reply required
588  g_event_message.flags = 0x07;
589  // Chip 0,0
590  g_event_message.dest_addr = config->sdp_dest;
591  // Dump through Ethernet
592  g_event_message.dest_port = PORT_ETH;
593  // Set up monitoring address and port
594  g_event_message.srce_addr = spin1_get_chip_id();
595  g_event_message.srce_port = (3 << PORT_SHIFT) | spin1_get_core_id();
596 
597  // check incompatible options
598  if (config->payload_timestamp && config->payload_apply_prefix
599  && HAVE_PAYLOAD(config->packet_type)) {
600  log_error("Timestamp can either be included as payload prefix or as"
601  "payload to each key, not both");
602  return false;
603  }
604  if (config->payload_timestamp && !config->payload_apply_prefix
605  && !HAVE_PAYLOAD(config->packet_type)) {
606  log_error("Timestamp can either be included as payload prefix or as"
607  "payload to each key, but current configuration does not"
608  "specify either of these");
609  return false;
610  }
611 
612  // initialise AER header
613  // pointer to data space
615 
619  eieio_constant_header |= config->payload_apply_prefix << APPLY_PAYLOAD_PREFIX;
620  eieio_constant_header |= config->payload_timestamp << PAYLOAD_IS_TIMESTAMP;
621  eieio_constant_header |= config->packet_type << PACKET_TYPE;
622 
623  // pointers for AER packet header, prefix and data
624  // Point to the half-word after main header half-word
626  if (config->apply_prefix) {
627  // pointer to key prefix, so data is one half-word further ahead
630  }
631 
632  if (config->payload_apply_prefix) {
633  // pointer to payload prefix
635 
636  if (!HAVE_WIDE_LOAD(config->packet_type)) {
637  //16 bit payload prefix; advance data position by one half word
639  if (!config->payload_timestamp) {
640  // add payload prefix as required - not a timestamp
641  write_short(sdp_msg_aer_payload_prefix, 0, config->payload_prefix);
642  }
643  } else {
644  //32 bit payload prefix; advance data position by two half words
645  sdp_msg_aer_data += 2;
646  if (!config->payload_timestamp) {
647  // add payload prefix as required - not a timestamp
648  write_word(sdp_msg_aer_payload_prefix, 0, config->payload_prefix);
649  }
650  }
651  }
652 
653  // compute header length in bytes
655  (sdp_msg_aer_data - sdp_msg_aer_header) * sizeof(uint16_t);
656 
657  log_debug("sdp_msg_aer_header: %08x", sdp_msg_aer_header);
658  log_debug("sdp_msg_aer_payload_prefix: %08x", sdp_msg_aer_payload_prefix);
659  log_debug("sdp_msg_aer_data: %08x", sdp_msg_aer_data);
660  log_debug("sdp_msg_aer_header_len: %d", sdp_msg_aer_header_len);
661 
662  packets_sent = 0;
663  buffer_index = 0;
664 
665  return true;
666 }
667 
669 void c_main(void) {
670  // Configure system
671  uint32_t timer_period = 0;
672  if (!initialize(&timer_period)) {
673  log_error("Error in initialisation - exiting!");
674  rt_error(RTE_SWERR);
675  }
676 
677  // Configure SDP message
678  if (!configure_sdp_msg()) {
679  rt_error(RTE_SWERR);
680  }
681 
682  // Set up circular buffers for multicast message reception
683  without_payload_buffer = circular_buffer_initialize(BUFFER_CAPACITY);
684  with_payload_buffer = circular_buffer_initialize(BUFFER_CAPACITY * 2);
685 
686  // Set timer_callback
687  spin1_set_timer_tick(timer_period);
688 
689  // Register callbacks
690  spin1_callback_on(MC_PACKET_RECEIVED, incoming_event_callback, MC_PACKET);
691  spin1_callback_on(
692  MCPL_PACKET_RECEIVED, incoming_event_payload_callback, MC_PACKET);
693  spin1_callback_on(USER_EVENT, incoming_event_process_callback, USER);
694  spin1_callback_on(TIMER_TICK, timer_callback, TIMER);
695 
696  // Start the time at "-1" so that the first tick will be 0
697  time = UINT32_MAX;
698  simulation_run();
699 }
@ PROVENANCE_REGION
Where to record provenance data. (Format: cs_provenance_t)
@ SYSTEM_REGION
Where simulation system information is stored.
Data type definitions for SpiNNaker Neuron-modelling.
uint32_t * address_t
A generic pointer to a word.
Data Specification region access API.
static void * data_specification_get_region(uint32_t region, data_specification_metadata_t *ds_regions)
Gets the address of a region.
data_specification_metadata_t * data_specification_get_data_address(void)
Gets the location of the data for this core using the user0 entry of the SARK VCPU structure.
bool data_specification_read_header(data_specification_metadata_t *ds_regions)
Reads the header from the address given and checks if the parameters are of the correct values.
The central structure that the DSE writes.
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.
EIEIO message header description.
@ PAYLOAD_IS_TIMESTAMP
eieio_header_bitfields::payload_is_timestamp
Definition: eieio.h:33
@ PACKET_TYPE
eieio_header_bitfields::packet_type
Definition: eieio.h:34
@ APPLY_PAYLOAD_PREFIX
eieio_header_bitfields::apply_payload_prefix
Definition: eieio.h:32
@ APPLY_PREFIX
eieio_header_bitfields::apply_prefix
Definition: eieio.h:30
@ PREFIX_UPPER
eieio_header_bitfields::prefix_upper
Definition: eieio.h:31
static sdp_msg_t g_event_message
The SDP message that we will send.
uint32_t sdp_dest
SDP destination to use when sending.
key_translation_entry translation_table[]
Translation table.
static uint32_t buffer_index
Index into our buffer in sdp_msg_aer_data.
uint32_t n_translation_entries
The number of entries in the translation table.
uint32_t payload_prefix
Payload prefix data (for the receiver)
uint32_t received_key_mask
Mask to apply to non-translated keys.
static uint32_t simulation_ticks
When we will run until.
#define HAVE_WIDE_LOAD(pkt_type)
Does the packet type include a double-width payload?
static uint16_t * sdp_msg_aer_data
Pointer to outbound message data. Might only be half-word aligned!
static uint8_t sdp_msg_aer_header_len
The length of the header, in bytes.
uint32_t payload_apply_prefix
D bit.
#define HAVE_PAYLOAD(pkt_type)
Does the packet type include a payload?
static bool initialize(uint32_t *timer_period)
Initialise the application.
#define CLAMP16(value)
How to use just the low 16 bits of an integer value.
static lpg_provenance_data_t provenance_data
The provenance information that we are collecting.
#define BUFFER_CAPACITY
The size of the circular buffers.
uint32_t key_right_shift
Right payload shift (for the sender)
static bool configure_sdp_msg(void)
Sets up the AER EIEIO data message.
static circular_buffer without_payload_buffer
Circular buffer of incoming multicast packets that lack payloads.
static uint8_t get_event_count(void)
Get how many events there are waiting to be sent.
uint32_t translated_key_right_shift
Shift to apply to received and translated keys.
static void record_provenance_data(address_t provenance_region_address)
Store provenance data elements into SDRAM.
static uint16_t * sdp_msg_aer_payload_prefix
The location of the payload prefix in the message. NULL if no prefix.
static bool processing_events
Whether we are processing events (or discarding them).
packet_types
EIEIO packet types.
static uint16_t * sdp_msg_aer_header
The location of the EIEIO header in the message.
static bool read_parameters(struct lpg_config *sdram_config)
Copies the application configuration from DSG SDRAM to DTCM.
static void flush_events(void)
Send buffered events to host via SDP AER message and clear internal buffers.
static void process_incoming_event(uint key)
Processes an incoming multicast packet without payload.
static uint32_t infinite_run
TRUE if we're running without bound. FALSE if we're only running for a limited period of time.
void c_main(void)
Entry point.
static void timer_callback(uint unused0, uint unused1)
Periodic timer callback.
uint32_t payload_timestamp
T bit.
uint32_t sdp_tag
SDP tag to use when sending.
@ TIMER
Timer interrupt is lowest priority.
@ DMA
DMA complete interrupt is low priority.
@ SDP
SDP interrupt is highest priority.
@ MC_PACKET
Multicast packet interrupt uses FIQ (super high prio)
@ USER
Interrupt for enqueued list of received packets.
static void process_incoming_event_payload(uint key, uint payload)
Processes an incoming multicast packet with payload.
uint32_t payload_right_shift
Right payload shift (for the sender)
static circular_buffer with_payload_buffer
Circular buffer of incoming multicast packets that have payloads.
uint32_t number_of_overflows_no_payload
Count of overflows when no payload was sent.
static void write_short(void *base, uint32_t index, uint32_t value)
Simple mirror of write_word() for true 16 bit values.
static bool find_translation_entry(uint32_t key, uint32_t *index)
find a key translation entry
uint32_t number_of_sent_messages
Number of messages sent to host.
static struct lpg_config * config
The configuration data of the application.
static uint32_t packets_sent
The number of packets sent so far this timestamp.
static void incoming_event_payload_callback(uint key, uint payload)
FIQ handler for incoming packets with payload.
static void flush_events_if_full(void)
Flush events to the outside world if our internal buffers are now full.
uint32_t packet_type
F bit (for the receiver)
uint32_t prefix
Prefix data.
uint32_t number_of_gathered_events
Number of events gathered and recorded.
uint32_t packets_per_timestamp
Maximum number of packets to send per timestep, or 0 for "send them all".
static uint16_t eieio_constant_header
Part of the generic EIEIO header that is constant.
static void write_word(void *base, uint32_t index, uint32_t value)
Because WHY OH WHY would you use aligned memory? At least with this we don't get data aborts.
static uint32_t time
Current simulation time.
uint32_t number_of_overflows_with_payload
Count of overflows when a payload was sent.
static void incoming_event_process_callback(uint unused0, uint unused1)
Handler for processing incoming packets that have been locally queued.
static uint8_t event_size
The size of an individual event.
uint32_t apply_prefix
P bit.
uint32_t prefix_type
Type bits.
static void incoming_event_callback(uint key, uint unused)
FIQ handler for incoming packets without payload.
#define CLAMP8(value)
How to use just the low 8 bits of an integer value.
Definitions of each element in the configuration.
Provenance data store.
uint32_t prefix_type
The type of prefix that is supplied.
uint32_t prefix
The prefix to apply.
uint32_t apply_prefix
Whether to always apply a prefix.
The configuration parameters for the application.
Simulation Functions Header File.
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
bool simulation_is_finished(void)
determine if the simulation is finished. Will also pause the simulation for resynchronisation if requ...
Definition: simulation.c:444
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
void simulation_run(void)
Starts the simulation running, returning when it is complete,.
Definition: simulation.c:108
bool simulation_initialise(address_t address, uint32_t expected_application_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_complete_priority)
initialises the simulation interface which involves:
Definition: simulation.c:370