Skip to content

Commit abc5315

Browse files
committed
A working version of the filter
1 parent 1e34d1e commit abc5315

File tree

7 files changed

+408
-88
lines changed

7 files changed

+408
-88
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright (c) 2014 The University of Manchester
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
APP = synapse_filter
16+
SOURCES = neuron/synapse_filter.c
17+
18+
include ../neural_support.mk

neural_modelling/src/neuron/spike_processing_fast.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,10 @@ static inline bool get_next_spike(uint32_t time, spike_t *spike) {
233233
// Detect a looped back spike
234234
if ((*spike & key_config.mask) == key_config.key) {
235235
// Process event if not self-connected (if it is, this happens later)
236-
if (!key_config.self_connected) {
236+
if (!key_config.self_connected) {
237237
synapse_dynamics_process_post_synaptic_event(
238238
time, (*spike & key_config.spike_id_mask) >> key_config.colour_shift);
239-
}
239+
}
240240
return key_config.self_connected;
241241
}
242242
return true;
@@ -250,7 +250,7 @@ static inline bool get_next_spike(uint32_t time, spike_t *spike) {
250250
//! \param[out] result The result of the lookup
251251
//! \return True if a DMA was started
252252
static inline bool start_first_dma(uint32_t time, spike_t *spike,
253-
pop_table_lookup_result_t *result) {
253+
pop_table_lookup_result_t *result) {
254254

255255
do {
256256
if (population_table_get_first_address(*spike, result)) {
@@ -268,7 +268,7 @@ static inline bool start_first_dma(uint32_t time, spike_t *spike,
268268
//! \param[out] result The details of the transfer to do
269269
//! \return True if there is a DMA to do
270270
static inline bool get_next_dma(uint32_t time, spike_t *spike,
271-
pop_table_lookup_result_t *result) {
271+
pop_table_lookup_result_t *result) {
272272
if (population_table_is_next() && population_table_get_next_address(spike, result)) {
273273
return true;
274274
}
@@ -326,7 +326,7 @@ static inline void process_current_row(uint32_t time, bool dma_in_progress) {
326326
dma_buffer *buffer = &dma_buffers[next_buffer_to_process];
327327

328328
if (!synapses_process_synaptic_row(time, buffer->colour, buffer->colour_mask,
329-
buffer->row, &write_back)) {
329+
buffer->row, &write_back)) {
330330
handle_row_error(buffer);
331331
}
332332
synaptogenesis_spike_received(time, buffer->originating_spike);
@@ -448,7 +448,7 @@ static inline void do_rewiring(uint32_t time, uint32_t n_rewires) {
448448
dma_buffers[next_buffer].sdram_writeback_address = result.row_address;
449449
dma_buffers[next_buffer].n_bytes_transferred = result.n_bytes_to_transfer;
450450
do_fast_dma_read(result.row_address, dma_buffers[next_buffer].row,
451-
result.n_bytes_to_transfer);
451+
result.n_bytes_to_transfer);
452452
next_buffer = (next_buffer + 1) & DMA_BUFFER_MOD_MASK;
453453
dma_in_progress = true;
454454
}
@@ -475,7 +475,7 @@ static inline void do_rewiring(uint32_t time, uint32_t n_rewires) {
475475
dma_buffers[next_buffer].sdram_writeback_address = result.row_address;
476476
dma_buffers[next_buffer].n_bytes_transferred = result.n_bytes_to_transfer;
477477
do_fast_dma_read(result.row_address, dma_buffers[next_buffer].row,
478-
result.n_bytes_to_transfer);
478+
result.n_bytes_to_transfer);
479479
next_buffer = (next_buffer + 1) & DMA_BUFFER_MOD_MASK;
480480
}
481481

@@ -586,13 +586,11 @@ void multicast_packet_received_callback(uint key, UNUSED uint unused) {
586586
//! \param[in] key: The key of the packet. The spike.
587587
//! \param payload: the payload of the packet. The count.
588588
void multicast_packet_pl_received_callback(uint key, uint payload) {
589-
log_debug("Received spike %x with payload %d", key, payload);
589+
log_debug("Received input %x with spike %d", key, payload);
590590
p_per_ts_struct.packets_this_time_step++;
591591

592-
// cycle through the packet insertion
593-
for (uint count = payload; count > 0; count--) {
594-
in_spikes_add_spike(key);
595-
}
592+
// In this case we add the payload as the key, as it came from a filter
593+
in_spikes_add_spike(payload);
596594
check_times();
597595
}
598596

@@ -605,8 +603,8 @@ bool spike_processing_fast_initialise(
605603
for (uint32_t i = 0; i < N_DMA_BUFFERS; i++) {
606604
dma_buffers[i].row = spin1_malloc(row_max_n_words * sizeof(uint32_t));
607605
if (dma_buffers[i].row == NULL) {
608-
log_error("Could not initialise DMA buffers of %u words",
609-
row_max_n_words);
606+
log_error("Could not initialise DMA buffers of %u words",
607+
row_max_n_words);
610608
return false;
611609
}
612610
log_debug("DMA buffer %u allocated at 0x%08x",

neural_modelling/src/neuron/synapse_filter.c

Lines changed: 64 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#include <filter_info.h>
2323
#include <circular_buffer.h>
2424
#include <wfi.h>
25-
#include <population_table/population_table.h>
25+
#include "population_table/population_table.h"
2626

2727
enum {
2828

@@ -68,6 +68,8 @@ typedef struct {
6868
uint32_t n_spikes_invalid_app_id;
6969
//! The number of times the spike input queue was full (these are lost)
7070
uint32_t n_times_queue_overflowed;
71+
//! The number of times the filter stopped a packet from being sent
72+
uint32_t n_times_filter_stopped_packet;
7173
} filter_provenance_t;
7274

7375
typedef struct {
@@ -95,6 +97,12 @@ typedef struct {
9597
bit_field_t data;
9698
} bit_field_filter_info_t;
9799

100+
static uint32_t time = UINT32_MAX;
101+
102+
static uint32_t n_timesteps;
103+
104+
static uint32_t run_forever;
105+
98106
static filter_config_t *config;
99107

100108
static circular_buffer input_queue;
@@ -109,14 +117,14 @@ static volatile bool running = false;
109117

110118
static inline bool check_app_id(uint32_t spike, uint32_t *app_id) {
111119
*app_id = (spike & config->app_id_mask) >> config->app_id_shift;
112-
return (app_id <= config->app_id_max) && (app_id >= config->app_id_min);
120+
return (*app_id <= config->app_id_max) && (*app_id >= config->app_id_min);
113121
}
114122

115123
//! \brief Get the source core index from a spike
116124
//! \param[in] filter: The filter info for the spike
117125
//! \param[in] spike: The spike received
118126
//! \return the source core index in the list of source cores
119-
static inline uint32_t get_core_index(bit_field_filter_info_t filter,
127+
static inline uint32_t get_filter_core_index(bit_field_filter_info_t filter,
120128
spike_t spike) {
121129
return (spike >> filter.core_shift) & filter.core_mask;
122130
}
@@ -125,18 +133,18 @@ static inline uint32_t get_core_index(bit_field_filter_info_t filter,
125133
//! \param[in] filter: The filter info for the spike
126134
//! \param[in] spike: The spike received
127135
//! \return the base neuron number of this core
128-
static inline uint32_t get_core_sum(bit_field_filter_info_t filter,
136+
static inline uint32_t get_filter_core_sum(bit_field_filter_info_t filter,
129137
spike_t spike) {
130-
return get_core_index(filter, spike) * filter.n_neurons;
138+
return get_filter_core_index(filter, spike) * filter.n_neurons;
131139
}
132140

133141
//! \brief Get the neuron id of the neuron on the source core
134142
//! \param[in] filter: the filter info for the spike
135143
//! \param[in] spike: the spike received
136144
//! \return the source neuron id local to the core
137-
static inline uint32_t get_local_neuron_id(bit_field_filter_info_t filter,
138-
spike_t spike) {
139-
return spike & filter.mask;
145+
static inline uint32_t get_filter_local_neuron_id(
146+
bit_field_filter_info_t filter, spike_t spike) {
147+
return (spike & filter.mask) >> filter.n_colour_bits;
140148
}
141149

142150
static inline bool accepted(uint32_t app_id, uint32_t spike) {
@@ -149,12 +157,17 @@ static inline bool accepted(uint32_t app_id, uint32_t spike) {
149157
if (filters[pos].all_ones) {
150158
return true;
151159
}
152-
uint32_t neuron_id = get_core_sum(filters[pos], spike)
153-
+ get_local_neuron_id(filters[pos], spike);
154-
return bit_field_get(bit_field, neuron_id);
160+
uint32_t neuron_id = get_filter_core_sum(filters[pos], spike)
161+
+ get_filter_local_neuron_id(filters[pos], spike);
162+
if (bit_field_test(bit_field, neuron_id)) {
163+
return true;
164+
} else {
165+
prov.n_times_filter_stopped_packet += 1;
166+
return false;
167+
}
155168
}
156169

157-
static inline uint32_t get_key() {
170+
static inline uint32_t get_key(void) {
158171
uint32_t target = next_target;
159172
next_target = (next_target + 1);
160173
if (next_target >= config->n_targets) {
@@ -164,15 +177,15 @@ static inline uint32_t get_key() {
164177
}
165178

166179
static inline void process_spike(void) {
167-
uint32_t spike;
168-
circular_buffer_pop(input_queue, &spike);
180+
uint32_t spike = 0;
181+
circular_buffer_get_next(input_queue, &spike);
169182

170-
// Check against the bitfield
183+
// Check against the bit-field
171184
uint32_t app_id;
172185
if (!check_app_id(spike, &app_id)) {
173186
// Not in range, drop
174187
prov.n_spikes_invalid_app_id += 1;
175-
continue;
188+
return;
176189
}
177190

178191
// If accepted, forward to the targets
@@ -183,7 +196,8 @@ static inline void process_spike(void) {
183196
}
184197
}
185198

186-
void start_callback(void) {
199+
void start_callback(UNUSED uint unused0, UNUSED uint unused1) {
200+
log_info("Running");
187201
running = true;
188202
while (running) {
189203
// Get the next packet
@@ -200,45 +214,61 @@ void start_callback(void) {
200214
process_spike();
201215
}
202216
}
217+
log_info("Exiting Run loop");
203218
}
204219

205-
void exit_callback(void) {
206-
running = false;
220+
void timer_callback(UNUSED uint unused0, UNUSED uint unused1) {
221+
time++;
222+
log_debug("Time is %u", time);
223+
if (time == 0) {
224+
spin1_schedule_callback(start_callback, 0, 0, 1);
225+
}
226+
if (simulation_is_finished()) {
227+
simulation_handle_pause_resume(NULL);
228+
running = false;
229+
simulation_ready_to_read();
230+
}
207231
}
208232

209-
void store_provenance_data(void *prov_region_addr) {
233+
void store_provenance_data(uint32_t *prov_region_addr) {
210234
// Copy across the provenance data
211235
spin1_memcpy(prov_region_addr, &prov, sizeof(filter_provenance_t));
212236
}
213237

214238
void receive_spike_callback(uint key, uint payload) {
215239
// Try to put the spike in the input queue
216-
prov.n_spikes_received += 1;
217-
if (!circular_buffer_push(input_queue, key)) {
218-
// Queue overflowed
219-
prov.n_times_queue_overflowed += 1;
240+
if (payload == 0) {
241+
// No payload = 0, which means 1 spike
242+
payload = 1;
243+
}
244+
prov.n_spikes_received += payload;
245+
for (uint32_t i = 0; i < payload; i++) {
246+
if (!circular_buffer_add(input_queue, key)) {
247+
// Queue overflowed
248+
prov.n_times_queue_overflowed += 1;
249+
}
220250
}
221251
}
222252

223-
bool initialise() {
253+
static bool initialise(void) {
224254
data_specification_metadata_t *ds = data_specification_get_data_address();
225255
if (!data_specification_read_header(ds)) {
226256
log_error("Failed to read data specification header");
227257
return false;
228258
}
229259

230260
// set up the simulation interface
231-
uint32_t n_steps;
232-
bool run_forever;
233-
uint32_t step;
234-
if (!simulation_steps_initialise(
261+
uint32_t timer_period;
262+
if (!simulation_initialise(
235263
data_specification_get_region(FILTER_REGION_SYSTEM, ds),
236-
APPLICATION_NAME_HASH, &n_steps, &run_forever, &step, 0, -2)) {
264+
APPLICATION_NAME_HASH, &timer_period, &n_timesteps, &run_forever,
265+
&time, 0, -2)) {
237266
return false;
238267
}
239268
simulation_set_provenance_function(
240269
store_provenance_data,
241270
data_specification_get_region(FILTER_REGION_PROVENANCE, ds));
271+
spin1_set_timer_tick(timer_period);
242272

243273
// Read in the filter configuration
244274
filter_config_t *sdram_config = data_specification_get_region(
@@ -305,7 +335,7 @@ bool initialise() {
305335
uint32_t size = get_bit_field_size(
306336
filters_sdram[i].n_atoms) * sizeof(uint32_t);
307337
filters[pos].data = spin1_malloc(size);
308-
if (filters[pos] == NULL) {
338+
if (filters[pos].data == NULL) {
309339
log_error("Failed to allocate bit field of %u atoms for app id %u",
310340
filters_sdram[i].n_atoms, app_id);
311341
return false;
@@ -319,13 +349,12 @@ bool initialise() {
319349
//! \brief The entry point for this model.
320350
void c_main(void) {
321351
// initialise the model
322-
if (!initialize()) {
352+
if (!initialise()) {
323353
rt_error(RTE_SWERR);
324354
}
325355

326-
simulation_set_exit_function(exit_callback);
327-
simulation_set_start_function(start_callback);
328-
simulation_set_uses_timer(false);
329356
spin1_callback_on(MC_PACKET_RECEIVED, receive_spike_callback, -1);
357+
spin1_callback_on(MCPL_PACKET_RECEIVED, receive_spike_callback, -1);
358+
spin1_callback_on(TIMER_TICK, timer_callback, 0);
330359
simulation_run();
331360
}

0 commit comments

Comments
 (0)