SpiNNFrontEndCommon  7.4.2
Common support code for user-facing front end systems.
recording.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 #include <recording.h>
24 #include <simulation.h>
25 #include <buffered_eieio_defs.h>
26 #include <sark.h>
27 #include <circular_buffer.h>
28 #include <spin1_api_params.h>
29 #include <debug.h>
30 #include <wfi.h>
31 
32 //---------------------------------------
33 // Structures
34 //---------------------------------------
38 typedef struct recording_channel_t {
39  uint8_t *start;
40  uint8_t *end;
41  uint8_t *write;
42  uint32_t space: 31;
43  uint32_t missing: 1;
45 
47 typedef struct recording_region_t {
49  uint32_t space;
51  uint32_t size:31;
53  uint32_t missing: 1;
55  uint8_t *data;
57 
59 typedef struct recording_regions_t {
61  uint32_t n_regions;
64 
66 
67 //---------------------------------------
68 // Globals
69 //---------------------------------------
70 
73 
76 
77 //---------------------------------------
81 static inline bool has_been_initialised(recording_channel_t *rec) {
82  return rec->start != NULL;
83 }
84 
85 //----------------------------------------
88 static inline void close_channel(recording_channel_t *rec) {
89  rec->start = NULL;
90 }
91 
96 static inline void copy_data(
97  void *restrict target, const void *source, uint n_words) {
98  uint *to = target;
99  const uint *from = source;
100  while (n_words-- > 0) {
101  *to++ = *from++;
102  }
103 }
104 
105 bool recording_record(uint8_t channel, void *data, uint32_t size_bytes) {
106  recording_channel_t *rec = &channels[channel];
107  if (has_been_initialised(rec)) {
108 
109  if (rec->space >= size_bytes) {
110  if ((((int) data & 0x3) != 0) || ((size_bytes & 0x3) != 0)) {
111  spin1_memcpy(rec->write, data, size_bytes);
112  } else {
113  copy_data(rec->write, data, size_bytes >> 2);
114  }
115  rec->space -= size_bytes;
116  rec->write += size_bytes;
117  return true;
118  }
119 
120  if (!rec->missing) {
121  log_warning("WARNING: recording channel %u out of space", channel);
122  rec->missing = 1;
123  }
124  }
125 
126  return false;
127 }
128 
129 __attribute__((noreturn))
133 void recording_bad_offset(void *data, uint32_t size) {
134  log_error("DMA transfer of non-word data quantity in recording! "
135  "(data=0x%08x, size=0x%x)", data, size);
136  rt_error(RTE_SWERR);
137 }
138 
139 void recording_finalise(void) {
140  log_debug("Finalising recording channels");
141 
142  // Loop through channels
143  for (uint32_t channel = 0; channel < regions->n_regions; channel++) {
144  recording_channel_t *rec = &channels[channel];
145  // If this channel's in use, copy things back to SDRAM
146  if (has_been_initialised(rec)) {
147  recording_region_t *reg = &regions->regions[channel];
148  log_info("Recording channel %u, start=0x%08x, end=0x%08x, write=0x%08x, space=%u",
149  channel, rec->start, rec->end, rec->write, rec->space);
150  reg->size = rec->write - rec->start;
151  reg->missing = rec->missing;
152  if (rec->missing) {
153  log_info("Recording channel %u - has missing data", channel);
154  }
155  log_info("Recording channel %u wrote %u bytes", channel, reg->size);
156  close_channel(rec);
157  }
158  }
159 }
160 
162  void **recording_data_address, uint32_t *recording_flags) {
163  // Get the parameters
164  regions = *recording_data_address;
165 
166  // Update the pointer to after the data
167  uint32_t n_regions = regions->n_regions;
168  *recording_data_address = &regions->regions[n_regions];
169 
170  // Set up the space for holding recording pointers and sizes
171  channels = spin1_malloc(n_regions * sizeof(recording_channel_t));
172  if (channels == NULL) {
173  log_error("Not enough space to allocate recording channels");
174  return false;
175  }
176 
177  // Set up the recording flags
178  if (recording_flags != NULL) {
179  *recording_flags = 0;
180  }
181 
182  /* Reserve the actual recording regions.
183  *
184  */
185  for (uint32_t i = 0; i < n_regions; i++) {
186  recording_region_t *region = &regions->regions[i];
187  uint32_t space = region->space;
188  if (space > 0) {
189  region->data = sark_xalloc(
190  sv->sdram_heap, space, 0,
191  ALLOC_LOCK + ALLOC_ID + (sark_vec->app_id << 8));
192  if (region->data == NULL) {
193  log_error("Could not allocate recording region %u of %u bytes,"
194  " available was %u bytes", i, space,
195  sark_heap_max(sv->sdram_heap, 0));
196  return false;
197  }
198  log_info("Allocated %u bytes for recording channel %u at 0x%08x",
199  space, i, region->data);
200  if (recording_flags != NULL) {
201  *recording_flags = (*recording_flags | (1 << i));
202  }
203  }
204  }
205 
206  // Set up the channels and write the initial state data
207  recording_reset();
208 
209  return true;
210 }
211 
212 void recording_reset(void) {
213  // Go through the regions and set up the data
214  for (uint32_t i = 0; i < regions->n_regions; i++) {
215  recording_region_t *region = &regions->regions[i];
216  recording_channel_t *channel = &channels[i];
217  uint32_t space = region->space;
218  if (space > 0) {
219  uint8_t *data = region->data;
220  channel->start = data;
221  channel->end = data + space;
222  channel->space = space;
223  channel->write = data;
224  channel->missing = 0;
225 
226  log_info("Recording channel %u configured to use %u byte memory block"
227  " starting at 0x%08x", i, channel->space, channel->start);
228  } else {
229  close_channel(channel);
230  log_info("Recording channel %u left uninitialised", i);
231  }
232  }
233 }
Definitions for the streaming-over-EIEIO buffering protocol.
static uint32_t recording_flags
General recording flags. (Unused by this code.)
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_warning(const char *message,...)
This function logs warnings.
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.
uint32_t space
The size of the region to record into.
Definition: recording.c:49
uint8_t * write
Where to write to next.
Definition: recording.c:41
recording_region_t regions[]
Item for each region.
Definition: recording.c:63
uint32_t size
The size of the region after recording.
Definition: recording.c:51
static bool has_been_initialised(recording_channel_t *rec)
checks that a channel has been initialised
Definition: recording.c:81
bool recording_initialize(void **recording_data_address, uint32_t *recording_flags)
initialises the recording of data
Definition: recording.c:161
static recording_regions_t * regions
The parameters of the recording.
Definition: recording.c:75
static recording_channel_t * channels
Array containing all possible channels.
Definition: recording.c:72
uint32_t missing
Flag indicating if recording missed data.
Definition: recording.c:43
void recording_finalise(void)
Finishes recording - should only be called if recording_flags is not 0.
Definition: recording.c:139
uint8_t * data
Pointer to the recorded data.
Definition: recording.c:55
uint32_t space
The space remaining in the channel.
Definition: recording.c:42
static void close_channel(recording_channel_t *rec)
closes a channel
Definition: recording.c:88
static void copy_data(void *restrict target, const void *source, uint n_words)
copy data in word-size chunks
Definition: recording.c:96
uint32_t missing
Flag indicating if any data is missing.
Definition: recording.c:53
uint8_t * end
One byte past the end of the buffer.
Definition: recording.c:40
uint32_t n_regions
The number of recording regions.
Definition: recording.c:61
bool recording_record(uint8_t channel, void *data, uint32_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
void recording_bad_offset(void *data, uint32_t size)
Stop the program because of a bad recording request.
Definition: recording.c:133
uint8_t * start
The first byte of the buffer.
Definition: recording.c:39
Structure that defines a channel in memory.
Definition: recording.c:38
Data for an individual region.
Definition: recording.c:47
header of general structure describing all recordings
Definition: recording.c:59
interface for recording data into "channels" on the SDRAM in a standard way, and storing buffers to b...
Simulation Functions Header File.
Wait for interrupt.