sPyNNaker neural_modelling  7.4.2
post_events.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 The University of Manchester
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
19 #ifndef _POST_EVENTS_H_
20 #define _POST_EVENTS_H_
21 
22 // Standard includes
23 #include <stdbool.h>
24 #include <stdint.h>
25 
26 // Include debug header for log_info etc
27 #include <debug.h>
28 
29 //---------------------------------------
30 // Macros
31 //---------------------------------------
33 #define MAX_POST_SYNAPTIC_EVENTS 16
34 
35 //---------------------------------------
36 // Structures
37 //---------------------------------------
39 typedef struct {
41  uint32_t count_minus_one;
43  uint32_t times[MAX_POST_SYNAPTIC_EVENTS];
47 
49 typedef struct {
53  uint32_t prev_time;
57  const uint32_t *next_time;
59  uint32_t num_events;
61  uint32_t prev_time_valid;
63 
64 //---------------------------------------
65 // Inline functions
66 //---------------------------------------
67 
68 #if LOG_LEVEL >= LOG_DEBUG
71 static inline void print_event_history(const post_event_history_t *events) {
72  log_debug(" ## printing entire post event history ##");
73  for (uint32_t i = 0; i <= events->count_minus_one; i++) {
74  log_debug("post event: %u, time: %u, trace: %u",
75  i, events->times[i], events->traces[i]);
76  }
77 }
78 #endif
79 
84  uint32_t n_neurons) {
86  spin1_malloc(n_neurons * sizeof(post_event_history_t));
87  // Check allocations succeeded
88  if (post_event_history == NULL) {
89  log_error("Unable to allocate global STDP structures - Out of DTCM: Try "
90  "reducing the number of neurons per core to fix this problem ");
91  return NULL;
92  }
93 
94  // Loop through neurons
95  for (uint32_t n = 0; n < n_neurons; n++) {
96  // Add initial placeholder entry to buffer
97  post_event_history[n].times[0] = 0;
100  }
101 
102  return post_event_history;
103 }
104 
105 //---------------------------------------
112  const post_event_history_t *events, uint32_t begin_time,
113  uint32_t end_time) {
114  // Start at end event - beyond end of post-event history
115  const uint32_t count = events->count_minus_one + 1;
116  const uint32_t *end_event_time = events->times + count;
117  const uint32_t *event_time = end_event_time;
118  const post_trace_t *event_trace = events->traces + count;
119 
120  post_event_window_t window;
121  do {
122  // If this event is still in the future, set it as the end
123  if (*event_time > end_time) {
124  end_event_time = event_time;
125  }
126 
127  // Cache pointer to this event as potential next event and go back one
128  // event.
129  // **NOTE** next_time can be invalid
130  window.next_time = event_time--;
131  window.next_trace = event_trace--;
132 
133  // Keep looping while event occurred after start of window and we
134  // haven't hit beginning of array...
135  } while (*event_time > begin_time && event_time != events->times);
136 
137  // Deference event to use as previous
138  window.prev_time = *event_time;
139  window.prev_trace = *event_trace;
140  window.prev_time_valid = event_time != events->times;
141 
142  // Calculate number of events
143  window.num_events = (end_event_time - window.next_time);
144 
145  // Return window
146  return window;
147 }
148 
149 //---------------------------------------
154  post_event_window_t window) {
155  // Update previous time and increment next time
156  window.prev_time = *window.next_time++;
157  window.prev_trace = *window.next_trace++;
158 
159  // Time will now be valid for sure!
160  window.prev_time_valid = 1;
161 
162  // Decrement remaining events
163  window.num_events--;
164  return window;
165 }
166 
167 //---------------------------------------
172 static inline void post_events_add(
173  uint32_t time, post_event_history_t *events, post_trace_t trace) {
174  if (events->count_minus_one < MAX_POST_SYNAPTIC_EVENTS - 1) {
175  // If there's still space, store time at current end
176  // and increment count minus 1
177  const uint32_t new_index = ++events->count_minus_one;
178  events->times[new_index] = time;
179  events->traces[new_index] = trace;
180  } else {
181  // Otherwise Shuffle down elements
182  // **NOTE** 1st element is always an entry at time 0
183  for (uint32_t e = 2; e < MAX_POST_SYNAPTIC_EVENTS; e++) {
184  events->times[e - 1] = events->times[e];
185  events->traces[e - 1] = events->traces[e];
186  }
187 
188  // Stick new time at end
189  events->times[MAX_POST_SYNAPTIC_EVENTS - 1] = time;
190  events->traces[MAX_POST_SYNAPTIC_EVENTS - 1] = trace;
191  }
192 }
193 
194 #if LOG_LEVEL >= LOG_DEBUG
200 static inline void print_delayed_window_events(
202  uint32_t begin_time, uint32_t end_time, uint32_t delay_dendritic) {
203  log_info(" ## printing post window ##");
205  post_event_history, begin_time, end_time);
206 
207  while (post_window.num_events > 0) {
208  const uint32_t delayed_post_time =
209  *post_window.next_time + delay_dendritic;
210  log_info("post spike: %u, time: %u, trace: %u",
211  post_window.num_events, delayed_post_time,
212  *post_window.next_trace);
213 
214  post_window = post_events_next(post_window);
215  }
216 }
217 #endif
218 
219 #endif // _POST_EVENTS_H_
static uint32_t time
Simulation time.
static uint32_t n_neurons
The number of neurons on the core.
Definition: neuron.c:45
#define MAX_POST_SYNAPTIC_EVENTS
Maximum number of post-synaptic events supported.
Definition: post_events.h:33
static post_event_history_t * post_events_init_buffers(uint32_t n_neurons)
Initialise an array of post-synaptic event histories.
Definition: post_events.h:83
static void print_event_history(const post_event_history_t *events)
Print a post-synaptic event history.
Definition: post_events.h:71
static post_event_window_t post_events_next(post_event_window_t window)
Advance a post-synaptic event window to the next event.
Definition: post_events.h:153
static void post_events_add(uint32_t time, post_event_history_t *events, post_trace_t trace)
Add a post-synaptic event to the history.
Definition: post_events.h:172
static post_event_window_t post_events_get_window_delayed(const post_event_history_t *events, uint32_t begin_time, uint32_t end_time)
Get the post-synaptic event window.
Definition: post_events.h:111
static void print_delayed_window_events(const post_event_history_t *post_event_history, uint32_t begin_time, uint32_t end_time, uint32_t delay_dendritic)
Print the post-synaptic event history.
Definition: post_events.h:200
uint32_t num_events
The number of events.
Definition: post_events.h:59
post_trace_t prev_trace
The previous post-synaptic event trace.
Definition: post_events.h:51
const uint32_t * next_time
The next post-synaptic event time.
Definition: post_events.h:57
uint32_t prev_time
The previous post-synaptic event time.
Definition: post_events.h:53
const post_trace_t * next_trace
The next post-synaptic event trace.
Definition: post_events.h:55
uint32_t prev_time_valid
Whether the previous post-synaptic event is valid (based on time)
Definition: post_events.h:61
Post event window description.
Definition: post_events.h:49
uint32_t count_minus_one
Number of events stored (minus one)
Definition: post_events.h:41
uint32_t times[MAX_POST_SYNAPTIC_EVENTS]
Event times.
Definition: post_events.h:43
post_trace_t traces[MAX_POST_SYNAPTIC_EVENTS]
Event traces.
Definition: post_events.h:45
Trace history of post-synaptic events.
Definition: post_events.h:39
static post_event_history_t * post_event_history
The history data of post-events.
static post_trace_t timing_get_initial_post_trace(void)
Get an initial post-synaptic timing trace.
The type of post-spike traces.