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); } }
/****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); } }
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); } } }
/****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); } }
//! \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); }
//! \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(); }
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); }