SpiNNFrontEndCommon 7.3.1
Common support code for user-facing front end systems.
Loading...
Searching...
No Matches
reverse_iptag_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
23
24#include <common-typedefs.h>
25#include <data_specification.h>
26#include <debug.h>
27#include <simulation.h>
28#include <sark.h>
29#include <eieio.h>
30#include <buffered_eieio_defs.h>
31#include "recording.h"
32#include <wfi.h>
33
34// ------------------------------------------------------------------------
35
36#ifndef APPLICATION_NAME_HASH
37#error APPLICATION_NAME_HASH must be defined
38#endif
39
40#ifndef __use
41#define __use(x) do { (void) (x); } while (0)
42#endif
43
46 DMA = 0,
47 SDP_CALLBACK = 1,
48 TIMER = 2
49};
50
83
86 SYSTEM,
87 CONFIGURATION,
88 RECORDING_REGION,
89 BUFFER_REGION,
91};
92
101
103#define NUMBER_OF_REGIONS_TO_RECORD 1
105#define SPIKE_HISTORY_CHANNEL 0
106
108#define MIN_BUFFER_SPACE 10
109
111#define TICKS_BETWEEN_REQUESTS 25
112
114#define MAX_PACKET_SIZE 272
115
116#pragma pack(1)
117
124
135
136#pragma pack()
137
138// ------------------------------------------------------------------------
139// Globals
140
143
146
149
151static bool apply_prefix;
152
155
158
160static bool has_key;
161
164
167
170
173
176
179
182
185
188
191
194
197
200
203
206
209
212
215
218
221
224
227
230
233
239
243
246
248static bool stopped = false;
249
252
253// ------------------------------------------------------------------------
254
261#define BITS(value, shift, mask) \
262 (((value) >> (shift)) & (mask))
263
271
272 switch (command_number) {
273 case EVENT_PADDING:
277 return 2;
279 return 12;
281 // does not include the EIEIO packet payload
282 return 4;
284 return 16;
285 case HOST_DATA_READ:
286 return 8;
287 default:
288 return 0;
289 }
290 return 0;
291}
292
306
307 switch (pkt_type) {
308 case KEY_16_BIT:
309 event_size = 2;
310 break;
312 case KEY_32_BIT:
313 event_size = 4;
314 break;
316 event_size = 8;
317 break;
318 }
319
320 if (pkt_apply_prefix) {
321 header_size += 2;
322 }
324 if (pkt_type == 0 || pkt_type == 1) {
325 header_size += 2;
326 } else {
327 header_size += 4;
328 }
329 }
330
332 return total_size;
333}
334
348
352static inline void print_packet_bytes(
354 __use(eieio_msg_ptr);
355 __use(length);
356#if LOG_LEVEL >= LOG_DEBUG
357 uint8_t *ptr = (uint8_t *) eieio_msg_ptr;
358
359 log_debug("packet of %d bytes:", length);
360
361 for (int i = 0; i < length; i++) {
362 if ((i & 7) == 0) {
363 io_printf(IO_BUF, "\n");
364 }
365 io_printf(IO_BUF, "%02x", ptr[i]);
366 }
367 io_printf(IO_BUF, "\n");
368#endif
369}
370
376static inline void print_packet(const eieio_msg_t eieio_msg_ptr) {
377 __use(eieio_msg_ptr);
378#if LOG_LEVEL >= LOG_DEBUG
381#endif
382}
383
390static inline void signal_software_error(
391 const eieio_msg_t eieio_msg_ptr, uint16_t length) {
392 __use(eieio_msg_ptr);
393 __use(length);
394#if LOG_LEVEL >= LOG_DEBUG
397#endif
398}
399
408 return final_space + initial_space;
409 } else if (write_pointer < read_pointer) {
412 // If pointers are equal, buffer is full if last operation is write
413 return 0;
414 } else {
415 // If pointers are equal, buffer is empty if last operation is read
416 return buffer_region_size;
417 }
418}
419
422static inline bool is_eieio_packet_in_buffer(void) {
423 // If there is no buffering being done, there are no packets
424 if (buffer_region_size == 0) {
425 return false;
426 }
427
428 // There are packets as long as the buffer is not empty; the buffer is
429 // empty if the pointers are equal and the last operation was read
430 return (write_pointer != read_pointer) ||
432}
433
441 bool pkt_has_timestamp = (bool)
445
446 // If the packet is actually a command packet, return the current time
447 if (!pkt_apply_prefix && pkt_class) {
448 return time;
449 }
450
451 // If the packet indicates that payloads are timestamps
452 if (pkt_has_timestamp) {
457 bool got_payload_time = false;
459
460 // If there is a payload prefix
462 // If there is a key prefix, the payload prefix is after that
463 if (pkt_apply_prefix) {
464 event_ptr++;
465 }
466
467 if (pkt_type & 0x2) {
468 // 32 bit packet
469 payload_time = (event_ptr[1] << 16) | event_ptr[0];
470 event_ptr += 2;
471 } else {
472 // 16 bit packet
474 event_ptr++;
475 }
476 got_payload_time = true;
477 }
478
479 // If the packets have a payload
480 if (pkt_type & 0x1) {
481 if (pkt_type & 0x2) {
482 // 32 bit packet
483 payload_time |= (event_ptr[1] << 16) | event_ptr[0];
484 } else {
485 // 16 bit packet
487 }
488 got_payload_time = true;
489 }
490
491 // If no actual time was found, return the current time
492 if (!got_payload_time) {
493 return time;
494 }
495 return payload_time;
496 }
497
498 // This is not a timed packet, return the current time
499 return time;
500}
501
507static inline bool add_eieio_packet_to_sdram(
508 const eieio_msg_t eieio_msg_ptr, uint32_t length) {
510
511 log_debug("read_pointer = 0x%.8x, write_pointer= = 0x%.8x,"
512 "last_buffer_operation == read = %d, packet length = %d",
515 if ((read_pointer < write_pointer) ||
520
521 if (final_space >= length) {
522 log_debug("Packet fits in final space of %d", final_space);
523
525 write_pointer += length;
529 }
530 return true;
531 } else {
534 if (total_space < length) {
535 log_debug("Not enough space (%d bytes)", total_space);
536 return false;
537 }
538
539 log_debug("Copying first %d bytes to final space of %d",
540 length, final_space);
544
545 uint32_t final_len = length - final_space;
546 log_debug("Copying remaining %d bytes", final_len);
552 }
553 return true;
554 }
555 } else if (write_pointer < read_pointer) {
558 if (middle_space < length) {
559 log_debug("Not enough space in middle (%d bytes)", middle_space);
560 return false;
561 }
562
563 log_debug("Packet fits in middle space of %d", middle_space);
565 write_pointer += length;
569 }
570 return true;
571 }
572
573 log_debug("Buffer already full");
574 return false;
575}
576
586static inline void process_16_bit_packets(
588 uint32_t pkt_count,
591 log_debug("process_16_bit_packets");
592 log_debug("event_pointer: %08x", (uint32_t) event_pointer);
593 log_debug("count: %d", pkt_count);
594 log_debug("pkt_prefix: %08x", pkt_key_prefix);
595 log_debug("pkt_payload_prefix: %08x", pkt_payload_prefix);
596 log_debug("payload on: %d", pkt_has_payload);
597 log_debug("pkt_format: %d", pkt_prefix_upper);
598
599 for (uint32_t i = 0; i < pkt_count; i++) {
601 log_debug("Packet key = %d", key);
603 uint32_t payload = 0;
604 if (pkt_has_payload) {
605 payload = (uint32_t) event_pointer[0];
607 }
608
609 if (!pkt_prefix_upper) {
610 key <<= 16;
611 }
612 key |= pkt_key_prefix;
613 payload |= pkt_payload_prefix;
614
615 log_debug("check before send packet: check_key_in_space=%d, key=0x%08x,"
616 " mask=0x%08x, key_space=%d: %d",
618 (!check_key_in_space || (key & mask) == key_space));
619
620 if (has_key) {
621 if (!check_key_in_space || (key & mask) == key_space) {
624 log_debug("mc packet 16-bit key=%d, payload=%d",
625 key, payload);
626 while (!spin1_send_mc_packet(key, payload, WITH_PAYLOAD)) {
627 spin1_delay_us(1);
628 }
629 } else {
630 log_debug("mc packet 16-bit key=%d", key);
631 while (!spin1_send_mc_packet(key, 0, NO_PAYLOAD)) {
632 spin1_delay_us(1);
633 }
634 }
635 } else {
637 }
638 }
639 }
640}
641
650static inline void process_32_bit_packets(
651 const uint16_t* event_pointer, uint32_t pkt_count,
654 // Careful! event_pointer is not necessarily word aligned!
655 log_debug("process_32_bit_packets");
656 log_debug("event_pointer: %08x", (uint32_t) event_pointer);
657 log_debug("count: %d", pkt_count);
658 log_debug("pkt_prefix: %08x", pkt_key_prefix);
659 log_debug("pkt_payload_prefix: %08x", pkt_payload_prefix);
660 log_debug("payload on: %d", pkt_has_payload);
661
662 for (uint32_t i = 0; i < pkt_count; i++) {
663 uint32_t key = (event_pointer[1] << 16) | event_pointer[0];
664 log_debug("Packet key = 0x%08x", key);
665 event_pointer += 2;
666 uint32_t payload = 0;
667 if (pkt_has_payload) {
668 payload = (event_pointer[1] << 16) | event_pointer[0];
669 event_pointer += 2;
670 }
671
672 key |= pkt_key_prefix;
673 payload |= pkt_payload_prefix;
674
675 log_debug("check before send packet: %d",
676 (!check_key_in_space || (key & mask) == key_space));
677
678 if (has_key) {
679 if (!check_key_in_space || (key & mask) == key_space) {
682 log_debug("mc packet 32-bit key=0x%08x, payload=0x%08x",
683 key, payload);
684 while (!spin1_send_mc_packet(key, payload, WITH_PAYLOAD)) {
685 spin1_delay_us(1);
686 }
687 } else {
688 log_debug("mc packet 32-bit key=0x%08x", key);
689 while (!spin1_send_mc_packet(key, 0, NO_PAYLOAD)) {
690 spin1_delay_us(1);
691 }
692 }
693 } else {
695 }
696 }
697 }
698}
699
703static inline void record_packet(
704 const eieio_msg_t eieio_msg_ptr, uint32_t length) {
705 if (recording_flags > 0) {
706
707 // Ensure that the recorded data size is a multiple of 4
708 uint32_t recording_length = 4 * ((length + 3) / 4);
709 log_debug("recording a EIEIO message with length %u",
714
715 // NOTE: recording_length could be bigger than the length of the valid
716 // data in eieio_msg_ptr. This is OK as the data pointed to by
717 // eieio_msg_ptr is always big enough to have extra space in it. The
718 // bytes in this data will be random, but are also ignored by
719 // whatever reads the data.
721 }
722}
723
732static inline bool eieio_data_parse_packet(
733 const eieio_msg_t eieio_msg_ptr, uint32_t length) {
734 log_debug("eieio_data_process_data_packet");
736
738 const void *event_pointer = (const void *) &eieio_msg_ptr[1];
739
740 if (data_hdr_value == 0) {
741 // Count is 0, so no data
742 return true;
743 }
744
745 log_debug("====================================");
746 log_debug("eieio_msg_ptr: %08x", (uint32_t) eieio_msg_ptr);
747 log_debug("event_pointer: %08x", (uint32_t) event_pointer);
749
757 uint8_t pkt_count = (uint8_t) BITS(data_hdr_value, COUNT, 0xFF);
758 bool pkt_has_payload = (bool) (pkt_type & 0x1);
759 bool pkt_is_32bit = (bool) (pkt_type & 0x2);
760
763
764 log_debug("data_hdr_value: %04x", data_hdr_value);
765 log_debug("pkt_apply_prefix: %d", pkt_apply_prefix);
766 log_debug("pkt_format: %d", pkt_prefix_upper);
767 log_debug("pkt_payload_prefix: %d", pkt_payload_apply_prefix);
768 log_debug("pkt_timestamp: %d", pkt_payload_is_timestamp);
769 log_debug("pkt_type: %d", pkt_type);
770 log_debug("pkt_count: %d", pkt_count);
771 log_debug("payload_on: %d", pkt_has_payload);
772
773 const uint16_t *hdr_pointer = (const uint16_t *) event_pointer;
774
775 if (pkt_apply_prefix) {
776 // Key prefix in the packet
778 hdr_pointer++;
779
780 // If the prefix is in the upper part, shift the prefix
781 if (pkt_prefix_upper) {
782 pkt_key_prefix <<= 16;
783 }
784 } else if (!pkt_apply_prefix && apply_prefix) {
785 // If there isn't a key prefix, but the config applies a prefix,
786 // apply the prefix depending on the key_left_shift
788 if (prefix_type == PREFIX_TYPE_UPPER_HALF_WORD) {
789 pkt_prefix_upper = true;
790 } else {
791 pkt_prefix_upper = false;
792 }
793 }
794
796 if (!pkt_is_32bit) {
797 // If there is a payload prefix and the payload is 16-bit
799 hdr_pointer++;
800 } else {
801 // If there is a payload prefix and the payload is 32-bit
803 ((uint32_t) hdr_pointer[1] << 16) | hdr_pointer[0];
804 hdr_pointer += 2;
805 }
806 }
807
808 // Take the event pointer to start at the header pointer
809 event_pointer = (const void *) hdr_pointer;
810
811 // If the packet has a payload that is a timestamp, but the timestamp
812 // is not the current time, buffer it
815 if (pkt_payload_prefix > time) {
817 return true;
818 }
820 return false;
821 }
822
823 if (!pkt_is_32bit) {
827 } else {
829 event_pointer, pkt_count, pkt_key_prefix,
831 }
833 return true;
834}
835
841 log_debug("Stopping packet requests - parse_stop_packet_reqs");
842 send_packet_reqs = false;
844}
845
851 log_debug("Starting packet requests - parse_start_packet_reqs");
852 send_packet_reqs = true;
853}
854
859 const eieio_msg_t eieio_msg_ptr, uint16_t length) {
866
867 if (region_id != BUFFER_REGION) {
868 log_debug("received sequenced eieio packet with invalid region ID:"
869 " %d.", region_id);
872 }
873
874 log_debug("Received packet sequence number: %d", sequence_value);
875
877 // parse_event_pkt returns false in case there is an error and the
878 // packet is dropped (i.e. as it was never received)
879 log_debug("add_eieio_packet_to_sdram");
881 eieio_content_pkt, length - 4);
882 log_debug("add_eieio_packet_to_sdram return value: %d", ret_value);
883
884 if (ret_value) {
886 log_debug("Updating last sequence seen to %d",
888 } else {
889 log_debug("unable to buffer sequenced data packet.");
892 }
893 }
894}
895
901 const eieio_msg_t eieio_msg_ptr, uint16_t length) {
904
905 switch (pkt_command) {
907 log_debug("command: HOST_SEND_SEQUENCED_DATA");
909 break;
911 log_debug("command: STOP_SENDING_REQUESTS");
913 break;
915 log_debug("command: START_SENDING_REQUESTS");
917 break;
919 log_debug("command: EVENT_STOP");
920 stopped = true;
922 break;
923 default:
924 return false;
925 }
926 return true;
927}
928
934static inline bool packet_handler_selector(
935 const eieio_msg_t eieio_msg_ptr, uint16_t length) {
936 log_debug("packet_handler_selector");
937
940
941 if (pkt_class == 0x01) {
942 log_debug("parsing a command packet");
944 } else {
945 log_debug("parsing an event packet");
947 }
948}
949
951static void fetch_and_process_packet(void) {
952 uint32_t last_len = 2;
953
954 log_debug("in fetch_and_process_packet");
955 msg_from_sdram_in_use = false;
956
957 // If we are not buffering, there is nothing to do
958 log_debug("buffer size is %d", buffer_region_size);
959 if (buffer_region_size == 0) {
960 return;
961 }
962
963 log_debug("dealing with SDRAM is set to %d", msg_from_sdram_in_use);
964 log_debug("has_eieio_packet_in_buffer set to %d",
967 (last_len > 0)) {
968 // If there is padding, move on 2 bytes
970 if (next_header == 0x4002) {
971 read_pointer += 2;
974 }
975 } else {
980
981 last_len = len;
982 if (len > MAX_PACKET_SIZE) {
983 log_error("Packet from SDRAM at 0x%08x of %u bytes is too big!",
984 src_ptr, len);
986 }
988
989 log_debug("packet with length %d, from address: %08x", len,
991
992 if (len > final_space) {
993 // If the packet is split, get the bits
994 log_debug("split packet");
995 log_debug("1 - reading packet to %08x from %08x length: %d",
998
1002 log_debug("2 - reading packet to %08x from %08x length: %d",
1004
1007 } else {
1008 // If the packet is whole, get the packet
1009 log_debug("full packet");
1010 log_debug("1 - reading packet to %08x from %08x length: %d",
1012
1014 read_pointer += len;
1017 }
1018 }
1019
1021
1024 log_debug("packet time: %d, current time: %d",
1026
1027 if (next_buffer_time <= time) {
1029 } else {
1030 msg_from_sdram_in_use = true;
1032 }
1033 }
1034 }
1035}
1036
1038static void send_buffer_request_pkt(void) {
1040 if ((space >= space_before_data_request) &&
1041 ((space != last_space) || (space == buffer_region_size))) {
1042 log_debug("sending request packet with space: %d and seq_no: %d at %u",
1044
1045 last_space = space;
1047 req_ptr->space_available = space;
1048 spin1_send_sdp_msg(&sdp_host_req, 1);
1049 req_ptr->sequence = 0;
1051 }
1052}
1053
1057static bool read_parameters(struct config *config) {
1058 // Get the configuration data
1060 prefix = config->prefix;
1065 mask = config->mask;
1072
1073 // There is no point in sending requests until there is space for
1074 // at least one packet
1077 }
1078
1079 // Set the initial values
1082 msg_from_sdram_in_use = false;
1083 next_buffer_time = 0;
1085 send_packet_reqs = true;
1087
1088 if (buffer_region_size != 0) {
1090 } else {
1092 }
1093
1094 // allocate a buffer size of the maximum SDP payload size
1095 msg_from_sdram = spin1_malloc(MAX_PACKET_SIZE);
1096 recorded_packet = spin1_malloc(sizeof(recorded_packet_t));
1097
1098 sdp_host_req.length = 8 + sizeof(req_packet_sdp_t);
1099 sdp_host_req.flags = 0x7;
1101 sdp_host_req.dest_port = 0xFF;
1109 req_ptr->_pad1 = 0;
1110 req_ptr->region = BUFFER_REGION & 0x0F;
1111
1112 log_info("apply_prefix: %d", apply_prefix);
1113 log_info("prefix: %d", prefix);
1114 log_info("prefix_type: %d", prefix_type);
1115 log_info("check_key_in_space: %d", check_key_in_space);
1116 log_info("key_space: 0x%08x", key_space);
1117 log_info("mask: 0x%08x", mask);
1118 log_info("space_before_read_request: %d", space_before_data_request);
1119 log_info("return_tag_id: %d", return_tag_id);
1120 log_info("return_tag_dest: 0x%08x", return_tag_dest);
1121 log_info("tx_offset: %d", tx_offset);
1122
1123 return true;
1124}
1125
1134
1135 log_info("buffer_region: 0x%.8x", buffer_region);
1136 log_info("buffer_region_size: %d", buffer_region_size);
1137 log_info("end_of_buffer_region: 0x%.8x", end_of_buffer_region);
1138
1139 return true;
1140}
1141
1144static bool initialise_recording(void) {
1148 RECORDING_REGION, ds_regions);
1149
1150 log_info("Recording starts at 0x%08x", recording_region);
1151
1153 log_info("Recording flags = 0x%08x", recording_flags);
1154 return success;
1155}
1156
1159static void provenance_callback(address_t address) {
1160 ripmcs_provenance_t *prov = (void *) address;
1161
1162 prov->received_packets = provenance.received_packets;
1163 prov->sent_packets = provenance.sent_packets;
1164 prov->incorrect_keys = provenance.incorrect_keys;
1165 prov->incorrect_packets = provenance.incorrect_packets;
1166 prov->late_packets = provenance.late_packets;
1167}
1168
1172static bool initialise(uint32_t *timer_period) {
1173 // Get the address this core's DTCM data starts at from SRAM
1176
1177 // Read the header
1179 return false;
1180 }
1181
1182 // Get the timing details and set up the simulation interface
1186 &infinite_run, &time, SDP_CALLBACK, DMA)) {
1187 return false;
1188 }
1192
1193 // Read the parameters
1194 if (!read_parameters(
1195 data_specification_get_region(CONFIGURATION, ds_regions))) {
1196 return false;
1197 }
1198
1199 // set up recording data structures
1200 if (!initialise_recording()) {
1201 return false;
1202 }
1203
1204 // Read the buffer region
1205 if (buffer_region_size > 0) {
1207 BUFFER_REGION, ds_regions))) {
1208 return false;
1209 }
1210 }
1211
1212 return true;
1213}
1214
1216static void resume_callback(void) {
1220 BUFFER_REGION, ds_regions));
1221
1222 // set the code to start sending packet requests again
1223 send_packet_reqs = true;
1224
1225 // magic state to allow the model to check for stuff in the SDRAM
1227
1228 // have fallen out of a resume mode, set up the functions to start
1229 // resuming again
1231
1232 stopped = false;
1233}
1234
1239 time++;
1240
1241 log_debug("timer_callback, final time: %d, current time: %d,"
1242 "next packet buffer time: %d",
1244
1246 // Enter pause and resume state to avoid another tick
1248
1249 // close recording channels
1250 if (recording_flags > 0) {
1252 }
1253 // clear the next buffer time
1254 next_buffer_time = 0;
1255 log_debug("Last time of stop notification request: %d",
1257
1259 return;
1260 }
1261
1262 if (send_packet_reqs &&
1266 }
1267
1268 if (!msg_from_sdram_in_use) {
1270 } else if (next_buffer_time < time) {
1273 } else if (next_buffer_time == time) {
1276 }
1277}
1278
1286 sdp_msg_t *msg = (sdp_msg_t *) mailbox;
1287 uint16_t length = msg->length;
1289
1291
1293
1294 // free the message to stop overload
1295 spin1_msg_free(msg);
1296}
1297
1299void c_main(void) {
1300 // Configure system
1301 uint32_t timer_period = 0;
1302 if (!initialise(&timer_period)) {
1304 return;
1305 }
1306
1307 // Set timer_callback
1309
1310 // Register callbacks
1313
1314 // Start the time at "-1" so that the first tick will be 0
1315 time = UINT32_MAX;
1317}
Definitions for the streaming-over-EIEIO buffering protocol.
buffered_operations
The different buffer operations.
@ BUFFER_OPERATION_READ
The last operation was a read.
@ BUFFER_OPERATION_WRITE
The last operation was a write.
@ STOP_SENDING_REQUESTS
Stop complaining that there is SDRAM free space for buffers.
@ SPINNAKER_REQUEST_BUFFERS
SpiNNaker requesting new buffers for spike source population.
@ SPINNAKER_REQUEST_READ_DATA
Buffers available to be read from a buffered out vertex.
@ HOST_SEND_SEQUENCED_DATA
Buffers being sent from host to SpiNNaker.
@ HOST_DATA_READ
Host confirming data being read form SpiNNaker memory.
@ EVENT_PADDING
Fill in buffer area with padding.
@ START_SENDING_REQUESTS
Start complaining that there is SDRAM free space for buffers.
@ EVENT_STOP_COMMANDS
End of all buffers, stop execution.
uint16_t * eieio_msg_t
pointer to an EIEIO message
#define MAX_SEQUENCE_NO
The maximum sequence number.
@ TIMER
The timer callback is highest priority.
@ DMA
DMA processing is lowest priority.
@ SYSTEM
The system data region ID.
@ PROVENANCE_REGION
Where to record provenance data. (Format: cs_provenance_t)
Data type definitions for SpiNNaker Neuron-modelling.
uint32_t * address_t
A generic pointer to a word.
Data Specification region access API.
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.
static void * data_specification_get_region(uint32_t region, data_specification_metadata_t *ds_regions)
Gets the address of a region.
The central structure that the DSE writes.
static uint32_t data[ITEMS_PER_DATA_PACKET]
static void initialise(void)
Sets up the application.
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.
eieio_prefix_types
The EIEIO prefix types.
Definition eieio.h:105
@ PACKET_CLASS
eieio_header_bitfields::packet_class
Definition eieio.h:36
@ COUNT
eieio_header_bitfields::count
Definition eieio.h:35
@ PAYLOAD_IS_TIMESTAMP
eieio_header_bitfields::payload_is_timestamp
Definition eieio.h:33
@ PACKET_COMMAND
eieio_header_bitfields::packet_command
Definition eieio.h:37
@ 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
@ KEY_16_BIT
Message is just a key, 16 bits long.
Definition eieio.h:95
@ KEY_32_BIT
Message is just a key, 32 bits long.
Definition eieio.h:99
@ KEY_PAYLOAD_32_bIT
Message is a key and a payload, each 32 bits long.
Definition eieio.h:101
@ KEY_PAYLOAD_16_BIT
Message is a key and a payload, each 16 bits long.
Definition eieio.h:97
static uint32_t packets_sent
The number of packets sent so far this timestamp.
static uint8_t event_size
The size of an individual event.
interface for recording data into "channels" on the SDRAM in a standard way, and storing buffers to b...
bool recording_initialize(void **recording_data_address, uint32_t *recording_flags)
initialises the recording of data
Definition recording.c:161
void recording_finalise(void)
Finishes recording - should only be called if recording_flags is not 0.
Definition recording.c:139
bool recording_record(channel_index_t channel, void *data, size_t size_bytes)
records some data into a specific recording channel.
Definition recording.c:105
void recording_reset(void)
resets recording to the state just after initialisation
Definition recording.c:212
region_ids
The memory regions.
static uint32_t prefix
The prefix to apply.
static uint8_t pkt_last_sequence_seen
Most recently seen message sequence number.
uint8_t sequence
What sequence number we expect.
static uint8_t * write_pointer
Points to next byte to write in buffer_region.
static bool apply_prefix
If a prefix should be applied.
#define BITS(value, shift, mask)
Extract a field from a bitfield value.
static bool initialise_recording(void)
Initialises the recording parts of the model.
#define TICKS_BETWEEN_REQUESTS
the amount of ticks to wait between requests
static bool setup_buffer_region(uint8_t *region_address)
Initialises the buffer region.
static uint32_t tx_offset
The timer offset to use for transmissions.
uint32_t time
The timestamp of this recording event.
static uint32_t simulation_ticks
The time that the simulation is scheduled to stop at.
uint32_t space_before_data_request
The point where we ask for the host to clear up space.
static void print_packet(const eieio_msg_t eieio_msg_ptr)
Dumps a message to IOBUF if debug messages are enabled.
uint8_t data[MAX_PACKET_SIZE]
The content of the packet.
static recorded_packet_t * recorded_packet
Buffer used for recording inbound packets.
uint32_t prefix_type
The type of prefix that is supplied.
uint16_t chip_id
What chip is making the request.
uint8_t region
What region is full.
static bool is_eieio_packet_in_buffer(void)
Whether we have a packet in the buffer.
uint32_t prefix
The prefix to apply.
static uint8_t * end_of_buffer_region
Points to the end of the buffer (to first byte that must not be written)
static uint32_t buffer_region_size
Size of buffer in buffer_region.
static void fetch_and_process_packet(void)
Process a stored packet.
static bool stopped
Whether this app has been asked to stop running.
static void eieio_command_parse_sequenced_data(const eieio_msg_t eieio_msg_ptr, uint16_t length)
Handle the command to store a request for later processing.
static uint32_t space_before_data_request
Threshold at which we ask for buffers to be cleared.
static uint32_t return_tag_dest
The SDP destination for sending messages to host.
uint32_t apply_prefix
Whether to always apply a prefix.
interrupt_priorities
human readable versions of the different priorities and usages.
uint16_t eieio_header_command
The command header.
static void send_buffer_request_pkt(void)
Sends a message saying what our state is.
static eieio_msg_t msg_from_sdram
DTCM buffer holding message copied from buffer_region.
static void record_packet(const eieio_msg_t eieio_msg_ptr, uint32_t length)
Asynchronously record an EIEIO message.
uint32_t key_space
The key space used for packet selection.
static uint8_t * buffer_region
Points to the buffer used to store data being collected to transfer out.
uint32_t buffer_region_size
The size of the buffer region.
uint32_t buffered_in_sdp_port
The SDP port that we buffer messages in on.
static sdp_msg_t sdp_host_req
An SDP message ready to send to host.
static buffered_operations last_buffer_operation
What the last operation done on buffer_region was.
static void process_16_bit_packets(const uint16_t *event_pointer, bool pkt_prefix_upper, uint32_t pkt_count, uint32_t pkt_key_prefix, uint32_t pkt_payload_prefix, bool pkt_has_payload, bool pkt_payload_is_timestamp)
Handle an SDP message containing 16 bit events. The events are converted into SpiNNaker multicast pac...
uint32_t incorrect_keys
Number of bad keys.
uint32_t mask
The mask used for packet selection.
static bool eieio_data_parse_packet(const eieio_msg_t eieio_msg_ptr, uint32_t length)
Parses an EIEIO message.
static bool eieio_commmand_parse_packet(const eieio_msg_t eieio_msg_ptr, uint16_t length)
Handle a command message.
static uint32_t key_space
Pattern of keys that must be matched when check_key_in_space is true.
static bool packet_handler_selector(const eieio_msg_t eieio_msg_ptr, uint16_t length)
Handle an EIEIO message, which can either be a command or an event description message.
static req_packet_sdp_t * req_ptr
Payload part of sdp_host_req.
static void sdp_packet_callback(uint mailbox, uint port)
Handles an incoming SDP message.
static bool check_key_in_space
Whether only packets with keys in the masked key space should be sent.
#define MIN_BUFFER_SPACE
the minimum space required for a buffer to work
uint32_t length
The real length of recorded_packet_t::data.
#define MAX_PACKET_SIZE
the maximum size of a packet excluding header
uint32_t return_tag_dest
The SDP destination for sending messages to host.
static void eieio_command_parse_start_requests(const eieio_msg_t eieio_msg_ptr, uint16_t length)
Handle the command to start parsing requests.
uint8_t processor
What core is making the request.
static uint32_t last_stop_notification_request
DEBUG: time of last stop notification.
static void process_32_bit_packets(const uint16_t *event_pointer, uint32_t pkt_count, uint32_t pkt_key_prefix, uint32_t pkt_payload_prefix, bool pkt_has_payload, bool pkt_payload_is_timestamp)
Handle an SDP message containing 32 bit events. The events are converted into SpiNNaker multicast pac...
static uint32_t buffered_in_sdp_port
The SDP port that we buffer messages in on.
static uint32_t recording_flags
Keeps track of which types of recording should be done to this model.
uint32_t sent_packets
How many MC packets were sent.
static bool read_parameters(struct config *config)
Reads our configuration region.
static uint32_t infinite_run
True if the simulation will "run forever" (until user interrupt).
void c_main(void)
Entry point.
static int msg_from_sdram_length
Length of msg_from_sdram.
uint32_t return_tag_id
The SDP tag for sending messages to host.
static void timer_callback(uint unused0, uint unused1)
The fundamental operation loop for the application.
static void provenance_callback(address_t address)
Writes our provenance data into the provenance region.
uint32_t received_packets
How many EIEIO packets were received.
static bool has_key
Whether a key is present; nothing is sent if no key is present.
static uint16_t calculate_eieio_packet_command_size(const eieio_msg_t eieio_msg_ptr)
What is the size of a command message?
static uint16_t calculate_eieio_packet_size(eieio_msg_t eieio_msg_ptr)
What is the size of a message?
uint32_t space_available
How much space is available.
static uint32_t next_buffer_time
Simulation time associated with message in msg_from_sdram.
static bool add_eieio_packet_to_sdram(const eieio_msg_t eieio_msg_ptr, uint32_t length)
Places a packet into the buffer.
static uint16_t calculate_eieio_packet_event_size(const eieio_msg_t eieio_msg_ptr)
What is the size of an event message?
static uint32_t last_request_tick
Last (sim) time we forced the buffers clear from timer_callback()
static uint32_t last_space
Last value of result of get_sdram_buffer_space_available() in send_buffer_request_pkt()
#define SPIKE_HISTORY_CHANNEL
The recording channel used to track the history of what spikes were sent.
uint32_t has_key
Whether a key is provided.
static bool msg_from_sdram_in_use
Does msg_from_sdram currently contain a message being processed?
static uint8_t return_tag_id
The SDP tag for sending messages to host.
static bool send_packet_reqs
Whether request packets should be sent.
uint32_t incorrect_packets
Number of bad packets (in non-debug mode)
static uint32_t mask
Mask for keys to determine if the key matches the key_space.
static eieio_prefix_types prefix_type
How to apply the prefix.
static void eieio_command_parse_stop_requests(const eieio_msg_t eieio_msg_ptr, uint16_t length)
Handle the command to stop parsing requests.
uint32_t tx_offset
The timer offset to use for transmissions.
static uint32_t time
Current simulation time.
static uint32_t get_sdram_buffer_space_available(void)
Computes how much space is available in the buffer.
static uint8_t * read_pointer
Points to next byte to read in buffer_region.
static void signal_software_error(const eieio_msg_t eieio_msg_ptr, uint16_t length)
Flags up that bad input was received.
static void print_packet_bytes(eieio_msg_t eieio_msg_ptr, uint16_t length)
Dumps a message to IOBUF if debug messages are enabled.
static uint32_t extract_time_from_eieio_msg(const eieio_msg_t eieio_msg_ptr)
Get the time from a message.
static void resume_callback(void)
Reinitialises the application after it was paused.
static ripmcs_provenance_t provenance
The provenance information that we're collecting.
uint32_t late_packets
Number of packets dropped for being late.
uint32_t check_keys
Whether only packets with keys in the masked key space should be sent.
The configuration parameters for the application.
What information is recorded about a packet.
An EIEIO request-for-more-space message.
The provenance data items.
uchar dest_port
ushort cmd_rc
void io_printf(char *stream, char *format,...)
uchar srce_port
RTE_SWERR
#define IO_BUF
ushort length
void rt_error(uint code,...)
ushort dest_addr
ushort srce_addr
uchar flags
static struct simulation_provenance * prov
the region ID for storing provenance data from the chip
Definition simulation.c:58
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
bool simulation_sdp_callback_on(uint sdp_port, callback_t sdp_callback)
Registers an additional SDP callback on a given SDP port. This is required when using simulation_regi...
Definition simulation.c:323
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
TIMER_TICK
void spin1_set_timer_tick_and_phase(uint time, uint phase)
void spin1_memcpy(void *dst, void const *src, uint len)
NO_PAYLOAD
WITH_PAYLOAD
uint spin1_get_chip_id(void)
uint spin1_get_core_id(void)
void spin1_callback_on(uint event_id, callback_t cback, int priority)
unsigned int uint
Wait for interrupt.