SpiNNFrontEndCommon  development
Common support code for user-facing front end systems.
command_sender_multicast_source.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 
24 
25 #include <common-typedefs.h>
26 #include <data_specification.h>
27 #include <debug.h>
28 #include <simulation.h>
29 #include <stdbool.h>
30 
36 typedef struct command {
38  uint32_t key;
42  uint32_t payload;
45  uint32_t repeats;
47  uint32_t delay;
48 } command;
49 
51 typedef struct timed_command {
52  uint32_t time;
55 
59 typedef struct command_list {
60  uint32_t size;
62 } command_list;
63 
67 typedef struct timed_command_list {
68  uint32_t size;
71 
72 // Globals
74 static uint32_t time;
76 static uint32_t simulation_ticks;
78 static uint32_t infinite_run;
86 static uint32_t n_timed_commands;
88 static uint32_t n_start_resume_commands;
90 static uint32_t n_pause_stop_commands;
92 static uint32_t next_timed_command;
94 static bool resume = true;
96 static uint32_t n_commands_sent;
97 
99 typedef enum callback_priorities {
100  SDP = 0,
101  DMA = 1,
102  TIMER = 2
104 
106 typedef enum region_identifiers {
121 
123 typedef struct cs_provenance_t {
125  uint32_t n_commands_sent;
127 
129 enum {
130  FIRST_TIME = 0
131 };
132 
136 static void transmit_command(command *command_to_send) {
137  // check for repeats
138  if (command_to_send->repeats != 0) {
139  for (uint32_t repeat_count = 0;
140  repeat_count <= command_to_send->repeats;
141  repeat_count++) {
142  if (command_to_send->has_payload) {
143  log_debug("Sending %08x, %08x at time %u with %u repeats and "
144  "%u delay",
145  command_to_send->key, command_to_send->payload, time,
146  command_to_send->repeats, command_to_send->delay);
147  spin1_send_mc_packet(
148  command_to_send->key, command_to_send->payload,
149  WITH_PAYLOAD);
150  } else {
151  log_debug("Sending %08x at time %u with %u repeats and "
152  "%u delay",
153  command_to_send->key, time, command_to_send->repeats,
154  command_to_send->delay);
155  spin1_send_mc_packet(command_to_send->key, 0, NO_PAYLOAD);
156  }
157  n_commands_sent++;
158 
159  // if the delay is 0, don't call delay
160  if (command_to_send->delay > 0) {
161  spin1_delay_us(command_to_send->delay);
162  }
163  }
164  } else {
165  if (command_to_send->has_payload) {
166  log_debug("Sending %08x, %08x at time %u",
167  command_to_send->key, command_to_send->payload, time);
168 
169  //if no repeats, then just send the message
170  spin1_send_mc_packet(
171  command_to_send->key, command_to_send->payload,
172  WITH_PAYLOAD);
173  } else {
174  log_debug("Sending %08x at time %u", command_to_send->key, time);
175  spin1_send_mc_packet(command_to_send->key, 0, NO_PAYLOAD);
176  }
177  n_commands_sent++;
178  }
179 }
180 
183 static void run_stop_pause_commands(void) {
184  log_info("Transmit pause/stop commands");
185  for (uint32_t i = 0; i < n_pause_stop_commands; i++) {
187  }
188 }
189 
192 static void run_start_resume_commands(void) {
193  log_info("Transmit start/resume commands");
194  for (uint32_t i = 0; i < n_start_resume_commands; i++) {
196  }
197 }
198 
203 static bool read_scheduled_parameters(timed_command_list *sdram_timed_commands) {
204  n_timed_commands = sdram_timed_commands->size;
205  log_info("%d timed commands", n_timed_commands);
206 
207  // if no data, do not read it in
208  if (n_timed_commands == 0) {
209  return true;
210  }
211 
212  // Allocate the space for the scheduled_commands
213  timed_commands = spin1_malloc(n_timed_commands * sizeof(timed_command));
214 
215  if (timed_commands == NULL) {
216  log_error("Could not allocate the scheduled commands");
217  return false;
218  }
219 
220  spin1_memcpy(timed_commands, sdram_timed_commands->commands,
221  n_timed_commands * sizeof(timed_command));
222 
223  log_info("Schedule commands starts at time %u",
224  timed_commands[FIRST_TIME].time);
225  return true;
226 }
227 
232 static bool read_start_resume_commands(command_list *sdram_commands) {
233  n_start_resume_commands = sdram_commands->size;
234  log_info("%u start/resume commands", n_start_resume_commands);
235 
236  if (n_start_resume_commands == 0) {
237  return true;
238  }
239 
240  // Allocate the space for the start resume
242  spin1_malloc(n_start_resume_commands * sizeof(command));
243  if (start_resume_commands == NULL) {
244  log_error("Could not allocate the start/resume commands");
245  return false;
246  }
247 
248  spin1_memcpy(start_resume_commands, sdram_commands->commands,
249  n_start_resume_commands * sizeof(command));
250  return true;
251 }
252 
257 static bool read_pause_stop_commands(command_list *sdram_commands) {
258  n_pause_stop_commands = sdram_commands->size;
259  log_info("%u pause/stop commands", n_pause_stop_commands);
260 
261  if (n_pause_stop_commands == 0) {
262  return true;
263  }
264 
265  // Allocate the space for the start resume
267  spin1_malloc(n_pause_stop_commands * sizeof(command));
268  if (pause_stop_commands == NULL) {
269  log_error("Could not allocate the pause/stop commands");
270  return false;
271  }
272 
273  spin1_memcpy(pause_stop_commands, sdram_commands->commands,
274  n_pause_stop_commands * sizeof(command));
275  return true;
276 }
277 
278 // Callbacks
284 static void timer_callback(UNUSED uint unused0, UNUSED uint unused1) {
285  time++;
286 
287  if (resume) {
288  log_info("running first start resume commands");
290  resume = false;
291  }
292 
293  if (simulation_is_finished()) {
295 
297 
298  log_info("in pause resume mode");
299  resume = true;
300 
301  // Subtract 1 from the time so this tick gets done again on the next
302  // run
303  time--;
304 
306  return;
307  }
308 
313  }
314 }
315 
318 static void write_provenance(address_t address) {
319  cs_provenance_t *sdram_prov = (void *) address;
320  sdram_prov->n_commands_sent = n_commands_sent;
321 }
322 
326 static bool initialize(uint32_t *timer_period) {
327  // Get the address this core's DTCM data starts at from SRAM
328  data_specification_metadata_t *ds_regions =
330 
331  // Read the header
332  if (!data_specification_read_header(ds_regions)) {
333  return false;
334  }
335 
336  // Get the timing details and set up the simulation interface
339  APPLICATION_NAME_HASH, timer_period, &simulation_ticks,
340  &infinite_run, &time, SDP, DMA)) {
341  return false;
342  }
347 
348  // Read the parameters
349  bool success;
351  COMMANDS_WITH_ARBITRARY_TIMES, ds_regions));
353  COMMANDS_AT_START_RESUME, ds_regions));
355  COMMANDS_AT_STOP_PAUSE, ds_regions));
356  return success;
357 }
358 
360 void c_main(void) {
361  // Configure system
362  uint32_t timer_period = 0;
363  if (!initialize(&timer_period)) {
364  log_error("Error in initialisation - exiting!");
365  rt_error(RTE_SWERR);
366  }
367 
368  // Set timer_callback
369  spin1_set_timer_tick(timer_period);
370 
371  // Register callbacks
372  spin1_callback_on(TIMER_TICK, timer_callback, TIMER);
373 
374  // Start the time at "-1" so that the first tick will be 0
375  time = UINT32_MAX;
376  simulation_run();
377 }
uint32_t n_commands_sent
The number of commands sent.
static bool resume
Whether we are in the state where the next run will be a start/resume.
static uint32_t n_commands_sent
The number of commands sent.
static timed_command * timed_commands
The commands to send at particular times.
static uint32_t simulation_ticks
The number of ticks to run for.
static command * start_resume_commands
The commands to run when a simulation starts or resumes after pause.
uint32_t repeats
The number of times to repeat the packet.
uint32_t time
The simulation time to send a packet.
command commands[]
The commands to send.
static bool initialize(uint32_t *timer_period)
Initialises the core.
static uint32_t n_start_resume_commands
The number of commands to send on start/resume.
uint32_t key
The key of the packet.
callback_priorities
values for the priority for each callback
@ TIMER
Responding to timers is lowest priority, and most common.
@ DMA
Handling memory transfers is next highest.
@ SDP
Responding to network traffic is highest priority.
static bool read_scheduled_parameters(timed_command_list *sdram_timed_commands)
Copy the list of commands to run at particular times into DTCM.
uint32_t payload
The payload for the packet.
region_identifiers
region identifiers
@ PROVENANCE_REGION
Where to record provenance data. (Format: cs_provenance_t)
@ SYSTEM_REGION
Where simulation system information is stored.
static void run_start_resume_commands(void)
Sends all the commands registered for sending on simulation start or resume.
uint32_t size
The number of commands to send.
static void write_provenance(address_t address)
Write our provenance data into the provenance region.
static uint32_t n_timed_commands
The number of timed commands.
uint32_t size
The number of commands to send.
static uint32_t infinite_run
Whether the simulation is running "forever" (robotics mode).
static bool read_start_resume_commands(command_list *sdram_commands)
Copy the list of commands to run on start or resume into DTCM.
void c_main(void)
Entry point.
static uint32_t next_timed_command
The index of the next timed command to run.
static uint32_t n_pause_stop_commands
The number of commands to send on stop/pause.
static void timer_callback(uint unused0, uint unused1)
The timer tick callback. Sends those commands that are due in the current simulation state and time.
static bool read_pause_stop_commands(command_list *sdram_commands)
Copy the list of commands to run on stop or pause into DTCM.
static void run_stop_pause_commands(void)
Sends all the commands registered for sending on simulation stop or pause.
static command * pause_stop_commands
The commands to run when a simulation stops or pauses.
command command
What to send.
uint32_t delay
The time (in microseconds) to delay between sending each repeat.
static uint32_t time
The simulation timer.
static void transmit_command(command *command_to_send)
Immediately sends SpiNNaker multicast packets in response to a command.
timed_command commands[]
The commands to send, sorted in time order.
bool has_payload
Whether to send a payload with the packet.
Command structure, describing a SpiNNaker multicast packet to be sent at some point.
A collection of commands to be sent in response to an event.
A command that happens at a particular simulation time.
A collection of commands to be sent at particular simulation times.
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.
static dsupg_provenance_t * sdram_prov
The SDRAM copy of the provenance.
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.
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
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
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