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.