CARLsim  5.0.0
CARLsim: a GPU-accelerated SNN simulator
snn_cpu_module.cpp
Go to the documentation of this file.
1 /* * Copyright (c) 2016 Regents of the University of California. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions
5 * are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * 3. The names of its contributors may not be used to endorse or promote
15 * products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * *********************************************************************************************** *
31 * CARLsim
32 * created by: (MDR) Micah Richert, (JN) Jayram M. Nageswaran
33 * maintained by:
34 * (MA) Mike Avery <averym@uci.edu>
35 * (MB) Michael Beyeler <mbeyeler@uci.edu>,
36 * (KDC) Kristofor Carlson <kdcarlso@uci.edu>
37 * (TSC) Ting-Shuo Chou <tingshuc@uci.edu>
38 * (HK) Hirak J Kashyap <kashyaph@uci.edu>
39 *
40 * CARLsim v1.0: JM, MDR
41 * CARLsim v2.0/v2.1/v2.2: JM, MDR, MA, MB, KDC
42 * CARLsim3: MB, KDC, TSC
43 * CARLsim4: TSC, HK
44 * CARLsim5: HK, JX, KC
45 *
46 * CARLsim available from http://socsci.uci.edu/~jkrichma/CARLsim/
47 * Ver 12/31/2016
48 */
49 
50 #include <snn.h>
51 
52 #include <spike_buffer.h>
53 
54 // spikeGeneratorUpdate_CPU on CPUs
55 #if defined(WIN32) || defined(WIN64) || defined(__APPLE__)
56  void SNN::spikeGeneratorUpdate_CPU(int netId) {
57 #else // POSIX
58  void* SNN::spikeGeneratorUpdate_CPU(int netId) {
59 #endif
60  assert(runtimeData[netId].allocated);
61  assert(runtimeData[netId].memType == CPU_MEM);
62 
63  // FIXME: skip this step if all spike gen neuron are possion neuron (generated by rate)
64  // update the random number for poisson spike generator (spikes generated by rate)
65  for (int poisN = 0; poisN < networkConfigs[netId].numNPois; poisN++) {
66  // set CPU_MODE Random Gen, store random number to g(c)puRandNums
67  runtimeData[netId].randNum[poisN] = drand48();
68  }
69 
70  // Use spike generators (user-defined callback function)
71  if (networkConfigs[netId].numNSpikeGen > 0) {
72  assert(managerRuntimeData.spikeGenBits != NULL);
73 
74  // reset the bit status of the spikeGenBits...
75  memset(managerRuntimeData.spikeGenBits, 0, sizeof(int) * (networkConfigs[netId].numNSpikeGen / 32 + 1));
76 
77  // fill spikeGenBits from SpikeBuffer
78  fillSpikeGenBits(netId);
79 
80  // copy the spikeGenBits from the manager to the CPU runtime
81  memcpy(runtimeData[netId].spikeGenBits, managerRuntimeData.spikeGenBits, sizeof(int) * (networkConfigs[netId].numNSpikeGen / 32 + 1));
82  }
83 }
84 
85 #if !defined(WIN32) && !defined(WIN64) && !defined(__APPLE__) // Linux or MAC
86  // Static multithreading subroutine method - helper for the above method
87  void* SNN::helperSpikeGeneratorUpdate_CPU(void* arguments) {
88  ThreadStruct* args = (ThreadStruct*) arguments;
89  //printf("\nThread ID: %lu and CPU: %d\n",pthread_self(), sched_getcpu());
90  ((SNN *)args->snn_pointer) -> spikeGeneratorUpdate_CPU(args->netId);
91  pthread_exit(0);
92  }
93 #endif
94 
95 #if defined(WIN32) || defined(WIN64) || defined(__APPLE__)
96  void SNN::updateTimingTable_CPU(int netId) {
97 #else // POSIX
98  void* SNN::updateTimingTable_CPU(int netId) {
99 #endif
100  assert(runtimeData[netId].memType == CPU_MEM);
101 
102  runtimeData[netId].timeTableD2[simTimeMs + networkConfigs[netId].maxDelay + 1] = runtimeData[netId].spikeCountD2Sec + runtimeData[netId].spikeCountLastSecLeftD2;
103  runtimeData[netId].timeTableD1[simTimeMs + networkConfigs[netId].maxDelay + 1] = runtimeData[netId].spikeCountD1Sec;
104 }
105 
106 #if !defined(WIN32) && !defined(WIN64) && !defined(__APPLE__) // Linux or MAC
107  // Static multithreading subroutine method - helper for the above method
108  void* SNN::helperUpdateTimingTable_CPU(void* arguments) {
109  ThreadStruct* args = (ThreadStruct*) arguments;
110  //printf("\nThread ID: %lu and CPU: %d\n",pthread_self(), sched_getcpu());
111  ((SNN *)args->snn_pointer) -> updateTimingTable_CPU(args->netId);
112  pthread_exit(0);
113  }
114 #endif
115 
116 //void SNN::routeSpikes_CPU() {
117 // int firingTableIdxD2, firingTableIdxD1;
118 // int GtoLOffset;
119 // // ToDo: route spikes using routing table. currently only exchange spikes between GPU0 and GPU1
120 // // GPU0 -> GPU1
121 // if (!groupPartitionLists[0].empty() && !groupPartitionLists[1].empty()) {
122 // memcpy(managerRuntimeData.extFiringTableEndIdxD2, runtimeData[0].extFiringTableEndIdxD2, sizeof(int) * networkConfigs[0].numGroups);
123 // memcpy(managerRuntimeData.extFiringTableEndIdxD1, runtimeData[0].extFiringTableEndIdxD1, sizeof(int) * networkConfigs[0].numGroups);
124 // memcpy(managerRuntimeData.extFiringTableD2, runtimeData[0].extFiringTableD2, sizeof(int*) * networkConfigs[0].numGroups);
125 // memcpy(managerRuntimeData.extFiringTableD1, runtimeData[0].extFiringTableD1, sizeof(int*) * networkConfigs[0].numGroups);
126 // //KERNEL_DEBUG("GPU0 D1ex:%d/D2ex:%d", managerRuntimeData.extFiringTableEndIdxD1[0], managerRuntimeData.extFiringTableEndIdxD2[0]);
127 //
128 // memcpy(managerRuntimeData.timeTableD2, runtimeData[1].timeTableD2, sizeof(int) * (1000 + glbNetworkConfig.maxDelay + 1));
129 // memcpy(managerRuntimeData.timeTableD1, runtimeData[1].timeTableD1, sizeof(int) * (1000 + glbNetworkConfig.maxDelay + 1));
130 // firingTableIdxD2 = managerRuntimeData.timeTableD2[simTimeMs + glbNetworkConfig.maxDelay + 1];
131 // firingTableIdxD1 = managerRuntimeData.timeTableD1[simTimeMs + glbNetworkConfig.maxDelay + 1];
132 // //KERNEL_DEBUG("GPU1 D1:%d/D2:%d", firingTableIdxD1, firingTableIdxD2);
133 //
134 // for (int lGrpId = 0; lGrpId < networkConfigs[0].numGroups; lGrpId++) {
135 // if (groupConfigs[0][lGrpId].hasExternalConnect && managerRuntimeData.extFiringTableEndIdxD2[lGrpId] > 0) {
136 // memcpy(runtimeData[1].firingTableD2 + firingTableIdxD2,
137 // managerRuntimeData.extFiringTableD2[lGrpId],
138 // sizeof(int) * managerRuntimeData.extFiringTableEndIdxD2[lGrpId]);
139 //
140 // for (std::list<GroupConfigMD>::iterator grpIt = groupPartitionLists[1].begin(); grpIt != groupPartitionLists[1].end(); grpIt++) {
141 // if (grpIt->gGrpId == groupConfigs[0][lGrpId].gGrpId)
142 // GtoLOffset = grpIt->GtoLOffset;
143 // }
144 //
145 // convertExtSpikesD2_CPU(1, firingTableIdxD2,
146 // firingTableIdxD2 + managerRuntimeData.extFiringTableEndIdxD2[lGrpId],
147 // GtoLOffset); // [StartIdx, EndIdx)
148 // firingTableIdxD2 += managerRuntimeData.extFiringTableEndIdxD2[lGrpId];
149 // }
150 //
151 // if (groupConfigs[0][lGrpId].hasExternalConnect && managerRuntimeData.extFiringTableEndIdxD1[lGrpId] > 0) {
152 // memcpy(runtimeData[1].firingTableD1 + firingTableIdxD1,
153 // managerRuntimeData.extFiringTableD1[lGrpId],
154 // sizeof(int) * managerRuntimeData.extFiringTableEndIdxD1[lGrpId]);
155 //
156 // for (std::list<GroupConfigMD>::iterator grpIt = groupPartitionLists[1].begin(); grpIt != groupPartitionLists[1].end(); grpIt++) {
157 // if (grpIt->gGrpId == groupConfigs[0][lGrpId].gGrpId)
158 // GtoLOffset = grpIt->GtoLOffset;
159 // }
160 //
161 // convertExtSpikesD1_CPU(1, firingTableIdxD1,
162 // firingTableIdxD1 + managerRuntimeData.extFiringTableEndIdxD1[lGrpId],
163 // GtoLOffset); // [StartIdx, EndIdx)
164 // firingTableIdxD1 += managerRuntimeData.extFiringTableEndIdxD1[lGrpId];
165 //
166 // }
167 // //KERNEL_DEBUG("GPU1 New D1:%d/D2:%d", firingTableIdxD1, firingTableIdxD2);
168 // }
169 // managerRuntimeData.timeTableD2[simTimeMs + glbNetworkConfig.maxDelay + 1] = firingTableIdxD2;
170 // managerRuntimeData.timeTableD1[simTimeMs + glbNetworkConfig.maxDelay + 1] = firingTableIdxD1;
171 // memcpy(runtimeData[1].timeTableD2, managerRuntimeData.timeTableD2, sizeof(int)*(1000 + glbNetworkConfig.maxDelay + 1));
172 // memcpy(runtimeData[1].timeTableD1, managerRuntimeData.timeTableD1, sizeof(int)*(1000 + glbNetworkConfig.maxDelay + 1));
173 // }
174 //
175 // // GPU1 -> GPU0
176 // if (!groupPartitionLists[1].empty() && !groupPartitionLists[0].empty()) {
177 // memcpy(managerRuntimeData.extFiringTableEndIdxD2, runtimeData[1].extFiringTableEndIdxD2, sizeof(int) * networkConfigs[1].numGroups);
178 // memcpy(managerRuntimeData.extFiringTableEndIdxD1, runtimeData[1].extFiringTableEndIdxD1, sizeof(int) * networkConfigs[1].numGroups);
179 // memcpy(managerRuntimeData.extFiringTableD2, runtimeData[1].extFiringTableD2, sizeof(int*) * networkConfigs[1].numGroups);
180 // memcpy(managerRuntimeData.extFiringTableD1, runtimeData[1].extFiringTableD1, sizeof(int*) * networkConfigs[1].numGroups);
181 // //KERNEL_DEBUG("GPU1 D1ex:%d/D2ex:%d", managerRuntimeData.extFiringTableEndIdxD1[0], managerRuntimeData.extFiringTableEndIdxD2[0]);
182 //
183 // memcpy(managerRuntimeData.timeTableD2, runtimeData[0].timeTableD2, sizeof(int)*(1000 + glbNetworkConfig.maxDelay + 1));
184 // memcpy(managerRuntimeData.timeTableD1, runtimeData[0].timeTableD1, sizeof(int)*(1000 + glbNetworkConfig.maxDelay + 1));
185 // firingTableIdxD2 = managerRuntimeData.timeTableD2[simTimeMs + glbNetworkConfig.maxDelay + 1];
186 // firingTableIdxD1 = managerRuntimeData.timeTableD1[simTimeMs + glbNetworkConfig.maxDelay + 1];
187 // //KERNEL_DEBUG("GPU0 D1:%d/D2:%d", firingTableIdxD1, firingTableIdxD2);
188 //
189 // for (int lGrpId = 0; lGrpId < networkConfigs[1].numGroups; lGrpId++) {
190 // if (groupConfigs[1][lGrpId].hasExternalConnect && managerRuntimeData.extFiringTableEndIdxD2[lGrpId] > 0) {
191 // memcpy(runtimeData[0].firingTableD2 + firingTableIdxD2,
192 // managerRuntimeData.extFiringTableD2[lGrpId],
193 // sizeof(int) * managerRuntimeData.extFiringTableEndIdxD2[lGrpId]);
194 //
195 // for (std::list<GroupConfigMD>::iterator grpIt = groupPartitionLists[0].begin(); grpIt != groupPartitionLists[0].end(); grpIt++) {
196 // if (grpIt->gGrpId == groupConfigs[1][lGrpId].gGrpId)
197 // GtoLOffset = grpIt->GtoLOffset;
198 // }
199 //
200 // convertExtSpikesD2_CPU(0, firingTableIdxD2,
201 // firingTableIdxD2 + managerRuntimeData.extFiringTableEndIdxD2[lGrpId],
202 // GtoLOffset); // [StartIdx, EndIdx)
203 // firingTableIdxD2 += managerRuntimeData.extFiringTableEndIdxD2[lGrpId];
204 // }
205 //
206 // if (groupConfigs[1][lGrpId].hasExternalConnect && managerRuntimeData.extFiringTableEndIdxD1[lGrpId] > 0) {
207 // memcpy(runtimeData[0].firingTableD1 + firingTableIdxD1,
208 // managerRuntimeData.extFiringTableD1[lGrpId],
209 // sizeof(int) * managerRuntimeData.extFiringTableEndIdxD1[lGrpId]);
210 //
211 // for (std::list<GroupConfigMD>::iterator grpIt = groupPartitionLists[0].begin(); grpIt != groupPartitionLists[0].end(); grpIt++) {
212 // if (grpIt->gGrpId == groupConfigs[1][lGrpId].gGrpId)
213 // GtoLOffset = grpIt->GtoLOffset;
214 // }
215 //
216 // convertExtSpikesD1_CPU(0, firingTableIdxD1,
217 // firingTableIdxD1 + managerRuntimeData.extFiringTableEndIdxD1[lGrpId],
218 // GtoLOffset); // [StartIdx, EndIdx)
219 // firingTableIdxD1 += managerRuntimeData.extFiringTableEndIdxD1[lGrpId];
220 // }
221 // //KERNEL_DEBUG("GPU0 New D1:%d/D2:%d", firingTableIdxD1, firingTableIdxD2);
222 // }
223 // managerRuntimeData.timeTableD2[simTimeMs + glbNetworkConfig.maxDelay + 1] = firingTableIdxD2;
224 // managerRuntimeData.timeTableD1[simTimeMs + glbNetworkConfig.maxDelay + 1] = firingTableIdxD1;
225 // memcpy(runtimeData[0].timeTableD2, managerRuntimeData.timeTableD2, sizeof(int)*(1000 + glbNetworkConfig.maxDelay + 1));
226 // memcpy(runtimeData[0].timeTableD1, managerRuntimeData.timeTableD1, sizeof(int)*(1000 + glbNetworkConfig.maxDelay + 1));
227 // }
228 //
229 //}
230 
231 #if defined(WIN32) || defined(WIN64) || defined(__APPLE__)
232  void SNN::convertExtSpikesD2_CPU(int netId, int startIdx, int endIdx, int GtoLOffset) {
233 #else // POSIX
234  void* SNN::convertExtSpikesD2_CPU(int netId, int startIdx, int endIdx, int GtoLOffset) {
235 #endif
236  int spikeCountExtRx = endIdx - startIdx; // received external spike count
237 
238  runtimeData[netId].spikeCountD2Sec += spikeCountExtRx;
239  runtimeData[netId].spikeCountExtRxD2 += spikeCountExtRx;
240  runtimeData[netId].spikeCountExtRxD2Sec += spikeCountExtRx;
241 
242  // FIXME: if endIdx - startIdx > 64 * 128
243  //if (firingTableIdx < endIdx)
244  for (int extIdx = startIdx; extIdx < endIdx; extIdx++)
245  runtimeData[netId].firingTableD2[extIdx] += GtoLOffset;
246 }
247 
248 #if !defined(WIN32) && !defined(WIN64) && !defined(__APPLE__) // Linux or MAC
249  // Static multithreading subroutine method - helper for the above method
250  void* SNN::helperConvertExtSpikesD2_CPU(void* arguments) {
251  ThreadStruct* args = (ThreadStruct*) arguments;
252  //printf("\nThread ID: %lu and CPU: %d\n",pthread_self(), sched_getcpu());
253  ((SNN *)args->snn_pointer) -> convertExtSpikesD2_CPU(args->netId, args->startIdx, args->endIdx, args->GtoLOffset);
254  pthread_exit(0);
255  }
256 #endif
257 
258 #if defined(WIN32) || defined(WIN64) || defined(__APPLE__)
259  void SNN::convertExtSpikesD1_CPU(int netId, int startIdx, int endIdx, int GtoLOffset) {
260 #else // POSIX
261  void* SNN::convertExtSpikesD1_CPU(int netId, int startIdx, int endIdx, int GtoLOffset) {
262 #endif
263  int spikeCountExtRx = endIdx - startIdx; // received external spike count
264 
265  runtimeData[netId].spikeCountD1Sec += spikeCountExtRx;
266  runtimeData[netId].spikeCountExtRxD1 += spikeCountExtRx;
267  runtimeData[netId].spikeCountExtRxD1Sec += spikeCountExtRx;
268 
269  // FIXME: if endIdx - startIdx > 64 * 128
270  for (int extIdx = startIdx; extIdx < endIdx; extIdx++)
271  runtimeData[netId].firingTableD1[extIdx] += GtoLOffset;
272 }
273 
274 #if !defined(WIN32) && !defined(WIN64) && !defined(__APPLE__) // Linux or MAC
275  // Static multithreading subroutine method - helper for the above method
276  void* SNN::helperConvertExtSpikesD1_CPU(void* arguments) {
277  ThreadStruct* args = (ThreadStruct*) arguments;
278  //printf("\nThread ID: %lu and CPU: %d\n",pthread_self(), sched_getcpu());
279  ((SNN *)args->snn_pointer) -> convertExtSpikesD1_CPU(args->netId, args->startIdx, args->endIdx, args->GtoLOffset);
280  pthread_exit(0);
281  }
282 #endif
283 
284 #if defined(WIN32) || defined(WIN64) || defined(__APPLE__)
285  void SNN::clearExtFiringTable_CPU(int netId) {
286 #else // POSIX
287  void* SNN::clearExtFiringTable_CPU(int netId) {
288 #endif
289  assert(runtimeData[netId].memType == CPU_MEM);
290 
291  memset(runtimeData[netId].extFiringTableEndIdxD1, 0, sizeof(int) * networkConfigs[netId].numGroups);
292  memset(runtimeData[netId].extFiringTableEndIdxD2, 0, sizeof(int) * networkConfigs[netId].numGroups);
293 }
294 
295 #if !defined(WIN32) && !defined(WIN64) && !defined(__APPLE__) // Linux or MAC
296  // Static multithreading subroutine method - helper for the above method
297  void* SNN::helperClearExtFiringTable_CPU(void* arguments) {
298  ThreadStruct* args = (ThreadStruct*) arguments;
299  //printf("\nThread ID: %lu and CPU: %d\n",pthread_self(), sched_getcpu());
300  ((SNN *)args->snn_pointer) -> clearExtFiringTable_CPU(args->netId);
301  pthread_exit(0);
302  }
303 #endif
304 
305 void SNN::copyTimeTable(int netId, bool toManager) {
306  assert(netId >= CPU_RUNTIME_BASE);
307 
308  if (toManager) {
309  memcpy(managerRuntimeData.timeTableD2, runtimeData[netId].timeTableD2, sizeof(int) * (1000 + glbNetworkConfig.maxDelay + 1));
310  memcpy(managerRuntimeData.timeTableD1, runtimeData[netId].timeTableD1, sizeof(int) * (1000 + glbNetworkConfig.maxDelay + 1));
311  } else {
312  memcpy(runtimeData[netId].timeTableD2, managerRuntimeData.timeTableD2, sizeof(int)*(1000 + glbNetworkConfig.maxDelay + 1));
313  memcpy(runtimeData[netId].timeTableD1, managerRuntimeData.timeTableD1, sizeof(int)*(1000 + glbNetworkConfig.maxDelay + 1));
314  }
315 }
316 
317 void SNN::copyExtFiringTable(int netId) {
318  assert(netId >= CPU_RUNTIME_BASE);
319 
320  memcpy(managerRuntimeData.extFiringTableEndIdxD2, runtimeData[netId].extFiringTableEndIdxD2, sizeof(int) * networkConfigs[netId].numGroups);
321  memcpy(managerRuntimeData.extFiringTableEndIdxD1, runtimeData[netId].extFiringTableEndIdxD1, sizeof(int) * networkConfigs[netId].numGroups);
322  memcpy(managerRuntimeData.extFiringTableD2, runtimeData[netId].extFiringTableD2, sizeof(int*) * networkConfigs[netId].numGroups);
323  memcpy(managerRuntimeData.extFiringTableD1, runtimeData[netId].extFiringTableD1, sizeof(int*) * networkConfigs[netId].numGroups);
324  //KERNEL_DEBUG("GPU0 D1ex:%d/D2ex:%d", managerRuntimeData.extFiringTableEndIdxD1[0], managerRuntimeData.extFiringTableEndIdxD2[0]);
325 }
326 
327 // resets nSpikeCnt[]
328 // used for management of manager runtime data
329 // FIXME: make sure this is right when separating cpu_module to a standalone class
330 // FIXME: currently this function clear nSpikeCnt of manager runtime data
331 #if defined(WIN32) || defined(WIN64) || defined(__APPLE__)
332  void SNN::resetSpikeCnt_CPU(int netId, int lGrpId) {
333 #else // POSIX
334  void* SNN::resetSpikeCnt_CPU(int netId, int lGrpId) {
335 #endif
336  assert(runtimeData[netId].memType == CPU_MEM);
337 
338  if (lGrpId == ALL) {
339  memset(runtimeData[netId].nSpikeCnt, 0, sizeof(int) * networkConfigs[netId].numN);
340  } else {
341  int lStartN = groupConfigs[netId][lGrpId].lStartN;
342  int numN = groupConfigs[netId][lGrpId].numN;
343  memset(runtimeData[netId].nSpikeCnt + lStartN, 0, sizeof(int) * numN);
344  }
345 }
346 
347 #if !defined(WIN32) && !defined(WIN64) && !defined(__APPLE__) // Linux or MAC
348  // Static multithreading subroutine method - helper for the above method
349  void* SNN::helperResetSpikeCnt_CPU(void* arguments) {
350  ThreadStruct* args = (ThreadStruct*) arguments;
351  //printf("\nThread ID: %lu and CPU: %d\n",pthread_self(), sched_getcpu());
352  ((SNN *)args->snn_pointer) -> resetSpikeCnt_CPU(args->netId, args->lGrpId);
353  pthread_exit(0);
354  }
355 #endif
356 
357 // This method loops through all spikes that are generated by neurons with a delay of 1ms
358 // and delivers the spikes to the appropriate post-synaptic neuron
359 #if defined(WIN32) || defined(WIN64) || defined(__APPLE__)
360  void SNN::doCurrentUpdateD1_CPU(int netId) {
361 #else // POSIX
362  void* SNN::doCurrentUpdateD1_CPU(int netId) {
363 #endif
364  assert(runtimeData[netId].memType == CPU_MEM);
365 
366  int k = runtimeData[netId].timeTableD1[simTimeMs + networkConfigs[netId].maxDelay + 1] - 1;
367  int k_end = runtimeData[netId].timeTableD1[simTimeMs + networkConfigs[netId].maxDelay];
368 
369  while((k >= k_end) && (k >= 0)) {
370  int lNId = runtimeData[netId].firingTableD1[k];
371  //assert(lNId < networkConfigs[netId].numN);
372 
373  DelayInfo dPar = runtimeData[netId].postDelayInfo[lNId * (networkConfigs[netId].maxDelay + 1)];
374 
375  unsigned int offset = runtimeData[netId].cumulativePost[lNId];
376 
377  for(int idx_d = dPar.delay_index_start; idx_d < (dPar.delay_index_start + dPar.delay_length); idx_d = idx_d + 1) {
378  // get synaptic info...
379  SynInfo postInfo = runtimeData[netId].postSynapticIds[offset + idx_d];
380 
381  int postNId = GET_CONN_NEURON_ID(postInfo);
382  assert(postNId < networkConfigs[netId].numNAssigned);
383 
384  int synId = GET_CONN_SYN_ID(postInfo);
385  assert(synId < (runtimeData[netId].Npre[postNId]));
386 
387  if (postNId < networkConfigs[netId].numN) // test if post-neuron is a local neuron
388  generatePostSynapticSpike(lNId /* preNId */, postNId, synId, 0, netId);
389  }
390 
391  k = k - 1;
392  }
393 }
394 
395 #if !defined(WIN32) && !defined(WIN64) && !defined(__APPLE__) // Linux or MAC
396  // Static multithreading subroutine method - helper for the above method
397  void* SNN::helperDoCurrentUpdateD1_CPU(void* arguments) {
398  ThreadStruct* args = (ThreadStruct*) arguments;
399  //printf("\nThread ID: %lu and CPU: %d\n",pthread_self(), sched_getcpu());
400  ((SNN *)args->snn_pointer) -> doCurrentUpdateD1_CPU(args->netId);
401  pthread_exit(0);
402  }
403 #endif
404 
405 // This method loops through all spikes that are generated by neurons with a delay of 2+ms
406 // and delivers the spikes to the appropriate post-synaptic neuron
407 #if defined(WIN32) || defined(WIN64) || defined(__APPLE__)
408  void SNN::doCurrentUpdateD2_CPU(int netId) {
409 #else // POSIX
410  void* SNN::doCurrentUpdateD2_CPU(int netId) {
411 #endif
412  assert(runtimeData[netId].memType == CPU_MEM);
413 
414  if (networkConfigs[netId].maxDelay > 1) {
415  int k = runtimeData[netId].timeTableD2[simTimeMs + 1 + networkConfigs[netId].maxDelay] - 1;
416  int k_end = runtimeData[netId].timeTableD2[simTimeMs + 1];
417  int t_pos = simTimeMs;
418 
419  while ((k >= k_end) && (k >= 0)) {
420  // get the neuron id from the index k
421  int lNId = runtimeData[netId].firingTableD2[k];
422 
423  // find the time of firing from the timeTable using index k
424  while (!((k >= runtimeData[netId].timeTableD2[t_pos + networkConfigs[netId].maxDelay]) && (k < runtimeData[netId].timeTableD2[t_pos + networkConfigs[netId].maxDelay + 1]))) {
425  t_pos = t_pos - 1;
426  assert((t_pos + networkConfigs[netId].maxDelay - 1) >= 0);
427  }
428 
429  // \TODO: Instead of using the complex timeTable, can neuronFiringTime value...???
430  // Calculate the time difference between time of firing of neuron and the current time...
431  int tD = simTimeMs - t_pos;
432 
433  assert((tD < networkConfigs[netId].maxDelay) && (tD >= 0));
434  //assert(lNId < networkConfigs[netId].numN);
435 
436  DelayInfo dPar = runtimeData[netId].postDelayInfo[lNId * (networkConfigs[netId].maxDelay + 1) + tD];
437 
438  unsigned int offset = runtimeData[netId].cumulativePost[lNId];
439 
440  // for each delay variables
441  for (int idx_d = dPar.delay_index_start; idx_d < (dPar.delay_index_start + dPar.delay_length); idx_d = idx_d + 1) {
442  // get synaptic info...
443  SynInfo postInfo = runtimeData[netId].postSynapticIds[offset + idx_d];
444 
445  int postNId = GET_CONN_NEURON_ID(postInfo);
446  assert(postNId < networkConfigs[netId].numNAssigned);
447 
448  int synId = GET_CONN_SYN_ID(postInfo);
449  assert(synId < (runtimeData[netId].Npre[postNId]));
450 
451  if (postNId < networkConfigs[netId].numN) // test if post-neuron is a local neuron
452  generatePostSynapticSpike(lNId /* preNId */, postNId, synId, tD, netId);
453  }
454 
455  k = k - 1;
456  }
457  }
458 }
459 
460 #if !defined(WIN32) && !defined(WIN64) && !defined(__APPLE__) // Linux or MAC
461  // Static multithreading subroutine method - helper for the above method
462  void* SNN::helperDoCurrentUpdateD2_CPU(void* arguments) {
463  ThreadStruct* args = (ThreadStruct*) arguments;
464  //printf("\nThread ID: %lu and CPU: %d\n",pthread_self(), sched_getcpu());
465  ((SNN *)args->snn_pointer) -> doCurrentUpdateD2_CPU(args->netId);
466  pthread_exit(0);
467  }
468 #endif
469 
470 #if defined(WIN32) || defined(WIN64) || defined(__APPLE__)
471  void SNN::doSTPUpdateAndDecayCond_CPU(int netId) {
472 #else // POSIX
473  void* SNN::doSTPUpdateAndDecayCond_CPU(int netId) {
474 #endif
475  assert(runtimeData[netId].memType == CPU_MEM);
476  // ToDo: This can be further optimized using multiple threads allocated on mulitple CPU cores
477  //decay the STP variables before adding new spikes.
478  for (int lGrpId = 0; lGrpId < networkConfigs[netId].numGroups; lGrpId++) {
479  for(int lNId = groupConfigs[netId][lGrpId].lStartN; lNId <= groupConfigs[netId][lGrpId].lEndN; lNId++) {
480  if (groupConfigs[netId][lGrpId].WithSTP) {
481  int ind_plus = STP_BUF_POS(lNId, simTime, glbNetworkConfig.maxDelay);
482  int ind_minus = STP_BUF_POS(lNId, (simTime - 1), glbNetworkConfig.maxDelay);
483  runtimeData[netId].stpu[ind_plus] = runtimeData[netId].stpu[ind_minus] * (1.0f - groupConfigs[netId][lGrpId].STP_tau_u_inv);
484  runtimeData[netId].stpx[ind_plus] = runtimeData[netId].stpx[ind_minus] + (1.0f - runtimeData[netId].stpx[ind_minus]) * groupConfigs[netId][lGrpId].STP_tau_x_inv;
485  }
486 
487  // decay conductances
488  if (networkConfigs[netId].sim_with_conductances && IS_REGULAR_NEURON(lNId, networkConfigs[netId].numNReg, networkConfigs[netId].numNPois)) {
489  runtimeData[netId].gAMPA[lNId] *= dAMPA;
490  if (sim_with_NMDA_rise) {
491  runtimeData[netId].gNMDA_r[lNId] *= rNMDA; // rise
492  runtimeData[netId].gNMDA_d[lNId] *= dNMDA; // decay
493  } else {
494  runtimeData[netId].gNMDA[lNId] *= dNMDA; // instantaneous rise
495  }
496 
497  runtimeData[netId].gGABAa[lNId] *= dGABAa;
498  if (sim_with_GABAb_rise) {
499  runtimeData[netId].gGABAb_r[lNId] *= rGABAb; // rise
500  runtimeData[netId].gGABAb_d[lNId] *= dGABAb; // decay
501  } else {
502  runtimeData[netId].gGABAb[lNId] *= dGABAb; // instantaneous rise
503  }
504  }
505  }
506  }
507 }
508 
509 #if !defined(WIN32) && !defined(WIN64) && !defined(__APPLE__) // Linux or MAC
510  // Static multithreading subroutine method - helper for the above method
511  void* SNN::helperDoSTPUpdateAndDecayCond_CPU(void* arguments) {
512  ThreadStruct* args = (ThreadStruct*) arguments;
513  //printf("\nThread ID: %lu and CPU: %d\n",pthread_self(), sched_getcpu());
514  ((SNN *)args->snn_pointer) -> doSTPUpdateAndDecayCond_CPU(args->netId);
515  pthread_exit(0);
516  }
517 #endif
518 
519 #if defined(WIN32) || defined(WIN64) || defined(__APPLE__)
520  void SNN::findFiring_CPU(int netId) {
521 #else // POSIX
522  void* SNN::findFiring_CPU(int netId) {
523 #endif
524  assert(runtimeData[netId].memType == CPU_MEM);
525  // ToDo: This can be further optimized using multiple threads allocated on mulitple CPU cores
526  for(int lGrpId = 0; lGrpId < networkConfigs[netId].numGroups; lGrpId++) {
527  for (int lNId = groupConfigs[netId][lGrpId].lStartN; lNId <= groupConfigs[netId][lGrpId].lEndN; lNId++) {
528  bool needToWrite = false;
529  // given group of neurons belong to the poisson group....
530  if (groupConfigs[netId][lGrpId].Type & POISSON_NEURON) {
531  if(groupConfigs[netId][lGrpId].isSpikeGenFunc) {
532  unsigned int offset = lNId - groupConfigs[netId][lGrpId].lStartN + groupConfigs[netId][lGrpId].Noffset;
533  needToWrite = getSpikeGenBit(offset, netId);
534  } else { // spikes generated by poission rate
535  needToWrite = getPoissonSpike(lNId, netId);
536  }
537  // Note: valid lastSpikeTime of spike gen neurons is required by userDefinedSpikeGenerator()
538  if (needToWrite)
539  runtimeData[netId].lastSpikeTime[lNId] = simTime;
540  } else { // Regular neuron
541  if (runtimeData[netId].curSpike[lNId]) {
542  runtimeData[netId].curSpike[lNId] = false;
543  needToWrite = true;
544  }
545 
546  // log v, u value if any active neuron monitor is presented
547  if (networkConfigs[netId].sim_with_nm && lNId - groupConfigs[netId][lGrpId].lStartN < MAX_NEURON_MON_GRP_SZIE) {
548  int idxBase = networkConfigs[netId].numGroups * MAX_NEURON_MON_GRP_SZIE * simTimeMs + lGrpId * MAX_NEURON_MON_GRP_SZIE;
549  runtimeData[netId].nVBuffer[idxBase + lNId - groupConfigs[netId][lGrpId].lStartN] = runtimeData[netId].voltage[lNId];
550  runtimeData[netId].nUBuffer[idxBase + lNId - groupConfigs[netId][lGrpId].lStartN] = runtimeData[netId].recovery[lNId];
551  //KERNEL_INFO("simTimeMs: %d --base:%d -- %f -- %f --%f --%f", simTimeMs, idxBase + lNId - groupConfigs[netId][lGrpId].lStartN, runtimeData[netId].voltage[lNId], runtimeData[netId].recovery[lNId], runtimeData[netId].nVBuffer[idxBase + lNId - groupConfigs[netId][lGrpId].lStartN], runtimeData[netId].nUBuffer[idxBase + lNId - groupConfigs[netId][lGrpId].lStartN]);
552  }
553  }
554 
555  // his flag is set if with_stdp is set and also grpType is set to have GROUP_SYN_FIXED
556  if (needToWrite) {
557  bool hasSpace = false;
558  int fireId = -1;
559 
560  // update spike count: spikeCountD2Sec(W), spikeCountD1Sec(W), spikeCountLastSecLeftD2(R)
561  if (groupConfigs[netId][lGrpId].MaxDelay == 1)
562  {
563  if (runtimeData[netId].spikeCountD1Sec + 1 < networkConfigs[netId].maxSpikesD1) {
564  fireId = runtimeData[netId].spikeCountD1Sec;
565  runtimeData[netId].spikeCountD1Sec++;
566  }
567  } else { // MaxDelay > 1
568  if (runtimeData[netId].spikeCountD2Sec + runtimeData[netId].spikeCountLastSecLeftD2 + 1 < networkConfigs[netId].maxSpikesD2) {
569  fireId = runtimeData[netId].spikeCountD2Sec + runtimeData[netId].spikeCountLastSecLeftD2;
570  runtimeData[netId].spikeCountD2Sec++;
571  }
572  }
573 
574  if (fireId == -1) // no space availabe in firing table, drop the spike
575  continue;
576 
577  // update firing table: firingTableD1(W), firingTableD2(W)
578  if (groupConfigs[netId][lGrpId].MaxDelay == 1) {
579  runtimeData[netId].firingTableD1[fireId] = lNId;
580  } else { // MaxDelay > 1
581  runtimeData[netId].firingTableD2[fireId] = lNId;
582  }
583 
584  // update external firing table: extFiringTableEndIdxD1(W), extFiringTableEndIdxD2(W), extFiringTableD1(W), extFiringTableD2(W)
585  if (groupConfigs[netId][lGrpId].hasExternalConnect) {
586  int extFireId = -1;
587  if (groupConfigs[netId][lGrpId].MaxDelay == 1) {
588  extFireId = runtimeData[netId].extFiringTableEndIdxD1[lGrpId]++;
589  runtimeData[netId].extFiringTableD1[lGrpId][extFireId] = lNId + groupConfigs[netId][lGrpId].LtoGOffset;
590  } else { // MaxDelay > 1
591  extFireId = runtimeData[netId].extFiringTableEndIdxD2[lGrpId]++;
592  runtimeData[netId].extFiringTableD2[lGrpId][extFireId] = lNId + groupConfigs[netId][lGrpId].LtoGOffset;
593  }
594  assert(extFireId != -1);
595  }
596 
597  // update STP for neurons that fire
598  if (groupConfigs[netId][lGrpId].WithSTP) {
599  firingUpdateSTP(lNId, lGrpId, netId);
600  }
601 
602  // keep track of number spikes per neuron
603  runtimeData[netId].nSpikeCnt[lNId]++;
604 
605  if (IS_REGULAR_NEURON(lNId, networkConfigs[netId].numNReg, networkConfigs[netId].numNPois))
606  resetFiredNeuron(lNId, lGrpId, netId);
607 
608  // STDP calculation: the post-synaptic neuron fires after the arrival of a pre-synaptic spike
609  if (!sim_in_testing && groupConfigs[netId][lGrpId].WithSTDP) {
610  updateLTP(lNId, lGrpId, netId);
611  }
612  }
613  }
614  }
615 }
616 
617 #if !defined(WIN32) && !defined(WIN64) && !defined(__APPLE__) // Linux or MAC
618  // Static multithreading subroutine method - helper for the above method
619  void* SNN::helperFindFiring_CPU(void* arguments) {
620  ThreadStruct* args = (ThreadStruct*) arguments;
621  //printf("\nThread ID: %lu and CPU: %d\n",pthread_self(), sched_getcpu());
622  ((SNN *)args->snn_pointer) -> findFiring_CPU(args->netId);
623  pthread_exit(0);
624  }
625 #endif
626 
627 
628 void SNN::updateLTP(int lNId, int lGrpId, int netId) {
629  unsigned int pos_ij = runtimeData[netId].cumulativePre[lNId]; // the index of pre-synaptic neuron
630  for(int j = 0; j < runtimeData[netId].Npre_plastic[lNId]; pos_ij++, j++) {
631  int stdp_tDiff = (simTime - runtimeData[netId].synSpikeTime[pos_ij]);
632  assert(!((stdp_tDiff < 0) && (runtimeData[netId].synSpikeTime[pos_ij] != MAX_SIMULATION_TIME)));
633 
634  if (stdp_tDiff > 0) {
635  // check this is an excitatory or inhibitory synapse
636  if (groupConfigs[netId][lGrpId].WithESTDP && runtimeData[netId].maxSynWt[pos_ij] >= 0) { // excitatory synapse
637  // Handle E-STDP curve
638  switch (groupConfigs[netId][lGrpId].WithESTDPcurve) {
639  case EXP_CURVE: // exponential curve
640  if (stdp_tDiff * groupConfigs[netId][lGrpId].TAU_PLUS_INV_EXC < 25)
641  runtimeData[netId].wtChange[pos_ij] += STDP(stdp_tDiff, groupConfigs[netId][lGrpId].ALPHA_PLUS_EXC, groupConfigs[netId][lGrpId].TAU_PLUS_INV_EXC);
642  break;
643  case TIMING_BASED_CURVE: // sc curve
644  if (stdp_tDiff * groupConfigs[netId][lGrpId].TAU_PLUS_INV_EXC < 25) {
645  if (stdp_tDiff <= groupConfigs[netId][lGrpId].GAMMA)
646  runtimeData[netId].wtChange[pos_ij] += groupConfigs[netId][lGrpId].OMEGA + groupConfigs[netId][lGrpId].KAPPA * STDP(stdp_tDiff, groupConfigs[netId][lGrpId].ALPHA_PLUS_EXC, groupConfigs[netId][lGrpId].TAU_PLUS_INV_EXC);
647  else // stdp_tDiff > GAMMA
648  runtimeData[netId].wtChange[pos_ij] -= STDP(stdp_tDiff, groupConfigs[netId][lGrpId].ALPHA_PLUS_EXC, groupConfigs[netId][lGrpId].TAU_PLUS_INV_EXC);
649  }
650  break;
651  default:
652  KERNEL_ERROR("Invalid E-STDP curve!");
653  break;
654  }
655  } else if (groupConfigs[netId][lGrpId].WithISTDP && runtimeData[netId].maxSynWt[pos_ij] < 0) { // inhibitory synapse
656  // Handle I-STDP curve // Handle I-STDP curve
657  switch (groupConfigs[netId][lGrpId].WithISTDPcurve) {
658  case EXP_CURVE: // exponential curve
659  if (stdp_tDiff * groupConfigs[netId][lGrpId].TAU_PLUS_INV_INB < 25) { // LTP of inhibitory synapse, which decreases synapse weight
660  runtimeData[netId].wtChange[pos_ij] -= STDP(stdp_tDiff, groupConfigs[netId][lGrpId].ALPHA_PLUS_INB, groupConfigs[netId][lGrpId].TAU_PLUS_INV_INB);
661  }
662  break;
663  case PULSE_CURVE: // pulse curve
664  if (stdp_tDiff <= groupConfigs[netId][lGrpId].LAMBDA) { // LTP of inhibitory synapse, which decreases synapse weight
665  runtimeData[netId].wtChange[pos_ij] -= groupConfigs[netId][lGrpId].BETA_LTP;
666  //printf("I-STDP LTP\n");
667  } else if (stdp_tDiff <= groupConfigs[netId][lGrpId].DELTA) { // LTD of inhibitory syanpse, which increase sysnapse weight
668  runtimeData[netId].wtChange[pos_ij] -= groupConfigs[netId][lGrpId].BETA_LTD;
669  //printf("I-STDP LTD\n");
670  } else { /*do nothing*/}
671  break;
672  default:
673  KERNEL_ERROR("Invalid I-STDP curve!");
674  break;
675  }
676  }
677  }
678  }
679 }
680 
681 void SNN::firingUpdateSTP(int lNId, int lGrpId, int netId) {
682  // update the spike-dependent part of du/dt and dx/dt
683  // we need to retrieve the STP values from the right buffer position (right before vs. right after the spike)
684  int ind_plus = STP_BUF_POS(lNId, simTime, networkConfigs[netId].maxDelay); // index of right after the spike, such as in u^+
685  int ind_minus = STP_BUF_POS(lNId, (simTime - 1), networkConfigs[netId].maxDelay); // index of right before the spike, such as in u^-
686 
687  // du/dt = -u/tau_F + U * (1-u^-) * \delta(t-t_{spk})
688  runtimeData[netId].stpu[ind_plus] += groupConfigs[netId][lGrpId].STP_U * (1.0f - runtimeData[netId].stpu[ind_minus]);
689 
690  // dx/dt = (1-x)/tau_D - u^+ * x^- * \delta(t-t_{spk})
691  runtimeData[netId].stpx[ind_plus] -= runtimeData[netId].stpu[ind_plus] * runtimeData[netId].stpx[ind_minus];
692 }
693 
694 void SNN::resetFiredNeuron(int lNId, short int lGrpId, int netId) {
695  if (groupConfigs[netId][lGrpId].WithSTDP)
696  runtimeData[netId].lastSpikeTime[lNId] = simTime;
697 
698  if (networkConfigs[netId].sim_with_homeostasis) {
699  // with homeostasis flag can be used here.
700  runtimeData[netId].avgFiring[lNId] += 1000 / (groupConfigs[netId][lGrpId].avgTimeScale * 1000);
701  }
702 }
703 
704 bool SNN::getPoissonSpike(int lNId, int netId) {
705  // Random number value is less than the poisson firing probability
706  // if poisson firing probability is say 1.0 then the random poisson ptr
707  // will always be less than 1.0 and hence it will continiously fire
708  return runtimeData[netId].randNum[lNId - networkConfigs[netId].numNReg] * 1000.0f
709  < runtimeData[netId].poissonFireRate[lNId - networkConfigs[netId].numNReg];
710 }
711 
712 bool SNN::getSpikeGenBit(unsigned int nIdPos, int netId) {
713  const int nIdBitPos = nIdPos % 32;
714  const int nIdIndex = nIdPos / 32;
715  return ((runtimeData[netId].spikeGenBits[nIdIndex] >> nIdBitPos) & 0x1);
716 }
717 
718 /*
719 * The sequence of handling an post synaptic spike in CPU mode:
720 * P1. Load wt into change (temporary variable)
721 * P2. Modulate change by STP (if enabled)
722 * P3-1. Modulate change by d_mulSynSlow and d_mulSynFast
723 * P3-2. Accumulate g(AMPA,NMDA,GABAa,GABAb) or current
724 * P4. Update synSpikeTime
725 * P5. Update DA,5HT,ACh,NE accordingly
726 * P6. Update STDP wtChange
727 * P7. Update v(voltage), u(recovery)
728 * P8. Update homeostasis
729 * P9. Decay and log DA,5HT,ACh,NE
730 */
731 void SNN::generatePostSynapticSpike(int preNId, int postNId, int synId, int tD, int netId) {
732  // get the cumulative position for quick access
733  unsigned int pos = runtimeData[netId].cumulativePre[postNId] + synId;
734  assert(postNId < networkConfigs[netId].numNReg); // \FIXME is this assert supposed to be for pos?
735 
736  // get group id of pre- / post-neuron
737  short int post_grpId = runtimeData[netId].grpIds[postNId];
738  short int pre_grpId = runtimeData[netId].grpIds[preNId];
739 
740  unsigned int pre_type = groupConfigs[netId][pre_grpId].Type;
741 
742  // get connect info from the cumulative synapse index for mulSynFast/mulSynSlow (requires less memory than storing
743  // mulSynFast/Slow per synapse or storing a pointer to grpConnectInfo_s)
744  // mulSynFast will be applied to fast currents (either AMPA or GABAa)
745  // mulSynSlow will be applied to slow currents (either NMDA or GABAb)
746  short int mulIndex = runtimeData[netId].connIdsPreIdx[pos];
747  assert(mulIndex >= 0 && mulIndex < numConnections);
748 
749  // P1
750  // for each presynaptic spike, postsynaptic (synaptic) current is going to increase by some amplitude (change)
751  // generally speaking, this amplitude is the weight; but it can be modulated by STP
752  float change = runtimeData[netId].wt[pos];
753 
754  // P2
755  if (groupConfigs[netId][pre_grpId].WithSTP) {
756  // if pre-group has STP enabled, we need to modulate the weight
757  // NOTE: Order is important! (Tsodyks & Markram, 1998; Mongillo, Barak, & Tsodyks, 2008)
758  // use u^+ (value right after spike-update) but x^- (value right before spike-update)
759 
760  // dI/dt = -I/tau_S + A * u^+ * x^- * \delta(t-t_{spk})
761  // I noticed that for connect(.., RangeDelay(1), ..) tD will be 0
762  int ind_minus = STP_BUF_POS(preNId, (simTime-tD-1), networkConfigs[netId].maxDelay);
763  int ind_plus = STP_BUF_POS(preNId, (simTime-tD), networkConfigs[netId].maxDelay);
764 
765  change *= groupConfigs[netId][pre_grpId].STP_A * runtimeData[netId].stpu[ind_plus] * runtimeData[netId].stpx[ind_minus];
766 
767  //printf("%d: %d[%d], numN=%d, td=%d, maxDelay_=%d, ind-=%d, ind+=%d, stpu=[%f,%f], stpx=[%f,%f], change=%f, wt=%f\n",
768  // simTime, pre_grpId, preNId,
769  // groupConfigs[netId][pre_grpId].numN, tD, networkConfigs[netId].maxDelay, ind_minus, ind_plus,
770  // runtimeData[netId].stpu[ind_minus], runtimeData[netId].stpu[ind_plus],
771  // runtimeData[netId].stpx[ind_minus], runtimeData[netId].stpx[ind_plus],
772  // change, runtimeData[netId].wt[pos]);
773  }
774 
775  // P3-1, P3-2
776  // update currents
777  // NOTE: it's faster to += 0.0 rather than checking for zero and not updating
778  if (sim_with_conductances) {
779  if (pre_type & TARGET_AMPA) // if postNId expresses AMPAR
780  runtimeData[netId].gAMPA [postNId] += change * mulSynFast[mulIndex]; // scale by some factor
781  if (pre_type & TARGET_NMDA) {
782  if (sim_with_NMDA_rise) {
783  runtimeData[netId].gNMDA_r[postNId] += change * sNMDA * mulSynSlow[mulIndex];
784  runtimeData[netId].gNMDA_d[postNId] += change * sNMDA * mulSynSlow[mulIndex];
785  } else {
786  runtimeData[netId].gNMDA [postNId] += change * mulSynSlow[mulIndex];
787  }
788  }
789  if (pre_type & TARGET_GABAa)
790  runtimeData[netId].gGABAa[postNId] -= change * mulSynFast[mulIndex]; // wt should be negative for GABAa and GABAb
791  if (pre_type & TARGET_GABAb) {
792  if (sim_with_GABAb_rise) {
793  runtimeData[netId].gGABAb_r[postNId] -= change * sGABAb * mulSynSlow[mulIndex];
794  runtimeData[netId].gGABAb_d[postNId] -= change * sGABAb * mulSynSlow[mulIndex];
795  } else {
796  runtimeData[netId].gGABAb[postNId] -= change * mulSynSlow[mulIndex];
797  }
798  }
799  } else {
800  runtimeData[netId].current[postNId] += change;
801  }
802 
803  // P4
804  runtimeData[netId].synSpikeTime[pos] = simTime;
805 
806  // P5
807  // Got one spike from dopaminergic neuron, increase dopamine concentration in the target area
808  if (pre_type & TARGET_DA) {
809  runtimeData[netId].grpDA[post_grpId] += 0.04;
810  }
811 
812  // P6
813  // STDP calculation: the post-synaptic neuron fires before the arrival of a pre-synaptic spike
814  if (!sim_in_testing && groupConfigs[netId][post_grpId].WithSTDP) {
815  int stdp_tDiff = (simTime - runtimeData[netId].lastSpikeTime[postNId]);
816 
817  if (stdp_tDiff >= 0) {
818  if (groupConfigs[netId][post_grpId].WithISTDP && ((pre_type & TARGET_GABAa) || (pre_type & TARGET_GABAb))) { // inhibitory syanpse
819  // Handle I-STDP curve
820  switch (groupConfigs[netId][post_grpId].WithISTDPcurve) {
821  case EXP_CURVE: // exponential curve
822  if (stdp_tDiff * groupConfigs[netId][post_grpId].TAU_MINUS_INV_INB < 25) { // LTD of inhibitory syanpse, which increase synapse weight
823  runtimeData[netId].wtChange[pos] -= STDP(stdp_tDiff, groupConfigs[netId][post_grpId].ALPHA_MINUS_INB, groupConfigs[netId][post_grpId].TAU_MINUS_INV_INB);
824  }
825  break;
826  case PULSE_CURVE: // pulse curve
827  if (stdp_tDiff <= groupConfigs[netId][post_grpId].LAMBDA) { // LTP of inhibitory synapse, which decreases synapse weight
828  runtimeData[netId].wtChange[pos] -= groupConfigs[netId][post_grpId].BETA_LTP;
829  } else if (stdp_tDiff <= groupConfigs[netId][post_grpId].DELTA) { // LTD of inhibitory syanpse, which increase synapse weight
830  runtimeData[netId].wtChange[pos] -= groupConfigs[netId][post_grpId].BETA_LTD;
831  } else { /*do nothing*/ }
832  break;
833  default:
834  KERNEL_ERROR("Invalid I-STDP curve");
835  break;
836  }
837  } else if (groupConfigs[netId][post_grpId].WithESTDP && ((pre_type & TARGET_AMPA) || (pre_type & TARGET_NMDA))) { // excitatory synapse
838  // Handle E-STDP curve
839  switch (groupConfigs[netId][post_grpId].WithESTDPcurve) {
840  case EXP_CURVE: // exponential curve
841  case TIMING_BASED_CURVE: // sc curve
842  if (stdp_tDiff * groupConfigs[netId][post_grpId].TAU_MINUS_INV_EXC < 25)
843  runtimeData[netId].wtChange[pos] += STDP(stdp_tDiff, groupConfigs[netId][post_grpId].ALPHA_MINUS_EXC, groupConfigs[netId][post_grpId].TAU_MINUS_INV_EXC);
844  break;
845  default:
846  KERNEL_ERROR("Invalid E-STDP curve");
847  break;
848  }
849  } else { /*do nothing*/ }
850  }
851  assert(!((stdp_tDiff < 0) && (runtimeData[netId].lastSpikeTime[postNId] != MAX_SIMULATION_TIME)));
852  }
853 }
854 
855 // single integration step for voltage equation of 4-param Izhikevich
856 inline
857 float dvdtIzhikevich4(float volt, float recov, float totalCurrent, float timeStep = 1.0f) {
858  return (((0.04f * volt + 5.0f) * volt + 140.0f - recov + totalCurrent) * timeStep);
859 }
860 
861 // single integration step for recovery equation of 4-param Izhikevich
862 inline
863 float dudtIzhikevich4(float volt, float recov, float izhA, float izhB, float timeStep = 1.0f) {
864  return (izhA * (izhB * volt - recov) * timeStep);
865 }
866 
867 // single integration step for voltage equation of 9-param Izhikevich
868 inline
869 float dvdtIzhikevich9(float volt, float recov, float invCapac, float izhK, float voltRest,
870  float voltInst, float totalCurrent, float timeStep = 1.0f)
871 {
872  return ((izhK * (volt - voltRest) * (volt - voltInst) - recov + totalCurrent) * invCapac * timeStep);
873 }
874 
875 // single integration step for recovery equation of 9-param Izhikevich
876 inline
877 float dudtIzhikevich9(float volt, float recov, float voltRest, float izhA, float izhB, float timeStep = 1.0f) {
878  return (izhA * (izhB * (volt - voltRest) - recov) * timeStep);
879 }
880 
881 // single integration step for voltage equation of LIF neurons
882 inline
883 float dvdtLIF(float volt, float lif_vReset, float lif_gain, float lif_bias, int lif_tau_m, float totalCurrent, float timeStep = 1.0f) {
884  return ((lif_vReset -volt + ((totalCurrent * lif_gain) + lif_bias))/ (float) lif_tau_m) * timeStep;
885 }
886 
887 float SNN::getCompCurrent(int netid, int lGrpId, int lneurId, float const0, float const1) {
888  float compCurrent = 0.0f;
889  for (int k = 0; k < groupConfigs[netid][lGrpId].numCompNeighbors; k++) {
890  // compartment connections are always one-to-one, which means that the i-th neuron in grpId connects
891  // to the i-th neuron in grpIdOther
892  int lGrpIdOther = groupConfigs[netid][lGrpId].compNeighbors[k];
893  int lneurIdOther = lneurId - groupConfigs[netid][lGrpId].lStartN + groupConfigs[netid][lGrpIdOther].lStartN;
894  compCurrent += groupConfigs[netid][lGrpId].compCoupling[k] * ((runtimeData[netid].voltage[lneurIdOther] + const1)
895  - (runtimeData[netid].voltage[lneurId] + const0));
896  }
897 
898  return compCurrent;
899 }
900 
901 #if defined(WIN32) || defined(WIN64) || defined(__APPLE__)
902  void SNN::globalStateUpdate_CPU(int netId) {
903 #else // POSIX
904  void* SNN::globalStateUpdate_CPU(int netId) {
905 #endif
906  assert(runtimeData[netId].memType == CPU_MEM);
907 
908  float timeStep = networkConfigs[netId].timeStep;
909 
910  // loop that allows smaller integration time step for v's and u's
911  for (int j = 1; j <= networkConfigs[netId].simNumStepsPerMs; j++) {
912  bool lastIter = (j == networkConfigs[netId].simNumStepsPerMs);
913  for (int lGrpId = 0; lGrpId < networkConfigs[netId].numGroups; lGrpId++) {
914  if (groupConfigs[netId][lGrpId].Type & POISSON_NEURON) {
915  if (groupConfigs[netId][lGrpId].WithHomeostasis & (lastIter)) {
916  for (int lNId = groupConfigs[netId][lGrpId].lStartN; lNId <= groupConfigs[netId][lGrpId].lEndN; lNId++)
917  runtimeData[netId].avgFiring[lNId] *= groupConfigs[netId][lGrpId].avgTimeScale_decay;
918  }
919  continue;
920  }
921 
922  for (int lNId = groupConfigs[netId][lGrpId].lStartN; lNId <= groupConfigs[netId][lGrpId].lEndN; lNId++) {
923  assert(lNId < networkConfigs[netId].numNReg);
924 
925  // P7
926  // update conductances
927  float v = runtimeData[netId].voltage[lNId];
928  float v_next = runtimeData[netId].nextVoltage[lNId];
929  float u = runtimeData[netId].recovery[lNId];
930  float I_sum, NMDAtmp;
931  float gNMDA, gGABAb;
932 
933  // pre-load izhikevich variables to avoid unnecessary memory accesses & unclutter the code.
934  float k = runtimeData[netId].Izh_k[lNId];
935  float vr = runtimeData[netId].Izh_vr[lNId];
936  float vt = runtimeData[netId].Izh_vt[lNId];
937  float inverse_C = 1.0f / runtimeData[netId].Izh_C[lNId];
938  float vpeak = runtimeData[netId].Izh_vpeak[lNId];
939  float a = runtimeData[netId].Izh_a[lNId];
940  float b = runtimeData[netId].Izh_b[lNId];
941 
942  // pre-load LIF parameters
943  int lif_tau_m = runtimeData[netId].lif_tau_m[lNId];
944  int lif_tau_ref = runtimeData[netId].lif_tau_ref[lNId];
945  int lif_tau_ref_c = runtimeData[netId].lif_tau_ref_c[lNId];
946  float lif_vTh = runtimeData[netId].lif_vTh[lNId];
947  float lif_vReset = runtimeData[netId].lif_vReset[lNId];
948  float lif_gain = runtimeData[netId].lif_gain[lNId];
949  float lif_bias = runtimeData[netId].lif_bias[lNId];
950 
951  float totalCurrent = runtimeData[netId].extCurrent[lNId];
952 
953  if (networkConfigs[netId].sim_with_conductances) {
954  NMDAtmp = (v + 80.0f) * (v + 80.0f) / 60.0f / 60.0f;
955  gNMDA = (networkConfigs[netId].sim_with_NMDA_rise) ? (runtimeData[netId].gNMDA_d[lNId] - runtimeData[netId].gNMDA_r[lNId]) : runtimeData[netId].gNMDA[lNId];
956  gGABAb = (networkConfigs[netId].sim_with_GABAb_rise) ? (runtimeData[netId].gGABAb_d[lNId] - runtimeData[netId].gGABAb_r[lNId]) : runtimeData[netId].gGABAb[lNId];
957 
958  I_sum = -(runtimeData[netId].gAMPA[lNId] * (v - 0.0f)
959  + gNMDA * NMDAtmp / (1.0f + NMDAtmp) * (v - 0.0f)
960  + runtimeData[netId].gGABAa[lNId] * (v + 70.0f)
961  + gGABAb * (v + 90.0f));
962 
963  totalCurrent += I_sum;
964  }
965  else {
966  totalCurrent += runtimeData[netId].current[lNId];
967  }
968  if (groupConfigs[netId][lGrpId].withCompartments) {
969  totalCurrent += getCompCurrent(netId, lGrpId, lNId);
970  }
971 
972  switch (networkConfigs[netId].simIntegrationMethod) {
973  case FORWARD_EULER:
974  if (!groupConfigs[netId][lGrpId].withParamModel_9 && !groupConfigs[netId][lGrpId].isLIF)
975  {
976  // update vpos and upos for the current neuron
977  v_next = v + dvdtIzhikevich4(v, u, totalCurrent, timeStep);
978  if (v_next > 30.0f) {
979  v_next = 30.0f; // break the loop but evaluate u[i]
980  runtimeData[netId].curSpike[lNId] = true;
981  v_next = runtimeData[netId].Izh_c[lNId];
982  u += runtimeData[netId].Izh_d[lNId];
983  }
984  }
985  else if (!groupConfigs[netId][lGrpId].isLIF)
986  {
987  // update vpos and upos for the current neuron
988  v_next = v + dvdtIzhikevich9(v, u, inverse_C, k, vr, vt, totalCurrent, timeStep);
989  if (v_next > vpeak) {
990  v_next = vpeak; // break the loop but evaluate u[i]
991  runtimeData[netId].curSpike[lNId] = true;
992  v_next = runtimeData[netId].Izh_c[lNId];
993  u += runtimeData[netId].Izh_d[lNId];
994  }
995  }
996 
997  else{
998  if (lif_tau_ref_c > 0){
999  if(lastIter){
1000  runtimeData[netId].lif_tau_ref_c[lNId] -= 1;
1001  v_next = lif_vReset;
1002  }
1003  }
1004  else{
1005  if (v_next > lif_vTh) {
1006  runtimeData[netId].curSpike[lNId] = true;
1007  v_next = lif_vReset;
1008 
1009  if(lastIter){
1010  runtimeData[netId].lif_tau_ref_c[lNId] = lif_tau_ref;
1011  }
1012  else{
1013  runtimeData[netId].lif_tau_ref_c[lNId] = lif_tau_ref + 1;
1014  }
1015  }
1016  else{
1017  v_next = v + dvdtLIF(v, lif_vReset, lif_gain, lif_bias, lif_tau_m, totalCurrent, timeStep);
1018  }
1019  }
1020  }
1021 
1022  if (groupConfigs[netId][lGrpId].isLIF){
1023  if (v_next < lif_vReset) v_next = lif_vReset;
1024  }
1025  else{
1026  if (v_next < -90.0f) v_next = -90.0f;
1027 
1028  if (!groupConfigs[netId][lGrpId].withParamModel_9)
1029  {
1030  u += dudtIzhikevich4(v_next, u, a, b, timeStep);
1031  }
1032  else
1033  {
1034  u += dudtIzhikevich9(v_next, u, vr, a, b, timeStep);
1035  }
1036  }
1037  break;
1038 
1039  case RUNGE_KUTTA4:
1040 
1041  if (!groupConfigs[netId][lGrpId].withParamModel_9 && !groupConfigs[netId][lGrpId].isLIF) {
1042  // 4-param Izhikevich
1043  float k1 = dvdtIzhikevich4(v, u, totalCurrent, timeStep);
1044  float l1 = dudtIzhikevich4(v, u, a, b, timeStep);
1045 
1046  float k2 = dvdtIzhikevich4(v + k1 / 2.0f, u + l1 / 2.0f, totalCurrent,
1047  timeStep);
1048  float l2 = dudtIzhikevich4(v + k1 / 2.0f, u + l1 / 2.0f, a, b, timeStep);
1049 
1050  float k3 = dvdtIzhikevich4(v + k2 / 2.0f, u + l2 / 2.0f, totalCurrent,
1051  timeStep);
1052  float l3 = dudtIzhikevich4(v + k2 / 2.0f, u + l2 / 2.0f, a, b, timeStep);
1053 
1054  float k4 = dvdtIzhikevich4(v + k3, u + l3, totalCurrent, timeStep);
1055  float l4 = dudtIzhikevich4(v + k3, u + l3, a, b, timeStep);
1056  v_next = v + (1.0f / 6.0f) * (k1 + 2.0f * k2 + 2.0f * k3 + k4);
1057  if (v_next > 30.0f) {
1058  v_next = 30.0f;
1059  runtimeData[netId].curSpike[lNId] = true;
1060  v_next = runtimeData[netId].Izh_c[lNId];
1061  u += runtimeData[netId].Izh_d[lNId];
1062  }
1063  if (v_next < -90.0f) v_next = -90.0f;
1064 
1065  u += (1.0f / 6.0f) * (l1 + 2.0f * l2 + 2.0f * l3 + l4);
1066  }
1067  else if(!groupConfigs[netId][lGrpId].isLIF){
1068  // 9-param Izhikevich
1069  float k1 = dvdtIzhikevich9(v, u, inverse_C, k, vr, vt, totalCurrent,
1070  timeStep);
1071  float l1 = dudtIzhikevich9(v, u, vr, a, b, timeStep);
1072 
1073  float k2 = dvdtIzhikevich9(v + k1 / 2.0f, u + l1 / 2.0f, inverse_C, k, vr, vt,
1074  totalCurrent, timeStep);
1075  float l2 = dudtIzhikevich9(v + k1 / 2.0f, u + l1 / 2.0f, vr, a, b, timeStep);
1076 
1077  float k3 = dvdtIzhikevich9(v + k2 / 2.0f, u + l2 / 2.0f, inverse_C, k, vr, vt,
1078  totalCurrent, timeStep);
1079  float l3 = dudtIzhikevich9(v + k2 / 2.0f, u + l2 / 2.0f, vr, a, b, timeStep);
1080 
1081  float k4 = dvdtIzhikevich9(v + k3, u + l3, inverse_C, k, vr, vt,
1082  totalCurrent, timeStep);
1083  float l4 = dudtIzhikevich9(v + k3, u + l3, vr, a, b, timeStep);
1084 
1085  v_next = v + (1.0f / 6.0f) * (k1 + 2.0f * k2 + 2.0f * k3 + k4);
1086 
1087  if (v_next > vpeak) {
1088  v_next = vpeak; // break the loop but evaluate u[i]
1089  runtimeData[netId].curSpike[lNId] = true;
1090  v_next = runtimeData[netId].Izh_c[lNId];
1091  u += runtimeData[netId].Izh_d[lNId];
1092  }
1093 
1094  if (v_next < -90.0f) v_next = -90.0f;
1095 
1096  u += (1.0f / 6.0f) * (l1 + 2.0f * l2 + 2.0f * l3 + l4);
1097  }
1098  else{
1099  //LIF integration is always FORWARD_EULER
1100  if (lif_tau_ref_c > 0){
1101  if(lastIter){
1102  runtimeData[netId].lif_tau_ref_c[lNId] -= 1;
1103  v_next = lif_vReset;
1104  }
1105  }
1106  else{
1107  if (v_next > lif_vTh) {
1108  runtimeData[netId].curSpike[lNId] = true;
1109  v_next = lif_vReset;
1110 
1111  if(lastIter){
1112  runtimeData[netId].lif_tau_ref_c[lNId] = lif_tau_ref;
1113  }
1114  else{
1115  runtimeData[netId].lif_tau_ref_c[lNId] = lif_tau_ref + 1;
1116  }
1117  }
1118  else{
1119  v_next = v + dvdtLIF(v, lif_vReset, lif_gain, lif_bias, lif_tau_m, totalCurrent, timeStep);
1120  }
1121  }
1122  if (v_next < lif_vReset) v_next = lif_vReset;
1123  }
1124  break;
1125  case UNKNOWN_INTEGRATION:
1126  default:
1127  exitSimulation(1);
1128  }
1129 
1130  runtimeData[netId].nextVoltage[lNId] = v_next;
1131  runtimeData[netId].recovery[lNId] = u;
1132 
1133  // update current & average firing rate for homeostasis once per globalStateUpdate_CPU call
1134  if (lastIter)
1135  {
1136  if (networkConfigs[netId].sim_with_conductances) {
1137  runtimeData[netId].current[lNId] = I_sum;
1138  }
1139  else {
1140  // current must be reset here for CUBA and not STPUpdateAndDecayConductances
1141  runtimeData[netId].current[lNId] = 0.0f;
1142  }
1143 
1144  // P8
1145  // update average firing rate for homeostasis
1146  if (groupConfigs[netId][lGrpId].WithHomeostasis)
1147  runtimeData[netId].avgFiring[lNId] *= groupConfigs[netId][lGrpId].avgTimeScale_decay;
1148 
1149  // log i value if any active neuron monitor is presented
1150  if (networkConfigs[netId].sim_with_nm && lNId - groupConfigs[netId][lGrpId].lStartN < MAX_NEURON_MON_GRP_SZIE) {
1151  int idxBase = networkConfigs[netId].numGroups * MAX_NEURON_MON_GRP_SZIE * simTimeMs + lGrpId * MAX_NEURON_MON_GRP_SZIE;
1152  runtimeData[netId].nIBuffer[idxBase + lNId - groupConfigs[netId][lGrpId].lStartN] = totalCurrent;
1153  }
1154  }
1155  } // end StartN...EndN
1156 
1157  // decay dopamine concentration once per globalStateUpdate_CPU call
1158  if (lastIter)
1159  {
1160  // P9
1161  // decay dopamine concentration
1162  if ((groupConfigs[netId][lGrpId].WithESTDPtype == DA_MOD || groupConfigs[netId][lGrpId].WithISTDP == DA_MOD) && runtimeData[netId].grpDA[lGrpId] > groupConfigs[netId][lGrpId].baseDP) {
1163  runtimeData[netId].grpDA[lGrpId] *= groupConfigs[netId][lGrpId].decayDP;
1164  }
1165  runtimeData[netId].grpDABuffer[lGrpId * 1000 + simTimeMs] = runtimeData[netId].grpDA[lGrpId];
1166  }
1167  } // end numGroups
1168 
1169  // Only after we are done computing nextVoltage for all neurons do we copy the new values to the voltage array.
1170  // This is crucial for GPU (asynchronous kernel launch) and in the future for a multi-threaded CARLsim version.
1171 
1172  memcpy(runtimeData[netId].voltage, runtimeData[netId].nextVoltage, sizeof(float)*networkConfigs[netId].numNReg);
1173 
1174  } // end simNumStepsPerMs loop
1175 }
1176 
1177 #if !defined(WIN32) && !defined(WIN64) && !defined(__APPLE__) // Linux or MAC
1178  // Static multithreading subroutine method - helper for the above method
1179  void* SNN::helperGlobalStateUpdate_CPU(void* arguments) {
1180  ThreadStruct* args = (ThreadStruct*) arguments;
1181  //printf("\nThread ID: %lu and CPU: %d\n",pthread_self(), sched_getcpu());
1182  ((SNN *)args->snn_pointer) -> globalStateUpdate_CPU(args->netId);
1183  pthread_exit(0);
1184  }
1185 #endif
1186 
1187 // This function updates the synaptic weights from its derivatives..
1188 #if defined(WIN32) || defined(WIN64) || defined(__APPLE__)
1189  void SNN::updateWeights_CPU(int netId) {
1190 #else // POSIX
1191  void* SNN::updateWeights_CPU(int netId) {
1192 #endif
1193  // at this point we have already checked for sim_in_testing and sim_with_fixedwts
1194  assert(sim_in_testing==false);
1195  assert(sim_with_fixedwts==false);
1196  assert(runtimeData[netId].memType == CPU_MEM);
1197 
1198  // update synaptic weights here for all the neurons..
1199  for (int lGrpId = 0; lGrpId < networkConfigs[netId].numGroups; lGrpId++) {
1200  // no changable weights so continue without changing..
1201  if (groupConfigs[netId][lGrpId].FixedInputWts || !(groupConfigs[netId][lGrpId].WithSTDP))
1202  continue;
1203 
1204  for (int lNId = groupConfigs[netId][lGrpId].lStartN; lNId <= groupConfigs[netId][lGrpId].lEndN; lNId++) {
1205  assert(lNId < networkConfigs[netId].numNReg);
1206  unsigned int offset = runtimeData[netId].cumulativePre[lNId];
1207  float diff_firing = 0.0;
1208  float homeostasisScale = 1.0;
1209 
1210  if (groupConfigs[netId][lGrpId].WithHomeostasis) {
1211  assert(runtimeData[netId].baseFiring[lNId] > 0);
1212  diff_firing = 1 - runtimeData[netId].avgFiring[lNId] / runtimeData[netId].baseFiring[lNId];
1213  homeostasisScale = groupConfigs[netId][lGrpId].homeostasisScale;
1214  }
1215 
1216  if (lNId == groupConfigs[netId][lGrpId].lStartN)
1217  KERNEL_DEBUG("Weights, Change at %d (diff_firing: %f)", simTimeSec, diff_firing);
1218 
1219  for (int j = 0; j < runtimeData[netId].Npre_plastic[lNId]; j++) {
1220  // if (i==groupConfigs[0][g].StartN)
1221  // KERNEL_DEBUG("%1.2f %1.2f \t", wt[offset+j]*10, wtChange[offset+j]*10);
1222  float effectiveWtChange = stdpScaleFactor_ * runtimeData[netId].wtChange[offset + j];
1223  // if (wtChange[offset+j])
1224  // printf("connId=%d, wtChange[%d]=%f\n",connIdsPreIdx[offset+j],offset+j,wtChange[offset+j]);
1225 
1226  // homeostatic weight update
1227  // FIXME: check WithESTDPtype and WithISTDPtype first and then do weight change update
1228  switch (groupConfigs[netId][lGrpId].WithESTDPtype) {
1229  case STANDARD:
1230  if (groupConfigs[netId][lGrpId].WithHomeostasis) {
1231  runtimeData[netId].wt[offset + j] += (diff_firing*runtimeData[netId].wt[offset + j] * homeostasisScale + runtimeData[netId].wtChange[offset + j])*runtimeData[netId].baseFiring[lNId] / groupConfigs[netId][lGrpId].avgTimeScale / (1 + fabs(diff_firing) * 50);
1232  } else {
1233  // just STDP weight update
1234  runtimeData[netId].wt[offset + j] += effectiveWtChange;
1235  }
1236  break;
1237  case DA_MOD:
1238  if (groupConfigs[netId][lGrpId].WithHomeostasis) {
1239  effectiveWtChange = runtimeData[netId].grpDA[lGrpId] * effectiveWtChange;
1240  runtimeData[netId].wt[offset + j] += (diff_firing*runtimeData[netId].wt[offset + j] * homeostasisScale + effectiveWtChange)*runtimeData[netId].baseFiring[lNId] / groupConfigs[netId][lGrpId].avgTimeScale / (1 + fabs(diff_firing) * 50);
1241  } else {
1242  runtimeData[netId].wt[offset + j] += runtimeData[netId].grpDA[lGrpId] * effectiveWtChange;
1243  }
1244  break;
1245  case UNKNOWN_STDP:
1246  default:
1247  // we shouldn't even be in here if !WithSTDP
1248  break;
1249  }
1250 
1251  switch (groupConfigs[netId][lGrpId].WithISTDPtype) {
1252  case STANDARD:
1253  if (groupConfigs[netId][lGrpId].WithHomeostasis) {
1254  runtimeData[netId].wt[offset + j] += (diff_firing*runtimeData[netId].wt[offset + j] * homeostasisScale + runtimeData[netId].wtChange[offset + j])*runtimeData[netId].baseFiring[lNId] / groupConfigs[netId][lGrpId].avgTimeScale / (1 + fabs(diff_firing) * 50);
1255  } else {
1256  // just STDP weight update
1257  runtimeData[netId].wt[offset + j] += effectiveWtChange;
1258  }
1259  break;
1260  case DA_MOD:
1261  if (groupConfigs[netId][lGrpId].WithHomeostasis) {
1262  effectiveWtChange = runtimeData[netId].grpDA[lGrpId] * effectiveWtChange;
1263  runtimeData[netId].wt[offset + j] += (diff_firing*runtimeData[netId].wt[offset + j] * homeostasisScale + effectiveWtChange)*runtimeData[netId].baseFiring[lNId] / groupConfigs[netId][lGrpId].avgTimeScale / (1 + fabs(diff_firing) * 50);
1264  } else {
1265  runtimeData[netId].wt[offset + j] += runtimeData[netId].grpDA[lGrpId] * effectiveWtChange;
1266  }
1267  break;
1268  case UNKNOWN_STDP:
1269  default:
1270  // we shouldn't even be in here if !WithSTDP
1271  break;
1272  }
1273 
1274  // It is users' choice to decay weight change or not
1275  // see setWeightAndWeightChangeUpdate()
1276  runtimeData[netId].wtChange[offset + j] *= wtChangeDecay_;
1277 
1278  // if this is an excitatory or inhibitory synapse
1279  if (runtimeData[netId].maxSynWt[offset + j] >= 0) {
1280  if (runtimeData[netId].wt[offset + j] >= runtimeData[netId].maxSynWt[offset + j])
1281  runtimeData[netId].wt[offset + j] = runtimeData[netId].maxSynWt[offset + j];
1282  if (runtimeData[netId].wt[offset + j] < 0)
1283  runtimeData[netId].wt[offset + j] = 0.0;
1284  }
1285  else {
1286  if (runtimeData[netId].wt[offset + j] <= runtimeData[netId].maxSynWt[offset + j])
1287  runtimeData[netId].wt[offset + j] = runtimeData[netId].maxSynWt[offset + j];
1288  if (runtimeData[netId].wt[offset + j] > 0)
1289  runtimeData[netId].wt[offset + j] = 0.0;
1290  }
1291  }
1292  }
1293  }
1294 }
1295 
1296 #if !defined(WIN32) && !defined(WIN64) && !defined(__APPLE__) // Linux or MAC
1297  // Static multithreading subroutine method - helper for the above method
1298  void* SNN::helperUpdateWeights_CPU(void* arguments) {
1299  ThreadStruct* args = (ThreadStruct*) arguments;
1300  //printf("\nThread ID: %lu and CPU: %d\n",pthread_self(), sched_getcpu());
1301  ((SNN *)args->snn_pointer) -> updateWeights_CPU(args->netId);
1302  pthread_exit(0);
1303  }
1304 #endif
1305 
1310  #if defined(WIN32) || defined(WIN64) || defined(__APPLE__)
1311  void SNN::shiftSpikeTables_CPU(int netId) {
1312 #else // POSIX
1313  void* SNN::shiftSpikeTables_CPU(int netId) {
1314 #endif
1315  assert(runtimeData[netId].memType == CPU_MEM);
1316  // Read the neuron ids that fired in the last glbNetworkConfig.maxDelay seconds
1317  // and put it to the beginning of the firing table...
1318  for(int p = runtimeData[netId].timeTableD2[999], k = 0; p < runtimeData[netId].timeTableD2[999 + networkConfigs[netId].maxDelay + 1]; p++, k++) {
1319  runtimeData[netId].firingTableD2[k] = runtimeData[netId].firingTableD2[p];
1320  }
1321 
1322  for(int i = 0; i < networkConfigs[netId].maxDelay; i++) {
1323  runtimeData[netId].timeTableD2[i + 1] = runtimeData[netId].timeTableD2[1000 + i + 1] - runtimeData[netId].timeTableD2[1000];
1324  runtimeData[netId].timeTableD1[i + 1] = runtimeData[netId].timeTableD1[1000 + i + 1] - runtimeData[netId].timeTableD1[1000];
1325  }
1326 
1327  runtimeData[netId].timeTableD1[networkConfigs[netId].maxDelay] = 0;
1328  runtimeData[netId].spikeCountD2 += runtimeData[netId].spikeCountD2Sec;
1329  runtimeData[netId].spikeCountD1 += runtimeData[netId].spikeCountD1Sec;
1330 
1331  runtimeData[netId].spikeCountD2Sec = 0;
1332  runtimeData[netId].spikeCountD1Sec = 0;
1333 
1334  runtimeData[netId].spikeCountExtRxD2Sec = 0;
1335  runtimeData[netId].spikeCountExtRxD1Sec = 0;
1336 
1337  runtimeData[netId].spikeCountLastSecLeftD2 = runtimeData[netId].timeTableD2[networkConfigs[netId].maxDelay];
1338 }
1339 
1340 #if !defined(WIN32) && !defined(WIN64) && !defined(__APPLE__) // Linux or MAC
1341  // Static multithreading subroutine method - helper for the above method
1342  void* SNN::helperShiftSpikeTables_CPU(void* arguments) {
1343  ThreadStruct* args = (ThreadStruct*) arguments;
1344  //printf("\nThread ID: %lu and CPU: %d\n",pthread_self(), sched_getcpu());
1345  ((SNN *)args->snn_pointer) -> shiftSpikeTables_CPU(args->netId);
1346  pthread_exit(0);
1347  }
1348 #endif
1349 
1350 void SNN::allocateSNN_CPU(int netId) {
1351  // setup memory type of CPU runtime data
1352  runtimeData[netId].memType = CPU_MEM;
1353 
1354  // display some memory management info
1355  //size_t avail, total, previous;
1356  //float toMB = std::pow(1024.0f, 2);
1357  //KERNEL_INFO("CPU Memory Management: (Total %2.3f MB)",(float)(total/toMB));
1358  //KERNEL_INFO("Data\t\t\tSize\t\tTotal Used\tTotal Available");
1359  //KERNEL_INFO("Init:\t\t\t%2.3f MB\t%2.3f MB\t%2.3f MB",(float)(total)/toMB,(float)((total-avail)/toMB), (float)(avail/toMB));
1360  //previous=avail;
1361 
1362  // allocate SNN::runtimeData[0].randNum for random number generators
1363  runtimeData[netId].randNum = new float[networkConfigs[netId].numNPois];
1364  //KERNEL_INFO("Random Gen:\t\t%2.3f MB\t%2.3f MB\t%2.3f MB",(float)(previous-avail)/toMB, (float)((total-avail)/toMB),(float)(avail/toMB));
1365  //previous=avail;
1366 
1367 
1368  // initialize (copy from SNN) runtimeData[0].Npre, runtimeData[0].Npre_plastic, runtimeData[0].Npre_plasticInv, runtimeData[0].cumulativePre
1369  // initialize (copy from SNN) runtimeData[0].cumulativePost, runtimeData[0].Npost, runtimeData[0].postDelayInfo
1370  // initialize (copy from SNN) runtimeData[0].postSynapticIds, runtimeData[0].preSynapticIds
1371  copyPreConnectionInfo(netId, ALL, &runtimeData[netId], &managerRuntimeData, true);
1372  copyPostConnectionInfo(netId, ALL, &runtimeData[netId], &managerRuntimeData, true);
1373  //KERNEL_INFO("Conn Info:\t\t%2.3f MB\t%2.3f MB\t%2.3f MB",(float)(previous-avail)/toMB,(float)((total-avail)/toMB), (float)(avail/toMB));
1374  //previous=avail;
1375 
1376  // initialize (copy from SNN) runtimeData[0].wt, runtimeData[0].wtChange, runtimeData[0].maxSynWt
1377  copySynapseState(netId, &runtimeData[netId], &managerRuntimeData, true);
1378  //KERNEL_INFO("Syn State:\t\t%2.3f MB\t%2.3f MB\t%2.3f MB",(float)(previous-avail)/toMB,(float)((total-avail)/toMB), (float)(avail/toMB));
1379  //previous=avail;
1380 
1381  // copy the neuron state information to the CPU runtime
1382  // initialize (copy from managerRuntimeData) runtimeData[0].recovery, runtimeData[0].voltage, runtimeData[0].current
1383  // initialize (copy from managerRuntimeData) runtimeData[0].gGABAa, runtimeData[0].gGABAb, runtimeData[0].gAMPA, runtimeData[0].gNMDA
1384  // initialize (copy from SNN) runtimeData[0].Izh_a, runtimeData[0].Izh_b, runtimeData[0].Izh_c, runtimeData[0].Izh_d
1385  // initialize (copy form SNN) runtimeData[0].baseFiring, runtimeData[0].baseFiringInv
1386  // initialize (copy from SNN) runtimeData[0].n(V,U,I)Buffer[]
1387  copyNeuronState(netId, ALL, &runtimeData[netId], true);
1388 
1389  // copy STP state, considered as neuron state
1390  if (sim_with_stp) {
1391  // initialize (copy from SNN) stpu, stpx
1392  copySTPState(netId, ALL, &runtimeData[netId], &managerRuntimeData, true);
1393  }
1394  //KERNEL_INFO("Neuron State:\t\t%2.3f MB\t%2.3f MB\t%2.3f MB",(float)(previous-avail)/toMB,(float)((total-avail)/toMB), (float)(avail/toMB));
1395  //previous=avail;
1396 
1397  // initialize (copy from SNN) runtimeData[0].grpDA(5HT,ACh,NE)
1398  // initialize (copy from SNN) runtimeData[0].grpDA(5HT,ACh,NE)Buffer[]
1399  copyGroupState(netId, ALL, &runtimeData[netId], &managerRuntimeData, true);
1400  //KERNEL_INFO("Group State:\t\t%2.3f MB\t%2.3f MB\t%2.3f MB",(float)(previous-avail)/toMB,(float)((total-avail)/toMB), (float)(avail/toMB));
1401  //previous=avail;
1402 
1403  // initialize (cudaMemset) runtimeData[0].I_set, runtimeData[0].poissonFireRate
1404  // initialize (copy from SNN) runtimeData[0].firingTableD1, runtimeData[0].firingTableD2
1405  // initialize (cudaMalloc) runtimeData[0].spikeGenBits
1406  // initialize (copy from managerRuntimeData) runtimeData[0].nSpikeCnt,
1407  // initialize (copy from SNN) runtimeData[0].synSpikeTime, runtimeData[0].lastSpikeTime
1408  copyAuxiliaryData(netId, ALL, &runtimeData[netId], true);
1409  //KERNEL_INFO("Auxiliary Data:\t\t%2.3f MB\t%2.3f MB\t%2.3f MB\n\n",(float)(previous-avail)/toMB,(float)((total-avail)/toMB), (float)(avail/toMB));
1410  //previous=avail;
1411 
1412  // TODO: move mulSynFast, mulSynSlow to ConnectConfig structure
1413  // copy connection configs
1414  //CUDA_CHECK_ERRORS(cudaMemcpyToSymbol(d_mulSynFast, mulSynFast, sizeof(float) * networkConfigs[netId].numConnections, 0, cudaMemcpyHostToDevice));
1415  //CUDA_CHECK_ERRORS(cudaMemcpyToSymbol(d_mulSynSlow, mulSynSlow, sizeof(float) * networkConfigs[netId].numConnections, 0, cudaMemcpyHostToDevice));
1416 
1417  KERNEL_DEBUG("Transfering group settings to CPU:");
1418  for (int lGrpId = 0; lGrpId < networkConfigs[netId].numGroupsAssigned; lGrpId++) {
1419  KERNEL_DEBUG("Settings for Group %s:", groupConfigMap[groupConfigs[netId][lGrpId].gGrpId].grpName.c_str());
1420 
1421  KERNEL_DEBUG("\tType: %d",(int)groupConfigs[netId][lGrpId].Type);
1422  KERNEL_DEBUG("\tNumN: %d",groupConfigs[netId][lGrpId].numN);
1423  KERNEL_DEBUG("\tM: %d",groupConfigs[netId][lGrpId].numPostSynapses);
1424  KERNEL_DEBUG("\tPreM: %d",groupConfigs[netId][lGrpId].numPreSynapses);
1425  KERNEL_DEBUG("\tspikeGenerator: %d",(int)groupConfigs[netId][lGrpId].isSpikeGenerator);
1426  KERNEL_DEBUG("\tFixedInputWts: %d",(int)groupConfigs[netId][lGrpId].FixedInputWts);
1427  KERNEL_DEBUG("\tMaxDelay: %d",(int)groupConfigs[netId][lGrpId].MaxDelay);
1428  KERNEL_DEBUG("\tWithSTDP: %d",(int)groupConfigs[netId][lGrpId].WithSTDP);
1429  if (groupConfigs[netId][lGrpId].WithSTDP) {
1430  KERNEL_DEBUG("\t\tE-STDP type: %s",stdpType_string[groupConfigs[netId][lGrpId].WithESTDPtype]);
1431  KERNEL_DEBUG("\t\tTAU_PLUS_INV_EXC: %f",groupConfigs[netId][lGrpId].TAU_PLUS_INV_EXC);
1432  KERNEL_DEBUG("\t\tTAU_MINUS_INV_EXC: %f",groupConfigs[netId][lGrpId].TAU_MINUS_INV_EXC);
1433  KERNEL_DEBUG("\t\tALPHA_PLUS_EXC: %f",groupConfigs[netId][lGrpId].ALPHA_PLUS_EXC);
1434  KERNEL_DEBUG("\t\tALPHA_MINUS_EXC: %f",groupConfigs[netId][lGrpId].ALPHA_MINUS_EXC);
1435  KERNEL_DEBUG("\t\tI-STDP type: %s",stdpType_string[groupConfigs[netId][lGrpId].WithISTDPtype]);
1436  KERNEL_DEBUG("\t\tTAU_PLUS_INV_INB: %f",groupConfigs[netId][lGrpId].TAU_PLUS_INV_INB);
1437  KERNEL_DEBUG("\t\tTAU_MINUS_INV_INB: %f",groupConfigs[netId][lGrpId].TAU_MINUS_INV_INB);
1438  KERNEL_DEBUG("\t\tALPHA_PLUS_INB: %f",groupConfigs[netId][lGrpId].ALPHA_PLUS_INB);
1439  KERNEL_DEBUG("\t\tALPHA_MINUS_INB: %f",groupConfigs[netId][lGrpId].ALPHA_MINUS_INB);
1440  KERNEL_DEBUG("\t\tLAMBDA: %f",groupConfigs[netId][lGrpId].LAMBDA);
1441  KERNEL_DEBUG("\t\tDELTA: %f",groupConfigs[netId][lGrpId].DELTA);
1442  KERNEL_DEBUG("\t\tBETA_LTP: %f",groupConfigs[netId][lGrpId].BETA_LTP);
1443  KERNEL_DEBUG("\t\tBETA_LTD: %f",groupConfigs[netId][lGrpId].BETA_LTD);
1444  }
1445  KERNEL_DEBUG("\tWithSTP: %d",(int)groupConfigs[netId][lGrpId].WithSTP);
1446  if (groupConfigs[netId][lGrpId].WithSTP) {
1447  KERNEL_DEBUG("\t\tSTP_U: %f", groupConfigs[netId][lGrpId].STP_U);
1448 // KERNEL_DEBUG("\t\tSTP_tD: %f",groupConfigs[netId][lGrpId].STP_tD);
1449 // KERNEL_DEBUG("\t\tSTP_tF: %f",groupConfigs[netId][lGrpId].STP_tF);
1450  }
1451  KERNEL_DEBUG("\tspikeGen: %s", groupConfigs[netId][lGrpId].isSpikeGenFunc? "is Set" : "is not set ");
1452  }
1453 
1454  // allocation of CPU runtime data is done
1455  runtimeData[netId].allocated = true;
1456 }
1457 
1476 void SNN::copyPreConnectionInfo(int netId, int lGrpId, RuntimeData* dest, RuntimeData* src, bool allocateMem) {
1477  int lengthN, lengthSyn, posN, posSyn;
1478 
1479  if (lGrpId == ALL) {
1480  lengthN = networkConfigs[netId].numNAssigned;
1481  posN = 0;
1482  } else {
1483  lengthN = groupConfigs[netId][lGrpId].numN;
1484  posN = groupConfigs[netId][lGrpId].lStartN;
1485  }
1486 
1487  // connection synaptic lengths and cumulative lengths...
1488  if(allocateMem)
1489  dest->Npre = new unsigned short[networkConfigs[netId].numNAssigned];
1490  memcpy(&dest->Npre[posN], &src->Npre[posN], sizeof(short) * lengthN);
1491 
1492  // we don't need these data structures if the network doesn't have any plastic synapses at all
1493  if (!sim_with_fixedwts) {
1494  // presyn excitatory connections
1495  if(allocateMem)
1496  dest->Npre_plastic = new unsigned short[networkConfigs[netId].numNAssigned];
1497  memcpy(&dest->Npre_plastic[posN], &src->Npre_plastic[posN], sizeof(short) * lengthN);
1498 
1499  // Npre_plasticInv is only used on GPUs, only allocate and copy it during initialization
1500  if(allocateMem) {
1501  float* Npre_plasticInv = new float[networkConfigs[netId].numNAssigned];
1502 
1503  for (int i = 0; i < networkConfigs[netId].numNAssigned; i++)
1504  Npre_plasticInv[i] = 1.0f / managerRuntimeData.Npre_plastic[i];
1505 
1506  dest->Npre_plasticInv = new float[networkConfigs[netId].numNAssigned];
1507  memcpy(dest->Npre_plasticInv, Npre_plasticInv, sizeof(float) * networkConfigs[netId].numNAssigned);
1508 
1509  delete[] Npre_plasticInv;
1510  }
1511  }
1512 
1513  // beginning position for the pre-synaptic information
1514  if(allocateMem)
1515  dest->cumulativePre = new unsigned int[networkConfigs[netId].numNAssigned];
1516  memcpy(&dest->cumulativePre[posN], &src->cumulativePre[posN], sizeof(int) * lengthN);
1517 
1518  // Npre, cumulativePre has been copied to destination
1519  if (lGrpId == ALL) {
1520  lengthSyn = networkConfigs[netId].numPreSynNet;
1521  posSyn = 0;
1522  } else {
1523  lengthSyn = 0;
1524  for (int lNId = groupConfigs[netId][lGrpId].lStartN; lNId <= groupConfigs[netId][lGrpId].lEndN; lNId++)
1525  lengthSyn += dest->Npre[lNId];
1526 
1527  posSyn = dest->cumulativePre[groupConfigs[netId][lGrpId].lStartN];
1528  }
1529 
1530  if(allocateMem)
1531  dest->preSynapticIds = new SynInfo[networkConfigs[netId].numPreSynNet];
1532  memcpy(&dest->preSynapticIds[posSyn], &src->preSynapticIds[posSyn], sizeof(SynInfo) * lengthSyn);
1533 }
1534 
1551 void SNN::copyPostConnectionInfo(int netId, int lGrpId, RuntimeData* dest, RuntimeData* src, bool allocateMem) {
1552  int lengthN, lengthSyn, posN, posSyn;
1553 
1554  if (lGrpId == ALL) {
1555  lengthN = networkConfigs[netId].numNAssigned;
1556  posN = 0;
1557  } else {
1558  lengthN = groupConfigs[netId][lGrpId].numN;
1559  posN = groupConfigs[netId][lGrpId].lStartN;
1560  }
1561 
1562  // number of postsynaptic connections
1563  if(allocateMem)
1564  dest->Npost = new unsigned short[networkConfigs[netId].numNAssigned];
1565  memcpy(&dest->Npost[posN], &src->Npost[posN], sizeof(short) * lengthN);
1566 
1567  // beginning position for the post-synaptic information
1568  if(allocateMem)
1569  dest->cumulativePost = new unsigned int[networkConfigs[netId].numNAssigned];
1570  memcpy(&dest->cumulativePost[posN], &src->cumulativePost[posN], sizeof(int) * lengthN);
1571 
1572 
1573  // Npost, cumulativePost has been copied to destination
1574  if (lGrpId == ALL) {
1575  lengthSyn = networkConfigs[netId].numPostSynNet;
1576  posSyn = 0;
1577  } else {
1578  lengthSyn = 0;
1579  for (int lNId = groupConfigs[netId][lGrpId].lStartN; lNId <= groupConfigs[netId][lGrpId].lEndN; lNId++)
1580  lengthSyn += dest->Npost[lNId];
1581 
1582  posSyn = dest->cumulativePost[groupConfigs[netId][lGrpId].lStartN];
1583  }
1584 
1585  // actual post synaptic connection information...
1586  if(allocateMem)
1587  dest->postSynapticIds = new SynInfo[networkConfigs[netId].numPostSynNet];
1588  memcpy(&dest->postSynapticIds[posSyn], &src->postSynapticIds[posSyn], sizeof(SynInfo) * lengthSyn);
1589 
1590  // static specific mapping and actual post-synaptic delay metric
1591  if(allocateMem)
1592  dest->postDelayInfo = new DelayInfo[networkConfigs[netId].numNAssigned * (glbNetworkConfig.maxDelay + 1)];
1593  memcpy(&dest->postDelayInfo[posN * (glbNetworkConfig.maxDelay + 1)], &src->postDelayInfo[posN * (glbNetworkConfig.maxDelay + 1)], sizeof(DelayInfo) * lengthN * (glbNetworkConfig.maxDelay + 1));
1594 }
1595 
1611 void SNN::copySynapseState(int netId, RuntimeData* dest, RuntimeData* src, bool allocateMem) {
1612  assert(networkConfigs[netId].numPreSynNet > 0);
1613 
1614  // synaptic information based
1615  if(allocateMem)
1616  dest->wt = new float[networkConfigs[netId].numPreSynNet];
1617  memcpy(dest->wt, src->wt, sizeof(float) * networkConfigs[netId].numPreSynNet);
1618 
1619  // we don't need these data structures if the network doesn't have any plastic synapses at all
1620  // they show up in updateLTP() and updateSynapticWeights(), two functions that do not get called if
1621  // sim_with_fixedwts is set
1622  if (!sim_with_fixedwts) {
1623  // synaptic weight derivative
1624  if(allocateMem)
1625  dest->wtChange = new float[networkConfigs[netId].numPreSynNet];
1626  memcpy(dest->wtChange, src->wtChange, sizeof(float) * networkConfigs[netId].numPreSynNet);
1627 
1628  // synaptic weight maximum value
1629  if(allocateMem)
1630  dest->maxSynWt = new float[networkConfigs[netId].numPreSynNet];
1631  memcpy(dest->maxSynWt, src->maxSynWt, sizeof(float) * networkConfigs[netId].numPreSynNet);
1632  }
1633 }
1634 
1651 void SNN::copyNeuronState(int netId, int lGrpId, RuntimeData* dest, bool allocateMem) {
1652  int ptrPos, length;
1653 
1654  if(lGrpId == ALL) {
1655  ptrPos = 0;
1656  length = networkConfigs[netId].numNReg;
1657  }
1658  else {
1659  ptrPos = groupConfigs[netId][lGrpId].lStartN;
1660  length = groupConfigs[netId][lGrpId].numN;
1661  }
1662 
1663  assert(length <= networkConfigs[netId].numNReg);
1664 
1665  if (length == 0)
1666  return;
1667 
1668  if(!allocateMem && groupConfigs[netId][lGrpId].Type & POISSON_NEURON)
1669  return;
1670 
1671  if(allocateMem)
1672  dest->recovery = new float[length];
1673  memcpy(&dest->recovery[ptrPos], &managerRuntimeData.recovery[ptrPos], sizeof(float) * length);
1674 
1675  if(allocateMem)
1676  dest->voltage = new float[length];
1677  memcpy(&dest->voltage[ptrPos], &managerRuntimeData.voltage[ptrPos], sizeof(float) * length);
1678 
1679  if (allocateMem)
1680  dest->nextVoltage = new float[length];
1681  memcpy(&dest->nextVoltage[ptrPos], &managerRuntimeData.nextVoltage[ptrPos], sizeof(float) * length);
1682 
1683  //neuron input current...
1684  if(allocateMem)
1685  dest->current = new float[length];
1686  memcpy(&dest->current[ptrPos], &managerRuntimeData.current[ptrPos], sizeof(float) * length);
1687 
1688  if (sim_with_conductances) {
1689  //conductance information
1690  copyConductanceAMPA(netId, lGrpId, dest, &managerRuntimeData, allocateMem, 0);
1691  copyConductanceNMDA(netId, lGrpId, dest, &managerRuntimeData, allocateMem, 0);
1692  copyConductanceGABAa(netId, lGrpId, dest, &managerRuntimeData, allocateMem, 0);
1693  copyConductanceGABAb(netId, lGrpId, dest, &managerRuntimeData, allocateMem, 0);
1694  }
1695 
1696  // copying external current needs to be done separately because setExternalCurrent needs to call it, too
1697  // do it only from host to device
1698  copyExternalCurrent(netId, lGrpId, dest, allocateMem);
1699 
1700  if (allocateMem)
1701  dest->curSpike = new bool[length];
1702  memcpy(&dest->curSpike[ptrPos], &managerRuntimeData.curSpike[ptrPos], sizeof(bool) * length);
1703 
1704  copyNeuronParameters(netId, lGrpId, dest, allocateMem);
1705 
1706  if (networkConfigs[netId].sim_with_nm)
1707  copyNeuronStateBuffer(netId, lGrpId, dest, &managerRuntimeData, allocateMem);
1708 
1709  if (sim_with_homeostasis) {
1710  //Included to enable homeostasis in CPU_MODE.
1711  // Avg. Firing...
1712  if(allocateMem)
1713  dest->avgFiring = new float[length];
1714  memcpy(&dest->avgFiring[ptrPos], &managerRuntimeData.avgFiring[ptrPos], sizeof(float) * length);
1715  }
1716 }
1717 
1736 void SNN::copyConductanceAMPA(int netId, int lGrpId, RuntimeData* dest, RuntimeData* src, bool allocateMem, int destOffset) {
1737  assert(isSimulationWithCOBA());
1738 
1739  int ptrPos, length;
1740 
1741  if(lGrpId == ALL) {
1742  ptrPos = 0;
1743  length = networkConfigs[netId].numNReg;
1744  } else {
1745  ptrPos = groupConfigs[netId][lGrpId].lStartN;
1746  length = groupConfigs[netId][lGrpId].numN;
1747  }
1748  assert(length <= networkConfigs[netId].numNReg);
1749  assert(length > 0);
1750 
1751  //conductance information
1752  assert(src->gAMPA != NULL);
1753  if(allocateMem)
1754  dest->gAMPA = new float[length];
1755  memcpy(&dest->gAMPA[ptrPos + destOffset], &src->gAMPA[ptrPos], sizeof(float) * length);
1756 }
1757 
1776 void SNN::copyConductanceNMDA(int netId, int lGrpId, RuntimeData* dest, RuntimeData* src, bool allocateMem, int destOffset) {
1777  assert(isSimulationWithCOBA());
1778 
1779  int ptrPos, length;
1780 
1781  if(lGrpId == ALL) {
1782  ptrPos = 0;
1783  length = networkConfigs[netId].numNReg;
1784  } else {
1785  ptrPos = groupConfigs[netId][lGrpId].lStartN;
1786  length = groupConfigs[netId][lGrpId].numN;
1787  }
1788  assert(length <= networkConfigs[netId].numNReg);
1789  assert(length > 0);
1790 
1791  if (isSimulationWithNMDARise()) {
1792  assert(src->gNMDA_r != NULL);
1793  if(allocateMem)
1794  dest->gNMDA_r = new float[length];
1795  memcpy(&dest->gNMDA_r[ptrPos], &src->gNMDA_r[ptrPos], sizeof(float) * length);
1796 
1797  assert(src->gNMDA_d != NULL);
1798  if(allocateMem)
1799  dest->gNMDA_d = new float[length];
1800  memcpy(&dest->gNMDA_d[ptrPos], &src->gNMDA_d[ptrPos], sizeof(float) * length);
1801  } else {
1802  assert(src->gNMDA != NULL);
1803  if(allocateMem)
1804  dest->gNMDA = new float[length];
1805  memcpy(&dest->gNMDA[ptrPos + destOffset], &src->gNMDA[ptrPos], sizeof(float) * length);
1806  }
1807 }
1808 
1827 void SNN::copyConductanceGABAa(int netId, int lGrpId, RuntimeData* dest, RuntimeData* src, bool allocateMem, int destOffset) {
1828  assert(isSimulationWithCOBA());
1829 
1830  int ptrPos, length;
1831 
1832  if(lGrpId == ALL) {
1833  ptrPos = 0;
1834  length = networkConfigs[netId].numNReg;
1835  } else {
1836  ptrPos = groupConfigs[netId][lGrpId].lStartN;
1837  length = groupConfigs[netId][lGrpId].numN;
1838  }
1839  assert(length <= networkConfigs[netId].numNReg);
1840  assert(length > 0);
1841 
1842  assert(src->gGABAa != NULL);
1843  if(allocateMem)
1844  dest->gGABAa = new float[length];
1845  memcpy(&dest->gGABAa[ptrPos + destOffset], &src->gGABAa[ptrPos], sizeof(float) * length);
1846 }
1847 
1866 void SNN::copyConductanceGABAb(int netId, int lGrpId, RuntimeData* dest, RuntimeData* src, bool allocateMem, int destOffset) {
1867  assert(isSimulationWithCOBA());
1868 
1869  int ptrPos, length;
1870 
1871  if (lGrpId == ALL) {
1872  ptrPos = 0;
1873  length = networkConfigs[netId].numNReg;
1874  } else {
1875  ptrPos = groupConfigs[netId][lGrpId].lStartN;
1876  length = groupConfigs[netId][lGrpId].numN;
1877  }
1878  assert(length <= networkConfigs[netId].numNReg);
1879  assert(length > 0);
1880 
1881  if (isSimulationWithGABAbRise()) {
1882  assert(src->gGABAb_r != NULL);
1883  if(allocateMem)
1884  dest->gGABAb_r = new float[length];
1885  memcpy(&dest->gGABAb_r[ptrPos], &src->gGABAb_r[ptrPos], sizeof(float) * length);
1886 
1887  assert(src->gGABAb_d != NULL);
1888  if(allocateMem)
1889  dest->gGABAb_d = new float[length];
1890  memcpy(&dest->gGABAb_d[ptrPos], &src->gGABAb_d[ptrPos], sizeof(float) * length);
1891  } else {
1892  assert(src->gGABAb != NULL);
1893  if(allocateMem)
1894  dest->gGABAb = new float[length];
1895  memcpy(&dest->gGABAb[ptrPos + destOffset], &src->gGABAb[ptrPos], sizeof(float) * length);
1896  }
1897 }
1898 
1916 void SNN::copyNeuronStateBuffer(int netId, int lGrpId, RuntimeData* dest, RuntimeData* src, bool allocateMem) {
1917  int ptrPos, length;
1918 
1919  assert(src->nVBuffer != NULL);
1920  if (allocateMem) dest->nVBuffer = new float[networkConfigs[netId].numGroups * MAX_NEURON_MON_GRP_SZIE * 1000];
1921 
1922  assert(src->nUBuffer != NULL);
1923  if (allocateMem) dest->nUBuffer = new float[networkConfigs[netId].numGroups * MAX_NEURON_MON_GRP_SZIE * 1000];
1924 
1925  assert(src->nIBuffer != NULL);
1926  if (allocateMem) dest->nIBuffer = new float[networkConfigs[netId].numGroups * MAX_NEURON_MON_GRP_SZIE * 1000];
1927 
1928  if (lGrpId == ALL) {
1929  ptrPos = 0;
1930  length = networkConfigs[netId].numGroups * MAX_NEURON_MON_GRP_SZIE * 1000;
1931 
1932  // copy neuron information
1933  memcpy(&dest->nVBuffer[ptrPos], &src->nVBuffer[ptrPos], sizeof(float) * length);
1934  memcpy(&dest->nUBuffer[ptrPos], &src->nUBuffer[ptrPos], sizeof(float) * length);
1935  memcpy(&dest->nIBuffer[ptrPos], &src->nIBuffer[ptrPos], sizeof(float) * length);
1936  }
1937  else {
1938  for (int t = 0; t < 1000; t++) {
1939  ptrPos = networkConfigs[netId].numGroups * MAX_NEURON_MON_GRP_SZIE * t + lGrpId * MAX_NEURON_MON_GRP_SZIE;
1940  length = MAX_NEURON_MON_GRP_SZIE;
1941 
1942  assert((ptrPos + length) <= networkConfigs[netId].numGroups * MAX_NEURON_MON_GRP_SZIE * 1000);
1943  assert(length > 0);
1944 
1945  // copy neuron information
1946  memcpy(&dest->nVBuffer[ptrPos], &src->nVBuffer[ptrPos], sizeof(float) * length);
1947  memcpy(&dest->nUBuffer[ptrPos], &src->nUBuffer[ptrPos], sizeof(float) * length);
1948  memcpy(&dest->nIBuffer[ptrPos], &src->nIBuffer[ptrPos], sizeof(float) * length);
1949  }
1950  }
1951 }
1952 
1953 
1971 void SNN::copyExternalCurrent(int netId, int lGrpId, RuntimeData* dest, bool allocateMem) {
1972  int posN, lengthN;
1973 
1974  if(lGrpId == ALL) {
1975  posN = 0;
1976  lengthN = networkConfigs[netId].numNReg;
1977  } else {
1978  assert(lGrpId >= 0);
1979  posN = groupConfigs[netId][lGrpId].lStartN;
1980  lengthN = groupConfigs[netId][lGrpId].numN;
1981  }
1982  assert(lengthN >= 0 && lengthN <= networkConfigs[netId].numNReg); // assert NOT poisson neurons
1983 
1984  KERNEL_DEBUG("copyExternalCurrent: lGrpId=%d, ptrPos=%d, length=%d, allocate=%s", lGrpId, posN, lengthN, allocateMem?"y":"n");
1985 
1986  if(allocateMem)
1987  dest->extCurrent = new float[lengthN];
1988  memcpy(&(dest->extCurrent[posN]), &(managerRuntimeData.extCurrent[posN]), sizeof(float) * lengthN);
1989 }
1990 
2009 void SNN::copyNeuronParameters(int netId, int lGrpId, RuntimeData* dest, bool allocateMem) {
2010  int ptrPos, length;
2011 
2012  // when allocating we are allocating the memory.. we need to do it completely... to avoid memory fragmentation..
2013  if (allocateMem) {
2014  assert(lGrpId == ALL);
2015  assert(dest->Izh_a == NULL);
2016  assert(dest->Izh_b == NULL);
2017  assert(dest->Izh_c == NULL);
2018  assert(dest->Izh_d == NULL);
2019  assert(dest->Izh_C == NULL);
2020  assert(dest->Izh_k == NULL);
2021  assert(dest->Izh_vr == NULL);
2022  assert(dest->Izh_vt == NULL);
2023  assert(dest->Izh_vpeak == NULL);
2024  assert(dest->lif_tau_m == NULL);
2025  assert(dest->lif_tau_ref == NULL);
2026  assert(dest->lif_tau_ref_c == NULL);
2027  assert(dest->lif_vTh == NULL);
2028  assert(dest->lif_vReset == NULL);
2029  assert(dest->lif_gain == NULL);
2030  assert(dest->lif_bias == NULL);
2031  }
2032 
2033  if(lGrpId == ALL) {
2034  ptrPos = 0;
2035  length = networkConfigs[netId].numNReg;
2036  }
2037  else {
2038  ptrPos = groupConfigs[netId][lGrpId].lStartN;
2039  length = groupConfigs[netId][lGrpId].numN;
2040  }
2041 
2042  if(allocateMem)
2043  dest->Izh_a = new float[length];
2044  memcpy(&dest->Izh_a[ptrPos], &(managerRuntimeData.Izh_a[ptrPos]), sizeof(float) * length);
2045 
2046  if(allocateMem)
2047  dest->Izh_b = new float[length];
2048  memcpy(&dest->Izh_b[ptrPos], &(managerRuntimeData.Izh_b[ptrPos]), sizeof(float) * length);
2049 
2050  if(allocateMem)
2051  dest->Izh_c = new float[length];
2052  memcpy(&dest->Izh_c[ptrPos], &(managerRuntimeData.Izh_c[ptrPos]), sizeof(float) * length);
2053 
2054  if(allocateMem)
2055  dest->Izh_d = new float[length];
2056  memcpy(&dest->Izh_d[ptrPos], &(managerRuntimeData.Izh_d[ptrPos]), sizeof(float) * length);
2057 
2058  if (allocateMem)
2059  dest->Izh_C = new float[length];
2060  memcpy(&dest->Izh_C[ptrPos], &(managerRuntimeData.Izh_C[ptrPos]), sizeof(float) * length);
2061 
2062  if (allocateMem)
2063  dest->Izh_k = new float[length];
2064  memcpy(&dest->Izh_k[ptrPos], &(managerRuntimeData.Izh_k[ptrPos]), sizeof(float) * length);
2065 
2066  if (allocateMem)
2067  dest->Izh_vr = new float[length];
2068  memcpy(&dest->Izh_vr[ptrPos], &(managerRuntimeData.Izh_vr[ptrPos]), sizeof(float) * length);
2069 
2070  if (allocateMem)
2071  dest->Izh_vt = new float[length];
2072  memcpy(&dest->Izh_vt[ptrPos], &(managerRuntimeData.Izh_vt[ptrPos]), sizeof(float) * length);
2073 
2074  if (allocateMem)
2075  dest->Izh_vpeak = new float[length];
2076  memcpy(&dest->Izh_vpeak[ptrPos], &(managerRuntimeData.Izh_vpeak[ptrPos]), sizeof(float) * length);
2077 
2078  //LIF neuron
2079  if(allocateMem)
2080  dest->lif_tau_m = new int[length];
2081  memcpy(&dest->lif_tau_m[ptrPos], &(managerRuntimeData.lif_tau_m[ptrPos]), sizeof(int) * length);
2082 
2083  if(allocateMem)
2084  dest->lif_tau_ref = new int[length];
2085  memcpy(&dest->lif_tau_ref[ptrPos], &(managerRuntimeData.lif_tau_ref[ptrPos]), sizeof(int) * length);
2086 
2087  if(allocateMem)
2088  dest->lif_tau_ref_c = new int[length];
2089  memcpy(&dest->lif_tau_ref_c[ptrPos], &(managerRuntimeData.lif_tau_ref_c[ptrPos]), sizeof(int) * length);
2090 
2091  if(allocateMem)
2092  dest->lif_vTh = new float[length];
2093  memcpy(&dest->lif_vTh[ptrPos], &(managerRuntimeData.lif_vTh[ptrPos]), sizeof(float) * length);
2094 
2095  if(allocateMem)
2096  dest->lif_vReset = new float[length];
2097  memcpy(&dest->lif_vReset[ptrPos], &(managerRuntimeData.lif_vReset[ptrPos]), sizeof(float) * length);
2098 
2099  if(allocateMem)
2100  dest->lif_gain = new float[length];
2101  memcpy(&dest->lif_gain[ptrPos], &(managerRuntimeData.lif_gain[ptrPos]), sizeof(float) * length);
2102 
2103  if(allocateMem)
2104  dest->lif_bias = new float[length];
2105  memcpy(&dest->lif_bias[ptrPos], &(managerRuntimeData.lif_bias[ptrPos]), sizeof(float) * length);
2106 
2107  // pre-compute baseFiringInv for fast computation on CPU cores
2108  if (sim_with_homeostasis) {
2109  float* baseFiringInv = new float[length];
2110  for(int nid = 0; nid < length; nid++) {
2111  if (managerRuntimeData.baseFiring[nid] != 0.0f)
2112  baseFiringInv[nid] = 1.0f / managerRuntimeData.baseFiring[ptrPos + nid];
2113  else
2114  baseFiringInv[nid] = 0.0;
2115  }
2116 
2117  if(allocateMem)
2118  dest->baseFiringInv = new float[length];
2119  memcpy(&dest->baseFiringInv[ptrPos], baseFiringInv, sizeof(float) * length);
2120 
2121  if(allocateMem)
2122  dest->baseFiring = new float[length];
2123  memcpy(&dest->baseFiring[ptrPos], managerRuntimeData.baseFiring, sizeof(float) * length);
2124 
2125  delete [] baseFiringInv;
2126  }
2127 }
2128 
2147 void SNN::copySTPState(int netId, int lGrpId, RuntimeData* dest, RuntimeData* src, bool allocateMem) {
2148  // STP feature is optional, do addtional check for memory space
2149  if(allocateMem) {
2150  assert(dest->stpu == NULL);
2151  assert(dest->stpx == NULL);
2152  } else {
2153  assert(dest->stpu != NULL);
2154  assert(dest->stpx != NULL);
2155  }
2156  assert(src->stpu != NULL); assert(src->stpx != NULL);
2157 
2158  if(allocateMem)
2159  dest->stpu = new float[networkConfigs[netId].numN * (networkConfigs[netId].maxDelay + 1)];
2160  memcpy(dest->stpu, src->stpu, sizeof(float) * networkConfigs[netId].numN * (networkConfigs[netId].maxDelay + 1));
2161 
2162  if(allocateMem)
2163  dest->stpx = new float[networkConfigs[netId].numN * (networkConfigs[netId].maxDelay + 1)];
2164  memcpy(dest->stpx, src->stpx, sizeof(float) * networkConfigs[netId].numN * (networkConfigs[netId].maxDelay + 1));
2165 }
2166 
2167 // ToDo: move grpDA(5HT, ACh, NE)Buffer to copyAuxiliaryData
2185 void SNN::copyGroupState(int netId, int lGrpId, RuntimeData* dest, RuntimeData* src, bool allocateMem) {
2186  if (allocateMem) {
2187  assert(dest->memType == CPU_MEM && !dest->allocated);
2188  dest->grpDA = new float[networkConfigs[netId].numGroups];
2189  dest->grp5HT = new float[networkConfigs[netId].numGroups];
2190  dest->grpACh = new float[networkConfigs[netId].numGroups];
2191  dest->grpNE = new float[networkConfigs[netId].numGroups];
2192  }
2193  memcpy(dest->grpDA, src->grpDA, sizeof(float) * networkConfigs[netId].numGroups);
2194  memcpy(dest->grp5HT, src->grp5HT, sizeof(float) * networkConfigs[netId].numGroups);
2195  memcpy(dest->grpACh, src->grpACh, sizeof(float) * networkConfigs[netId].numGroups);
2196  memcpy(dest->grpNE, src->grpNE, sizeof(float) * networkConfigs[netId].numGroups);
2197 
2198  if (lGrpId == ALL) {
2199  if (allocateMem) {
2200  assert(dest->memType == CPU_MEM && !dest->allocated);
2201  dest->grpDABuffer = new float[1000 * networkConfigs[netId].numGroups];
2202  dest->grp5HTBuffer = new float[1000 * networkConfigs[netId].numGroups];
2203  dest->grpAChBuffer = new float[1000 * networkConfigs[netId].numGroups];
2204  dest->grpNEBuffer = new float[1000 * networkConfigs[netId].numGroups];
2205  }
2206  memcpy(dest->grpDABuffer, src->grpDABuffer, sizeof(float) * 1000 * networkConfigs[netId].numGroups);
2207  memcpy(dest->grp5HTBuffer, src->grp5HTBuffer, sizeof(float) * 1000 * networkConfigs[netId].numGroups);
2208  memcpy(dest->grpAChBuffer, src->grpAChBuffer, sizeof(float) * 1000 * networkConfigs[netId].numGroups);
2209  memcpy(dest->grpNEBuffer, src->grpNEBuffer, sizeof(float) * 1000 * networkConfigs[netId].numGroups);
2210  } else {
2211  assert(!allocateMem);
2212  memcpy(&dest->grpDABuffer[lGrpId * 1000], &src->grpDABuffer[lGrpId * 1000], sizeof(float) * 1000);
2213  memcpy(&dest->grp5HTBuffer[lGrpId * 1000], &src->grp5HTBuffer[lGrpId * 1000], sizeof(float) * 1000);
2214  memcpy(&dest->grpAChBuffer[lGrpId * 1000], &src->grpAChBuffer[lGrpId * 1000], sizeof(float) * 1000);
2215  memcpy(&dest->grpNEBuffer[lGrpId * 1000], &src->grpNEBuffer[lGrpId * 1000], sizeof(float) * 1000);
2216  }
2217 }
2218 
2239 void SNN::copyAuxiliaryData(int netId, int lGrpId, RuntimeData* dest, bool allocateMem) {
2240  assert(networkConfigs[netId].numN > 0);
2241 
2242  if(allocateMem)
2243  dest->spikeGenBits = new unsigned int[networkConfigs[netId].numNSpikeGen / 32 + 1];
2244  memset(dest->spikeGenBits, 0, sizeof(int) * (networkConfigs[netId].numNSpikeGen / 32 + 1));
2245 
2246  // allocate the poisson neuron poissonFireRate
2247  if(allocateMem)
2248  dest->poissonFireRate = new float[networkConfigs[netId].numNPois];
2249  memset(dest->poissonFireRate, 0, sizeof(float) * networkConfigs[netId].numNPois);
2250 
2251  // synaptic auxiliary data
2252  // I_set: a bit vector indicates which synapse got a spike
2253  if(allocateMem) {
2254  networkConfigs[netId].I_setLength = ceil(((networkConfigs[netId].maxNumPreSynN) / 32.0f));
2255  dest->I_set = new int[networkConfigs[netId].numNReg * networkConfigs[netId].I_setLength];
2256  }
2257  assert(networkConfigs[netId].maxNumPreSynN >= 0);
2258  memset(dest->I_set, 0, sizeof(int) * networkConfigs[netId].numNReg * networkConfigs[netId].I_setLength);
2259 
2260  // synSpikeTime: an array indicates the last time when a synapse got a spike
2261  if(allocateMem)
2262  dest->synSpikeTime = new int[networkConfigs[netId].numPreSynNet];
2263  memcpy(dest->synSpikeTime, managerRuntimeData.synSpikeTime, sizeof(int) * networkConfigs[netId].numPreSynNet);
2264 
2265  // neural auxiliary data
2266  // lastSpikeTime: an array indicates the last time of a neuron emitting a spike
2267  // neuron firing time
2268  if(allocateMem)
2269  dest->lastSpikeTime = new int[networkConfigs[netId].numNAssigned];
2270  memcpy(dest->lastSpikeTime, managerRuntimeData.lastSpikeTime, sizeof(int) * networkConfigs[netId].numNAssigned);
2271 
2272  // auxiliary data for recording spike count of each neuron
2273  copyNeuronSpikeCount(netId, lGrpId, dest, &managerRuntimeData, true, 0);
2274 
2275  // quick lookup array for local group ids
2276  if(allocateMem)
2277  dest->grpIds = new short int[networkConfigs[netId].numNAssigned];
2278  memcpy(dest->grpIds, managerRuntimeData.grpIds, sizeof(short int) * networkConfigs[netId].numNAssigned);
2279 
2280  // quick lookup array for conn ids
2281  if(allocateMem)
2282  dest->connIdsPreIdx = new short int[networkConfigs[netId].numPreSynNet];
2283  memcpy(dest->connIdsPreIdx, managerRuntimeData.connIdsPreIdx, sizeof(short int) * networkConfigs[netId].numPreSynNet);
2284 
2285  // reset variable related to spike count
2286  // Note: the GPU counterpart is not required to do this
2287  dest->spikeCountSec = 0;
2288  dest->spikeCountD1Sec = 0;
2289  dest->spikeCountD2Sec = 0;
2290  dest->spikeCountExtRxD1Sec = 0;
2291  dest->spikeCountExtRxD2Sec = 0;
2292  dest->spikeCountLastSecLeftD2 = 0;
2293  dest->spikeCount = 0;
2294  dest->spikeCountD1 = 0;
2295  dest->spikeCountD2 = 0;
2296  dest->nPoissonSpikes = 0;
2297  dest->spikeCountExtRxD1 = 0;
2298  dest->spikeCountExtRxD2 = 0;
2299 
2300  // time talbe
2301  // Note: the GPU counterpart is not required to do this
2302  if (allocateMem) {
2303  assert(dest->timeTableD1 == NULL);
2304  assert(dest->timeTableD2 == NULL);
2305  }
2306 
2307  if (allocateMem)
2308  dest->timeTableD1 = new unsigned int[TIMING_COUNT];
2309  memset(dest->timeTableD1, 0, sizeof(int) * TIMING_COUNT);
2310 
2311  if (allocateMem)
2312  dest->timeTableD2 = new unsigned int[TIMING_COUNT];
2313  memset(dest->timeTableD2, 0, sizeof(int) * TIMING_COUNT);
2314 
2315  // firing table
2316  if (allocateMem) {
2317  assert(dest->firingTableD1 == NULL);
2318  assert(dest->firingTableD2 == NULL);
2319  }
2320 
2321  // allocate 1ms firing table
2322  if (allocateMem)
2323  dest->firingTableD1 = new int[networkConfigs[netId].maxSpikesD1];
2324  if (networkConfigs[netId].maxSpikesD1 > 0)
2325  memcpy(dest->firingTableD1, managerRuntimeData.firingTableD1, sizeof(int) * networkConfigs[netId].maxSpikesD1);
2326 
2327  // allocate 2+ms firing table
2328  if(allocateMem)
2329  dest->firingTableD2 = new int[networkConfigs[netId].maxSpikesD2];
2330  if (networkConfigs[netId].maxSpikesD2 > 0)
2331  memcpy(dest->firingTableD2, managerRuntimeData.firingTableD2, sizeof(int) * networkConfigs[netId].maxSpikesD2);
2332 
2333  // allocate external 1ms firing table
2334  if (allocateMem) {
2335  dest->extFiringTableD1 = new int*[networkConfigs[netId].numGroups];
2336  memset(dest->extFiringTableD1, 0 /* NULL */, sizeof(int*) * networkConfigs[netId].numGroups);
2337  for (int lGrpId = 0; lGrpId < networkConfigs[netId].numGroups; lGrpId++) {
2338  if (groupConfigs[netId][lGrpId].hasExternalConnect) {
2339  dest->extFiringTableD1[lGrpId] = new int[groupConfigs[netId][lGrpId].numN * NEURON_MAX_FIRING_RATE];
2340  memset(dest->extFiringTableD1[lGrpId], 0, sizeof(int) * groupConfigs[netId][lGrpId].numN * NEURON_MAX_FIRING_RATE);
2341  }
2342  }
2343  }
2344 
2345  // allocate external 2+ms firing table
2346  if (allocateMem) {
2347  dest->extFiringTableD2 = new int*[networkConfigs[netId].numGroups];
2348  memset(dest->extFiringTableD2, 0 /* NULL */, sizeof(int*) * networkConfigs[netId].numGroups);
2349  for (int lGrpId = 0; lGrpId < networkConfigs[netId].numGroups; lGrpId++) {
2350  if (groupConfigs[netId][lGrpId].hasExternalConnect) {
2351  dest->extFiringTableD2[lGrpId] = new int[groupConfigs[netId][lGrpId].numN * NEURON_MAX_FIRING_RATE];
2352  memset(dest->extFiringTableD2[lGrpId], 0, sizeof(int) * groupConfigs[netId][lGrpId].numN * NEURON_MAX_FIRING_RATE);
2353  }
2354  }
2355  }
2356 
2357  // allocate external 1ms firing table index
2358  if (allocateMem)
2359  dest->extFiringTableEndIdxD1 = new int[networkConfigs[netId].numGroups];
2360  memset(dest->extFiringTableEndIdxD1, 0, sizeof(int) * networkConfigs[netId].numGroups);
2361 
2362 
2363  // allocate external 2+ms firing table index
2364  if (allocateMem)
2365  dest->extFiringTableEndIdxD2 = new int[networkConfigs[netId].numGroups];
2366  memset(dest->extFiringTableEndIdxD2, 0, sizeof(int) * networkConfigs[netId].numGroups);
2367 }
2368 
2387 void SNN::copyNeuronSpikeCount(int netId, int lGrpId, RuntimeData* dest, RuntimeData* src, bool allocateMem, int destOffset) {
2388  int posN, lengthN;
2389 
2390  if(lGrpId == ALL) {
2391  posN = 0;
2392  lengthN = networkConfigs[netId].numN;
2393  } else {
2394  posN = groupConfigs[netId][lGrpId].lStartN;
2395  lengthN = groupConfigs[netId][lGrpId].numN;
2396  }
2397  assert(lengthN > 0 && lengthN <= networkConfigs[netId].numN);
2398 
2399  // spike count information
2400  if(allocateMem)
2401  dest->nSpikeCnt = new int[lengthN];
2402  memcpy(&dest->nSpikeCnt[posN + destOffset], &src->nSpikeCnt[posN], sizeof(int) * lengthN);
2403 }
2404 
2405 
2406 #if defined(WIN32) || defined(WIN64) || defined(__APPLE__)
2407  void SNN::assignPoissonFiringRate_CPU(int netId) {
2408 #else // POSIX
2409  void* SNN::assignPoissonFiringRate_CPU(int netId) {
2410 #endif
2411  assert(runtimeData[netId].memType == CPU_MEM);
2412 
2413  for (int lGrpId = 0; lGrpId < networkConfigs[netId].numGroups; lGrpId++) {
2414  // given group of neurons belong to the poisson group....
2415  if (groupConfigs[netId][lGrpId].isSpikeGenerator) {
2416  int lNId = groupConfigs[netId][lGrpId].lStartN;
2417  int gGrpId = groupConfigs[netId][lGrpId].gGrpId;
2418  PoissonRate* rate = groupConfigMDMap[gGrpId].ratePtr;
2419 
2420  // if spikeGenFunc group does not have a Poisson pointer, skip
2421  if (groupConfigMap[gGrpId].spikeGenFunc || rate == NULL)
2422  continue;
2423 
2424  assert(runtimeData[netId].poissonFireRate != NULL);
2425  assert(rate->isOnGPU() == false);
2426  // rates allocated on CPU
2427  memcpy(&runtimeData[netId].poissonFireRate[lNId - networkConfigs[netId].numNReg], rate->getRatePtrCPU(),
2428  sizeof(float) * rate->getNumNeurons());
2429  }
2430  }
2431 }
2432 
2433 #if !defined(WIN32) && !defined(WIN64) && !defined(__APPLE__) // Linux or MAC
2434  // Static multithreading subroutine method - helper for the above method
2435  void* SNN::helperAssignPoissonFiringRate_CPU(void* arguments) {
2436  ThreadStruct* args = (ThreadStruct*) arguments;
2437  //printf("\nThread ID: %lu and CPU: %d\n",pthread_self(), sched_getcpu());
2438  ((SNN *)args->snn_pointer) -> assignPoissonFiringRate_CPU(args->netId);
2439  pthread_exit(0);
2440  }
2441 #endif
2442 
2457 void SNN::copyWeightState(int netId, int lGrpId) {
2458  int lengthSyn, posSyn;
2459 
2460  // first copy pre-connections info
2461  copyPreConnectionInfo(netId, lGrpId, &managerRuntimeData, &runtimeData[netId], false);
2462 
2463  if (lGrpId == ALL) {
2464  lengthSyn = networkConfigs[netId].numPreSynNet;
2465  posSyn = 0;
2466  }
2467  else {
2468  lengthSyn = 0;
2469  for (int lNId = groupConfigs[netId][lGrpId].lStartN; lNId <= groupConfigs[netId][lGrpId].lEndN; lNId++)
2470  lengthSyn += managerRuntimeData.Npre[lNId];
2471 
2472  posSyn = managerRuntimeData.cumulativePre[groupConfigs[netId][lGrpId].lStartN];
2473  }
2474 
2475  assert(posSyn < networkConfigs[netId].numPreSynNet || networkConfigs[netId].numPreSynNet == 0);
2476  assert(lengthSyn <= networkConfigs[netId].numPreSynNet);
2477 
2478  memcpy(&managerRuntimeData.wt[posSyn], &runtimeData[netId].wt[posSyn], sizeof(float) * lengthSyn);
2479 
2480  // copy firing time for individual synapses
2481  //CUDA_CHECK_ERRORS(cudaMemcpy(&managerRuntimeData.synSpikeTime[cumPos_syn], &runtimeData[netId].synSpikeTime[cumPos_syn], sizeof(int) * length_wt, cudaMemcpyDeviceToHost));
2482 
2483  if ((!sim_with_fixedwts) || sim_with_stdp) {
2484  // copy synaptic weight derivative
2485  memcpy(&managerRuntimeData.wtChange[posSyn], &runtimeData[netId].wtChange[posSyn], sizeof(float) * lengthSyn);
2486  }
2487 }
2488 
2489 void SNN::copyNetworkConfig(int netId) {
2490  // do nothing, CPU computing backend can access networkConfigs[] directly
2491 }
2492 
2493 void SNN::copyGrpIdsLookupArray(int netId) {
2494  memcpy(managerRuntimeData.grpIds, runtimeData[netId].grpIds, sizeof(short int) * networkConfigs[netId].numNAssigned);
2495 }
2496 
2497 void SNN::copyConnIdsLookupArray(int netId) {
2498  memcpy(managerRuntimeData.connIdsPreIdx, runtimeData[netId].connIdsPreIdx, sizeof(short int) * networkConfigs[netId].numPreSynNet);
2499 }
2500 
2501 void SNN::copyLastSpikeTime(int netId) {
2502  memcpy(managerRuntimeData.lastSpikeTime, runtimeData[netId].lastSpikeTime, sizeof(int) * networkConfigs[netId].numN);
2503 }
2504 
2508 void SNN::copyNetworkSpikeCount(int netId,
2509  unsigned int* spikeCountD1, unsigned int* spikeCountD2,
2510  unsigned int* spikeCountExtD1, unsigned int* spikeCountExtD2) {
2511 
2512  *spikeCountExtD2 = runtimeData[netId].spikeCountExtRxD2;
2513  *spikeCountExtD1 = runtimeData[netId].spikeCountExtRxD1;
2514  *spikeCountD2 = runtimeData[netId].spikeCountD2;
2515  *spikeCountD1 = runtimeData[netId].spikeCountD1;
2516 }
2517 
2523 void SNN::copySpikeTables(int netId) {
2524  unsigned int spikeCountD1Sec, spikeCountD2Sec, spikeCountLastSecLeftD2;
2525 
2526  spikeCountLastSecLeftD2 = runtimeData[netId].spikeCountLastSecLeftD2;
2527  spikeCountD2Sec = runtimeData[netId].spikeCountD2Sec;
2528  spikeCountD1Sec = runtimeData[netId].spikeCountD1Sec;
2529  memcpy(managerRuntimeData.firingTableD2, runtimeData[netId].firingTableD2, sizeof(int) * (spikeCountD2Sec + spikeCountLastSecLeftD2));
2530  memcpy(managerRuntimeData.firingTableD1, runtimeData[netId].firingTableD1, sizeof(int) * spikeCountD1Sec);
2531  memcpy(managerRuntimeData.timeTableD2, runtimeData[netId].timeTableD2, sizeof(int) * (1000 + networkConfigs[netId].maxDelay + 1));
2532  memcpy(managerRuntimeData.timeTableD1, runtimeData[netId].timeTableD1, sizeof(int) * (1000 + networkConfigs[netId].maxDelay + 1));
2533 }
2534 
2535 #if defined(WIN32) || defined(WIN64) || defined(__APPLE__)
2536  void SNN::deleteRuntimeData_CPU(int netId) {
2537 #else // POSIX
2538  void* SNN::deleteRuntimeData_CPU(int netId) {
2539 #endif
2540  assert(runtimeData[netId].memType == CPU_MEM);
2541  // free all pointers
2542  delete [] runtimeData[netId].voltage;
2543  delete [] runtimeData[netId].nextVoltage;
2544  delete [] runtimeData[netId].recovery;
2545  delete [] runtimeData[netId].current;
2546  delete [] runtimeData[netId].extCurrent;
2547  delete [] runtimeData[netId].curSpike;
2548  delete [] runtimeData[netId].Npre;
2549  delete [] runtimeData[netId].Npre_plastic;
2550  delete [] runtimeData[netId].Npre_plasticInv;
2551  delete [] runtimeData[netId].Npost;
2552  delete [] runtimeData[netId].cumulativePost;
2553  delete [] runtimeData[netId].cumulativePre;
2554  delete [] runtimeData[netId].synSpikeTime;
2555  delete [] runtimeData[netId].wt;
2556  delete [] runtimeData[netId].wtChange;
2557  delete [] runtimeData[netId].maxSynWt;
2558  delete [] runtimeData[netId].nSpikeCnt;
2559  delete [] runtimeData[netId].avgFiring;
2560  delete [] runtimeData[netId].baseFiring;
2561  delete [] runtimeData[netId].baseFiringInv;
2562 
2563  delete [] runtimeData[netId].grpDA;
2564  delete [] runtimeData[netId].grp5HT;
2565  delete [] runtimeData[netId].grpACh;
2566  delete [] runtimeData[netId].grpNE;
2567 
2568  delete [] runtimeData[netId].grpDABuffer;
2569  delete [] runtimeData[netId].grp5HTBuffer;
2570  delete [] runtimeData[netId].grpAChBuffer;
2571  delete [] runtimeData[netId].grpNEBuffer;
2572 
2573  if (networkConfigs[netId].sim_with_nm) {
2574  delete[] runtimeData[netId].nVBuffer;
2575  delete[] runtimeData[netId].nUBuffer;
2576  delete[] runtimeData[netId].nIBuffer;
2577  }
2578 
2579  delete [] runtimeData[netId].grpIds;
2580 
2581  delete [] runtimeData[netId].Izh_a;
2582  delete [] runtimeData[netId].Izh_b;
2583  delete [] runtimeData[netId].Izh_c;
2584  delete [] runtimeData[netId].Izh_d;
2585  delete [] runtimeData[netId].Izh_C;
2586  delete [] runtimeData[netId].Izh_k;
2587  delete [] runtimeData[netId].Izh_vr;
2588  delete [] runtimeData[netId].Izh_vt;
2589  delete [] runtimeData[netId].Izh_vpeak;
2590 
2591  delete [] runtimeData[netId].lif_tau_m;
2592  delete [] runtimeData[netId].lif_tau_ref;
2593  delete [] runtimeData[netId].lif_tau_ref_c;
2594  delete [] runtimeData[netId].lif_vTh;
2595  delete [] runtimeData[netId].lif_vReset;
2596  delete [] runtimeData[netId].lif_gain;
2597  delete [] runtimeData[netId].lif_bias;
2598 
2599  delete [] runtimeData[netId].gAMPA;
2600  if (sim_with_NMDA_rise) {
2601  delete [] runtimeData[netId].gNMDA_r;
2602  delete [] runtimeData[netId].gNMDA_d;
2603  }
2604  else {
2605  delete [] runtimeData[netId].gNMDA;
2606  }
2607  delete [] runtimeData[netId].gGABAa;
2608  if (sim_with_GABAb_rise) {
2609  delete [] runtimeData[netId].gGABAb_r;
2610  delete [] runtimeData[netId].gGABAb_d;
2611  }
2612  else {
2613  delete [] runtimeData[netId].gGABAb;
2614  }
2615 
2616  delete [] runtimeData[netId].stpu;
2617  delete [] runtimeData[netId].stpx;
2618 
2619  delete [] runtimeData[netId].connIdsPreIdx;
2620 
2621  delete [] runtimeData[netId].postDelayInfo;
2622  delete [] runtimeData[netId].postSynapticIds;
2623  delete [] runtimeData[netId].preSynapticIds;
2624  delete [] runtimeData[netId].I_set;
2625  delete [] runtimeData[netId].poissonFireRate;
2626  delete [] runtimeData[netId].lastSpikeTime;
2627  delete [] runtimeData[netId].spikeGenBits;
2628 
2629  delete [] runtimeData[netId].timeTableD1;
2630  delete [] runtimeData[netId].timeTableD2;
2631 
2632  delete [] runtimeData[netId].firingTableD2;
2633  delete [] runtimeData[netId].firingTableD1;
2634 
2635  int** tempPtrs;
2636  tempPtrs = new int*[networkConfigs[netId].numGroups];
2637 
2638  // fetch device memory address stored in extFiringTableD2
2639  memcpy(tempPtrs, runtimeData[netId].extFiringTableD2, sizeof(int*) * networkConfigs[netId].numGroups);
2640  for (int i = 0; i < networkConfigs[netId].numGroups; i++)
2641  delete [] tempPtrs[i];
2642  delete [] runtimeData[netId].extFiringTableD2;
2643 
2644  // fetch device memory address stored in extFiringTableD1
2645  memcpy(tempPtrs, runtimeData[netId].extFiringTableD1, sizeof(int*) * networkConfigs[netId].numGroups);
2646  for (int i = 0; i < networkConfigs[netId].numGroups; i++)
2647  delete [] tempPtrs[i];
2648  delete [] runtimeData[netId].extFiringTableD1;
2649 
2650  delete [] tempPtrs;
2651 
2652  delete [] runtimeData[netId].extFiringTableEndIdxD2;
2653  delete [] runtimeData[netId].extFiringTableEndIdxD1;
2654 
2655  if (runtimeData[netId].randNum != NULL) delete [] runtimeData[netId].randNum;
2656  runtimeData[netId].randNum = NULL;
2657 }
2658 
2659 #if !defined(WIN32) && !defined(WIN64) && !defined(__APPLE__) // Linux or MAC
2660  // Static multithreading subroutine method - helper for the above method
2661  void* SNN::helperDeleteRuntimeData_CPU(void* arguments) {
2662  ThreadStruct* args = (ThreadStruct*) arguments;
2663  //printf("\nThread ID: %lu and CPU: %d\n",pthread_self(), sched_getcpu());
2664  ((SNN *)args->snn_pointer) -> deleteRuntimeData_CPU(args->netId);
2665  pthread_exit(0);
2666  }
2667 #endif
ThreadStruct_s::endIdx
int endIdx
Definition: snn_datastructures.h:728
RuntimeData_s::gNMDA
float * gNMDA
conductance of gNMDA
Definition: snn_datastructures.h:495
RuntimeData_s::Izh_d
float * Izh_d
Definition: snn_datastructures.h:476
POISSON_NEURON
#define POISSON_NEURON
Definition: carlsim_definitions.h:66
TARGET_GABAb
#define TARGET_GABAb
Definition: carlsim_definitions.h:70
RuntimeData_s::spikeCountExtRxD2
unsigned int spikeCountExtRxD2
the number of external spikes with axonal delay > 1 in a simulation, used in CPU_MODE currently
Definition: snn_datastructures.h:462
RuntimeData_s::grpNEBuffer
float * grpNEBuffer
Definition: snn_datastructures.h:581
STP_BUF_POS
#define STP_BUF_POS(nid, t, maxDelay)
Definition: snn_definitions.h:103
SynInfo_s
Definition: snn_datastructures.h:90
RuntimeData_s::lif_tau_ref
int * lif_tau_ref
Definition: snn_datastructures.h:482
TIMING_COUNT
#define TIMING_COUNT
Definition: snn_definitions.h:156
TARGET_DA
#define TARGET_DA
Definition: carlsim_definitions.h:71
GroupConfigRT_s::decayDP
float decayDP
decay rate for Dopaamine, published by GroupConfig
Definition: snn_datastructures.h:435
DelayInfo_s
Definition: snn_datastructures.h:85
RuntimeData_s::poissonFireRate
float * poissonFireRate
Definition: snn_datastructures.h:555
RuntimeData_s::lif_tau_ref_c
int * lif_tau_ref_c
Definition: snn_datastructures.h:483
RuntimeData_s::timeTableD2
unsigned int * timeTableD2
firing table, only used in CPU_MODE currently
Definition: snn_datastructures.h:544
NetworkConfigRT_s::numNPois
int numNPois
number of poisson neurons
Definition: snn_datastructures.h:638
SNN::isSimulationWithGABAbRise
bool isSimulationWithGABAbRise()
Definition: snn.h:637
RuntimeData_s::wtChange
float * wtChange
stores the weight change of a synaptic connection
Definition: snn_datastructures.h:523
RuntimeData_s::Izh_vr
float * Izh_vr
Definition: snn_datastructures.h:470
RuntimeData_s
Definition: snn_datastructures.h:451
RuntimeData_s::nextVoltage
float * nextVoltage
membrane potential buffer (next/future time step) for each regular neuron
Definition: snn_datastructures.h:466
RuntimeData_s::baseFiring
float * baseFiring
Definition: snn_datastructures.h:566
EXP_CURVE
@ EXP_CURVE
standard exponential curve
Definition: carlsim_datastructures.h:179
RuntimeData_s::stpx
float * stpx
Definition: snn_datastructures.h:512
RuntimeData_s::Izh_vpeak
float * Izh_vpeak
Definition: snn_datastructures.h:472
RuntimeData_s::baseFiringInv
float * baseFiringInv
only used on GPU
Definition: snn_datastructures.h:565
PoissonRate::getRatePtrCPU
float * getRatePtrCPU()
Returns pointer to CPU-allocated firing rate array (deprecated)
Definition: poisson_rate.cpp:225
RuntimeData_s::Izh_b
float * Izh_b
Definition: snn_datastructures.h:474
RuntimeData_s::spikeCount
unsigned int spikeCount
the total number of spikes in a simulation, used in CPU_MODE currently
Definition: snn_datastructures.h:457
RuntimeData_s::spikeCountD2Sec
unsigned int spikeCountD2Sec
the total number of spikes with axonal delay > 1 in 1 second, used in CPU_MODE currently
Definition: snn_datastructures.h:454
RuntimeData_s::gGABAa
float * gGABAa
conductance of gGABAa
Definition: snn_datastructures.h:499
RuntimeData_s::current
float * current
Definition: snn_datastructures.h:477
RuntimeData_s::Npre
unsigned short * Npre
stores the number of input connections to a neuron
Definition: snn_datastructures.h:515
RuntimeData_s::grpAChBuffer
float * grpAChBuffer
Definition: snn_datastructures.h:580
RuntimeData_s::I_set
int * I_set
an array of bits indicating which synapse got a spike
Definition: snn_datastructures.h:504
PoissonRate
Class for generating Poisson spike trains.
Definition: poisson_rate.h:84
RuntimeData_s::spikeGenBits
unsigned int * spikeGenBits
Definition: snn_datastructures.h:588
RuntimeData_s::lif_vTh
float * lif_vTh
Definition: snn_datastructures.h:484
RuntimeData_s::recovery
float * recovery
Definition: snn_datastructures.h:467
RuntimeData_s::gAMPA
float * gAMPA
conductance of gAMPA
Definition: snn_datastructures.h:498
GroupConfigRT_s::OMEGA
float OMEGA
published by GroupConfig
Definition: snn_datastructures.h:414
NetworkConfigRT_s::maxDelay
int maxDelay
maximum axonal delay in the gloabl network
Definition: snn_datastructures.h:628
RuntimeData_s::lif_gain
float * lif_gain
Definition: snn_datastructures.h:486
RuntimeData_s::Izh_vt
float * Izh_vt
Definition: snn_datastructures.h:471
RUNGE_KUTTA4
@ RUNGE_KUTTA4
Definition: carlsim_datastructures.h:135
STDP
#define STDP(t, a, b)
Definition: snn_definitions.h:150
RuntimeData_s::Npost
unsigned short * Npost
stores the number of output connections from a neuron.
Definition: snn_datastructures.h:518
GroupConfigRT_s::numN
int numN
published by GroupConfig
Definition: snn_datastructures.h:385
ThreadStruct_s
CPU multithreading subroutine (that takes single argument) struct argument.
Definition: snn_datastructures.h:723
GlobalNetworkConfig_s::maxDelay
int maxDelay
maximum axonal delay in the gloabl network
Definition: snn_datastructures.h:611
RuntimeData_s::extCurrent
float * extCurrent
Definition: snn_datastructures.h:479
RuntimeData_s::nUBuffer
float * nUBuffer
Definition: snn_datastructures.h:585
PULSE_CURVE
@ PULSE_CURVE
symmetric pulse curve
Definition: carlsim_datastructures.h:180
RuntimeData_s::nPoissonSpikes
unsigned int nPoissonSpikes
the total number of spikes of poisson neurons, used in CPU_MODE currently
Definition: snn_datastructures.h:460
RuntimeData_s::wt
float * wt
stores the weight change of a synaptic connection
Definition: snn_datastructures.h:524
RuntimeData_s::nVBuffer
float * nVBuffer
Definition: snn_datastructures.h:584
MAX_NEURON_MON_GRP_SZIE
#define MAX_NEURON_MON_GRP_SZIE
Definition: snn_definitions.h:165
GroupConfigRT_s::Type
unsigned int Type
published by GroupConfig
Definition: snn_datastructures.h:384
CPU_RUNTIME_BASE
#define CPU_RUNTIME_BASE
Definition: snn_definitions.h:139
TIMING_BASED_CURVE
@ TIMING_BASED_CURVE
timing-based curve
Definition: carlsim_datastructures.h:181
FORWARD_EULER
@ FORWARD_EULER
Definition: carlsim_datastructures.h:134
RuntimeData_s::curSpike
bool * curSpike
Definition: snn_datastructures.h:492
dvdtIzhikevich4
float dvdtIzhikevich4(float volt, float recov, float totalCurrent, float timeStep=1.0f)
Definition: snn_cpu_module.cpp:857
GroupConfigRT_s::gGrpId
int gGrpId
published by GroupConfigMD
Definition: snn_datastructures.h:376
GroupConfigRT_s::compNeighbors
int compNeighbors[4]
Definition: snn_datastructures.h:446
RuntimeData_s::Npre_plasticInv
float * Npre_plasticInv
stores the 1/number of plastic input connections, only used on GPU
Definition: snn_datastructures.h:517
RuntimeData_s::postDelayInfo
DelayInfo * postDelayInfo
delay information
Definition: snn_datastructures.h:542
RuntimeData_s::timeTableD1
unsigned int * timeTableD1
firing table, only used in CPU_MODE currently
Definition: snn_datastructures.h:543
stdpType_string
static const char * stdpType_string[]
Definition: carlsim_datastructures.h:167
PoissonRate::getNumNeurons
int getNumNeurons()
Returns the number of neurons for which to generate Poisson spike trains.
Definition: poisson_rate.cpp:222
RuntimeData_s::voltage
float * voltage
membrane potential for each regular neuron
Definition: snn_datastructures.h:465
ThreadStruct_s::netId
int netId
Definition: snn_datastructures.h:725
RuntimeData_s::Npre_plastic
unsigned short * Npre_plastic
stores the number of plastic input connections to a neuron
Definition: snn_datastructures.h:516
RuntimeData_s::spikeCountD1Sec
unsigned int spikeCountD1Sec
the total number of spikes with axonal delay == 1 in 1 second, used in CPU_MODE currently
Definition: snn_datastructures.h:453
NEURON_MAX_FIRING_RATE
#define NEURON_MAX_FIRING_RATE
Definition: snn_definitions.h:148
RuntimeData_s::Izh_C
float * Izh_C
Definition: snn_datastructures.h:468
dudtIzhikevich9
float dudtIzhikevich9(float volt, float recov, float voltRest, float izhA, float izhB, float timeStep=1.0f)
Definition: snn_cpu_module.cpp:877
GroupConfigRT_s::compCoupling
float compCoupling[4]
Definition: snn_datastructures.h:447
RuntimeData_s::Izh_c
float * Izh_c
Definition: snn_datastructures.h:475
RuntimeData_s::gNMDA_r
float * gNMDA_r
Definition: snn_datastructures.h:496
MAX_SIMULATION_TIME
#define MAX_SIMULATION_TIME
Definition: snn_definitions.h:153
ALL
#define ALL
CARLsim common definitions.
Definition: carlsim_definitions.h:56
RuntimeData_s::nIBuffer
float * nIBuffer
Definition: snn_datastructures.h:586
RuntimeData_s::lastSpikeTime
int * lastSpikeTime
stores the last spike time of a neuron
Definition: snn_datastructures.h:520
KERNEL_ERROR
#define KERNEL_ERROR(formatc,...)
Definition: snn_definitions.h:110
RuntimeData_s::spikeCountExtRxD1
unsigned int spikeCountExtRxD1
the number of external spikes with axonal delay == 1 in a simulation, used in CPU_MODE currently
Definition: snn_datastructures.h:463
spike_buffer.h
GroupConfigRT_s::avgTimeScale_decay
float avgTimeScale_decay
published by GroupConfig
Definition: snn_datastructures.h:426
RuntimeData_s::grpDABuffer
float * grpDABuffer
Definition: snn_datastructures.h:578
DelayInfo_s::delay_index_start
short delay_index_start
Definition: snn_datastructures.h:86
RuntimeData_s::postSynapticIds
SynInfo * postSynapticIds
10 bit syn id, 22 bit neuron id, ordered based on delay
Definition: snn_datastructures.h:539
SNN::isSimulationWithNMDARise
bool isSimulationWithNMDARise()
Definition: snn.h:636
GroupConfigRT_s::Noffset
int Noffset
the offset of spike generator (poisson) neurons [0, numNPois), published by GroupConfigMD
Definition: snn_datastructures.h:401
RuntimeData_s::spikeCountSec
unsigned int spikeCountSec
the total number of spikes in 1 second, used in CPU_MODE currently
Definition: snn_datastructures.h:452
CPU_MEM
@ CPU_MEM
runtime data is allocated on CPU (main) memory
Definition: snn_datastructures.h:70
ThreadStruct_s::snn_pointer
void * snn_pointer
Definition: snn_datastructures.h:724
KERNEL_DEBUG
#define KERNEL_DEBUG(formatc,...)
Definition: snn_definitions.h:116
RuntimeData_s::connIdsPreIdx
short int * connIdsPreIdx
connectId, per synapse, presynaptic cumulative indexing
Definition: snn_datastructures.h:530
RuntimeData_s::firingTableD1
int * firingTableD1
Definition: snn_datastructures.h:546
ThreadStruct_s::startIdx
int startIdx
Definition: snn_datastructures.h:727
RuntimeData_s::spikeCountD2
unsigned int spikeCountD2
the total number of spikes with anxonal delay > 1 in a simulation, used in CPU_MODE currently
Definition: snn_datastructures.h:459
RuntimeData_s::cumulativePost
unsigned int * cumulativePost
Definition: snn_datastructures.h:527
UNKNOWN_STDP
@ UNKNOWN_STDP
Definition: carlsim_datastructures.h:164
RuntimeData_s::spikeCountD1
unsigned int spikeCountD1
the total number of spikes with anxonal delay == 1 in a simulation, used in CPU_MODE currently
Definition: snn_datastructures.h:458
RuntimeData_s::maxSynWt
float * maxSynWt
maximum synaptic weight for a connection
Definition: snn_datastructures.h:525
GroupConfigRT_s::numCompNeighbors
short numCompNeighbors
Definition: snn_datastructures.h:448
GroupConfigRT_s::lStartN
int lStartN
published by GroupConfigMD
Definition: snn_datastructures.h:380
ThreadStruct_s::GtoLOffset
int GtoLOffset
Definition: snn_datastructures.h:729
RuntimeData_s::Izh_k
float * Izh_k
Definition: snn_datastructures.h:469
RuntimeData_s::extFiringTableEndIdxD1
int * extFiringTableEndIdxD1
Definition: snn_datastructures.h:552
RuntimeData_s::synSpikeTime
int * synSpikeTime
stores the last spike time of a synapse
Definition: snn_datastructures.h:521
DA_MOD
@ DA_MOD
dopamine-modulated STDP, nearest-neighbor
Definition: carlsim_datastructures.h:163
RuntimeData_s::preSynapticIds
SynInfo * preSynapticIds
Definition: snn_datastructures.h:540
RuntimeData_s::gGABAb
float * gGABAb
conductance of gGABAb
Definition: snn_datastructures.h:500
RuntimeData_s::Izh_a
float * Izh_a
Definition: snn_datastructures.h:473
RuntimeData_s::lif_tau_m
int * lif_tau_m
parameters for a LIF spiking group
Definition: snn_datastructures.h:481
RuntimeData_s::avgFiring
float * avgFiring
Definition: snn_datastructures.h:567
RuntimeData_s::grpDA
float * grpDA
Definition: snn_datastructures.h:572
STANDARD
@ STANDARD
standard STDP of Bi & Poo (2001), nearest-neighbor
Definition: carlsim_datastructures.h:162
RuntimeData_s::extFiringTableD1
int ** extFiringTableD1
external firing table, only used on GPU
Definition: snn_datastructures.h:549
SNN::isSimulationWithCOBA
bool isSimulationWithCOBA()
Definition: snn.h:634
GroupConfigRT_s::lEndN
int lEndN
published by GroupConfigMD
Definition: snn_datastructures.h:381
dvdtLIF
float dvdtLIF(float volt, float lif_vReset, float lif_gain, float lif_bias, int lif_tau_m, float totalCurrent, float timeStep=1.0f)
Definition: snn_cpu_module.cpp:883
RuntimeData_s::extFiringTableEndIdxD2
int * extFiringTableEndIdxD2
Definition: snn_datastructures.h:553
RuntimeData_s::memType
MemType memType
Definition: snn_datastructures.h:506
RuntimeData_s::grpIds
short int * grpIds
Definition: snn_datastructures.h:531
SNN::exitSimulation
void exitSimulation(int val=1)
deallocates all dynamical structures and exits
Definition: snn_manager.cpp:995
GroupConfigRT_s::KAPPA
float KAPPA
published by GroupConfig
Definition: snn_datastructures.h:413
snn.h
GroupConfigRT_s::STP_A
float STP_A
published by GroupConfig
Definition: snn_datastructures.h:404
TARGET_NMDA
#define TARGET_NMDA
Definition: carlsim_definitions.h:68
RuntimeData_s::stpu
float * stpu
Definition: snn_datastructures.h:513
GroupConfigRT_s::LtoGOffset
int LtoGOffset
published by GroupConfigMD
Definition: snn_datastructures.h:382
SNN
Contains all of CARLsim's core functionality.
Definition: snn.h:115
RuntimeData_s::spikeCountExtRxD1Sec
unsigned int spikeCountExtRxD1Sec
Definition: snn_datastructures.h:455
RuntimeData_s::lif_bias
float * lif_bias
Definition: snn_datastructures.h:487
RuntimeData_s::grpNE
float * grpNE
Definition: snn_datastructures.h:575
RuntimeData_s::nSpikeCnt
int * nSpikeCnt
homeostatic plasticity variables
Definition: snn_datastructures.h:562
RuntimeData_s::extFiringTableD2
int ** extFiringTableD2
external firing table, only used on GPU
Definition: snn_datastructures.h:550
TARGET_AMPA
#define TARGET_AMPA
Definition: carlsim_definitions.h:67
DelayInfo_s::delay_length
short delay_length
Definition: snn_datastructures.h:87
RuntimeData_s::gNMDA_d
float * gNMDA_d
Definition: snn_datastructures.h:497
dudtIzhikevich4
float dudtIzhikevich4(float volt, float recov, float izhA, float izhB, float timeStep=1.0f)
Definition: snn_cpu_module.cpp:863
IS_REGULAR_NEURON
#define IS_REGULAR_NEURON(nid, numNReg, numNPois)
Definition: snn_definitions.h:69
RuntimeData_s::grp5HTBuffer
float * grp5HTBuffer
Definition: snn_datastructures.h:579
RuntimeData_s::grp5HT
float * grp5HT
Definition: snn_datastructures.h:573
dvdtIzhikevich9
float dvdtIzhikevich9(float volt, float recov, float invCapac, float izhK, float voltRest, float voltInst, float totalCurrent, float timeStep=1.0f)
Definition: snn_cpu_module.cpp:869
RuntimeData_s::firingTableD2
int * firingTableD2
Definition: snn_datastructures.h:547
RuntimeData_s::randNum
float * randNum
firing random number. max value is 10,000
Definition: snn_datastructures.h:556
RuntimeData_s::gGABAb_r
float * gGABAb_r
Definition: snn_datastructures.h:501
RuntimeData_s::spikeCountLastSecLeftD2
unsigned int spikeCountLastSecLeftD2
the nubmer of spike left in the last second, used in CPU_MODE currently
Definition: snn_datastructures.h:461
UNKNOWN_INTEGRATION
@ UNKNOWN_INTEGRATION
Definition: carlsim_datastructures.h:136
GroupConfigRT_s::STP_tau_u_inv
float STP_tau_u_inv
published by GroupConfig
Definition: snn_datastructures.h:406
ThreadStruct_s::lGrpId
int lGrpId
Definition: snn_datastructures.h:726
GET_CONN_NEURON_ID
#define GET_CONN_NEURON_ID(val)
Definition: snn_definitions.h:190
GroupConfigRT_s::STP_U
float STP_U
published by GroupConfig
Definition: snn_datastructures.h:405
RuntimeData_s::grpACh
float * grpACh
Definition: snn_datastructures.h:574
GroupConfigRT_s::BETA_LTP
float BETA_LTP
published by GroupConfig
Definition: snn_datastructures.h:419
TARGET_GABAa
#define TARGET_GABAa
Definition: carlsim_definitions.h:69
GET_CONN_SYN_ID
#define GET_CONN_SYN_ID(val)
Definition: snn_definitions.h:191
RuntimeData_s::spikeCountExtRxD2Sec
unsigned int spikeCountExtRxD2Sec
Definition: snn_datastructures.h:456
GroupConfigRT_s::homeostasisScale
float homeostasisScale
published by GroupConfig
Definition: snn_datastructures.h:428
GroupConfigRT_s::avgTimeScale
float avgTimeScale
published by GroupConfig
Definition: snn_datastructures.h:425
GroupConfigRT_s::BETA_LTD
float BETA_LTD
published by GroupConfig
Definition: snn_datastructures.h:420
RuntimeData_s::lif_vReset
float * lif_vReset
Definition: snn_datastructures.h:485
RuntimeData_s::cumulativePre
unsigned int * cumulativePre
Definition: snn_datastructures.h:528
RuntimeData_s::gGABAb_d
float * gGABAb_d
Definition: snn_datastructures.h:502
PoissonRate::isOnGPU
bool isOnGPU()
Checks whether the firing rates are allocated on CPU or GPU.
Definition: poisson_rate.cpp:227
RuntimeData_s::allocated
bool allocated
true if all data has been allocated
Definition: snn_datastructures.h:507