static inline void send(uint32_t direction, uint32_t speed) {
    uint32_t direction_key = direction | key;
    while (!spin1_send_mc_packet(direction_key, speed, WITH_PAYLOAD)) {
        spin1_delay_us(1);
    }
    if (delay_time > 0) {
        spin1_delay_us(delay_time);
    }
}
Example #2
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);
  }
  /* ------------------------------------------------------------------- */
}
/**
 * Restore the router's settings prior to ending the experiment.
 */
void
cleanup_router(void)
{
	// Only one core should restore the router config.
	if (leadAp) {
		// Restore router configuration (and reinitialise timers to clear deadlocks)
		rtr_unbuf[RTR_CONTROL] = rtr_control_orig_state | 1<<15;
		spin1_delay_us(10000);
		
		// Set the timer reset bit back to the original value again
		rtr_unbuf[RTR_CONTROL] = rtr_control_orig_state;
		spin1_delay_us(10000);
	}
}
Example #4
0
void filter_update(uint ticks, uint arg1) {
  use(arg1);
  if (simulation_ticks != UINT32_MAX && ticks >= simulation_ticks) {
    spin1_exit(0);
  }

  // Update the filters
  input_filter_step(&g_input, true);

  // Apply the transform to the input to get the output
  for (uint j = 0; j < g_filter.size_out; j++) {
    g_filter.output[j] = 0.0k;

    for (uint k = 0; k < g_filter.size_in; k++) {
      g_filter.output[j] += g_filter.transform[j*g_filter.size_in + k] *
                            g_filter.input[k];
    }
  }

  // Increment the counter and transmit if necessary
  delay_remaining--;
  if(delay_remaining == 0) {
    delay_remaining = g_filter.transmission_delay;

    uint val = 0x0000;
    for(uint d = 0; d < g_filter.size_out; d++) {
      val = bitsk(g_filter.output[d]);
      spin1_send_mc_packet(g_filter.keys[d], val, WITH_PAYLOAD);
      spin1_delay_us(g_filter.interpacket_pause);
    }
  }
}
Example #5
0
/****f* simple.c/app_done
*
* SUMMARY
*  This function is called at application exit.
*  It's used to report some statistics and say goodbye.
*
* SYNOPSIS
*  void app_done ()
*
* SOURCE
*/
void app_done ()
{
  /* skew io_printfs to avoid congesting tubotron */
  spin1_delay_us (200 * ((chipID << 5) + coreID));

  /* report simulation time */
  io_printf (IO_STD, "[core %d] simulation lasted %d ticks\n", coreID,
             spin1_get_simulation_time());
  spin1_delay_us (PRINT_DLY);

  /* report number of packets */
  io_printf (IO_STD, "[core %d] received %d packets\n", coreID, packets);
  spin1_delay_us (PRINT_DLY);

  /* report number of failed packets */
  io_printf (IO_STD, "[core %d] failed %d packets\n", coreID, pfailed);
  spin1_delay_us (PRINT_DLY);

  /* report number of failed user events*/
  io_printf (IO_STD, "[core %d] failed %d USER events\n", coreID, ufailed);
  spin1_delay_us (PRINT_DLY);

  /* report number of DMA transfers */
  io_printf (IO_STD, "[core %d] completed %d DMA transfers\n", coreID, transfers);
  spin1_delay_us (PRINT_DLY);

  /* report number of failed transfers */
  io_printf (IO_STD, "[core %d] failed %d DMA transfers\n", coreID, tfailed);
  spin1_delay_us (PRINT_DLY);
  if (tfailed)
  {
    io_printf (IO_STD, "\t%d : %d @ %d\n", tfvald, tfvals, tfaddr);
    spin1_delay_us (PRINT_DLY);
    io_printf (IO_STD, "\t%d : %d @ %d\n", dtcm_buffer[tfaddr],
               sdram_buffer[tfaddr], tfaddr);
    spin1_delay_us (PRINT_DLY);
  }

  /* say goodbye */
  io_printf (IO_STD, "[core %d] stopping simulation\n", coreID);
  spin1_delay_us (PRINT_DLY);
  io_printf (IO_STD, "[core %d] -----------------------\n", coreID);
}
void transmit_packet_region(uint* packets_region) {
  // Transmit each packet in turn
  mc_packet_t *packets = (mc_packet_t *) (&packets_region[1]);
  for (uint i = 0; i < packets_region[0]; i++) {
    spin1_send_mc_packet(packets[i].key, packets[i].payload,
                         packets[i].with_payload);
    io_printf(IO_BUF, "\tTime %d, Key 0x%08x, Payload 0x%08x\n",
              packets[i].timestamp, packets[i].key, packets[i].payload);
    spin1_delay_us(1);
  }
}
//! \brief handles spreading of Poisson spikes for even packet reception at
//! destination
//! \param[in] spike_key: the key to transmit
//! \return None
void _send_spike(uint spike_key, uint timer_count) {

    // Wait until the expected time to send
    while ((ticks == timer_count) && (tc[T1_COUNT] > expected_time)) {

        // Do Nothing
    }
    expected_time -= global_parameters.time_between_spikes;

    // Send the spike
    log_debug("Sending spike packet %x at %d\n", spike_key, time);
    while (!spin1_send_mc_packet(spike_key, 0, NO_PAYLOAD)) {
        spin1_delay_us(1);
    }
}
Example #8
0
//! \executes all the updates to neural parameters when a given timer period
//! has occurred.
//! \param[in] time the timer tick  value currently being executed
void neuron_do_timestep_update(timer_t time) {

    // update each neuron individually
    for (index_t neuron_index = 0; neuron_index < n_neurons; neuron_index++) {

        // Get the parameters for this neuron
        neuron_pointer_t neuron = &neuron_array[neuron_index];
        input_type_pointer_t input_type = &input_type_array[neuron_index];
        threshold_type_pointer_t threshold_type =
            &threshold_type_array[neuron_index];
        additional_input_pointer_t additional_input =
            &additional_input_array[neuron_index];
        state_t voltage = neuron_model_get_membrane_voltage(neuron);

        // If we should be recording potential, record this neuron parameter
        voltages->states[neuron_index] = voltage;

        // Get excitatory and inhibitory input from synapses and convert it
        // to current input
        input_t exc_input_value = input_type_get_input_value(
            synapse_types_get_excitatory_input(input_buffers, neuron_index),
            input_type);
        input_t inh_input_value = input_type_get_input_value(
            synapse_types_get_inhibitory_input(input_buffers, neuron_index),
            input_type);
        input_t exc_input = input_type_convert_excitatory_input_to_current(
            exc_input_value, input_type, voltage);
        input_t inh_input = input_type_convert_inhibitory_input_to_current(
            inh_input_value, input_type, voltage);

        // Get external bias from any source of intrinsic plasticity
        input_t external_bias =
            synapse_dynamics_get_intrinsic_bias(time, neuron_index) +
            additional_input_get_input_value_as_current(
                additional_input, voltage);

        // If we should be recording input, record the values
        inputs->inputs[neuron_index].exc = exc_input_value;
        inputs->inputs[neuron_index].inh = inh_input_value;

        // update neuron parameters
        state_t result = neuron_model_state_update(
            exc_input, inh_input, external_bias, neuron);

        //if ((time>=7000) && (time<=7500))
        //    if ((exc_input_value>0) || (inh_input_value>0))
        //        io_printf(IO_BUF,"%dms, voltage=%d    inh_input_value=%d\n", time, result, inh_input_value);
                //io_printf(IO_BUF,"%dms, voltage=%d    exc_input_value=%d    inh_input_value=%d\n", time, neuron_model_get_membrane_voltage(neuron), exc_input_value, inh_input_value);

        // determine if a spike should occur
        bool spike = threshold_type_is_above_threshold(result, threshold_type);

        // If the neuron has spiked
        if (spike) {
            log_debug("neuron %u spiked at time %u", neuron_index, time);

        //if ((time>5500) && (time<9000))
        //    io_printf(IO_BUF,"%dms, neuron spiked!\n", time);


            // Tell the neuron model
            neuron_model_has_spiked(neuron);

            // Tell the additional input
            additional_input_has_spiked(additional_input);

            // Do any required synapse processing
            synapse_dynamics_process_post_synaptic_event(time, neuron_index);

            // Record the spike
            out_spikes_set_spike(neuron_index);

            // Send the spike
            while (use_key &&
                   !spin1_send_mc_packet(key | neuron_index, 0, NO_PAYLOAD)) {
                spin1_delay_us(1);
            }
        } else {
            log_debug("the neuron %d has been determined to not spike",
                      neuron_index);
        }
    }

    // record neuron state (membrane potential) if needed
    if (recording_is_channel_enabled(recording_flags, V_RECORDING_CHANNEL)) {
        voltages->time = time;
        recording_record(V_RECORDING_CHANNEL, voltages, voltages_size);
    }

    // record neuron inputs if needed
    if (recording_is_channel_enabled(
            recording_flags, GSYN_RECORDING_CHANNEL)) {
        inputs->time = time;
        recording_record(GSYN_RECORDING_CHANNEL, inputs, input_size);
    }

    // do logging stuff if required
    out_spikes_print();
    _print_neurons();

    // Record any spikes this timestep
    if (recording_is_channel_enabled(
            recording_flags, SPIKE_RECORDING_CHANNEL)) {
        out_spikes_record(SPIKE_RECORDING_CHANNEL, time);
    }
    out_spikes_reset();
}
/**
 * Load the routing tables and router parameters as required by the current
 * experiment. The existing router parameters are stored into the
 * rtr_control_orig_state to be restored by cleanup_router at the end of the
 * experiment.
 */
