sPyNNaker neural_modelling 7.1.1
Loading...
Searching...
No Matches
post_events_with_da.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017 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
35typedef struct nm_post_trace_t {
36 int16_t dopamine_trace;
37 post_trace_t post_trace;
39
40//---------------------------------------
41// Structures
42//---------------------------------------
44typedef struct {
46 uint32_t count_minus_one;
48 uint32_t times[MAX_POST_SYNAPTIC_EVENTS];
54
56typedef struct {
60 uint32_t prev_time;
64 const uint32_t *next_time;
66 uint32_t num_events;
68 uint32_t prev_time_valid;
72
73//---------------------------------------
74// Inline functions
75//---------------------------------------
76
77#if LOG_LEVEL >= LOG_DEBUG
80static inline void print_event_history(const post_event_history_t *events) {
81 log_debug(" ## printing entire post event history ##");
82 for (uint32_t i = 0; i <= events->count_minus_one; i++) {
83 log_debug("post event: %u, time: %u, trace: %u",
84 i, events->times[i], events->traces[i]);
85 }
86}
87#endif
88
93 uint32_t n_neurons) {
95 spin1_malloc(n_neurons * sizeof(post_event_history_t));
96 // Check allocations succeeded
97 if (post_event_history == NULL) {
98 log_error("Unable to allocate global STDP structures - Out of DTCM: Try "
99 "reducing the number of neurons per core to fix this problem ");
100 return NULL;
101 }
102
103 // Loop through neurons
104 for (uint32_t n = 0; n < n_neurons; n++) {
105 // Add initial placeholder entry to buffer
106 post_event_history[n].times[0] = 0;
107 post_event_history[n].traces[0].dopamine_trace = 0;
108 post_event_history[n].traces[0].post_trace =
112 }
113
114 return post_event_history;
115}
116
117//---------------------------------------
124 const post_event_history_t *events, uint32_t begin_time,
125 uint32_t end_time) {
126 // Start at end event - beyond end of post-event history
127 const uint32_t count = events->count_minus_one + 1;
128 const uint32_t *end_event_time = events->times + count;
129 const uint32_t *event_time = end_event_time;
130 const nm_post_trace_t *event_trace = events->traces + count;
131
132 post_event_window_t window;
133 do {
134 // If this event is still in the future, set it as the end
135 if (*event_time > end_time) {
136 end_event_time = event_time;
137 }
138
139 // Cache pointer to this event as potential next event and go back one
140 // event.
141 // **NOTE** next_time can be invalid
142 window.next_time = event_time--;
143 window.next_trace = event_trace--;
144
145 // Keep looping while event occurred after start of window and we
146 // haven't hit beginning of array...
147 } while (*event_time > begin_time && event_time != events->times);
148
149 // Deference event to use as previous
150 window.prev_time = *event_time;
151 window.prev_trace = *event_trace;
152 window.prev_time_valid = event_time != events->times;
153
154 // Calculate number of events
155 window.num_events = (end_event_time - window.next_time);
156
157 // Find a vector of dopamine trace markers, with the LSB
158 // entry in the vector corresponding to the oldest trace in the window
160 events->dopamine_trace_markers >> (count - window.num_events);
161
162 // Return window
163 return window;
164}
165
166//---------------------------------------
171 post_event_window_t window) {
172 // Update previous time and increment next time
173 window.prev_time = *window.next_time++;
174 window.prev_trace = *window.next_trace++;
175
176 // Time will now be valid for sure!
177 window.prev_time_valid = 1;
178
179 // Decrement remaining events
180 window.num_events--;
181
182 // Shift the dopamine trace markers to place the next trace marker at LSB
183 window.dopamine_trace_markers >>= 1;
184 return window;
185}
186
187//---------------------------------------
188
189// Check the LSB of dopamine trace marker vector to figure out whether the
190// oldest trace in the given history trace window is dopamine trace
191static inline bool post_events_next_is_dopamine(
192 post_event_window_t window) {
193 return (window.dopamine_trace_markers & 0x1) != 0x0;
194}
195
196//---------------------------------------
201static inline void post_events_add(
202 uint32_t time, post_event_history_t *events, post_trace_t post_trace,
203 int16_t dopamine_trace, bool dopamine) {
204 if (events->count_minus_one < MAX_POST_SYNAPTIC_EVENTS - 1) {
205 // If there's still space, store time at current end
206 // and increment count minus 1
207 const uint32_t new_index = ++events->count_minus_one;
208 events->times[new_index] = time;
209 events->traces[new_index].post_trace = post_trace;
210 events->traces[new_index].dopamine_trace = dopamine_trace;
211 if (dopamine) {
212 events->dopamine_trace_markers |= (1 << new_index);
213 } else {
214 events->dopamine_trace_markers &= ~(1 << new_index);
215 }
216 } else {
217 // Otherwise Shuffle down elements
218 // **NOTE** 1st element is always an entry at time 0
219 for (uint32_t e = 2; e < MAX_POST_SYNAPTIC_EVENTS; e++) {
220 events->times[e - 1] = events->times[e];
221 events->traces[e - 1] = events->traces[e];
222 }
223 events->dopamine_trace_markers >>= 1;
224
225 // Stick new time at end
226 events->times[MAX_POST_SYNAPTIC_EVENTS - 1] = time;
227 events->traces[MAX_POST_SYNAPTIC_EVENTS - 1].post_trace = post_trace;
228 events->traces[MAX_POST_SYNAPTIC_EVENTS - 1].dopamine_trace = dopamine_trace;
229 if (dopamine) {
230 events->dopamine_trace_markers |=
231 (1 << (MAX_POST_SYNAPTIC_EVENTS - 1));
232 } else {
233 events->dopamine_trace_markers &=
234 ~(1 << (MAX_POST_SYNAPTIC_EVENTS - 1));
235 }
236 }
237}
238
239#if LOG_LEVEL >= LOG_DEBUG
247 uint32_t begin_time, uint32_t end_time, uint32_t delay_dendritic) {
248 log_info(" ## printing post window ##");
250 post_event_history, begin_time, end_time);
251
252 while (post_window.num_events > 0) {
253 const uint32_t delayed_post_time =
254 *post_window.next_time + delay_dendritic;
255 log_info("post spike: %u, time: %u, trace: %u, dop_trace: %u",
256 post_window.num_events, delayed_post_time,
257 post_window.next_trace->post_trace,
258 post_window.next_trace->dopamine_trace);
259
260 post_window = post_events_next(post_window);
261 }
262}
263#endif
264
265#endif // _POST_EVENTS_H_
uint32_t time
The current timer tick value.
Definition c_main.c:94
void log_error(const char *message,...)
void log_debug(const char *message,...)
void log_info(const char *message,...)
static uint32_t n_neurons
The number of neurons on the core.
Definition neuron.c:45
nm_post_trace_t prev_trace
The previous post-synaptic event trace.
#define MAX_POST_SYNAPTIC_EVENTS
Maximum number of post-synaptic events supported.
uint32_t dopamine_trace_markers
Bit field to indicate whether a trace is dopamine or not.
static post_event_history_t * post_events_init_buffers(uint32_t n_neurons)
Initialise an array of post-synaptic event histories.
uint32_t num_events
The number of events.
Definition post_events.h:59
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
static void print_event_history(const post_event_history_t *events)
Print a post-synaptic event history.
static post_event_window_t post_events_next(post_event_window_t window)
Advance a post-synaptic event window to the next event.
static void post_events_add(uint32_t time, post_event_history_t *events, post_trace_t post_trace, int16_t dopamine_trace, bool dopamine)
Add a post-synaptic event to the history.
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
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.
uint32_t dopamine_trace_markers
Bit field to indicate whether a trace is dopamine or not.
uint32_t prev_time_valid
Whether the previous post-synaptic event is valid (based on time)
Definition post_events.h:61
const nm_post_trace_t * next_trace
The next post-synaptic event trace.
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.
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
Post event window description.
Definition post_events.h:49
#define NULL
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.