void read_parameters(address_t region_address) {
    log_info("Reading parameters from 0x%.8x", region_address);
    key = region_address[0];
    speed = region_address[1];
    sample_time = region_address[2];
    update_time = region_address[3];
    delay_time = region_address[4];
    delta_threshold = region_address[5];
    continue_if_not_different = region_address[6];

    // Allocate the space for the schedule
    counters = (uint32_t*) spin1_malloc(N_COUNTERS * sizeof(uint32_t));
    last_speed = (uint32_t*) spin1_malloc(N_COUNTERS * sizeof(uint32_t));

    for (uint32_t i = 0; i < N_COUNTERS; i++) {
        counters[i] = 0;
        last_speed[i] = 0;
    }

    log_info("Key = %d, speed = %d, sample_time = %d, update_time = %d,"
             " delay_time = %d, delta_threshold = %d,"
             " continue_if_not_different = %d",
             key, speed, sample_time, update_time, delay_time, delta_threshold,
             continue_if_not_different);
}
bool synaptic_current_data_filled (address_t address, uint32_t flags)
{
  use(flags);
  
  log_info("synaptic_current_data_filled: starting");
  
  // Loop through synapse types
  for(index_t s = 0; s < SYNAPSE_TYPE_COUNT; s++)
  {
    log_info("\tCopying %u synapse type %u parameters of size %u", num_neurons, s, sizeof(synapse_param_t));
    
    // Allocate block of memory for this synapse type's pre-calculated per-neuron decay
    neuron_synapse_params[s] = (synapse_param_t*) spin1_malloc(sizeof(synapse_param_t) * num_neurons);
    
    // Check for success
    if(neuron_synapse_params[s] == NULL)
    {
      sentinel("Cannot allocate neuron synapse decay parameters - Out of DTCM");
      return false;
    }
    
    log_info("\tCopying %u bytes to %u", num_neurons * sizeof(synapse_param_t), address + ((num_neurons * s * sizeof(synapse_param_t)) / 4));
    memcpy(neuron_synapse_params[s], address + ((num_neurons * s * sizeof(synapse_param_t)) / 4),
    		num_neurons * sizeof(synapse_param_t));
  }
  
  log_info("synaptic_current_data_filled: completed successfully");
  return true;
}
static inline void _mark_spike(uint32_t neuron_id, uint32_t n_spikes) {
    if (recording_flags > 0) {
        if (n_spike_buffers_allocated < n_spikes) {
            uint32_t new_size = 8 + (n_spikes * spike_buffer_size);
            timed_out_spikes *new_spikes = (timed_out_spikes *) spin1_malloc(
                new_size);
            if (new_spikes == NULL) {
                log_error("Cannot reallocate spike buffer");
                rt_error(RTE_SWERR);
            }
            uint32_t *data = (uint32_t *) new_spikes;
            for (uint32_t n = new_size >> 2; n > 0; n--) {
                data[n - 1] = 0;
            }
            if (spikes != NULL) {
                uint32_t old_size =
                    8 + (n_spike_buffers_allocated * spike_buffer_size);
                spin1_memcpy(new_spikes, spikes, old_size);
                sark_free(spikes);
            }
            spikes = new_spikes;
            n_spike_buffers_allocated = n_spikes;
        }
        if (spikes->n_buffers < n_spikes) {
            spikes->n_buffers = n_spikes;
        }
        for (uint32_t n = n_spikes; n > 0; n--) {
            bit_field_set(_out_spikes(n - 1), neuron_id);
        }
    }
param_generator_t param_generator_init(uint32_t hash, address_t *in_region) {

    // Look through the known generators
    for (uint32_t i = 0; i < N_PARAM_GENERATORS; i++) {

        // If the hash requested matches the hash of the generator, use it
        if (hash == param_generators[i].hash) {

            // Prepare a space for the data
            address_t region = *in_region;
            param_generator_t generator = spin1_malloc(
                sizeof(param_generator_t));
            if (generator == NULL) {
                log_error("Could not create generator");
                return NULL;
            }

            // Store the index
            generator->index = i;

            // Initialise the generator and store the data
            generator->data = param_generators[i].initialize(&region);
            *in_region = region;
            return generator;
        }
    }
    log_error("Param generator with hash %u not found", hash);
    return NULL;
}
//! \brief method for reading the parameters stored in Poisson parameter region
//! \param[in] address the absolute SDRAm memory address to which the
//!            Poisson parameter region starts.
//! \return a boolean which is True if the parameters were read successfully or
//!         False otherwise
static bool read_poisson_parameters(address_t address) {

    // Allocate DTCM for array of spike sources and copy block of data
    if (global_parameters.n_spike_sources > 0) {

        // the first time around, the array is set to NULL, afterwards,
        // assuming all goes well, there's an address here.
        if (poisson_parameters == NULL){
            poisson_parameters = (spike_source_t*) spin1_malloc(
                global_parameters.n_spike_sources * sizeof(spike_source_t));
        }

        // if failed to alloc memory, report and fail.
        if (poisson_parameters == NULL) {
            log_error("Failed to allocate poisson_parameters");
            return false;
        }


        // store spike source data into DTCM
        uint32_t spikes_offset = sizeof(global_parameters) / 4;
        spin1_memcpy(
            poisson_parameters, &address[spikes_offset],
            global_parameters.n_spike_sources * sizeof(spike_source_t));
    }
    log_info("read_poisson_parameters: completed successfully");
    return true;
}
Beispiel #6
0
bool synapses_initialise(address_t address, uint32_t n_neurons_value,
                         input_t **input_buffers_value,
                         uint32_t **ring_buffer_to_input_buffer_left_shifts) {

    log_info("synapses_initialise: starting");
    n_neurons = n_neurons_value;
    *input_buffers_value = input_buffers;

    // Set the initial values to 0
    for (uint32_t i = 0; i < INPUT_BUFFER_SIZE; i++) {
        input_buffers[i] = 0;
    }
    for (uint32_t i = 0; i < RING_BUFFER_SIZE; i++) {
        ring_buffers[i] = 0;
    }

    // Get the synapse shaping data
    for (index_t synapse_index = 0; synapse_index < SYNAPSE_TYPE_COUNT;
            synapse_index++) {
        log_debug("\tCopying %u synapse type %u parameters of size %u",
                n_neurons, synapse_index, sizeof(synapse_param_t));

        // Allocate block of memory for this synapse type'synapse_index
        // pre-calculated per-neuron decay
        neuron_synapse_shaping_params[synapse_index] =
            (synapse_param_t *) spin1_malloc(
                sizeof(synapse_param_t) * n_neurons);

        // Check for success
        if (neuron_synapse_shaping_params[synapse_index] == NULL) {
            log_error("Cannot allocate neuron synapse parameters"
                      "- Out of DTCM");
            return false;
        }

        log_debug(
            "\tCopying %u bytes from %u", n_neurons * sizeof(synapse_param_t),
            address + ((n_neurons * synapse_index
                       * sizeof(synapse_param_t)) / 4));
        memcpy(neuron_synapse_shaping_params[synapse_index],
                address + ((n_neurons * synapse_index
                           * sizeof(synapse_param_t)) / 4),
                n_neurons * sizeof(synapse_param_t));
    }

    // Get the ring buffer left shifts
    uint32_t ring_buffer_input_left_shifts_base =
        ((n_neurons * SYNAPSE_TYPE_COUNT * sizeof(synapse_param_t)) / 4);
    for (index_t synapse_index = 0; synapse_index < SYNAPSE_TYPE_COUNT;
           synapse_index++) {
        ring_buffer_to_input_left_shifts[synapse_index] =
            address[ring_buffer_input_left_shifts_base + synapse_index];
    }
    *ring_buffer_to_input_buffer_left_shifts = ring_buffer_to_input_left_shifts;

    log_info("synapses_initialise: completed successfully");
    return true;
}
Beispiel #7
0
/****f* simple.c/app_init
*
* SUMMARY
*  This function is called at application start-up.
*  It's used to say hello, setup multicast routing table entries,
*  and initialise application variables.
*
* SYNOPSIS
*  void app_init ()
*
* SOURCE
*/
void app_init ()
{
  uint i;

  /* ------------------------------------------------------------------- */
  /* initialise routing entries                                          */
  /* ------------------------------------------------------------------- */
  /* set a MC routing table entry to send my packets back to me */

  spin1_set_mc_table_entry(coreID,                    // entry
                     coreID,                    // key
                     0xffffffff,                // mask
                     (uint) (1 << (coreID+6))   // route
                    );

  /* ------------------------------------------------------------------- */

  /* ------------------------------------------------------------------- */
  /* initialize the application processor resources                      */
  /* ------------------------------------------------------------------- */
  /* say hello */
  io_printf (IO_STD, "[core %d] -----------------------\n", coreID);
  spin1_delay_us (PRINT_DLY);
  io_printf (IO_STD, "[core %d] starting simulation\n", coreID);
  spin1_delay_us (PRINT_DLY);

  /* use a buffer in the middle of system RAM - avoid conflict with RTK */
  sysram_buffer = (uint *) (SPINN_SYSRAM_BASE + SPINN_SYSRAM_SIZE/2
                            + (coreID * BUFFER_SIZE * sizeof(uint)));
  /* use a buffer somewhere in SDRAM */
  sdram_buffer  = (uint *) (SPINN_SDRAM_BASE + SPINN_SDRAM_SIZE/8
                            + (coreID * BUFFER_SIZE * sizeof(uint)));

  /* allocate buffer in DTCM */
  if ((dtcm_buffer = (uint *) spin1_malloc(BUFFER_SIZE*sizeof(uint))) == 0)
  {
    test_DMA = FALSE;
    io_printf (IO_STD, "[core %d] error - cannot allocate dtcm buffer\n", coreID);
    spin1_delay_us (PRINT_DLY);
  }
  else
  {
    test_DMA = TRUE;
    /* initialize sections of DTCM, system RAM and SDRAM */
    for (i=0; i<BUFFER_SIZE; i++)
    {
      dtcm_buffer[i]   = i;
      sysram_buffer[i] = 0xa5a5a5a5;
      sdram_buffer[i]  = 0x5a5a5a5a;
    }
    io_printf (IO_STD, "[core %d] dtcm buffer @ 0x%8z\n", coreID,
               (uint) dtcm_buffer);
    spin1_delay_us (PRINT_DLY);
  }
  /* ------------------------------------------------------------------- */
}
//! \brief initialise the recording of spikes
//! \param[in] max_spike_sources the number of spike sources to be recorded
//! \return True if the initialisation was successful, false otherwise
bool out_spikes_initialize(size_t max_spike_sources) {
    out_spikes_size = get_bit_field_size(max_spike_sources);
    log_debug("Out spike size is %u words, allowing %u spike sources",
              out_spikes_size, max_spike_sources);
    spikes = (timed_out_spikes *) spin1_malloc(
        sizeof(timed_out_spikes) + (out_spikes_size * sizeof(uint32_t)));
    if (spikes == NULL) {
        log_error("Out of DTCM when allocating out_spikes");
        return false;
    }
    out_spikes = &(spikes->out_spikes[0]);
    out_spikes_reset();
    return true;
}
neuron_pointer_t create_izh_neuron(  REAL A, REAL B, REAL C, REAL D, REAL V, REAL U, REAL I )
{
	neuron_pointer_t neuron = spin1_malloc( sizeof( neuron_t ) );

	neuron->A = A;  io_printf( WHERE_TO, "\nA = %11.4k \n", neuron->A );
	neuron->B = B;  io_printf( WHERE_TO, "B = %11.4k \n", neuron->B );
	neuron->C = C;  io_printf( WHERE_TO, "C = %11.4k mV\n", neuron->C );
	neuron->D = D;  io_printf( WHERE_TO, "D = %11.4k ??\n\n", neuron->D );

	neuron->V = V;  io_printf( WHERE_TO, "V = %11.4k mV\n", neuron->V );
	neuron->U = U;  io_printf( WHERE_TO, "U = %11.4k ??\n\n", neuron->U );

	neuron->I_offset = I;  io_printf( WHERE_TO, "I = %11.4k nA?\n", neuron->I_offset );

	neuron->this_h = machine_timestep * REAL_CONST(1.001);  io_printf( WHERE_TO, "h = %11.4k ms\n", neuron->this_h );

	return neuron;
}
Beispiel #10
0
void configure_model()
{
    // Initialize spike queue
    delay_us = ((neuron_t *)population->neuron)[0].delay;
    spike_ring = (spike_ring_t*)spin1_malloc((3+SPIKE_QUEUE_SIZE)*sizeof(uint));
    if (spike_ring == NULL) {
      io_printf(IO_STD, "DendriticDelay: Impossible to allocate memory for the event ring\n");
      while(1) ;
    }
    spike_ring->ring_start = 0;
    spike_ring->ring_end = 0;
    spike_ring->ring_empty = 1;

    missed_events = 0;
    events_received = 0;
    events_sent = 0;

    io_printf(IO_STD, "Running DendriticDelay model with delay %u...\n", delay_us);
}
Beispiel #11
0
void configure_recording_space()
{
    record_v = (short *) 0x72136400 + 0x200000 * (app_data.virtual_core_id - 1);
    record_i = (short *) 0x7309a400 + 0x200000 * (app_data.virtual_core_id - 1);

    // cleaning
    for (uint i = 0; i < 0x100000; i++)    record_v[i] = 0;
    for (uint i = 0; i < 0x100000; i++)    record_i[i] = 0;

    record_spikes = (uint *) 0x72040000;
    for(uint i = 0; i < 1000; i++) record_spikes[i] = 0; //TODO improve

    // spike count

    int *spike_count_dest = NULL;
    spike_count_dest = (int *) spin1_malloc(num_populations);
    spike_count =  (int *) spike_count_dest;
    for(uint i = 0; i < num_populations; i++) spike_count[i] = 0; //TODO improve
}
/**
 *! \brief Read the data for the generator
 *! \param[in] delay_params_address The address of the delay extension
 *!                                 parameters
 *! \param[in] params_address The address of the expander parameters
 *! \return True if the expander finished correctly, False if there was an
 *!         error
 */
bool read_sdram_data(
        address_t delay_params_address, address_t params_address) {

    // Read the global parameters from the delay extension
    uint32_t num_neurons = delay_params_address[N_ATOMS];
    uint32_t neuron_bit_field_words = get_bit_field_size(num_neurons);
    uint32_t n_stages = delay_params_address[N_DELAY_STAGES];

    // Set up the bit fields
    bit_field_t *neuron_delay_stage_config = (bit_field_t*) spin1_malloc(
        n_stages * sizeof(bit_field_t));
    for (uint32_t d = 0; d < n_stages; d++) {
        neuron_delay_stage_config[d] = (bit_field_t)
            &(delay_params_address[DELAY_BLOCKS])
            + (d * neuron_bit_field_words);
        clear_bit_field(neuron_delay_stage_config[d], neuron_bit_field_words);
    }

    // Read the global parameters from the expander region
    uint32_t n_out_edges = *params_address++;
    uint32_t pre_slice_start = *params_address++;
    uint32_t pre_slice_count = *params_address++;

    log_debug("Generating %u delay edges for %u atoms starting at %u",
        n_out_edges, pre_slice_count, pre_slice_start);

    // Go through each connector and make the delay data
    for (uint32_t edge = 0; edge < n_out_edges; edge++) {
        if (!read_delay_builder_region(
                &params_address, neuron_delay_stage_config,
                pre_slice_start, pre_slice_count)) {
            return false;
        }
    }

    return true;
}
Beispiel #13
0
//! \brief Set up the neuron models
//! \param[in] address the absolute address in SDRAM for the start of the
//!            NEURON_PARAMS data region in SDRAM
//! \param[in] recording_flags_param the recordings parameters
//!            (contains which regions are active and how big they are)
//! \param[out] n_neurons_value The number of neurons this model is to emulate
//! \return True is the initialisation was successful, otherwise False
bool neuron_initialise(address_t address, uint32_t recording_flags_param,
        uint32_t *n_neurons_value, uint32_t *incoming_spike_buffer_size) {
    log_info("neuron_initialise: starting");

    // Check if there is a key to use
    use_key = address[HAS_KEY];

    // Read the spike key to use
    key = address[TRANSMISSION_KEY];

    // output if this model is expecting to transmit
    if (!use_key){
        log_info("\tThis model is not expecting to transmit as it has no key");
    }
    else{
        log_info("\tThis model is expected to transmit with key = %08x", key);
    }

    // Read the neuron details
    n_neurons = address[N_NEURONS_TO_SIMULATE];
    *n_neurons_value = n_neurons;

    // Read the size of the incoming spike buffer to use
    *incoming_spike_buffer_size = address[INCOMING_SPIKE_BUFFER_SIZE];

    uint32_t next = START_OF_GLOBAL_PARAMETERS;

    // Read the global parameter details
    if (sizeof(global_neuron_params_t) > 0) {
        global_parameters = (global_neuron_params_t *) spin1_malloc(
            sizeof(global_neuron_params_t));
        if (global_parameters == NULL) {
            log_error("Unable to allocate global neuron parameters"
                      "- Out of DTCM");
            return false;
        }
        memcpy(global_parameters, &address[next],
               sizeof(global_neuron_params_t));
        next += sizeof(global_neuron_params_t) / 4;
    }

    log_info(
        "\t neurons = %u, spike buffer size = %u, params size = %u,"
        "input type size = %u, threshold size = %u", n_neurons,
        *incoming_spike_buffer_size, sizeof(neuron_t),
        sizeof(input_type_t), sizeof(threshold_type_t));

    // Allocate DTCM for neuron array and copy block of data
    if (sizeof(neuron_t) != 0) {
        neuron_array = (neuron_t *) spin1_malloc(n_neurons * sizeof(neuron_t));
        if (neuron_array == NULL) {
            log_error("Unable to allocate neuron array - Out of DTCM");
            return false;
        }
        memcpy(neuron_array, &address[next], n_neurons * sizeof(neuron_t));
        next += (n_neurons * sizeof(neuron_t)) / 4;
    }

    // Allocate DTCM for input type array and copy block of data
    if (sizeof(input_type_t) != 0) {
        input_type_array = (input_type_t *) spin1_malloc(
            n_neurons * sizeof(input_type_t));
        if (input_type_array == NULL) {
            log_error("Unable to allocate input type array - Out of DTCM");
            return false;
        }
        memcpy(input_type_array, &address[next],
               n_neurons * sizeof(input_type_t));
        next += (n_neurons * sizeof(input_type_t)) / 4;
    }

    // Allocate DTCM for additional input array and copy block of data
    if (sizeof(additional_input_t) != 0) {
        additional_input_array = (additional_input_pointer_t) spin1_malloc(
            n_neurons * sizeof(additional_input_t));
        if (additional_input_array == NULL) {
            log_error("Unable to allocate additional input array"
                      " - Out of DTCM");
            return false;
        }
        memcpy(additional_input_array, &address[next],
               n_neurons * sizeof(additional_input_t));
        next += (n_neurons * sizeof(additional_input_t)) / 4;
    }

    // Allocate DTCM for threshold type array and copy block of data
    if (sizeof(threshold_type_t) != 0) {
        threshold_type_array = (threshold_type_t *) spin1_malloc(
            n_neurons * sizeof(threshold_type_t));
        if (threshold_type_array == NULL) {
            log_error("Unable to allocate threshold type array - Out of DTCM");
            return false;
        }
        memcpy(threshold_type_array, &address[next],
               n_neurons * sizeof(threshold_type_t));
    }

    // Set up the out spikes array
    if (!out_spikes_initialize(n_neurons)) {
        return false;
    }

    // Set up the neuron model
    neuron_model_set_global_neuron_params(global_parameters);

    recording_flags = recording_flags_param;

    voltages_size = sizeof(uint32_t) + sizeof(state_t) * n_neurons;
    voltages = (timed_state_t *) spin1_malloc(voltages_size);
    input_size = sizeof(uint32_t) + sizeof(input_struct_t) * n_neurons;
    inputs = (timed_input_t *) spin1_malloc(input_size);

    _print_neuron_parameters();

    return true;
}
void c_main(void) {
  // Set the system up
  io_printf(IO_BUF, "[Ensemble] C_MAIN\n");
  address_t address = system_load_sram();
  if (!data_system(region_start(1, address))) {
    io_printf(IO_BUF, "[Ensemble] Failed to start.\n");
    return;
  }

  // Get data
  data_get_bias(region_start(2, address), g_ensemble.n_neurons);
  data_get_encoders(region_start(3, address), g_ensemble.n_neurons, g_input.n_dimensions);
  data_get_decoders(region_start(4, address), g_ensemble.n_neurons, g_n_output_dimensions);
  data_get_keys(region_start(5, address), g_n_output_dimensions);

  // Get the inhibitory gains
  g_ensemble.inhib_gain = spin1_malloc(g_ensemble.n_neurons * sizeof(value_t));
  if (g_ensemble.inhib_gain == NULL) {
    io_printf(IO_BUF, "[Ensemble] Failed to malloc inhib gains.\n");
    return;
  }
  spin1_memcpy(g_ensemble.inhib_gain, region_start(10, address),
               g_ensemble.n_neurons * sizeof(value_t));
  for (uint n = 0; n < g_ensemble.n_neurons; n++) {
    io_printf(IO_BUF, "Inhib gain[%d] = %k\n", n, g_ensemble.inhib_gain[n]);
  }

  // Load subcomponents
  if (!input_filter_get_filters(&g_input, region_start(6, address)) ||
      !input_filter_get_filter_routes(&g_input, region_start(7, address)) ||
      !input_filter_get_filters(&g_input_inhibitory, region_start(8, address)) ||
      !input_filter_get_filter_routes(&g_input_inhibitory, region_start(9, address)) ||
      !input_filter_get_filters(&g_input_modulatory, region_start(11, address)) ||
      !input_filter_get_filter_routes(&g_input_modulatory, region_start(12, address))) 
  {
    io_printf(IO_BUF, "[Ensemble] Failed to start.\n");
    return;
  }
  
  if(!get_pes(region_start(13, address)))
  {
    io_printf(IO_BUF, "[Ensemble] Failed to start.\n");
    return;
  }

  // Set up recording
  if (!record_buffer_initialise(&g_ensemble.recd, region_start(15, address),
                                simulation_ticks, g_ensemble.n_neurons)) {
    io_printf(IO_BUF, "[Ensemble] Failed to start.\n");
    return;
  }

  // Set up routing tables
  io_printf(IO_BUF, "[Ensemble] C_MAIN Configuring system.\n");
  if(leadAp){
    system_lead_app_configured();
  }

  // Setup timer tick, start
  io_printf(IO_BUF, "[Ensemble] C_MAIN Set timer and spin1_start.\n");
  spin1_set_timer_tick(g_ensemble.machine_timestep);
  spin1_start(SYNC_WAIT);
}
Beispiel #15
0
static bool read_parameters(address_t address) {

    log_info("read_parameters: starting");

    // changed from above for new file format 13-1-2014
    key = address[0];
    log_info("\tkey = %08x", key);

    num_neurons = address[1];
    neuron_bit_field_words = get_bit_field_size(num_neurons);

    num_delay_stages = address[2];
    uint32_t num_delay_slots = num_delay_stages * DELAY_STAGE_LENGTH;
    uint32_t num_delay_slots_pot = round_to_next_pot(num_delay_slots);
    num_delay_slots_mask = (num_delay_slots_pot - 1);

    log_info("\tparrot neurons = %u, neuron bit field words = %u,"
             " num delay stages = %u, num delay slots = %u (pot = %u),"
             " num delay slots mask = %08x",
             num_neurons, neuron_bit_field_words,
             num_delay_stages, num_delay_slots, num_delay_slots_pot,
             num_delay_slots_mask);

    // Create array containing a bitfield specifying whether each neuron should
    // emit spikes after each delay stage
    neuron_delay_stage_config = (bit_field_t*) spin1_malloc(
        num_delay_stages * sizeof(bit_field_t));

    // Loop through delay stages
    for (uint32_t d = 0; d < num_delay_stages; d++) {
        log_info("\tdelay stage %u", d);

        // Allocate bit-field
        neuron_delay_stage_config[d] = (bit_field_t) spin1_malloc(
            neuron_bit_field_words * sizeof(uint32_t));

        // Copy delay stage configuration bits into delay stage configuration bit-field
        address_t neuron_delay_stage_config_data_address =
            &address[3] + (d * neuron_bit_field_words);
        memcpy(neuron_delay_stage_config[d],
               neuron_delay_stage_config_data_address,
               neuron_bit_field_words * sizeof(uint32_t));

        for (uint32_t w = 0; w < neuron_bit_field_words; w++) {
            log_debug("\t\tdelay stage config word %u = %08x", w,
                      neuron_delay_stage_config[d][w]);
        }
    }

    // Allocate array of counters for each delay slot
    spike_counters = (uint8_t**) spin1_malloc(
        num_delay_slots_pot * sizeof(uint8_t*));

    for (uint32_t s = 0; s < num_delay_slots_pot; s++) {

        // Allocate an array of counters for each neuron and zero
        spike_counters[s] = (uint8_t*) spin1_malloc(
            num_neurons * sizeof(uint8_t));
        memset(spike_counters[s], 0, num_neurons * sizeof(uint8_t));
    }

    log_info("read_parameters: completed successfully");
    return true;
}