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); } } }
void sdp_tx_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); // Increment the counter and transmit if necessary delay_remaining--; if(delay_remaining == 0) { delay_remaining = g_sdp_tx.transmission_delay; // Construct and transmit the SDP Message sdp_msg_t message; message.dest_addr = 0x0000; // (0, 0) message.dest_port = 0xff; message.srce_addr = sv->p2p_addr; // Sender P2P address message.srce_port = spin1_get_id(); message.flags = 0x07; // No reply expected message.tag = 1; // Send to IPtag 1 message.cmd_rc = 1; spin1_memcpy( message.data, g_sdp_tx.input, g_sdp_tx.n_dimensions * sizeof(value_t)); message.length = sizeof(sdp_hdr_t) + sizeof(cmd_hdr_t) + g_sdp_tx.n_dimensions * sizeof(value_t); spin1_send_sdp_msg(&message, 100); } }
void tick(uint ticks, uint arg1) { use(arg1); if (simulation_ticks != UINT32_MAX && ticks > simulation_ticks) { // Transmit all packets assigned to be sent after the end of the simulation transmit_packet_region(end_packets); spin1_exit(0); } }
void hSDP(uint mailbox, uint port) { sdp_msg_t *msg = (sdp_msg_t *) mailbox; #if(DEBUG_LEVEL>2) io_printf(IO_STD, "[INFO] sdp on port-%d\n", port); #endif // use DEF_HOST_SDP_PORT for communication with the host via eth if(port==DEF_HOST_SDP_PORT) { switch(msg->cmd_rc) { case HOST_REQ_PLL_INFO: //spin1_schedule_callback(showPLLinfo, 1, 0, SCHEDULED_PRIORITY_VAL); //io_printf(IO_STD, "[INFO] HOST_REQ_PLL_INFO..\n"); showPLLinfo(0, 0); break; case HOST_REQ_PROFILER_STREAM: // then use seq to determine: 0 stop, 1 start if(msg->seq==0) { io_printf(IO_STD, "[INFO] Streaming off...\n"); streaming = FALSE; } else { io_printf(IO_STD, "[INFO] Streaming on...\n"); streaming = TRUE; } break; case HOST_SET_FREQ_VALUE: { // seq structure: byte-1 component, byte-0 frequency PLL_PART comp = (PLL_PART)(msg->seq >> 8); uint f = msg->seq & 0xFF; #if(DEBUG_LEVEL>2) io_printf(IO_STD, "[INFO] Request for comp-%d with f=%d\n", comp, f); #endif changeFreq(comp, f); break; } case HOST_TELL_STOP: spin1_exit(0); } } // use DEF_INTERNAL_SDP_PORT for internal (inter-chip) communication // such as with monitor core for SCP else if(port==DEF_INTERNAL_SDP_PORT){
//! \brief Timer interrupt callback //! \param[in] timer_count the number of times this call back has been //! executed since start of simulation //! \param[in] unused unused parameter kept for API consistency //! \return None void timer_callback(uint timer_count, uint unused) { use(timer_count); use(unused); time++; log_debug("Timer tick %u \n", time); /* if a fixed number of simulation ticks that were specified at startup then do reporting for finishing */ if (infinite_run != TRUE && time >= simulation_ticks) { log_info("Simulation complete.\n"); // print statistics into logging region synapses_print_pre_synaptic_events(); synapses_print_saturation_count(); spike_processing_print_buffer_overflows(); // Finalise any recordings that are in progress, writing back the final // amounts of samples recorded to SDRAM if (recording_flags > 0) { recording_finalise(); } spin1_exit(0); return; } // otherwise do synapse and neuron time step updates synapses_do_timestep_update(time); neuron_do_timestep_update(time); // trigger buffering_out_mechanism if (recording_flags > 0) { recording_do_timestep_update(time); } }
// ------------------------------------------------------------------------ // process received packets (stop, FORWARD and BACKPROP types) // ------------------------------------------------------------------------ void s_receivePacket (uint key, uint payload) { // check if stop packet if ((key & SPINN_TYPE_MASK) == SPINN_STOP_KEY) { // stop packet received #ifdef DEBUG stp_recv++; #endif // STOP decision arrived tick_stop = key & SPINN_STPD_MASK; #ifdef DEBUG_VRB io_printf (IO_BUF, "sc:%x\n", tick_stop); #endif // check if all threads done if (sf_thrds_done == 0) { // if done initialise semaphore sf_thrds_done = 1; // and advance tick spin1_schedule_callback (sf_advance_tick, NULL, NULL, SPINN_S_TICK_P); } else { // if not done report processing thread done sf_thrds_done -= 1; } } // check if network stop packet else if ((key & SPINN_TYPE_MASK) == SPINN_STPN_KEY) { // network stop packet received #ifdef DEBUG stn_recv++; #endif //done spin1_exit (SPINN_NO_ERROR); return; } else { #ifdef DEBUG pkt_recv++; #endif // check if space in packet queue, uint new_tail = (s_pkt_queue.tail + 1) % SPINN_SUM_PQ_LEN; if (new_tail == s_pkt_queue.head) { // if queue full exit and report failure spin1_exit (SPINN_QUEUE_FULL); } else { // if not full queue packet, s_pkt_queue.queue[s_pkt_queue.tail].key = key; s_pkt_queue.queue[s_pkt_queue.tail].payload = payload; s_pkt_queue.tail = new_tail; // and schedule processing thread -- if not active already if (!s_active) { s_active = TRUE; spin1_schedule_callback (s_process, NULL, NULL, SPINN_S_PROCESS_P); } } } }
void terminate(uint arg0, uint arg1) { io_printf(IO_STD, "Received -%d packets!\n", pktCntr); spin1_exit(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); }