32#define REPEAT_PER_NEURON 0xFFFFFFFF
34#define REPEAT_PER_NEURON_RECORDED 0x7FFFFFFF
40#define FLOOR_TO_2 0xFFFFFFFE
49static const uint32_t ADD[4][3] = {
56static inline uint32_t align_offset(uint32_t offset, uint32_t size) {
61 uint32_t size_mod = size & MOD_4;
65 return ADD[offset & MOD_4][size & MOD_4];
68typedef struct neuron_param_item {
75typedef struct neuron_param {
85typedef struct neuron_params_struct {
87 uint32_t bytes_per_repeat;
89 uint32_t n_repeats_total;
91 uint32_t struct_size_bytes;
100typedef struct sdram_variable_recording_data {
102 uint32_t n_recording;
103 uint32_t element_size;
107typedef struct sdram_bitfield_recording_data {
109 uint32_t n_recording;
113typedef struct recording_index {
114 uint32_t n_repeats:31;
115 uint32_t is_recording:1;
118typedef struct variable_recording {
120 uint32_t element_size;
121 uint32_t n_recording;
122 uint32_t n_index_items;
126typedef struct bitfield_recording {
128 uint32_t n_recording;
129 uint32_t n_index_items;
133typedef struct recording_params {
135 uint32_t n_recordable_variables;
137 uint32_t n_recordable_bit_fields;
141__attribute__((aligned(4)))
142typedef struct expander_config {
143 uint32_t neuron_params_region;
144 uint32_t neuron_recording_region;
170 void **neuron_params_region, uint32_t
n_neurons) {
178 uint32_t n_params =
config->n_params;
179 uint32_t bytes_per_repeat =
config->bytes_per_repeat;
180 uint32_t n_repeats_total =
config->n_repeats_total;
181 if (n_repeats_total == REPEAT_PER_NEURON) {
184 log_debug(
"Reading %u params, %u bytes per neuron, %u neurons, "
185 "%u bytes to end of struct", n_params, bytes_per_repeat,
186 n_repeats_total,
config->struct_size_bytes);
189 uint8_t* struct_ptr = *neuron_params_region;
190 *neuron_params_region = &(struct_ptr[bytes_per_repeat * n_repeats_total]);
193 uint32_t param_offset = 0;
197 for (uint32_t p = 0; p < n_params; p++) {
198 log_debug(
" Param %u, type=%u, n_items=%u", p, param->param_type,
202 type_info *writer = get_type_writer(param->param_type);
205 param_offset += align_offset(param_offset, writer->size);
206 log_debug(
" Writing %u bytes each time to struct offset %u",
207 writer->size, param_offset);
210 uint32_t n_items = param->n_items;
212 for (uint32_t i = 0; i < n_items; i++) {
214 log_debug(
" Item %u, generator=%u, n_repeats=%u",
215 i, item.generator, item.n_repeats);
222 uint32_t n_repeats = item.n_repeats;
223 if (n_repeats == REPEAT_PER_NEURON) {
225 log_debug(
" (Really only repeating %u times!)", n_repeats);
229 for (uint32_t r = 0; r < n_repeats; r++) {
231 uint32_t index = offset + param_offset;
232 log_debug(
" Writing %k to offset %u", value, index);
233 writer->writer(&(struct_ptr[index]), value);
234 offset += bytes_per_repeat;
242 param_offset += writer->size;
253 uint32_t
n_neurons, uint32_t n_neurons_max, uint32_t n_neurons_recording,
254 uint16_t *sdram_out) {
256 uint16_t indices[n_neurons_max];
257 uint32_t neuron_id = 0;
258 uint16_t next_index = 0;
259 for (uint32_t i = 0; i < n_items; i++) {
265 uint32_t n_repeats = item.n_repeats;
266 if (n_repeats == REPEAT_PER_NEURON_RECORDED) {
269 if (item.is_recording) {
270 for (uint32_t r = 0; r < n_repeats; r++) {
271 if (next_index >= n_neurons_recording) {
272 log_error(
"The next index %u >= the maximum %u", next_index,
273 n_neurons_recording);
276 indices[neuron_id++] = next_index++;
279 for (uint32_t r = 0; r < n_repeats; r++) {
280 indices[neuron_id++] = (uint16_t) n_neurons_recording;
286 uint32_t *index_words = (uint32_t *) &(indices[0]);
287 uint32_t *sdram_out_words = (uint32_t *) sdram_out;
288 for (uint32_t i = 0; i < (n_neurons_max >> 1); i++) {
289 sdram_out_words[i] = index_words[i];
293static void write_zero_index(uint32_t n_neurons_max, uint16_t *sdram_out) {
294 uint32_t *sdram_out_words = (uint32_t *) sdram_out;
295 for (uint32_t i = 0; i < (n_neurons_max >> 1); i++) {
296 sdram_out_words[i] = 0;
300static inline uint32_t get_n_recording(uint32_t n_recording, uint32_t
n_neurons) {
301 if (n_recording == REPEAT_PER_NEURON) {
307static void read_recorded_variable(
void **
region,
void **recording_region,
308 uint32_t
n_neurons, uint32_t n_neurons_max) {
311 uint32_t n_items = rec->n_index_items;
312 *
region = &(rec->index_items[n_items]);
316 *recording_region = &(sdram_out->indices[n_neurons_max]);
319 uint32_t rate = rec->rate;
320 uint32_t n_recording = get_n_recording(rec->n_recording,
n_neurons);
321 sdram_out->rate = rate;
322 sdram_out->element_size = rec->element_size;
323 sdram_out->n_recording = n_recording;
326 write_zero_index(n_neurons_max, &sdram_out->indices[0]);
328 read_index(n_items, &rec->index_items[0],
n_neurons, n_neurons_max,
329 n_recording, &sdram_out->indices[0]);
333static void read_recorded_bitfield(
void **
region,
void **recording_region,
334 uint32_t
n_neurons, uint32_t n_neurons_max) {
337 uint32_t n_items = rec->n_index_items;
338 *
region = &(rec->index_items[n_items]);
342 *recording_region = &(sdram_out->indices[n_neurons_max]);
345 uint32_t rate = rec->rate;
346 uint32_t n_recording = get_n_recording(rec->n_recording,
n_neurons);
347 sdram_out->rate = rate;
348 sdram_out->n_recording = n_recording;
351 write_zero_index(n_neurons_max, &sdram_out->indices[0]);
353 read_index(n_items, &rec->index_items[0],
n_neurons, n_neurons_max,
354 n_recording, &sdram_out->indices[0]);
366 void *params_address) {
369 expander_config_t *
config = spin1_malloc(
sizeof(expander_config_t));
374 void *neuron_params_region = data_specification_get_region(
375 config->neuron_params_region, ds_regions);
394 for (uint32_t s = 0; s <
config->n_structs; s++) {
404 config->neuron_recording_region, ds_regions);
407 uint32_t n_variables = recording_params->n_recordable_variables;
408 uint32_t n_bitfields = recording_params->n_recordable_bit_fields;
409 sdram_recording_params->n_recordable_variables = n_variables;
410 sdram_recording_params->n_recordable_bit_fields = n_bitfields;
413 address = &(recording_params[1]);
414 void *sdram_address = &(sdram_recording_params[1]);
420 for (uint32_t i = 0; i < n_variables; i++) {
421 read_recorded_variable(&address, &sdram_address,
n_neurons, n_neurons_max);
424 for (uint32_t i = 0; i < n_bitfields; i++) {
425 read_recorded_bitfield(&address, &sdram_address,
n_neurons, n_neurons_max);
441 log_info(
"Starting To Build Connectors");
452 void *params_address = data_specification_get_region(user1, ds_regions);
453 log_info(
"\tReading SDRAM at 0x%08x", params_address);
457 log_info(
"!!! Error reading SDRAM data !!!");
461 log_info(
"Finished On Machine Connectors!");
Utility functions for working with memory.
static void fast_memcpy(void *restrict to, const void *restrict from, size_t num_bytes)
A small and fast version of memcpy().
data_specification_metadata_t * data_specification_get_data_address(void)
void log_error(const char *message,...)
void log_debug(const char *message,...)
void log_info(const char *message,...)
static uint32_t n_neurons
The number of neurons on the core.
#define FLOOR_TO_2
When bitwise anded with a number will floor to the nearest multiple of 2.
rng_t * core_rng
An RNG that is local to the current core.
static bool run_neuron_expander(data_specification_metadata_t *ds_regions, void *params_address)
Read the data for the expander.
void c_main(void)
Entry point.
#define CEIL_TO_2
Add to a number before applying floor to 2 to turn it into a ceil operation.
rng_t * population_rng
An RNG that starts in the same place on every core of the Population.
static bool read_struct_builder_region(void **region, void **neuron_params_region, uint32_t n_neurons)
Generate the synapses for a single connector.
The configuration of a struct.
void param_generator_free(param_generator_t generator)
Finish with a parameter generator.
param_generator_t param_generator_init(uint32_t hash, void **in_region)
Initialise a specific parameter generator.
accum param_generator_generate(param_generator_t generator)
Generate value with a parameter generator.
Interface for parameter generator.
Random number generator interface.
The Random number generator parameters.
void sark_cpu_state(cpu_state state)
void rt_error(uint code,...)
region
spike source array region IDs in human readable form
A region of SDRAM used to transfer synapses.
uint spin1_get_core_id(void)
The type converters for parameter generation.