void
setup_router(void)
{
	// Install the router entries
	for (int i = 0; i < config_root.num_router_entries; i++) {
		if (!spin1_set_mc_table_entry( i
		                             , config_router_entries[i].key
		                             , config_router_entries[i].mask
		                             , config_router_entries[i].route
		                             )) {
			io_printf( IO_BUF, "Could not load routing table entry %d with key 0x%08x"
			         , i
			         , config_router_entries[i].key
			         );
			config_root.completion_state = COMPLETION_STATE_FAILIURE;
		}
	}
	
	// Only one core should configure the router
	if (leadAp) {
		// Store the current router configuration
		rtr_control_orig_state = rtr_unbuf[RTR_CONTROL];
		
		// Set up the packet drop timeout
		rtr_unbuf[RTR_CONTROL] = (rtr_unbuf[RTR_CONTROL] & ~0x00FF8000u)
		                       | (config_root.rtr_drop_e<<4 | config_root.rtr_drop_m) << 16
		                       | 1<<15 // Re-initialise counters
		                       ;
		
		// Configure forwarded packets counter
		rtr_unbuf[FWD_CNTR_CFG] = (0x1<< 0) // Type = nn
		                        | (0x1<< 4) // ER = 0 (non-emergency-routed packets)
		                        | (  0<< 8) // M = 0 (match emergency flag on incoming packets)
		                        | (0x3<<10) // Def = Match default and non-default routed packets
		                        | (0x3<<12) // PL = Match packets with and without payloads
		                        | (0x3<<14) // Loc = Match local and external packets
		                        | ( (0x1F<<19) // Match all external links
		                          | (   0<<18) // Don't match monitor packets
		                          | (   1<<17) // Match packets to local non-monitor cores
		                          | (   0<<16) // Don't match dropped packets
		                          ) // Dest = Which destinations should be matched
		                        | (  0<<30) // E = Don't enable interrupt on event
		                        ;
		
		// Configure dropped packets counter
		rtr_unbuf[DRP_CNTR_CFG] = (0x1<< 0) // Type = nn
		                        | (0x1<< 4) // ER = 0 (non-emergency-routed packets)
		                        | (  0<< 8) // M = 0 (match emergency flag on incoming packets)
		                        | (0x3<<10) // Def = Match default and non-default routed packets
		                        | (0x3<<12) // PL = Match packets with and without payloads
		                        | (0x3<<14) // Loc = Match local and external packets
		                        | ( (0x00<<19) // Don't match external links
		                          | (   0<<18) // Don't match monitor packets
		                          | (   0<<17) // Don't match packets to local non-monitor cores
		                          | (   1<<16) // Match dropped packets
		                          ) // Dest = Which destinations should be matched
		                        | (  0<<30) // E = Don't enable interrupt on event
		                        ;
	}
	
	// Allow change to make it into the router
	spin1_delay_us(10000);
}
Example #10
0
//! \executes all the updates to neural parameters when a given timer period
//! has occurred.
//! \param[in] time the timer tic  value currently being executed
//! \return nothing
void neuron_do_timestep_update(timer_t time) {
    use(time);

    // update each neuron individually
    for (index_t neuron_index = 0; neuron_index < n_neurons; neuron_index++) {

        // Get the parameters for this neuron
        neuron_pointer_t neuron = &neuron_array[neuron_index];
        input_type_pointer_t input_type = &input_type_array[neuron_index];
        threshold_type_pointer_t threshold_type =
            &threshold_type_array[neuron_index];
        additional_input_pointer_t additional_input =
            &additional_input_array[neuron_index];
        state_t voltage = neuron_model_get_membrane_voltage(neuron);

        // If we should be recording potential, record this neuron parameter
        if (recording_is_channel_enabled(recording_flags,
                e_recording_channel_neuron_potential)) {
            recording_record(e_recording_channel_neuron_potential, &voltage,
                             sizeof(state_t));
        }

        // Get excitatory and inhibitory input from synapses and convert it
        // to current input
        input_t exc_input_value = input_type_get_input_value(
            synapse_types_get_excitatory_input(input_buffers, neuron_index),
            input_type);
        input_t inh_input_value = input_type_get_input_value(
            synapse_types_get_inhibitory_input(input_buffers, neuron_index),
            input_type);
        input_t exc_input = input_type_convert_excitatory_input_to_current(
            exc_input_value, input_type, voltage);
        input_t inh_input = input_type_convert_inhibitory_input_to_current(
            inh_input_value, input_type, voltage);

        // Get external bias from any source of intrinsic plasticity
        input_t external_bias =
            synapse_dynamics_get_intrinsic_bias(time, neuron_index) +
            additional_input_get_input_value_as_current(
                additional_input, voltage);

        // If we should be recording input, record the values
        if (recording_is_channel_enabled(recording_flags,
                e_recording_channel_neuron_gsyn)) {
            recording_record(e_recording_channel_neuron_gsyn,
                             &exc_input_value, sizeof(input_t));
            recording_record(e_recording_channel_neuron_gsyn,
                             &inh_input_value, sizeof(input_t));
        }

        // update neuron parameters
        state_t result = neuron_model_state_update(
            exc_input, inh_input, external_bias, neuron);

        // determine if a spike should occur
        bool spike = threshold_type_is_above_threshold(result, threshold_type);

        // If the neuron has spiked
        if (spike) {
            log_debug("the neuron %d has been determined to spike",
                      neuron_index);

            // Tell the neuron model
            neuron_model_has_spiked(neuron);

            // Tell the additional input
            additional_input_has_spiked(additional_input);

            // Do any required synapse processing
            synapse_dynamics_process_post_synaptic_event(time, neuron_index);

            // Record the spike
            out_spikes_set_spike(neuron_index);

            // Send the spike
            while (use_key &&
                   !spin1_send_mc_packet(key | neuron_index, 0, NO_PAYLOAD)) {
                spin1_delay_us(1);
            }
        } else {
            log_debug("the neuron %d has been determined to not spike",
                      neuron_index);
        }
    }

    // do logging stuff if required
    out_spikes_print();
    _print_neurons();

    // Record any spikes this timestep
    out_spikes_record(recording_flags);
    out_spikes_reset();
}
Example #11
0
void timer_callback(uint unused0, uint unused1) {
    use(unused0);
    use(unused1);

    time++;

    log_debug("Timer tick %u", time);

    // If a fixed number of simulation ticks are specified and these have passed
    if (simulation_ticks != UINT32_MAX && time >= simulation_ticks) {
        log_info("Simulation complete.\n");
        spin1_exit(0);
    }

    // Loop through delay stages
    for (uint32_t d = 0; d < num_delay_stages; d++) {

        // If any neurons emit spikes after this delay stage
        bit_field_t delay_stage_config = neuron_delay_stage_config[d];
        if (nonempty_bit_field(delay_stage_config, neuron_bit_field_words)) {

            // Get key mask for this delay stage and it's time slot
            uint32_t delay_stage_delay = (d + 1) * DELAY_STAGE_LENGTH;
            uint32_t delay_stage_time_slot =
                ((time - delay_stage_delay) & num_delay_slots_mask);
            uint8_t *delay_stage_spike_counters =
                spike_counters[delay_stage_time_slot];

            log_debug("Checking time slot %u for delay stage %u",
                      delay_stage_time_slot, d);

            // Loop through neurons
            for (uint32_t n = 0; n < num_neurons; n++) {

                // If this neuron emits a spike after this stage
                if (bit_field_test(delay_stage_config, n)) {

                    // Calculate key all spikes coming from this neuron will be
                    // sent with
                    uint32_t spike_key = ((d * num_neurons) + n) | key;

#if LOG_LEVEL >= LOG_DEBUG
                    if (delay_stage_spike_counters[n] > 0) {
                        log_debug("Neuron %u sending %u spikes after delay"
                                  "stage %u with key %x",
                                  n, delay_stage_spike_counters[n], d,
                                  spike_key);
                    }
#endif  // DEBUG

                    // Loop through counted spikes and send
                    for (uint32_t s = 0; s < delay_stage_spike_counters[n];
                            s++) {
                        while (!spin1_send_mc_packet(spike_key, 0,
                                                     NO_PAYLOAD)) {
                            spin1_delay_us(1);
                        }
                    }
                }
            }
        }
    }

    // Zero all counters in current time slot
    uint32_t current_time_slot = time & num_delay_slots_mask;
    uint8_t *current_time_slot_spike_counters =
        spike_counters[current_time_slot];
    memset(current_time_slot_spike_counters, 0, sizeof(uint8_t) * num_neurons);
}