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