AnimatLab  2
Test
snn_cpu.cpp
1 /*
2  * Copyright (c) 2013 Regents of the University of California. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * 3. The names of its contributors may not be used to endorse or promote
16  * products derived from this software without specific prior written
17  * permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * *********************************************************************************************** *
32  * CARLsim
33  * created by: (MDR) Micah Richert, (JN) Jayram M. Nageswaran
34  * maintained by: (MA) Mike Avery <averym@uci.edu>, (MB) Michael Beyeler <mbeyeler@uci.edu>,
35  * (KDC) Kristofor Carlson <kdcarlso@uci.edu>
36  *
37  * CARLsim available from http://socsci.uci.edu/~jkrichma/CARLsim/
38  * Ver 07/13/2013
39  */
40 
41 #include "snn.h"
42 #include <sstream>
43 
44 #if (_WIN32 || _WIN64)
45 #include <float.h>
46 #include <time.h>
47 #include <direct.h>
48 
49 #ifndef isnan
50 #define isnan(x) _isnan(x)
51 #endif
52 
53 #ifndef isinf
54 #define isinf(x) (!_finite(x))
55 #endif
56 
57 #ifndef srand48
58 #define srand48(x) srand(x)
59 #endif
60 
61 #ifndef drand48
62 #define drand48() (double(rand())/RAND_MAX)
63 #endif
64 
65 #else
66 #include <string.h>
67 #define strcmpi(s1,s2) strcasecmp(s1,s2)
68 #endif
69 
70 MTRand_closed getRandClosed;
71 MTRand getRand;
72 
73 RNG_rand48* gpuRand48 = NULL;
74 
75 // includes for mkdir
76 #if defined(CREATE_SPIKEDIR_IF_NOT_EXISTS)
77  #include <sys/stat.h>
78  #include <errno.h>
79 
80  #if ! (_WIN32 || _WIN64)
81  #include <libgen.h>
82  #endif
83 #endif
84 
85 
86 /*********************************************/
87 
88 void CpuSNN::resetPointers()
89 {
90  voltage = NULL;
91  recovery = NULL;
92  Izh_a = NULL;
93  Izh_b = NULL;
94  Izh_c = NULL;
95  Izh_d = NULL;
96  current = NULL;
97  Npre = NULL;
98  Npost = NULL;
99  lastSpikeTime = NULL;
100  postSynapticIds = NULL;
101  postDelayInfo = NULL;
102  wt = NULL;
103  maxSynWt = NULL;
104  wtChange = NULL;
105  //stdpChanged = NULL;
106  synSpikeTime = NULL;
107  spikeGenBits = NULL;
108  firingTableD2 = NULL;
109  firingTableD1 = NULL;
110 
111  fpParam = NULL;
112  fpLog = NULL;
113  fpProgLog = stderr;
114  fpTuningLog = NULL;
115  cntTuning = 0;
116 
117  Npre_plastic=NULL;
118  cumulativePre=NULL;
119  cumulativePost=NULL;
120  curSpike=NULL;
121  nSpikeCnt=NULL;
122  intrinsicWeight=NULL;
123  preSynapticIds=NULL;
124  tmp_SynapticDelay=NULL;
125  timeTableD2=NULL;
126  timeTableD1=NULL;
127  pbuf=NULL;
128 }
129 
130 void CpuSNN::resetCurrent()
131 {
132  carlsim_assert(current != NULL);
133  memset(current, 0, sizeof(float)*numNReg);
134 }
135 
136 void CpuSNN::resetCounters()
137 {
138  carlsim_assert(numNReg <= numN);
139  memset( curSpike, 0, sizeof(bool)*numN);
140 }
141 
142 void CpuSNN::resetConductances()
143 {
144  if (sim_with_conductances) {
145  carlsim_assert(gAMPA != NULL);
146  memset(gAMPA, 0, sizeof(float)*numNReg);
147  memset(gNMDA, 0, sizeof(float)*numNReg);
148  memset(gGABAa, 0, sizeof(float)*numNReg);
149  memset(gGABAb, 0, sizeof(float)*numNReg);
150  }
151 }
152 
153 void CpuSNN::resetTimingTable()
154 {
155  memset(timeTableD2, 0, sizeof(int)*(CARLSIM_STEP_SIZE+D+1));
156  memset(timeTableD1, 0, sizeof(int)*(CARLSIM_STEP_SIZE+D+1));
157 }
158 
159 void CpuSNN::CpuSNNInit(unsigned int _numN, unsigned int _numPostSynapses, unsigned int _numPreSynapses, unsigned int _D)
160 {
161  numN = _numN;
162  numPostSynapses = _numPostSynapses;
163  D = _D;
164  numPreSynapses = _numPreSynapses;
165 
166  voltage = new float[numNReg];
167  recovery = new float[numNReg];
168  Izh_a = new float[numNReg];
169  Izh_b = new float[numNReg];
170  Izh_c = new float[numNReg];
171  Izh_d = new float[numNReg];
172  current = new float[numNReg];
173  cpuSnnSz.neuronInfoSize += (sizeof(int)*numNReg*12);
174 
175  if (sim_with_conductances) {
176  for (int g=0;g<numGrp;g++)
177  if (!grp_Info[g].WithConductances && ((grp_Info[g].Type&POISSON_NEURON)==0)) {
178  printf("If one group enables conductances then all groups, except for generators, must enable conductances. Group '%s' is not enabled.\n", grp_Info2[g].Name.c_str());
179  carlsim_assert(false);
180  }
181 
182  gAMPA = new float[numNReg];
183  gNMDA = new float[numNReg];
184  gGABAa = new float[numNReg];
185  gGABAb = new float[numNReg];
186  cpuSnnSz.neuronInfoSize += sizeof(int)*numNReg*4;
187  }
188 
189  resetCurrent();
190  resetConductances();
191 
192  lastSpikeTime = new uint32_t[numN];
193  cpuSnnSz.neuronInfoSize += sizeof(int)*numN;
194  memset(lastSpikeTime,0,sizeof(lastSpikeTime[0]*numN));
195 
196  curSpike = new bool[numN];
197  nSpikeCnt = new unsigned int[numN];
199  avgFiring = new float[numN];
200  baseFiring = new float[numN];
201 
202  intrinsicWeight = new float[numN];
203  memset(intrinsicWeight,0,sizeof(float)*numN);
204  cpuSnnSz.neuronInfoSize += (sizeof(int)*numN*2+sizeof(bool)*numN);
205 
206  if (sim_with_stp) {
207  stpu = new float[numN*STP_BUF_SIZE];
208  stpx = new float[numN*STP_BUF_SIZE];
209  for (int i=0; i < numN*STP_BUF_SIZE; i++) {
210  //MDR this should be set later.. (adding a default value)
211  stpu[i] = 1;
212  stpx[i] = 1;
213  }
214  cpuSnnSz.synapticInfoSize += (sizeof(stpu[0])*numN*STP_BUF_SIZE);
215  }
216 
217  Npre = new unsigned short[numN];
218  Npre_plastic = new unsigned short[numN];
219  Npost = new unsigned short[numN];
220  cumulativePost = new unsigned int[numN];
221  cumulativePre = new unsigned int[numN];
222  cpuSnnSz.networkInfoSize += (int)(sizeof(int)*numN*3.5);
223 
224  postSynCnt = 0;
225  preSynCnt = 0;
226  for(int g=0; g < numGrp; g++) {
227  // check for INT overflow: postSynCnt is O(numNeurons*numSynapses), must be able to fit within u int limit
228  carlsim_assert(postSynCnt < UINT_MAX - (grp_Info[g].SizeN*grp_Info[g].numPostSynapses));
229  carlsim_assert(preSynCnt < UINT_MAX - (grp_Info[g].SizeN*grp_Info[g].numPreSynapses));
230  postSynCnt += (grp_Info[g].SizeN*grp_Info[g].numPostSynapses);
231  preSynCnt += (grp_Info[g].SizeN*grp_Info[g].numPreSynapses);
232  }
233  carlsim_assert(postSynCnt/numN <= numPostSynapses); // divide by numN to prevent INT overflow
234  postSynapticIds = new post_info_t[postSynCnt+100];
235  tmp_SynapticDelay = new uint8_t[postSynCnt+100];
236  postDelayInfo = new delay_info_t[numN*(D+1)];
237  cpuSnnSz.networkInfoSize += ((sizeof(post_info_t)+sizeof(uint8_t))*postSynCnt+100) + (sizeof(delay_info_t)*numN*(D+1));
238  carlsim_assert(preSynCnt/numN <= numPreSynapses); // divide by numN to prevent INT overflow
239 
240  wt = new float[preSynCnt+100];
241  maxSynWt = new float[preSynCnt+100];
243  preSynapticIds = new post_info_t[preSynCnt+100];
244  // size due to weights and maximum weights
245  cpuSnnSz.synapticInfoSize += ((2*sizeof(float)+sizeof(post_info_t))*(preSynCnt+100));
246 
247  timeTableD2 = new unsigned int[CARLSIM_STEP_SIZE+D+1];
248  timeTableD1 = new unsigned int[CARLSIM_STEP_SIZE+D+1];
249  resetTimingTable();
250  cpuSnnSz.spikingInfoSize += sizeof(int)*2*(CARLSIM_STEP_SIZE+D+1);
251 
252  // random thalamic current included...
253  // randNeuronId = new int[numN];
254  // cpuSnnSz.addInfoSize += (sizeof(int)*numN);
255 
256  // poisson Firing Rate
257  cpuSnnSz.neuronInfoSize += (sizeof(int)*numNPois);
258 
259  tmp_SynapseMatrix_fixed = NULL;
260  tmp_SynapseMatrix_plastic = NULL;
261 }
262 
263 void CpuSNN::makePtrInfo()
264 {
265  // create the CPU Net Ptrs..
266  cpuNetPtrs.voltage = voltage;
267  cpuNetPtrs.recovery = recovery;
268  cpuNetPtrs.current = current;
269  cpuNetPtrs.Npre = Npre;
270  cpuNetPtrs.Npost = Npost;
271  cpuNetPtrs.cumulativePost = cumulativePost;
272  cpuNetPtrs.cumulativePre = cumulativePre;
273  cpuNetPtrs.synSpikeTime = synSpikeTime;
274  cpuNetPtrs.wt = wt;
275  cpuNetPtrs.wtChange = wtChange;
276  cpuNetPtrs.nSpikeCnt = nSpikeCnt;
277  cpuNetPtrs.curSpike = curSpike;
278  cpuNetPtrs.firingTableD2 = firingTableD2;
279  cpuNetPtrs.firingTableD1 = firingTableD1;
280  // homeostasis variables
281  cpuNetPtrs.avgFiring = avgFiring;
282  cpuNetPtrs.baseFiring = baseFiring;
283  cpuNetPtrs.gAMPA = gAMPA;
284  cpuNetPtrs.gNMDA = gNMDA;
285  cpuNetPtrs.gGABAa = gGABAa;
286  cpuNetPtrs.gGABAb = gGABAb;
287  cpuNetPtrs.allocated = true;
288  cpuNetPtrs.memType = CPU_MODE;
289  cpuNetPtrs.stpu = stpu;
290  cpuNetPtrs.stpx = stpx;
291 }
292 
293 void CpuSNN::resetSpikeCnt(int my_grpId )
294 {
295  int startGrp, endGrp;
296 
297  if(!doneReorganization)
298  return;
299 
300  if (my_grpId == -1) {
301  startGrp = 0;
302  endGrp = numGrp;
303  }
304  else {
305  startGrp = my_grpId;
306  endGrp = my_grpId+numConfig;
307  }
308 
309  for( int grpId=startGrp; grpId < endGrp; grpId++) {
310  int startN = grp_Info[grpId].StartN;
311  int endN = grp_Info[grpId].EndN+1;
312  for (int i=startN; i < endN; i++)
313  nSpikeCnt[i] = 0;
314  }
315 }
316 
317 
318 void CpuSNN::resetSpikeCntUtil(int my_grpId )
319 {
320  int startGrp, endGrp;
321 
322  if(!doneReorganization)
323  return;
324 
325  if(currentMode == GPU_MODE){
326  //call analogous function, return, else do CPU stuff
327  if (my_grpId == -1) {
328  startGrp = 0;
329  endGrp = numGrp;
330  }
331  else {
332  startGrp = my_grpId;
333  endGrp = my_grpId+numConfig;
334  }
335  resetSpikeCnt_GPU(startGrp, endGrp);
336  return;
337  }
338 
339  if (my_grpId == -1) {
340  startGrp = 0;
341  endGrp = numGrp;
342  }
343  else {
344  startGrp = my_grpId;
345  endGrp = my_grpId+numConfig;
346  }
347 
348  for( int grpId=startGrp; grpId < endGrp; grpId++) {
349  int startN = grp_Info[grpId].StartN;
350  int endN = grp_Info[grpId].EndN+1;
351  for (int i=startN; i < endN; i++)
352  nSpikeCnt[i] = 0;
353  }
354 }
355 
356 CpuSNN::CpuSNN(const string& _name, int _numConfig, int _randSeed, int _mode)
357 {
358  fprintf(stdout, "************************************************\n");
359  fprintf(stdout, "***** GPU-SNN Simulation Begins Version %d.%d *** \n",MAJOR_VERSION,MINOR_VERSION);
360  fprintf(stdout, "************************************************\n");
361 
362  // initialize propogated spike buffers.....
363  pbuf = new PropagatedSpikeBuffer(0, PROPAGATED_BUFFER_SIZE);
364 
365  numConfig = _numConfig;
366  finishedPoissonGroup = false;
367  carlsim_assert(numConfig > 0);
368  carlsim_assert(numConfig < 100);
369 
370  resetPointers();
371  numN = 0; numPostSynapses = 0; D = 0;
372  memset(&cpuSnnSz, 0, sizeof(cpuSnnSz));
373  enableSimLogs = false;
374  simLogDirName = "logs";//strdup("logs");
375 
376  fpLog=fopen("tmp_debug.log","w");
377  fpProgLog = NULL;
378  showLog = 0; // disable showing log..
379  showLogMode = 0; // show only basic logs. if set higher more logs generated
380  showGrpFiringInfo = true;
381 
382  currentMode = _mode;
383  memset(&cpu_gpuNetPtrs,0,sizeof(network_ptr_t));
384  memset(&net_Info,0,sizeof(network_info_t));
385  cpu_gpuNetPtrs.allocated = false;
386 
387  memset(&cpuNetPtrs,0, sizeof(network_ptr_t));
388  cpuNetPtrs.allocated = false;
389 
390 #ifndef VIEW_DOTTY
391 #define VIEW_DOTTY false
392 #endif
393  showDotty = VIEW_DOTTY;
394  numSpikeMonitor = 0;
395 
396  for (int i=0; i < MAX_GRP_PER_SNN; i++) {
397  grp_Info[i].Type = UNKNOWN_NEURON;
398  grp_Info[i].MaxFiringRate = UNKNOWN_NEURON_MAX_FIRING_RATE;
399  grp_Info[i].MonitorId = -1;
400  grp_Info[i].FiringCount1sec=0;
401  grp_Info[i].numPostSynapses = 0; // default value
402  grp_Info[i].numPreSynapses = 0; // default value
403  grp_Info[i].WithSTP = false;
404  grp_Info[i].WithSTDP = false;
405  grp_Info[i].FixedInputWts = true; // Default is true. This value changed to false
406  // if any incoming connections are plastic
407  grp_Info[i].WithConductances = false;
408  grp_Info[i].isSpikeGenerator = false;
409  grp_Info[i].RatePtr = NULL;
410 
411  grp_Info[i].homeoId = -1;
412  grp_Info[i].avgTimeScale = 10000.0;
413  /* grp_Info[i].STP_U = STP_U_Exc;
414  grp_Info[i].STP_tD = STP_tD_Exc;
415  grp_Info[i].STP_tF = STP_tF_Exc;
416  */
417 
418  grp_Info[i].dAMPA=1-(1.0/5);
419  grp_Info[i].dNMDA=1-(1.0/150);
420  grp_Info[i].dGABAa=1-(1.0/6);
421  grp_Info[i].dGABAb=1-(1.0/150);
422 
423  grp_Info[i].spikeGen = NULL;
424 
425  grp_Info[i].StartN = -1;
426  grp_Info[i].EndN = -1;
427 
428  grp_Info2[i].numPostConn = 0;
429  grp_Info2[i].numPreConn = 0;
430  grp_Info2[i].enablePrint = false;
431  grp_Info2[i].maxPostConn = 0;
432  grp_Info2[i].maxPreConn = 0;
433  grp_Info2[i].sumPostConn = 0;
434  grp_Info2[i].sumPreConn = 0;
435  }
436 
437  connectBegin = NULL;
438  numProbe = 0;
439  neuronProbe = NULL;
440 
441  simTimeMs = 0; simTimeSec = 0; simTime = 0;
442  spikeCountAll1sec = 0; secD1fireCntHost = 0; secD2fireCntHost = 0;
443  spikeCountAll = 0; spikeCountD2Host = 0; spikeCountD1Host = 0;
444  nPoissonSpikes = 0;
445 
446  networkName = _name; //new char[sizeof(_name)];
447  //strcpy(networkName, _name);
448  numGrp = 0;
449  numConnections = 0;
450  numSpikeGenGrps = 0;
451  NgenFunc = 0;
452  // numNoise = 0;
453  // numRandNeurons = 0;
454  simulatorDeleted = false;
455  enableGPUSpikeCntPtr = false;
456 
457  allocatedN = 0;
458  allocatedPre = 0;
459  allocatedPost = 0;
460  doneReorganization = false;
461  memoryOptimized = false;
462 
463  stpu = NULL;
464  stpx = NULL;
465  gAMPA = NULL;
466  gNMDA = NULL;
467  gGABAa = NULL;
468  gGABAb = NULL;
469 
470  if (_randSeed == -1) {
471  randSeed = time(NULL);
472  }
473  else if(_randSeed==0) {
474  randSeed=123;
475  }
476  srand48(randSeed);
477  getRand.seed(randSeed*2);
478  getRandClosed.seed(randSeed*3);
479 
480  fpParam = fopen("param.txt", "w");
481  if (fpParam==NULL) {
482  fprintf(stderr, "WARNING !!! Unable to open/create parameter file 'param.txt'; check if current directory is writable \n");
483 #ifdef USE_EXCEPTIONS
484  throw std::runtime_error("WARNING !!! Unable to open/create parameter file 'param.txt'; check if current directory is writable \n");
485 #else
486  exit(1);
487 #endif
488  return;
489  }
490  fprintf(fpParam, "// *****************************************\n");
491  time_t rawtime; struct tm * timeinfo;
492  time ( &rawtime ); timeinfo = localtime ( &rawtime );
493  fprintf ( fpParam, "// program name : %s \n", _name.c_str());
494  fprintf ( fpParam, "// rand val : %d \n", randSeed);
495  fprintf ( fpParam, "// Current local time and date: %s\n", asctime (timeinfo));
496  fflush(fpParam);
497 
498  CUDA_CREATE_TIMER(timer);
499  CUDA_RESET_TIMER(timer);
500  cumExecutionTime = 0.0;
501 
502  spikeRateUpdated = false;
503 
504  sim_with_fixedwts = true; // default is true, will be set to false if there are any plastic synapses
505  sim_with_conductances = false; // for all others, the default is false
506  sim_with_stdp = false;
507  sim_with_stp = false;
508 
509  maxSpikesD2 = maxSpikesD1 = 0;
510  readNetworkFID = NULL;
511 
512  // initialize parameters needed in snn_gpu.cu
513  CpuSNNinitGPUparams();
514 
515  stepFeedback = NULL;
516 }
517 
518 void CpuSNN::deleteObjects()
519 {
520  try
521  {
522 
523  if(simulatorDeleted)
524  return;
525 
526  if(fpLog) {
527  printSimSummary(fpLog); // TODO: can fpLog be stdout? In this case printSimSummary is executed twice
528  printSimSummary();
529  fclose(fpLog);
530  }
531 
532  // close param.txt
533  if (fpParam) {
534  fclose(fpParam);
535  }
536 
537  // if(val==0)
538  // saveConnectionWeights();
539 
540 
541  if (voltage!=NULL) delete[] voltage;
542  if (recovery!=NULL) delete[] recovery;
543  if (Izh_a!=NULL) delete[] Izh_a;
544  if (Izh_b!=NULL) delete[] Izh_b;
545  if (Izh_c!=NULL) delete[] Izh_c;
546  if (Izh_d!=NULL) delete[] Izh_d;
547  if (current!=NULL) delete[] current;
548 
549  if (Npre!=NULL) delete[] Npre;
550  if (Npre_plastic!=NULL) delete[] Npre_plastic;
551  if (Npost!=NULL) delete[] Npost;
552 
553  if (cumulativePre!=NULL) delete[] cumulativePre;
554  if (cumulativePost!=NULL) delete[] cumulativePost;
555 
556  if (gAMPA!=NULL) delete[] gAMPA;
557  if (gNMDA!=NULL) delete[] gNMDA;
558  if (gGABAa!=NULL) delete[] gGABAa;
559  if (gGABAb!=NULL) delete[] gGABAb;
560 
561  if (stpu!=NULL) delete[] stpu;
562  if (stpx!=NULL) delete[] stpx;
563 
564  if (lastSpikeTime!=NULL) delete[] lastSpikeTime;
565  if (synSpikeTime !=NULL) delete[] synSpikeTime;
566  if (curSpike!=NULL) delete[] curSpike;
567  if (nSpikeCnt!=NULL) delete[] nSpikeCnt;
568  if (intrinsicWeight!=NULL) delete[] intrinsicWeight;
569 
570  if (postDelayInfo!=NULL) delete[] postDelayInfo;
571  if (preSynapticIds!=NULL) delete[] preSynapticIds;
572  if (postSynapticIds!=NULL) delete[] postSynapticIds;
573  if (tmp_SynapticDelay!=NULL) delete[] tmp_SynapticDelay;
574 
575  if(wt!=NULL) delete[] wt;
576  if(maxSynWt!=NULL) delete[] maxSynWt;
577  if(wtChange !=NULL) delete[] wtChange;
578 
579  if (firingTableD2) delete[] firingTableD2;
580  if (firingTableD1) delete[] firingTableD1;
581  if (timeTableD2!=NULL) delete[] timeTableD2;
582  if (timeTableD1!=NULL) delete[] timeTableD1;
583 
584  delete pbuf;
585 
586  // clear all existing connection info...
587  while (connectBegin) {
588  grpConnectInfo_t* nextConn = connectBegin->next;
589  free(connectBegin);
590  connectBegin = nextConn;
591  }
592 
593  for (int i = 0; i < numSpikeMonitor; i++) {
594  delete[] monBufferFiring[i];
595  delete[] monBufferTimeCnt[i];
596  }
597 
598  if(spikeGenBits) delete[] spikeGenBits;
599 
600  // do the same as above, but for snn_gpu.cu
601  deleteObjectsGPU();
602 
603  CUDA_DELETE_TIMER(timer);
604 
605  simulatorDeleted = true;
606  }
607  catch(...)
608  {
609  fprintf(stderr, "Unknown exception ...\n");
610  }
611 }
612 
613 void CpuSNN::exitSimulation(int val, const char *errorString)
614 {
615  fprintf(stderr, errorString);
616 
617  deleteObjects();
618 
619 #ifdef USE_EXCEPTIONS
620  throw std::runtime_error(errorString);
621 #else
622  exit(val);
623 #endif
624 }
625 
626 CpuSNN::~CpuSNN()
627 {
628  if (!simulatorDeleted)
629  deleteObjects();
630 }
631 
632 void CpuSNN::setSTDP( int grpId, bool enable, int configId)
633 {
634  carlsim_assert(enable==false);
635  setSTDP(grpId,false,0,0,0,0,configId);
636 }
637 
638 void CpuSNN::setSTDP( int grpId, bool enable, float ALPHA_LTP, float TAU_LTP, float ALPHA_LTD, float TAU_LTD, int configId)
639 {
640  carlsim_assert(TAU_LTP >= 0.0);
641  carlsim_assert(TAU_LTD >= 0.0);
642 
643  if (grpId == ALL && configId == ALL) {
644  for(int g=0; g < numGrp; g++)
645  setSTDP(g, enable, ALPHA_LTP,TAU_LTP,ALPHA_LTD,TAU_LTD, 0);
646  } else if (grpId == ALL) {
647  for(int grpId1=0; grpId1 < numGrp; grpId1 += numConfig) {
648  int g = getGroupId(grpId1, configId);
649  setSTDP(g, enable, ALPHA_LTP,TAU_LTP,ALPHA_LTD,TAU_LTD, configId);
650  }
651  } else if (configId == ALL) {
652  for(int c=0; c < numConfig; c++)
653  setSTDP(grpId, enable, ALPHA_LTP,TAU_LTP,ALPHA_LTD,TAU_LTD, c);
654  } else {
655  int cGrpId = getGroupId(grpId, configId);
656 
657  sim_with_stdp |= enable;
658 
659  grp_Info[cGrpId].WithSTDP = enable;
660  grp_Info[cGrpId].ALPHA_LTP = ALPHA_LTP;
661  grp_Info[cGrpId].ALPHA_LTD = ALPHA_LTD;
662  grp_Info[cGrpId].TAU_LTP_INV = 1.0/TAU_LTP;
663  grp_Info[cGrpId].TAU_LTD_INV = 1.0/TAU_LTD;
664 
665  grp_Info[cGrpId].newUpdates = true;
666 
667  fprintf(stderr, "STDP %s for %d (%s): %f, %f, %f, %f\n", enable?"enabled":"disabled",
668  cGrpId, grp_Info2[cGrpId].Name.c_str(), ALPHA_LTP, ALPHA_LTD, TAU_LTP, TAU_LTD);
669  }
670 }
671 
672 void CpuSNN::setSTP( int grpId, bool enable, int configId)
673 {
674  carlsim_assert(enable==false);
675  setSTP(grpId,false,0,0,0,configId);
676 }
677 
678 void CpuSNN::setSTP(int grpId, bool enable, float STP_U, float STP_tD, float STP_tF, int configId)
679 {
680  if (grpId == ALL && configId == ALL) {
681  for(int g=0; g < numGrp; g++)
682  setSTP(g, enable, STP_U, STP_tD, STP_tF, 0);
683  } else if (grpId == ALL) {
684  for(int grpId1=0; grpId1 < numGrp; grpId1 += numConfig) {
685  int g = getGroupId(grpId1, configId);
686  setSTP(g, enable, STP_U, STP_tD, STP_tF, configId);
687  }
688  } else if (configId == ALL) {
689  for(int c=0; c < numConfig; c++)
690  setSTP(grpId, enable, STP_U, STP_tD, STP_tF, c);
691  } else {
692  int cGrpId = getGroupId(grpId, configId);
693 
694  sim_with_stp |= enable;
695 
696  grp_Info[cGrpId].WithSTP = enable;
697  grp_Info[cGrpId].STP_U=STP_U;
698  grp_Info[cGrpId].STP_tD=STP_tD;
699  grp_Info[cGrpId].STP_tF=STP_tF;
700 
701  grp_Info[cGrpId].newUpdates = true;
702 
703  fprintf(stderr, "STP %s for %d (%s): %f, %f, %f\n", enable?"enabled":"disabled",
704  cGrpId, grp_Info2[cGrpId].Name.c_str(), STP_U, STP_tD, STP_tF);
705  }
706 }
707 
708 void CpuSNN::setConductances( int grpId, bool enable, int configId)
709 {
710  carlsim_assert(enable==false);
711  setConductances(grpId,false,0,0,0,0,configId);
712 }
713 
714 void CpuSNN::setConductances(int grpId, bool enable, float tAMPA, float tNMDA, float tGABAa, float tGABAb, int configId)
715 {
716  if (grpId == ALL && configId == ALL) {
717  for(int g=0; g < numGrp; g++)
718  setConductances(g, enable, tAMPA, tNMDA, tGABAa, tGABAb, 0);
719  } else if (grpId == ALL) {
720  for(int grpId1=0; grpId1 < numGrp; grpId1 += numConfig) {
721  int g = getGroupId(grpId1, configId);
722  setConductances(g, enable, tAMPA, tNMDA, tGABAa, tGABAb, configId);
723  }
724  } else if (configId == ALL) {
725  for(int c=0; c < numConfig; c++)
726  setConductances(grpId, enable, tAMPA, tNMDA, tGABAa, tGABAb, c);
727  } else {
728  int cGrpId = getGroupId(grpId, configId);
729 
730  sim_with_conductances |= enable;
731 
732  grp_Info[cGrpId].WithConductances = enable;
733 
734  grp_Info[cGrpId].dAMPA=1-(1.0/tAMPA);
735  grp_Info[cGrpId].dNMDA=1-(1.0/tNMDA);
736  grp_Info[cGrpId].dGABAa=1-(1.0/tGABAa);
737  grp_Info[cGrpId].dGABAb=1-(1.0/tGABAb);
738 
739  grp_Info[cGrpId].newUpdates = true;
740 
741  fprintf(stderr, "Conductances %s for %d (%s): %f, %f, %f, %f\n", enable?"enabled":"disabled",
742  cGrpId, grp_Info2[cGrpId].Name.c_str(), tAMPA, tNMDA, tGABAa, tGABAb);
743  }
744 }
745 
746 void CpuSNN::setHomeostasis( int grpId, bool enable, int configId)
747 {
748  carlsim_assert(enable==false);
749  setHomeostasis(grpId,false,0,0,configId);
750 }
751 
752 void CpuSNN::setHomeostasis(int grpId, bool enable, float homeostasisScale, float avgTimeScale, int configId)
753 {
754  if (grpId == ALL && configId == ALL) {
755  for(int g=0; g < numGrp; g++)
756  setHomeostasis(g, enable, homeostasisScale, avgTimeScale, 0);
757  } else if (grpId == ALL) {
758  for(int grpId1=0; grpId1 < numGrp; grpId1 += numConfig) {
759  int g = getGroupId(grpId1, configId);
760  setHomeostasis(g, enable, homeostasisScale, avgTimeScale, configId);
761  }
762  } else if (configId == ALL) {
763  for(int c=0; c < numConfig; c++)
764  setHomeostasis(grpId, enable, homeostasisScale, avgTimeScale, c);
765  } else {
766  int cGrpId = getGroupId(grpId, configId);
767 
768  grp_Info[cGrpId].WithHomeostasis = enable;
769  grp_Info[cGrpId].homeostasisScale = homeostasisScale;
770  grp_Info[cGrpId].avgTimeScale = avgTimeScale;
771  grp_Info[cGrpId].avgTimeScaleInv = 1/avgTimeScale;
772  grp_Info[cGrpId].avgTimeScale_decay = (avgTimeScale*1000-1)/(avgTimeScale*1000);
773  fprintf(stderr, "Homeostasis parameters set for cGrpId: %d (%s)\n", cGrpId, grp_Info2[cGrpId].Name.c_str());
774 
775  grp_Info[cGrpId].newUpdates = true;
776  }
777 }
778 
779 void CpuSNN::setBaseFiring(int groupId, int configId, float _baseFiring, float _baseFiringSD)
780 {
781  int cGrpId = getGroupId(groupId, configId);
782  grp_Info2[cGrpId].baseFiring = _baseFiring;
783  grp_Info2[cGrpId].baseFiringSD = _baseFiringSD;
784  grp_Info[cGrpId].newUpdates = true;//TODO: I have to see how this is handled. -- KDC
785 }
786 
787 int CpuSNN::createGroup(const string& _name, unsigned int _numN, int _nType, int configId)
788 {
789  if (configId == ALL) {
790  for(int c=0; c < numConfig; c++)
791  createGroup(_name, _numN, _nType, c);
792  return (numGrp-numConfig);
793  } else {
794  carlsim_assert(numGrp < MAX_GRP_PER_SNN);
795 
796  if ( (!(_nType&TARGET_AMPA) && !(_nType&TARGET_NMDA) &&
797  !(_nType&TARGET_GABAa) && !(_nType&TARGET_GABAb)) || (_nType&POISSON_NEURON)) {
798  exitSimulation(1, "Invalid type using createGroup...\ncan not create poisson generators here...\n");
799  }
800 
801  grp_Info[numGrp].SizeN = _numN;
802  grp_Info[numGrp].Type = _nType;
803  grp_Info[numGrp].WithConductances = false;
804  grp_Info[numGrp].WithSTP = false;
805  grp_Info[numGrp].WithSTDP = false;
806  grp_Info[numGrp].WithHomeostasis = false;
807 
808  if ( (_nType&TARGET_GABAa) || (_nType&TARGET_GABAb)) {
809  grp_Info[numGrp].MaxFiringRate = INHIBITORY_NEURON_MAX_FIRING_RATE;
810  }
811  else {
812  grp_Info[numGrp].MaxFiringRate = EXCITATORY_NEURON_MAX_FIRING_RATE;
813  }
814  grp_Info2[numGrp].ConfigId = configId;
815  grp_Info2[numGrp].Name = _name;//new char[strlen(_name)];
816  grp_Info[numGrp].isSpikeGenerator = false;
817  grp_Info[numGrp].MaxDelay = 1;
818 
819  grp_Info2[numGrp].IzhGen = NULL;
820  grp_Info2[numGrp].Izh_a = -1;
821 
822  std::stringstream outStr;
823  outStr << configId;
824 
825  if (configId == 0)
826  grp_Info2[numGrp].Name = _name;
827  else
828  grp_Info2[numGrp].Name = _name + "_" + outStr.str();
829 
830  finishedPoissonGroup = true;
831 
832  numGrp++;
833 
834  return (numGrp-1);
835  }
836 }
837 
838 int CpuSNN::createSpikeGeneratorGroup(const string& _name, unsigned int size_n, int type, int configId)
839 {
840  if (configId == ALL) {
841  for(int c=0; c < numConfig; c++)
842  createSpikeGeneratorGroup(_name, size_n, type, c);
843  return (numGrp-numConfig);
844  } else {
845  grp_Info[numGrp].SizeN = size_n;
846  grp_Info[numGrp].Type = type | POISSON_NEURON;
847  grp_Info[numGrp].WithConductances = false;
848  grp_Info[numGrp].WithSTP = false;
849  grp_Info[numGrp].WithSTDP = false;
850  grp_Info[numGrp].WithHomeostasis = false;
851  grp_Info[numGrp].isSpikeGenerator = true; // these belong to the spike generator class...
852  grp_Info2[numGrp].ConfigId = configId;
853  grp_Info2[numGrp].Name = _name; //new char[strlen(_name)];
854  grp_Info[numGrp].MaxFiringRate = POISSON_MAX_FIRING_RATE;
855  std::stringstream outStr ;
856  outStr << configId;
857 
858  if (configId != 0)
859  grp_Info2[numGrp].Name = _name + "_" + outStr.str();
860 
861  numGrp++;
862  numSpikeGenGrps++;
863 
864  return (numGrp-1);
865  }
866 }
867 
868 int CpuSNN::getGroupId(int groupId, int configId)
869 {
870  carlsim_assert(configId < numConfig);
871  int cGrpId = (groupId+configId);
872  carlsim_assert(cGrpId < numGrp);
873  return cGrpId;
874 }
875 
876 // used for homeostasis functionality
877 int CpuSNN::getNextGroupId(int groupId) {
878  return (groupId+numConfig);
879 }
880 
881 // used for parameter tuning functionality
882 grpConnectInfo_t* CpuSNN::getConnectInfo(int connectId, int configId)
883 {
884  grpConnectInfo_t* nextConn = connectBegin;
885 
886  connectId = getConnectionId (connectId, configId);
887 
888  carlsim_assert(connectId >= 0); carlsim_assert(connectId < numConnections);
889 
890  // clear all existing connection info...
891  while (nextConn) {
892  if (nextConn->connId == connectId) {
893  nextConn->newUpdates = true;
894  return nextConn;
895  }
896  nextConn = nextConn->next;
897  }
898 
899  fprintf(stderr, "Total Connections = %d\n", numConnections);
900  fprintf(stderr, "ConnectId (%d) cannot be recognized\n", connectId);
901  return NULL;
902 }
903 
904 int CpuSNN::getConnectionId(int connId, int configId)
905 {
906  if(configId >= numConfig) {
907  fprintf(stderr, "getConnectionId(int, int): Assertion `configId(%d) < numConfig(%d)' failed\n", configId, numConfig);
908  carlsim_assert(0);
909  }
910  connId = connId+configId;
911  if (connId >= numConnections) {
912  fprintf(stderr, "getConnectionId(int, int): Assertion `connId(%d) < numConnections(%d)' failed\n", connId, numConnections);
913  carlsim_assert(0);
914  }
915  return connId;
916 }
917 
918 void CpuSNN::setNeuronParameters(int groupId, float _a, float _b, float _c, float _d, int configId)
919 {
920  setNeuronParameters(groupId, _a, 0, _b, 0, _c, 0, _d, 0, configId);
921 }
922 
923 void CpuSNN::setNeuronParameters(int groupId, float _a, float a_sd, float _b, float b_sd, float _c, float c_sd, float _d, float d_sd, int configId)
924 {
925  if (configId == ALL) {
926  for(int c=0; c < numConfig; c++)
927  setNeuronParameters(groupId, _a, a_sd, _b, b_sd, _c, c_sd, _d, d_sd, c);
928  } else {
929  int cGrpId = getGroupId(groupId, configId);
930  grp_Info2[cGrpId].Izh_a = _a;
931  grp_Info2[cGrpId].Izh_a_sd = a_sd;
932  grp_Info2[cGrpId].Izh_b = _b;
933  grp_Info2[cGrpId].Izh_b_sd = b_sd;
934  grp_Info2[cGrpId].Izh_c = _c;
935  grp_Info2[cGrpId].Izh_c_sd = c_sd;
936  grp_Info2[cGrpId].Izh_d = _d;
937  grp_Info2[cGrpId].Izh_d_sd = d_sd;
938  }
939 }
940 
941 void CpuSNN::setNeuronParameters(int groupId, IzhGenerator* IzhGen, int configId)
942 {
943  if (configId == ALL) {
944  for(int c=0; c < numConfig; c++)
945  setNeuronParameters(groupId, IzhGen, c);
946  } else {
947  int cGrpId = getGroupId(groupId, configId);
948 
949  grp_Info2[cGrpId].IzhGen = IzhGen;
950  }
951 }
952 
953 void CpuSNN::setGroupInfo(int grpId, group_info_t info, int configId)
954 {
955  if (configId == ALL) {
956  for(int c=0; c < numConfig; c++)
957  setGroupInfo(grpId, info, c);
958  } else {
959  int cGrpId = getGroupId(grpId, configId);
960  grp_Info[cGrpId] = info;
961  }
962 }
963 
964 group_info_t CpuSNN::getGroupInfo(int grpId, int configId)
965 {
966  int cGrpId = getGroupId(grpId, configId);
967  return grp_Info[cGrpId];
968 }
969 
970 void CpuSNN::buildPoissonGroup(int grpId)
971 {
972  carlsim_assert(grp_Info[grpId].StartN == -1);
973  grp_Info[grpId].StartN = allocatedN;
974  grp_Info[grpId].EndN = allocatedN + grp_Info[grpId].SizeN - 1;
975 
976  fprintf(fpLog, "Allocation for %d(%s), St=%d, End=%d\n",
977  grpId, grp_Info2[grpId].Name.c_str(), grp_Info[grpId].StartN, grp_Info[grpId].EndN);
978  resetSpikeCnt(grpId);
979 
980  allocatedN = allocatedN + grp_Info[grpId].SizeN;
981  carlsim_assert(allocatedN <= numN);
982 
983  for(int i=grp_Info[grpId].StartN; i <= grp_Info[grpId].EndN; i++) {
984  resetPoissonNeuron(i, grpId);
985  Npre_plastic[i] = 0;
986  Npre[i] = 0;
987  Npost[i] = 0;
988  cumulativePost[i] = allocatedPost;
989  cumulativePre[i] = allocatedPre;
990  allocatedPost += grp_Info[grpId].numPostSynapses;
991  allocatedPre += grp_Info[grpId].numPreSynapses;
992  }
993  carlsim_assert(allocatedPost <= postSynCnt);
994  carlsim_assert(allocatedPre <= preSynCnt);
995 }
996 
997 void CpuSNN::resetPoissonNeuron(unsigned int nid, int grpId)
998 {
999  carlsim_assert(nid < numN);
1000  lastSpikeTime[nid] = MAX_SIMULATION_TIME;
1001  avgFiring[nid] = 0.0;
1002 
1003  if(grp_Info[grpId].WithSTP) {
1004  for (int j=0; j < STP_BUF_SIZE; j++) {
1005  int ind=STP_BUF_POS(nid,j);
1006  stpu[ind] = grp_Info[grpId].STP_U;
1007  stpx[ind] = 1;
1008  }
1009  }
1010 }
1011 
1012 void CpuSNN::resetNeuron(unsigned int nid, int grpId)
1013 {
1014  carlsim_assert(nid < numNReg);
1015  if (grp_Info2[grpId].IzhGen == NULL) {
1016  if (grp_Info2[grpId].Izh_a == -1) {
1017  printf("setNeuronParameters must be called for group %s (%d)\n",grp_Info2[grpId].Name.c_str(),grpId);
1018 #ifdef USE_EXCEPTIONS
1019  std::ostringstream stringStream;
1020  stringStream << "setNeuronParameters must be called for group " << grp_Info2[grpId].Name.c_str() << "(" << grpId << ")\n";
1021  throw std::runtime_error(stringStream.str().c_str());
1022 #else
1023  exit(-1);
1024 #endif
1025  }
1026 
1027  Izh_a[nid] = grp_Info2[grpId].Izh_a + grp_Info2[grpId].Izh_a_sd*(float)getRandClosed();
1028  Izh_b[nid] = grp_Info2[grpId].Izh_b + grp_Info2[grpId].Izh_b_sd*(float)getRandClosed();
1029  Izh_c[nid] = grp_Info2[grpId].Izh_c + grp_Info2[grpId].Izh_c_sd*(float)getRandClosed();
1030  Izh_d[nid] = grp_Info2[grpId].Izh_d + grp_Info2[grpId].Izh_d_sd*(float)getRandClosed();
1031  } else {
1032  grp_Info2[grpId].IzhGen->set(this, grpId, nid, Izh_a[nid], Izh_b[nid], Izh_c[nid], Izh_d[nid]);
1033  }
1034 
1035  voltage[nid] = Izh_c[nid]; // initial values for new_v
1036  recovery[nid] = 0.2f*voltage[nid]; // initial values for u
1037 
1038 
1039  // set the baseFiring with some standard deviation.
1040  if(drand48()>0.5) {
1041  baseFiring[nid] = grp_Info2[grpId].baseFiring + grp_Info2[grpId].baseFiringSD*-log(drand48());
1042  }
1043  else {
1044  baseFiring[nid] = grp_Info2[grpId].baseFiring - grp_Info2[grpId].baseFiringSD*-log(drand48());
1045  if(baseFiring[nid] < 0.1) baseFiring[nid] = 0.1;
1046  }
1047 
1048  if( grp_Info2[grpId].baseFiring != 0.0) {
1049  avgFiring[nid] = baseFiring[nid];
1050  }
1051  else {
1052  baseFiring[nid] = 0.0;
1053  avgFiring[nid] = 0;
1054  }
1055 
1056  lastSpikeTime[nid] = MAX_SIMULATION_TIME;
1057 
1058  if(grp_Info[grpId].WithSTP) {
1059  for (int j=0; j < STP_BUF_SIZE; j++) {
1060  int ind=STP_BUF_POS(nid,j);
1061  stpu[ind] = grp_Info[grpId].STP_U;
1062  stpx[ind] = 1;
1063  }
1064  }
1065 }
1066 
1067 void CpuSNN::buildGroup(int grpId)
1068 {
1069  carlsim_assert(grp_Info[grpId].StartN == -1);
1070  grp_Info[grpId].StartN = allocatedN;
1071  grp_Info[grpId].EndN = allocatedN + grp_Info[grpId].SizeN - 1;
1072 
1073  fprintf(fpLog, "Allocation for %d(%s), St=%d, End=%d\n",
1074  grpId, grp_Info2[grpId].Name.c_str(), grp_Info[grpId].StartN, grp_Info[grpId].EndN);
1075 
1076  resetSpikeCnt(grpId);
1077 
1078  allocatedN = allocatedN + grp_Info[grpId].SizeN;
1079  carlsim_assert(allocatedN <= numN);
1080 
1081  for(int i=grp_Info[grpId].StartN; i <= grp_Info[grpId].EndN; i++) {
1082  resetNeuron(i, grpId);
1083  Npre_plastic[i] = 0;
1084  Npre[i] = 0;
1085  Npost[i] = 0;
1086  cumulativePost[i] = allocatedPost;
1087  cumulativePre[i] = allocatedPre;
1088  allocatedPost += grp_Info[grpId].numPostSynapses;
1089  allocatedPre += grp_Info[grpId].numPreSynapses;
1090  }
1091 
1092  carlsim_assert(allocatedPost <= postSynCnt);
1093  carlsim_assert(allocatedPre <= preSynCnt);
1094 }
1095 
1096 // set one specific connection from neuron id 'src' to neuron id 'dest'
1097 inline void CpuSNN::setConnection(int srcGrp, int destGrp, unsigned int src, unsigned int dest, float synWt, float maxWt, uint8_t dVal, int connProp)
1098 {
1099  carlsim_assert(dest<=CONN_SYN_NEURON_MASK); // total number of neurons is less than 1 million within a GPU
1100  carlsim_assert((dVal >=1) && (dVal <= D));
1101 
1102  // we have exceeded the number of possible connection for one neuron
1103  if(Npost[src] >= grp_Info[srcGrp].numPostSynapses) {
1104  fprintf(stderr, "setConnection(%d (Grp=%s), %d (Grp=%s), %f, %d)\n", src, grp_Info2[srcGrp].Name.c_str(), dest, grp_Info2[destGrp].Name.c_str(), synWt, dVal);
1105  fprintf(stderr, "(Npost[%d] = %d ) >= (numPostSynapses = %d) value given for the network very less\n", src, Npost[src], grp_Info[srcGrp].numPostSynapses);
1106  fprintf(stderr, "Large number of postsynaptic connections is established\n");
1107  fprintf(stderr, "Increase the numPostSynapses value for the Group = %s \n", grp_Info2[srcGrp].Name.c_str());
1108  carlsim_assert(0);
1109  }
1110 
1111  if(Npre[dest] >= grp_Info[destGrp].numPreSynapses) {
1112  fprintf(stderr, "setConnection(%d (Grp=%s), %d (Grp=%s), %f, %d)\n", src, grp_Info2[srcGrp].Name.c_str(), dest, grp_Info2[destGrp].Name.c_str(), synWt, dVal);
1113  fprintf(stderr, "(Npre[%d] = %d) >= (numPreSynapses = %d) value given for the network very less\n", dest, Npre[dest], grp_Info[destGrp].numPreSynapses);
1114  fprintf(stderr, "Large number of presynaptic connections established\n");
1115  fprintf(stderr, "Increase the numPostSynapses for the Grp = %s value \n", grp_Info2[destGrp].Name.c_str());
1116  carlsim_assert(0);
1117  }
1118 
1119  int p = Npost[src];
1120 
1121  carlsim_assert(Npost[src] >= 0);
1122  carlsim_assert(Npre[dest] >= 0);
1123  carlsim_assert((src*numPostSynapses+p)/numN < numPostSynapses); // divide by numN to prevent INT overflow
1124 
1125  unsigned int post_pos = cumulativePost[src] + Npost[src];
1126  unsigned int pre_pos = cumulativePre[dest] + Npre[dest];
1127 
1128  carlsim_assert(post_pos < postSynCnt);
1129  carlsim_assert(pre_pos < preSynCnt);
1130 
1131  postSynapticIds[post_pos] = SET_CONN_ID(dest, Npre[dest], destGrp); //generate a new postSynapticIds id for the current connection
1132  tmp_SynapticDelay[post_pos] = dVal;
1133 
1134  preSynapticIds[pre_pos] = SET_CONN_ID(src, Npost[src], srcGrp);
1135  wt[pre_pos] = synWt;
1136  maxSynWt[pre_pos] = maxWt;
1137 
1138  bool synWtType = GET_FIXED_PLASTIC(connProp);
1139 
1140  if (synWtType == SYN_PLASTIC) {
1141  sim_with_fixedwts = false; // if network has any plastic synapses at all, this will be set to true
1142  Npre_plastic[dest]++;
1143  // homeostasis
1144  if (grp_Info[destGrp].WithHomeostasis && grp_Info[destGrp].homeoId ==-1)
1145  grp_Info[destGrp].homeoId = dest; // this neuron info will be printed
1146  }
1147 
1148  Npre[dest]+=1;
1149  Npost[src]+=1;
1150 
1151  grp_Info2[srcGrp].numPostConn++;
1152  grp_Info2[destGrp].numPreConn++;
1153 
1154  if (Npost[src] > grp_Info2[srcGrp].maxPostConn)
1155  grp_Info2[srcGrp].maxPostConn = Npost[src];
1156 
1157  if (Npre[dest] > grp_Info2[destGrp].maxPreConn)
1158  grp_Info2[destGrp].maxPreConn = Npre[src];
1159 
1160 #if _DEBUG_
1161  //fprintf(fpLog, "setConnection(%d, %d, %f, %d Npost[%d]=%d, Npre[%d]=%d)\n", src, dest, initWt, dVal, src, Npost[src], dest, Npre[dest]);
1162 #endif
1163 
1164 }
1165 
1166 void CpuSNN::getPopWeights(int grpPreId, int grpPostId, float*& weights, int& matrixSize, int configId) {
1167  post_info_t* preId;
1168  int pre_nid, pos_ij;
1169  int numPre, numPost;
1170 
1171  if(configId < 0){
1172  printf("Invalid configId. You can not pass the ALL (ALL=-1) argument.\n");
1173  carlsim_assert(false);
1174  }
1175 
1176  int cGrpIdPre = getGroupId(grpPreId, configId);
1177  int cGrpIdPost = getGroupId(grpPostId, configId);
1178  //population sizes
1179  numPre = grp_Info[cGrpIdPre].SizeN;
1180  numPost = grp_Info[cGrpIdPost].SizeN;
1181 
1182  //first iteration gets the number of synaptic weights to place in our
1183  //weight matrix.
1184  matrixSize=0;
1185  //iterate over all neurons in the post group
1186  for (int i=grp_Info[cGrpIdPost].StartN; i<=grp_Info[cGrpIdPost].EndN; i++) {
1187  // for every post-neuron, find all pre
1188  pos_ij = cumulativePre[i]; // i-th post neuron, jth pre neuron
1189  //iterate over all presynaptic synapses of the current postsynaptic neuron
1190  for(int j=0; j<Npre[i]; pos_ij++,j++) {
1191  preId = &preSynapticIds[pos_ij];
1192  pre_nid = GET_CONN_NEURON_ID((*preId)); // neuron id of pre
1193  if (pre_nid<grp_Info[cGrpIdPre].StartN || pre_nid>grp_Info[cGrpIdPre].EndN)
1194  continue; // connection does not belong to group cGrpIdPre
1195  matrixSize++;
1196  }
1197  }
1198  //now we have the correct size matrix
1199  weights = new float[matrixSize];
1200 
1201  //second iteration assigns the weights
1202  int curr = 0; // iterator for return array
1203  //iterate over all neurons in the post group
1204  for (int i=grp_Info[cGrpIdPost].StartN; i<=grp_Info[cGrpIdPost].EndN; i++) {
1205  // for every post-neuron, find all pre
1206  pos_ij = cumulativePre[i]; // i-th neuron, j=0th synapse
1207  //do the GPU copy here. Copy the current weights from GPU to CPU.
1208  if(currentMode==GPU_MODE){
1209  copyWeightsGPU(i,cGrpIdPre);
1210  }
1211  //iterate over all presynaptic synapses
1212  for(int j=0; j<Npre[i]; pos_ij++,j++) {
1213  //TAGS:TODO: We have to double check we have access to preSynapticIds in GPU_MODE.
1214  //We can check where they were allocated and make sure that this occurs in
1215  //both the CPU and GPU modes.
1216  preId = &preSynapticIds[pos_ij];
1217  pre_nid = GET_CONN_NEURON_ID((*preId)); // neuron id of pre
1218  if (pre_nid<grp_Info[cGrpIdPre].StartN || pre_nid>grp_Info[cGrpIdPre].EndN)
1219  continue; // connection does not belong to group cGrpIdPre
1220  //the weights stored in wt were copied from the GPU in the above block
1221  weights[curr] = wt[pos_ij];
1222  curr++;
1223  }
1224  }
1225  return;
1226 }
1227 
1228 void CpuSNN::writePopWeights(string fname, int grpPreId, int grpPostId, int configId){
1229  float* weights;
1230  int matrixSize;
1231  FILE* fid;
1232  int numPre, numPost;
1233  fid = fopen(fname.c_str(), "wb");
1234  carlsim_assert(fid != NULL);
1235 
1236  if(!doneReorganization){
1237  printf("Simulation has not been run yet, cannot output weights.\n");
1238  carlsim_assert(false);
1239  }
1240 
1241  post_info_t* preId;
1242  int pre_nid, pos_ij;
1243 
1244  if(configId < 0){
1245  printf("Invalid configId. You can not pass the ALL (ALL=-1) argument.\n");
1246  carlsim_assert(false);
1247  }
1248 
1249  int cGrpIdPre = getGroupId(grpPreId, configId);
1250  int cGrpIdPost = getGroupId(grpPostId, configId);
1251 
1252  //population sizes
1253  numPre = grp_Info[cGrpIdPre].SizeN;
1254  numPost = grp_Info[cGrpIdPost].SizeN;
1255 
1256  //first iteration gets the number of synaptic weights to place in our
1257  //weight matrix.
1258  matrixSize=0;
1259  //iterate over all neurons in the post group
1260  for (int i=grp_Info[cGrpIdPost].StartN; i<=grp_Info[cGrpIdPost].EndN; i++) {
1261  // for every post-neuron, find all pre
1262  pos_ij = cumulativePre[i]; // i-th neuron, j=0th synapse
1263  //iterate over all presynaptic synapses
1264  for(int j=0; j<Npre[i]; pos_ij++,j++) {
1265  preId = &preSynapticIds[pos_ij];
1266  pre_nid = GET_CONN_NEURON_ID((*preId)); // neuron id of pre
1267  if (pre_nid<grp_Info[cGrpIdPre].StartN || pre_nid>grp_Info[cGrpIdPre].EndN)
1268  continue; // connection does not belong to group cGrpIdPre
1269  matrixSize++;
1270  }
1271  }
1272  //now we have the correct size
1273  weights = new float[matrixSize];
1274  //second iteration assigns the weights
1275  int curr = 0; // iterator for return array
1276  //iterate over all neurons in the post group
1277  for (int i=grp_Info[cGrpIdPost].StartN; i<=grp_Info[cGrpIdPost].EndN; i++) {
1278  // for every post-neuron, find all pre
1279  pos_ij = cumulativePre[i]; // i-th neuron, j=0th synapse
1280  //do the GPU copy here. Copy the current weights from GPU to CPU.
1281  if(currentMode==GPU_MODE){
1282  copyWeightsGPU(i,cGrpIdPre);
1283  }
1284  //iterate over all presynaptic synapses
1285  for(int j=0; j<Npre[i]; pos_ij++,j++) {
1286  preId = &preSynapticIds[pos_ij];
1287  pre_nid = GET_CONN_NEURON_ID((*preId)); // neuron id of pre
1288  if (pre_nid<grp_Info[cGrpIdPre].StartN || pre_nid>grp_Info[cGrpIdPre].EndN)
1289  continue; // connection does not belong to group cGrpIdPre
1290  weights[curr] = wt[pos_ij];
1291  curr++;
1292  }
1293  }
1294 
1295  fwrite(weights,sizeof(float),matrixSize,fid);
1296  fclose(fid);
1297  //Let my memory FREE!!!
1298  delete [] weights;
1299 
1300  return;
1301 }
1302 
1303 //We need pass the neuron id (nid) and the grpId just for the case when we want to
1304 //ramp up/down the weights. In that case we need to set the weights of each synapse
1305 //depending on their nid (their position with respect to one another). -- KDC
1306 float CpuSNN::getWeights(int connProp, float initWt, float maxWt, unsigned int nid, int grpId)
1307 {
1308  float actWts;
1309  bool setRandomWeights = GET_INITWTS_RANDOM(connProp);
1310  bool setRampDownWeights = GET_INITWTS_RAMPDOWN(connProp);
1311  bool setRampUpWeights = GET_INITWTS_RAMPUP(connProp);
1312 
1313  if ( setRandomWeights )
1314  actWts=initWt*drand48();
1315  else if (setRampUpWeights)
1316  actWts=(initWt+((nid-grp_Info[grpId].StartN)*(maxWt-initWt)/grp_Info[grpId].SizeN));
1317  else if (setRampDownWeights)
1318  actWts=(maxWt-((nid-grp_Info[grpId].StartN)*(maxWt-initWt)/grp_Info[grpId].SizeN));
1319  else
1320  actWts=initWt;
1321 
1322  return actWts;
1323 }
1324 
1325 // make 'C' random connections from grpSrc to grpDest
1326 void CpuSNN::connectRandom (grpConnectInfo_t* info)
1327 {
1328  int grpSrc = info->grpSrc;
1329  int grpDest = info->grpDest;
1330  for(int pre_nid=grp_Info[grpSrc].StartN; pre_nid<=grp_Info[grpSrc].EndN; pre_nid++) {
1331  for(int post_nid=grp_Info[grpDest].StartN; post_nid<=grp_Info[grpDest].EndN; post_nid++) {
1332  if (getRand() < info->p) {
1333  uint8_t dVal = info->minDelay + (int)(0.5+(getRandClosed()*(info->maxDelay-info->minDelay)));
1334  carlsim_assert((dVal >= info->minDelay) && (dVal <= info->maxDelay));
1335  float synWt = getWeights(info->connProp, info->initWt, info->maxWt, pre_nid, grpSrc);
1336  setConnection(grpSrc, grpDest, pre_nid, post_nid, synWt, info->maxWt, dVal, info->connProp);
1337  info->numberOfConnections++;
1338  }
1339  }
1340  }
1341 
1342  grp_Info2[grpSrc].sumPostConn += info->numberOfConnections;
1343  grp_Info2[grpDest].sumPreConn += info->numberOfConnections;
1344 }
1345 
1346 void CpuSNN::connectOneToOne (grpConnectInfo_t* info)
1347 {
1348  int grpSrc = info->grpSrc;
1349  int grpDest = info->grpDest;
1350  carlsim_assert( grp_Info[grpDest].SizeN == grp_Info[grpSrc].SizeN );
1351  // C = grp_Info[grpDest].SizeN;
1352 
1353  for(int nid=grp_Info[grpSrc].StartN,j=grp_Info[grpDest].StartN; nid<=grp_Info[grpSrc].EndN; nid++, j++) {
1354  uint8_t dVal = info->minDelay + (int)(0.5+(getRandClosed()*(info->maxDelay-info->minDelay)));
1355  carlsim_assert((dVal >= info->minDelay) && (dVal <= info->maxDelay));
1356  float synWt = getWeights(info->connProp, info->initWt, info->maxWt, nid, grpSrc);
1357  setConnection(grpSrc, grpDest, nid, j, synWt, info->maxWt, dVal, info->connProp);
1358  //setConnection(grpSrc, grpDest, nid, j, info->initWt, info->maxWt, dVal, info->connProp);
1359  info->numberOfConnections++;
1360  }
1361 
1362  // //dotty printf output
1363  // fprintf(fpDotty, "\t\tg%d -> g%d [style=%s, label=\"numPostSynapses=%d, wt=%3.3f , Dm=%d \"]\n", grpSrc, grpDest, (info->initWt > 0)?"bold":"dotted", info->numPostSynapses, info->maxWt, info->maxDelay);
1364  // fprintf(stdout, "Creating One-to-One Connection from '%s' to '%s'\n", grp_Info2[grpSrc].Name.c_str(), grp_Info2[grpDest].Name.c_str());
1365  // fprintf(fpLog, "Creating One-to-One Connection from '%s' to '%s'\n", grp_Info2[grpSrc].Name.c_str(), grp_Info2[grpDest].Name.c_str());
1366 
1367  grp_Info2[grpSrc].sumPostConn += info->numberOfConnections;
1368  grp_Info2[grpDest].sumPreConn += info->numberOfConnections;
1369 
1370 }
1371 
1372 // user-defined functions called here...
1373 // This is where we define our user-defined call-back function. -- KDC
1374 void CpuSNN::connectUserDefined (grpConnectInfo_t* info)
1375 {
1376  int grpSrc = info->grpSrc;
1377  int grpDest = info->grpDest;
1378  info->maxDelay = 0;
1379  for(int nid=grp_Info[grpSrc].StartN; nid<=grp_Info[grpSrc].EndN; nid++) {
1380  for(int nid2=grp_Info[grpDest].StartN; nid2 <= grp_Info[grpDest].EndN; nid2++) {
1381  int srcId = nid - grp_Info[grpSrc].StartN;
1382  int destId = nid2 - grp_Info[grpDest].StartN;
1383  float weight, maxWt, delay;
1384  bool connected;
1385 
1386  info->conn->connect(this, grpSrc, srcId, grpDest, destId, weight, maxWt, delay, connected);
1387  if(connected) {
1388  if (GET_FIXED_PLASTIC(info->connProp) == SYN_FIXED) maxWt = weight;
1389 
1390  carlsim_assert(delay>=1);
1391  carlsim_assert(delay<=MAX_SynapticDelay);
1392  carlsim_assert(weight<=maxWt);
1393 
1394  setConnection(grpSrc, grpDest, nid, nid2, weight, maxWt, delay, info->connProp);
1395  info->numberOfConnections++;
1396  if(delay > info->maxDelay)
1397  info->maxDelay = delay;
1398  }
1399  }
1400  }
1401 
1402  // // dotty printf output
1403  // fprintf(fpDotty, "\t\tg%d -> g%d [style=%s, label=\"user-defined\"]\n", grpSrc, grpDest, (info->initWt > 0)?"bold":"dotted");
1404  // fprintf(stdout, "Creating User-defined Connection from '%s' to '%s'\n", grp_Info2[grpSrc].Name.c_str(), grp_Info2[grpDest].Name.c_str());
1405  // fprintf(fpLog, "Creating User-defined Connection from '%s' to '%s'\n", grp_Info2[grpSrc].Name.c_str(), grp_Info2[grpDest].Name.c_str());
1406 
1407  grp_Info2[grpSrc].sumPostConn += info->numberOfConnections;
1408  grp_Info2[grpDest].sumPreConn += info->numberOfConnections;
1409 }
1410 
1411 // make 'C' full connections from grpSrc to grpDest
1412 void CpuSNN::connectFull(grpConnectInfo_t* info)
1413 {
1414  int grpSrc = info->grpSrc;
1415  int grpDest = info->grpDest;
1416  bool noDirect = (info->type == CONN_FULL_NO_DIRECT);
1417 
1418  for(int nid=grp_Info[grpSrc].StartN; nid<=grp_Info[grpSrc].EndN; nid++) {
1419  for(int j=grp_Info[grpDest].StartN; j <= grp_Info[grpDest].EndN; j++) {
1420  if((noDirect) && (nid - grp_Info[grpSrc].StartN) == (j - grp_Info[grpDest].StartN))
1421  continue;
1422  uint8_t dVal = info->minDelay + (int)(0.5+(getRandClosed()*(info->maxDelay-info->minDelay)));
1423  carlsim_assert((dVal >= info->minDelay) && (dVal <= info->maxDelay));
1424  float synWt = getWeights(info->connProp, info->initWt, info->maxWt, nid, grpSrc);
1425 
1426  setConnection(grpSrc, grpDest, nid, j, synWt, info->maxWt, dVal, info->connProp);
1427  info->numberOfConnections++;
1428  //setConnection(grpSrc, grpDest, nid, j, info->initWt, info->maxWt, dVal, info->connProp);
1429  }
1430  }
1431 
1432  // //dotty printf output
1433  // fprintf(fpDotty, "\t\tg%d -> g%d [style=%s, label=\"numPostSynapses=%d, wt=%3.3f, Dm=%d \"]\n", grpSrc, grpDest, (info->initWt > 0)?"bold":"dotted", info->numPostSynapses, info->maxWt, info->maxDelay);
1434  // fprintf(stdout, "Creating Full Connection %s from '%s' to '%s' with Probability %f\n",
1435  // (noDirect?"no-direct":" "), grp_Info2[grpSrc].Name.c_str(), grp_Info2[grpDest].Name.c_str(), info->numPostSynapses*1.0/grp_Info[grpDest].SizeN);
1436  // fprintf(fpLog, "Creating Full Connection %s from '%s' to '%s' with Probability %f\n",
1437  // (noDirect?"no-direct":" "), grp_Info2[grpSrc].Name.c_str(), grp_Info2[grpDest].Name.c_str(), info->numPostSynapses*1.0/grp_Info[grpDest].SizeN);
1438 
1439  grp_Info2[grpSrc].sumPostConn += info->numberOfConnections;
1440  grp_Info2[grpDest].sumPreConn += info->numberOfConnections;
1441 }
1442 
1443 
1444 void CpuSNN::connectFromMatrix(SparseWeightDelayMatrix* mat, int connProp)
1445 {
1446  for (int i=0;i<mat->count;i++) {
1447  int nIDpre = mat->preIds[i];
1448  int nIDpost = mat->postIds[i];
1449  float weight = mat->weights[i];
1450  float maxWeight = mat->maxWeights[i];
1451  uint8_t delay = mat->delay_opts[i];
1452  int gIDpre = findGrpId(nIDpre);
1453  int gIDpost = findGrpId(nIDpost);
1454 
1455  setConnection(gIDpre, gIDpost, nIDpre, nIDpost, weight, maxWeight, delay, connProp);
1456 
1457  grp_Info2[gIDpre].sumPostConn++;
1458  grp_Info2[gIDpost].sumPreConn++;
1459 
1460  if (delay > grp_Info[gIDpre].MaxDelay) grp_Info[gIDpre].MaxDelay = delay;
1461  }
1462 }
1463 
1465 {
1466  string fname(networkName+".dot");
1467  fpDotty = fopen(fname.c_str(),"w");
1468 
1469  fprintf(fpDotty, "\
1470 digraph G {\n\
1471 \t\tnode [style=filled];\n\
1472 \t\tcolor=blue;\n");
1473 
1474  for(int g=0; g < numGrp; g++) {
1475  //add a node to the dotty output
1476  char stype = grp_Info[g].Type;
1477  carlsim_assert(grp_Info2[g].numPostConn == grp_Info2[g].sumPostConn);
1478  carlsim_assert(grp_Info2[g].numPreConn == grp_Info2[g].sumPreConn);
1479 
1480  // fprintf(stdout, "Creating Spike Generator Group %s(id=%d) with numN=%d\n", grp_Info2[g].Name.c_str(), g, grp_Info[g].SizeN);
1481  // fprintf(fpLog, "Creating Spike Generator Group %s(id=%d) with numN=%d\n", grp_Info2[g].Name.c_str(), g, grp_Info[g].SizeN);
1482  // add a node to the dotty output
1483  fprintf (fpDotty, "\t\tg%d [%s label=\"id=%d:%s \\n numN=%d avgPost=%3.2f avgPre=%3.2f \\n maxPost=%d maxPre=%d\"];\n", g,
1484  (stype&POISSON_NEURON) ? "shape = box, ": " ", g, grp_Info2[g].Name.c_str(),
1485  grp_Info[g].SizeN, grp_Info2[g].numPostConn*1.0/grp_Info[g].SizeN,
1486  grp_Info2[g].numPreConn*1.0/grp_Info[g].SizeN, grp_Info2[g].maxPostConn, grp_Info2[g].maxPreConn);
1487  // fprintf(stdout, "Creating Group %s(id=%d) with numN=%d\n", grp_Info2[g].Name.c_str(), g, grp_Info[g].SizeN);
1488  // fprintf(fpLog, "Creating Group %s(id=%d) with numN=%d\n", grp_Info2[g].Name.c_str(), g, grp_Info[g].SizeN);
1489  }
1490 
1491  /*
1492  for (int noiseId=0; noiseId < numNoise; noiseId++) {
1493  int groupId = noiseGenGroup[noiseId].groupId;
1494  float currentStrength = noiseGenGroup[noiseId].currentStrength;
1495  float neuronPercentage = noiseGenGroup[noiseId].neuronPercentage;
1496  int numNeuron = ((groupId==-1)? -1: grp_Info[groupId].SizeN);
1497  if(groupId==-1)
1498  fprintf(fpDotty, "\t\tr%d [shape=box, label=\"Global Random Noise\\n(I=%2.2fmA, frac=%2.2f%%)\"];\n", noiseId, currentStrength, neuronPercentage);
1499  else
1500  fprintf(fpDotty, "\t\tr%d [shape=box, label=\"Random Noise\\n(I=%2.2fmA, frac=%2.2f%%)\"];\n", noiseId, currentStrength, neuronPercentage);
1501 
1502  if (groupId !=- 1)
1503  fprintf(fpDotty, "\t\tr%d -> g%d [label=\" n=%d \"];\n", noiseId, groupId, (int) (numNeuron*(neuronPercentage/100.0)));
1504  }
1505  */
1506 
1507  grpConnectInfo_t* info = connectBegin;
1508  while(info) {
1509  int grpSrc = info->grpSrc;
1510  int grpDest = info->grpDest;
1511 
1512  float avgPostM = info->numberOfConnections/grp_Info[grpSrc].SizeN;
1513  float avgPreM = info->numberOfConnections/grp_Info[grpDest].SizeN;
1514  //dotty printf output
1515  fprintf(fpDotty, "\t\tg%d -> g%d [style=%s, arrowType=%s, label=\"avgPost=%3.2f, avgPre=%3.2f, wt=%3.3f, maxD=%d \"]\n",
1516  grpSrc, grpDest, (info->initWt > 0)?"bold":"dotted", (info->initWt > 0)?"normal":"dot", avgPostM, avgPreM, info->maxWt, info->maxDelay);
1517  // fprintf(stdout, "Creating Connection from '%s' to '%s' with Probability %1.3f\n",
1518  // grp_Info2[grpSrc].Name.c_str(), grp_Info2[grpDest].Name.c_str(), avgPostM/grp_Info[grpDest].SizeN);
1519  // fprintf(fpLog, "Creating Connection from '%s' to '%s' with Probability %1.3f\n",
1520  // grp_Info2[grpSrc].Name.c_str(), grp_Info2[grpDest].Name.c_str(), avgPostM/grp_Info[grpDest].SizeN);
1521  info = info->next;
1522  }
1523 
1524  fprintf(fpDotty, "\n}\n");
1525  fclose(fpDotty);
1526 
1527  //std::stringstream cmd;
1528  //cmd << "kgraphviewer " << networkName << ".dot";
1529  char cmd[100];
1530  int dbg = sprintf(cmd, "kgraphviewer %s.dot", networkName.c_str());
1531  int retVal;
1532  showDotty = false;
1533  if(showDotty) {
1534  retVal = system(cmd);
1535  carlsim_assert(retVal >= 0);
1536  }
1537 
1538  fprintf(stdout, "\trun cmd to view graph: %s\n", cmd);
1539 }
1540 
1541 // make from each neuron in grpId1 to 'numPostSynapses' neurons in grpId2
1542 int CpuSNN::connect(int grpId1, int grpId2, ConnectionGenerator* conn, bool synWtType, int maxM, int maxPreM)
1543 {
1544  int retId=-1;
1545 
1546  for(int c=0; c < numConfig; c++, grpId1++, grpId2++) {
1547 
1548  carlsim_assert(grpId1 < numGrp);
1549  carlsim_assert(grpId2 < numGrp);
1550 
1551  if (maxM == 0)
1552  maxM = grp_Info[grpId2].SizeN;
1553 
1554  if (maxPreM == 0)
1555  maxPreM = grp_Info[grpId1].SizeN;
1556 
1557  if (maxM > MAX_numPostSynapses) {
1558  printf("Connection from %s (%d) to %s (%d) exceeded the maximum number of output synapses (%d), has %d.\n",grp_Info2[grpId1].Name.c_str(),grpId1,grp_Info2[grpId2].Name.c_str(), grpId2, MAX_numPostSynapses,maxM);
1559  carlsim_assert(maxM <= MAX_numPostSynapses);
1560  }
1561 
1562  if (maxPreM > MAX_numPreSynapses) {
1563  printf("Connection from %s (%d) to %s (%d) exceeded the maximum number of input synapses (%d), has %d.\n",grp_Info2[grpId1].Name.c_str(), grpId1,grp_Info2[grpId2].Name.c_str(), grpId2,MAX_numPreSynapses,maxPreM);
1564  carlsim_assert(maxPreM <= MAX_numPreSynapses);
1565  }
1566 
1567  grpConnectInfo_t* newInfo = (grpConnectInfo_t*) calloc(1, sizeof(grpConnectInfo_t));
1568 
1569  newInfo->grpSrc = grpId1;
1570  newInfo->grpDest = grpId2;
1571  newInfo->initWt = 1;
1572  newInfo->maxWt = 1;
1573  newInfo->maxDelay = 1;
1574  newInfo->minDelay = 1;
1575  newInfo->connProp = SET_CONN_PRESENT(1) | SET_FIXED_PLASTIC(synWtType);
1576  newInfo->type = CONN_USER_DEFINED;
1577  newInfo->numPostSynapses = maxM;
1578  newInfo->numPreSynapses = maxPreM;
1579  newInfo->conn = conn;
1580 
1581  newInfo->next = connectBegin; // build a linked list
1582  connectBegin = newInfo;
1583 
1584  // update the pre and post size...
1585  grp_Info[grpId1].numPostSynapses += newInfo->numPostSynapses;
1586  grp_Info[grpId2].numPreSynapses += newInfo->numPreSynapses;
1587 
1588  if (showLogMode >= 1)
1589  printf("grp_Info[%d, %s].numPostSynapses = %d, grp_Info[%d, %s].numPreSynapses = %d\n",grpId1,grp_Info2[grpId1].Name.c_str(),grp_Info[grpId1].numPostSynapses,grpId2,grp_Info2[grpId2].Name.c_str(),grp_Info[grpId2].numPreSynapses);
1590 
1591  newInfo->connId = numConnections++;
1592  if(c==0)
1593  retId = newInfo->connId;
1594  }
1595  carlsim_assert(retId != -1);
1596  return retId;
1597 }
1598 
1599 // make from each neuron in grpId1 to 'numPostSynapses' neurons in grpId2
1600 int CpuSNN::connect(int grpId1, int grpId2, const string& _type, float initWt, float maxWt, float p, uint8_t minDelay, uint8_t maxDelay, bool synWtType, const string& wtType)
1601 {
1602  int retId=-1;
1603  for(int c=0; c < numConfig; c++, grpId1++, grpId2++) {
1604  carlsim_assert(grpId1 < numGrp);
1605  carlsim_assert(grpId2 < numGrp);
1606  carlsim_assert(minDelay <= maxDelay);
1607 
1608  bool useRandWts = (wtType.find("random") != string::npos);
1609  bool useRampDownWts = (wtType.find("ramp-down") != string::npos);
1610  bool useRampUpWts = (wtType.find("ramp-up") != string::npos);
1611  uint32_t connProp = SET_INITWTS_RANDOM(useRandWts)
1612  | SET_CONN_PRESENT(1)
1613  | SET_FIXED_PLASTIC(synWtType)
1614  | SET_INITWTS_RAMPUP(useRampUpWts)
1615  | SET_INITWTS_RAMPDOWN(useRampDownWts);
1616 
1617  grpConnectInfo_t* newInfo = (grpConnectInfo_t*) calloc(1, sizeof(grpConnectInfo_t));
1618  newInfo->grpSrc = grpId1;
1619  newInfo->grpDest = grpId2;
1620  newInfo->initWt = initWt;
1621  newInfo->maxWt = maxWt;
1622  newInfo->maxDelay = maxDelay;
1623  newInfo->minDelay = minDelay;
1624  newInfo->connProp = connProp;
1625  newInfo->p = p;
1626  newInfo->type = CONN_UNKNOWN;
1627  newInfo->numPostSynapses = 1;
1628 
1629  newInfo->next = connectBegin; //linked list of connection..
1630  connectBegin = newInfo;
1631 
1632 
1633  if ( _type.find("random") != string::npos) {
1634  newInfo->type = CONN_RANDOM;
1635  newInfo->numPostSynapses = MIN(grp_Info[grpId2].SizeN,((int) (p*grp_Info[grpId2].SizeN +5*sqrt(p*(1-p)*grp_Info[grpId2].SizeN)+0.5))); // estimate the maximum number of connections we need. This uses a binomial distribution at 5 stds.
1636  newInfo->numPreSynapses = MIN(grp_Info[grpId1].SizeN,((int) (p*grp_Info[grpId1].SizeN +5*sqrt(p*(1-p)*grp_Info[grpId1].SizeN)+0.5))); // estimate the maximum number of connections we need. This uses a binomial distribution at 5 stds.
1637  }
1638  //so you're setting the size to be prob*Number of synapses in group info + some standard deviation ...
1639 
1640  else if ( _type.find("full") != string::npos) {
1641  newInfo->type = CONN_FULL;
1642  newInfo->numPostSynapses = grp_Info[grpId2].SizeN;
1643  newInfo->numPreSynapses = grp_Info[grpId1].SizeN;
1644  }
1645  else if ( _type.find("full-no-direct") != string::npos) {
1646  newInfo->type = CONN_FULL_NO_DIRECT;
1647  newInfo->numPostSynapses = grp_Info[grpId2].SizeN-1;
1648  newInfo->numPreSynapses = grp_Info[grpId1].SizeN-1;
1649  }
1650  else if ( _type.find("one-to-one") != string::npos) {
1651  newInfo->type = CONN_ONE_TO_ONE;
1652  newInfo->numPostSynapses = 1;
1653  newInfo->numPreSynapses = 1;
1654  }
1655  else {
1656  exitSimulation(-1, "Invalid connection type (should be 'random', 'full', 'one-to-one', or 'full-no-direct')\n");
1657  }
1658 
1659  if (newInfo->numPostSynapses > MAX_numPostSynapses) {
1660  printf("Connection exceeded the maximum number of output synapses (%d), has %d.\n",MAX_numPostSynapses,newInfo->numPostSynapses);
1661  carlsim_assert(newInfo->numPostSynapses <= MAX_numPostSynapses);
1662  }
1663 
1664  if (newInfo->numPreSynapses > MAX_numPreSynapses) {
1665  printf("Connection exceeded the maximum number of input synapses (%d), has %d.\n",MAX_numPreSynapses,newInfo->numPreSynapses);
1666  carlsim_assert(newInfo->numPreSynapses <= MAX_numPreSynapses);
1667  }
1668 
1669  // update the pre and post size...
1670  // Subtlety: each group has numPost/PreSynapses from multiple connections.
1671  // The newInfo->numPost/PreSynapses are just for this specific connection.
1672  // We are adding the synapses counted in this specific connection to the totals for both groups.
1673  grp_Info[grpId1].numPostSynapses += newInfo->numPostSynapses;
1674  grp_Info[grpId2].numPreSynapses += newInfo->numPreSynapses;
1675 
1676  if (showLogMode >= 1)
1677  printf("grp_Info[%d, %s].numPostSynapses = %d, grp_Info[%d, %s].numPreSynapses = %d\n",grpId1,grp_Info2[grpId1].Name.c_str(),grp_Info[grpId1].numPostSynapses,grpId2,grp_Info2[grpId2].Name.c_str(),grp_Info[grpId2].numPreSynapses);
1678 
1679  newInfo->connId = numConnections++;
1680  if(c==0)
1681  retId = newInfo->connId;
1682  }
1683  carlsim_assert(retId != -1);
1684  return retId;
1685 }
1686 
1687 int CpuSNN::updateSpikeTables()
1688 {
1689  int curD = 0;
1690  int grpSrc;
1691  // find the maximum delay in the given network
1692  // and also the maximum delay for each group.
1693  grpConnectInfo_t* newInfo = connectBegin;
1694  while(newInfo) {
1695  grpSrc = newInfo->grpSrc;
1696  if (newInfo->maxDelay > curD)
1697  curD = newInfo->maxDelay;
1698 
1699  // check if the current connection's delay meaning grp1's delay
1700  // is greater than the MaxDelay for grp1. We find the maximum
1701  // delay for the grp1 by this scheme.
1702  if (newInfo->maxDelay > grp_Info[grpSrc].MaxDelay)
1703  grp_Info[grpSrc].MaxDelay = newInfo->maxDelay;
1704  newInfo = newInfo->next;
1705  }
1706 
1707  for(int g=0; g < numGrp; g++) {
1708  if ( grp_Info[g].MaxDelay == 1)
1709  maxSpikesD1 += (grp_Info[g].SizeN*grp_Info[g].MaxFiringRate);
1710  else
1711  maxSpikesD2 += (grp_Info[g].SizeN*grp_Info[g].MaxFiringRate);
1712  }
1713 
1714  // maxSpikesD1 = (maxSpikesD1 == 0)? 1 : maxSpikesD1;
1715  // maxSpikesD2 = (maxSpikesD2 == 0)? 1 : maxSpikesD2;
1716 
1717  if ((maxSpikesD1+maxSpikesD2) < (numNExcReg+numNInhReg+numNPois)*UNKNOWN_NEURON_MAX_FIRING_RATE) {
1718  exitSimulation(1, "Insufficient amount of buffer allocated...\n");
1719  }
1720 
1721  // maxSpikesD2 = (maxSpikesD1 > maxSpikesD2)?maxSpikesD1:maxSpikesD2;
1722  // maxSpikesD1 = (maxSpikesD1 > maxSpikesD2)?maxSpikesD1:maxSpikesD2;
1723 
1724  firingTableD2 = new unsigned int[maxSpikesD2];
1725  firingTableD1 = new unsigned int[maxSpikesD1];
1726  cpuSnnSz.spikingInfoSize += sizeof(int)*((maxSpikesD2+maxSpikesD1) + 2*(1000+D+1));
1727 
1728  return curD;
1729 }
1730 
1731 void CpuSNN::buildNetwork()
1732 {
1733  grpConnectInfo_t* newInfo = connectBegin;
1734  int curN = 0, curD = 0, numPostSynapses = 0, numPreSynapses = 0;
1735 
1736  carlsim_assert(numConfig > 0);
1737 
1738  //update main set of parameters
1739  updateParameters(&curN, &numPostSynapses, &numPreSynapses, numConfig);
1740 
1741  curD = updateSpikeTables();
1742 
1743  carlsim_assert((curN > 0)&& (curN == numNExcReg + numNInhReg + numNPois));
1744  carlsim_assert(numPostSynapses > 0);
1745  carlsim_assert(numPreSynapses > 0);
1746 
1747  // display the evaluated network and delay length....
1748  fprintf(stdout, ">>>>>>>>>>>>>> NUM_CONFIGURATIONS = %d <<<<<<<<<<<<<<<<<<\n", numConfig);
1749  fprintf(stdout, "**********************************\n");
1750  fprintf(stdout, "numN = %d, numPostSynapses = %d, numPreSynapses = %d, D = %d\n", curN, numPostSynapses, numPreSynapses, curD);
1751  fprintf(stdout, "**********************************\n");
1752 
1753  fprintf(fpLog, "**********************************\n");
1754  fprintf(fpLog, "numN = %d, numPostSynapses = %d, numPreSynapses = %d, D = %d\n", curN, numPostSynapses, numPreSynapses, curD);
1755  fprintf(fpLog, "**********************************\n");
1756 
1757  carlsim_assert(curD != 0); carlsim_assert(numPostSynapses != 0); carlsim_assert(curN != 0); carlsim_assert(numPreSynapses != 0);
1758 
1759  if (showLogMode >= 1)
1760  for (int g=0;g<numGrp;g++)
1761  printf("grp_Info[%d, %s].numPostSynapses = %d, grp_Info[%d, %s].numPreSynapses = %d\n",g,grp_Info2[g].Name.c_str(),grp_Info[g].numPostSynapses,g,grp_Info2[g].Name.c_str(),grp_Info[g].numPreSynapses);
1762 
1763  if (numPostSynapses > MAX_numPostSynapses) {
1764  for (int g=0;g<numGrp;g++)
1765  if (grp_Info[g].numPostSynapses>MAX_numPostSynapses) printf("Grp: %s(%d) has too many output synapses (%d), max %d.\n",grp_Info2[g].Name.c_str(),g,grp_Info[g].numPostSynapses,MAX_numPostSynapses);
1766  carlsim_assert(numPostSynapses <= MAX_numPostSynapses);
1767  }
1768  if (numPreSynapses > MAX_numPreSynapses) {
1769  for (int g=0;g<numGrp;g++)
1770  if (grp_Info[g].numPreSynapses>MAX_numPreSynapses) printf("Grp: %s(%d) has too many input synapses (%d), max %d.\n",grp_Info2[g].Name.c_str(),g,grp_Info[g].numPreSynapses,MAX_numPreSynapses);
1771  carlsim_assert(numPreSynapses <= MAX_numPreSynapses);
1772  }
1773  carlsim_assert(curD <= MAX_SynapticDelay); carlsim_assert(curN <= 1000000);
1774 
1775  // initialize all the parameters....
1776  CpuSNNInit(curN, numPostSynapses, numPreSynapses, curD);
1777 
1778  // we build network in the order...
1782  int allocatedGrp = 0;
1783  for(int order=0; order < 4; order++) {
1784  for(int configId=0; configId < numConfig; configId++) {
1785  for(int g=0; g < numGrp; g++) {
1786  if (grp_Info2[g].ConfigId == configId) {
1787  if (IS_EXCITATORY_TYPE(grp_Info[g].Type) && (grp_Info[g].Type&POISSON_NEURON) && order==3) {
1788  buildPoissonGroup(g);
1789  allocatedGrp++;
1790  } else if (IS_INHIBITORY_TYPE(grp_Info[g].Type) && (grp_Info[g].Type&POISSON_NEURON) && order==2) {
1791  buildPoissonGroup(g);
1792  allocatedGrp++;
1793  } else if (IS_EXCITATORY_TYPE(grp_Info[g].Type) && !(grp_Info[g].Type&POISSON_NEURON) && order==0) {
1794  buildGroup(g);
1795  allocatedGrp++;
1796  } else if (IS_INHIBITORY_TYPE(grp_Info[g].Type) && !(grp_Info[g].Type&POISSON_NEURON) && order==1) {
1797  buildGroup(g);
1798  allocatedGrp++;
1799  }
1800  }
1801  }
1802  }
1803  }
1804  carlsim_assert(allocatedGrp == numGrp);
1805 
1806  if (readNetworkFID != NULL) {
1807  // we the user specified readNetwork the synaptic weights will be restored here...
1808 #if READNETWORK_ADD_SYNAPSES_FROM_FILE
1809  // read the plastic synapses first
1810  carlsim_assert(readNetwork_internal(true) >= 0);
1811 
1812  // read the fixed synapses secon
1813  carlsim_assert(readNetwork_internal(false) >= 0);
1814 #else
1815  carlsim_assert(readNetwork_internal() >= 0);
1816 
1817  connectFromMatrix(tmp_SynapseMatrix_plastic, SET_FIXED_PLASTIC(SYN_PLASTIC));
1818 
1819  connectFromMatrix(tmp_SynapseMatrix_fixed, SET_FIXED_PLASTIC(SYN_FIXED));
1820 #endif
1821  } else {
1822  // build all the connections here...
1823  // we run over the linked list two times...
1824  // first time, we make all plastic connections...
1825  // second time, we make all fixed connections...
1826  // this ensures that all the initial pre and post-synaptic
1827  // connections are of fixed type and later if of plastic type
1828  for(int con=0; con < 2; con++) {
1829  newInfo = connectBegin;
1830  while(newInfo) {
1831  bool synWtType = GET_FIXED_PLASTIC(newInfo->connProp);
1832  if (synWtType == SYN_PLASTIC) {
1833  grp_Info[newInfo->grpDest].FixedInputWts = false; // given group has plastic connection, and we need to apply STDP rule...
1834  }
1835 
1836  if( ((con == 0) && (synWtType == SYN_PLASTIC)) ||
1837  ((con == 1) && (synWtType == SYN_FIXED)))
1838  {
1839  switch(newInfo->type)
1840  {
1841  case CONN_RANDOM:
1842  connectRandom(newInfo);
1843  break;
1844  case CONN_FULL:
1845  connectFull(newInfo);
1846  break;
1847  case CONN_FULL_NO_DIRECT:
1848  connectFull(newInfo);
1849  break;
1850  case CONN_ONE_TO_ONE:
1851  connectOneToOne(newInfo);
1852  break;
1853  case CONN_USER_DEFINED:
1854  connectUserDefined(newInfo);
1855  break;
1856  default:
1857  printf("Invalid connection type( should be 'random', or 'full')\n");
1858  }
1859 
1860  float avgPostM = newInfo->numberOfConnections/grp_Info[newInfo->grpSrc].SizeN;
1861  float avgPreM = newInfo->numberOfConnections/grp_Info[newInfo->grpDest].SizeN;
1862 
1863  fprintf(stderr, "connect(%s(%d) => %s(%d), iWt=%f, mWt=%f, numPostSynapses=%d, numPreSynapses=%d, minD=%d, maxD=%d, %s)\n",
1864  grp_Info2[newInfo->grpSrc].Name.c_str(), newInfo->grpSrc, grp_Info2[newInfo->grpDest].Name.c_str(),
1865  newInfo->grpDest, newInfo->initWt, newInfo->maxWt, (int)avgPostM, (int)avgPreM,
1866  newInfo->minDelay, newInfo->maxDelay, synWtType?"Plastic":"Fixed");
1867  }
1868  newInfo = newInfo->next;
1869  }
1870  }
1871  }
1872 }
1873 
1874 int CpuSNN::findGrpId(int nid)
1875 {
1876  for(int g=0; g < numGrp; g++) {
1877  //printf("%d:%s s=%d e=%d\n", g, grp_Info2[g].Name.c_str(), grp_Info[g].StartN, grp_Info[g].EndN);
1878  if(nid >=grp_Info[g].StartN && (nid <=grp_Info[g].EndN)) {
1879  return g;
1880  }
1881  }
1882  fprintf(stderr, "findGrp(): cannot find the group for neuron %d\n", nid);
1883  carlsim_assert(0);
1884 }
1885 
1886 void CpuSNN::writeNetwork(FILE* fid)
1887 {
1888  unsigned int version = 1;
1889  fwrite(&version,sizeof(int),1,fid);
1890  fwrite(&numGrp,sizeof(int),1,fid);
1891  char name[100];
1892 
1893  for (int g=0;g<numGrp;g++) {
1894  fwrite(&grp_Info[g].StartN,sizeof(int),1,fid);
1895  fwrite(&grp_Info[g].EndN,sizeof(int),1,fid);
1896 
1897  strncpy(name,grp_Info2[g].Name.c_str(),100);
1898  fwrite(name,1,100,fid);
1899  }
1900 
1901  int nrCells = numN;
1902  fwrite(&nrCells,sizeof(int),1,fid);
1903 
1904  for (unsigned int i=0;i<nrCells;i++) {
1905  unsigned int offset = cumulativePost[i];
1906 
1907  unsigned int count = 0;
1908  for (int t=0;t<D;t++) {
1909  delay_info_t dPar = postDelayInfo[i*(D+1)+t];
1910 
1911  for(int idx_d = dPar.delay_index_start; idx_d < (dPar.delay_index_start + dPar.delay_length); idx_d = idx_d+1)
1912  count++;
1913  }
1914 
1915  fwrite(&count,sizeof(int),1,fid);
1916 
1917  for (int t=0;t<D;t++) {
1918  delay_info_t dPar = postDelayInfo[i*(D+1)+t];
1919 
1920  for(int idx_d = dPar.delay_index_start; idx_d < (dPar.delay_index_start + dPar.delay_length); idx_d = idx_d+1) {
1921 
1922  // get synaptic info...
1923  post_info_t post_info = postSynapticIds[offset + idx_d];
1924 
1925  // get neuron id
1926  //int p_i = (post_info&POST_SYN_NEURON_MASK);
1927  unsigned int p_i = GET_CONN_NEURON_ID(post_info);
1928  carlsim_assert(p_i<numN);
1929 
1930  // get syn id
1931  unsigned int s_i = GET_CONN_SYN_ID(post_info);
1932  //>>POST_SYN_NEURON_BITS)&POST_SYN_CONN_MASK;
1933  carlsim_assert(s_i<(Npre[p_i]));
1934 
1935  // get the cumulative position for quick access...
1936  unsigned int pos_i = cumulativePre[p_i] + s_i;
1937 
1938  uint8_t delay = t+1;
1939  uint8_t plastic = s_i < Npre_plastic[p_i]; // plastic or fixed.
1940 
1941  fwrite(&i,sizeof(int),1,fid);
1942  fwrite(&p_i,sizeof(int),1,fid);
1943  fwrite(&(wt[pos_i]),sizeof(float),1,fid);
1944  fwrite(&(maxSynWt[pos_i]),sizeof(float),1,fid);
1945  fwrite(&delay,sizeof(uint8_t),1,fid);
1946  fwrite(&plastic,sizeof(uint8_t),1,fid);
1947  }
1948  }
1949  }
1950 }
1951 
1952 void CpuSNN::readNetwork(FILE* fid)
1953 {
1954  readNetworkFID = fid;
1955 }
1956 
1957 
1958 #if READNETWORK_ADD_SYNAPSES_FROM_FILE
1959 int CpuSNN::readNetwork_internal(bool onlyPlastic)
1960 #else
1961  int CpuSNN::readNetwork_internal()
1962 #endif
1963 {
1964  long file_position = ftell(readNetworkFID); // so that we can restore the file position later...
1965  unsigned int version;
1966 
1967  if (!fread(&version,sizeof(int),1,readNetworkFID)) return -11;
1968 
1969  if (version > 1) return -10;
1970 
1971  int _numGrp;
1972  if (!fread(&_numGrp,sizeof(int),1,readNetworkFID)) return -11;
1973 
1974  if (numGrp != _numGrp) return -1;
1975 
1976  char name[100];
1977  int startN, endN;
1978 
1979  for (int g=0;g<numGrp;g++) {
1980  if (!fread(&startN,sizeof(int),1,readNetworkFID)) return -11;
1981  if (!fread(&endN,sizeof(int),1,readNetworkFID)) return -11;
1982 
1983  if (startN != grp_Info[g].StartN) return -2;
1984  if (endN != grp_Info[g].EndN) return -3;
1985 
1986  if (!fread(name,1,100,readNetworkFID)) return -11;
1987 
1988  if (strcmp(name,grp_Info2[g].Name.c_str()) != 0) return -4;
1989  }
1990 
1991  int nrCells;
1992  if (!fread(&nrCells,sizeof(int),1,readNetworkFID)) return -11;
1993 
1994  if (nrCells != numN) return -5;
1995 
1996  tmp_SynapseMatrix_fixed = new SparseWeightDelayMatrix(nrCells,nrCells,nrCells*10);
1997  tmp_SynapseMatrix_plastic = new SparseWeightDelayMatrix(nrCells,nrCells,nrCells*10);
1998 
1999  for (unsigned int i=0;i<nrCells;i++) {
2000  unsigned int nrSynapses = 0;
2001  if (!fread(&nrSynapses,sizeof(int),1,readNetworkFID)) return -11;
2002 
2003  for (int j=0;j<nrSynapses;j++) {
2004  unsigned int nIDpre;
2005  unsigned int nIDpost;
2006  float weight, maxWeight;
2007  uint8_t delay;
2008  uint8_t plastic;
2009 
2010  if (!fread(&nIDpre,sizeof(int),1,readNetworkFID)) return -11;
2011 
2012  if (nIDpre != i) return -6;
2013 
2014  if (!fread(&nIDpost,sizeof(int),1,readNetworkFID)) return -11;
2015 
2016  if (nIDpost >= nrCells) return -7;
2017 
2018  if (!fread(&weight,sizeof(float),1,readNetworkFID)) return -11;
2019 
2020  int gIDpre = findGrpId(nIDpre);
2021  if (IS_INHIBITORY_TYPE(grp_Info[gIDpre].Type) && (weight>0) || !IS_INHIBITORY_TYPE(grp_Info[gIDpre].Type) && (weight<0)) return -8;
2022 
2023  if (!fread(&maxWeight,sizeof(float),1,readNetworkFID)) return -11;
2024 
2025  if (IS_INHIBITORY_TYPE(grp_Info[gIDpre].Type) && (maxWeight>=0) || !IS_INHIBITORY_TYPE(grp_Info[gIDpre].Type) && (maxWeight<=0)) return -8;
2026 
2027  if (!fread(&delay,sizeof(uint8_t),1,readNetworkFID)) return -11;
2028 
2029  if (delay > MAX_SynapticDelay) return -9;
2030 
2031  if (!fread(&plastic,sizeof(uint8_t),1,readNetworkFID)) return -11;
2032 
2033 #if READNETWORK_ADD_SYNAPSES_FROM_FILE
2034  if ((plastic && onlyPlastic) || (!plastic && !onlyPlastic)) {
2035  int gIDpost = findGrpId(nIDpost);
2036  int connProp = SET_FIXED_PLASTIC(plastic?SYN_PLASTIC:SYN_FIXED);
2037 
2038  setConnection(gIDpre, gIDpost, nIDpre, nIDpost, weight, maxWeight, delay, connProp);
2039 
2040  grp_Info2[gIDpre].sumPostConn++;
2041  grp_Info2[gIDpost].sumPreConn++;
2042 
2043  if (delay > grp_Info[gIDpre].MaxDelay) grp_Info[gIDpre].MaxDelay = delay;
2044  }
2045 #else
2046  // add the synapse to the temporary Matrix so that it can be used in buildNetwork()
2047  if (plastic) {
2048  tmp_SynapseMatrix_plastic->add(nIDpre,nIDpost,weight,maxWeight,delay,plastic);
2049  } else {
2050  tmp_SynapseMatrix_fixed->add(nIDpre,nIDpost,weight,maxWeight,delay,plastic);
2051  }
2052 #endif
2053  }
2054  }
2055 #if READNETWORK_ADD_SYNAPSES_FROM_FILE
2056  fseek(readNetworkFID,file_position,SEEK_SET);
2057 #endif
2058  return 0;
2059 }
2060 
2061 
2062 // this is a user function
2063 // FIXME is this guy functional? replace it with Kris' version
2064 float* CpuSNN::getWeights(int gIDpre, int gIDpost, int& Npre, int& Npost, float* weights) {
2065  Npre = grp_Info[gIDpre].SizeN;
2066  Npost = grp_Info[gIDpost].SizeN;
2067 
2068  if (weights==NULL) weights = new float[Npre*Npost];
2069  memset(weights,0,Npre*Npost*sizeof(float));
2070 
2071  // copy the pre synaptic data from GPU, if needed
2072  // note: this will not include wtChange[] and synSpikeTime[] if sim_with_fixedwts
2073  if (currentMode == GPU_MODE)
2074  copyWeightState(&cpuNetPtrs, &cpu_gpuNetPtrs, cudaMemcpyDeviceToHost, false, gIDpost);
2075 
2076  for (int i=grp_Info[gIDpre].StartN;i<grp_Info[gIDpre].EndN;i++) {
2077  unsigned int offset = cumulativePost[i];
2078 
2079  for (int t=0;t<D;t++) {
2080  delay_info_t dPar = postDelayInfo[i*(D+1)+t];
2081 
2082  for(int idx_d = dPar.delay_index_start; idx_d < (dPar.delay_index_start + dPar.delay_length); idx_d = idx_d+1) {
2083 
2084  // get synaptic info...
2085  post_info_t post_info = postSynapticIds[offset + idx_d];
2086 
2087  // get neuron id
2088  //int p_i = (post_info&POST_SYN_NEURON_MASK);
2089  int p_i = GET_CONN_NEURON_ID(post_info);
2090  carlsim_assert(p_i<numN);
2091 
2092  if (p_i >= grp_Info[gIDpost].StartN && p_i <= grp_Info[gIDpost].EndN) {
2093  // get syn id
2094  int s_i = GET_CONN_SYN_ID(post_info);
2095 
2096  // get the cumulative position for quick access...
2097  unsigned int pos_i = cumulativePre[p_i] + s_i;
2098 
2099  weights[i+Npre*(p_i-grp_Info[gIDpost].StartN)] = cpuNetPtrs.wt[pos_i];
2100  }
2101  }
2102  }
2103  }
2104 
2105  return weights;
2106 }
2107 
2108 // this is a user function
2109 float* CpuSNN::getWeightChanges(int gIDpre, int gIDpost, int& Npre, int& Npost, float* weightChanges) {
2110  Npre = grp_Info[gIDpre].SizeN;
2111  Npost = grp_Info[gIDpost].SizeN;
2112 
2113  if (weightChanges==NULL) weightChanges = new float[Npre*Npost];
2114  memset(weightChanges,0,Npre*Npost*sizeof(float));
2115 
2116  // copy the pre synaptic data from GPU, if needed
2117  // note: this will not include wtChange[] and synSpikeTime[] if sim_with_fixedwts
2118  if (currentMode == GPU_MODE)
2119  copyWeightState(&cpuNetPtrs, &cpu_gpuNetPtrs, cudaMemcpyDeviceToHost, false, gIDpost);
2120 
2121  for (int i=grp_Info[gIDpre].StartN;i<grp_Info[gIDpre].EndN;i++) {
2122  unsigned int offset = cumulativePost[i];
2123 
2124  for (int t=0;t<D;t++) {
2125  delay_info_t dPar = postDelayInfo[i*(D+1)+t];
2126 
2127  for(int idx_d = dPar.delay_index_start; idx_d < (dPar.delay_index_start + dPar.delay_length); idx_d = idx_d+1) {
2128 
2129  // get synaptic info...
2130  post_info_t post_info = postSynapticIds[offset + idx_d];
2131 
2132  // get neuron id
2133  //int p_i = (post_info&POST_SYN_NEURON_MASK);
2134  int p_i = GET_CONN_NEURON_ID(post_info);
2135  carlsim_assert(p_i<numN);
2136 
2137  if (p_i >= grp_Info[gIDpost].StartN && p_i <= grp_Info[gIDpost].EndN) {
2138  // get syn id
2139  int s_i = GET_CONN_SYN_ID(post_info);
2140 
2141  // get the cumulative position for quick access...
2142  unsigned int pos_i = cumulativePre[p_i] + s_i;
2143 
2144  // if a group has fixed input weights, it will not have wtChange[] on the GPU side
2145  if (grp_Info[gIDpost].FixedInputWts)
2146  weightChanges[i+Npre*(p_i-grp_Info[gIDpost].StartN)] = 0.0f;
2147  else
2148  weightChanges[i+Npre*(p_i-grp_Info[gIDpost].StartN)] = wtChange[pos_i];
2149  }
2150  }
2151  }
2152  }
2153 
2154  return weightChanges;
2155 }
2156 
2157 
2158 
2159 uint8_t* CpuSNN::getDelays(int gIDpre, int gIDpost, int& Npre, int& Npost, uint8_t* delays) {
2160  Npre = grp_Info[gIDpre].SizeN;
2161  Npost = grp_Info[gIDpost].SizeN;
2162 
2163  if (delays == NULL) delays = new uint8_t[Npre*Npost];
2164  memset(delays,0,Npre*Npost);
2165 
2166  for (int i=grp_Info[gIDpre].StartN;i<grp_Info[gIDpre].EndN;i++) {
2167  unsigned int offset = cumulativePost[i];
2168 
2169  for (int t=0;t<D;t++) {
2170  delay_info_t dPar = postDelayInfo[i*(D+1)+t];
2171 
2172  for(int idx_d = dPar.delay_index_start; idx_d < (dPar.delay_index_start + dPar.delay_length); idx_d = idx_d+1) {
2173 
2174  // get synaptic info...
2175  post_info_t post_info = postSynapticIds[offset + idx_d];
2176 
2177  // get neuron id
2178  //int p_i = (post_info&POST_SYN_NEURON_MASK);
2179  int p_i = GET_CONN_NEURON_ID(post_info);
2180  carlsim_assert(p_i<numN);
2181 
2182  if (p_i >= grp_Info[gIDpost].StartN && p_i <= grp_Info[gIDpost].EndN) {
2183  // get syn id
2184  int s_i = GET_CONN_SYN_ID(post_info);
2185 
2186  // get the cumulative position for quick access...
2187  unsigned int pos_i = cumulativePre[p_i] + s_i;
2188 
2189  delays[i+Npre*(p_i-grp_Info[gIDpost].StartN)] = t+1;
2190  }
2191  }
2192  }
2193  }
2194 
2195  return delays;
2196 }
2197 
2198 // This function is called every second by simulator...
2199 // This function updates the firingTable by removing older firing values...
2200 // and also update the synaptic weights from its derivatives..
2201 void CpuSNN::updateStateAndFiringTable()
2202 {
2203  // Read the neuron ids that fired in the last D seconds
2204  // and put it to the beginning of the firing table...
2205  for(int p=timeTableD2[CARLSIM_STEP_SIZE-1],k=0;p<timeTableD2[CARLSIM_STEP_SIZE-1+D+1];p++,k++) {
2206  firingTableD2[k]=firingTableD2[p];
2207  }
2208 
2209  for(int i=0; i < D; i++) {
2210  timeTableD2[i+1] = timeTableD2[CARLSIM_STEP_SIZE+i+1]-timeTableD2[CARLSIM_STEP_SIZE];
2211  }
2212 
2213  timeTableD1[D] = 0;
2214 
2215  // update synaptic weights here for all the neurons..
2216  for(int g=0; g < numGrp; g++) {
2217  // no changable weights so continue without changing..
2218  if(grp_Info[g].FixedInputWts || !(grp_Info[g].WithSTDP)) {
2219  // for(int i=grp_Info[g].StartN; i <= grp_Info[g].EndN; i++)
2220  // nSpikeCnt[i]=0;
2221  continue;
2222  }
2223 
2224  for(int i=grp_Info[g].StartN; i <= grp_Info[g].EndN; i++) {
2226  carlsim_assert(i < numNReg);
2227  unsigned int offset = cumulativePre[i];
2228  float diff_firing = 0.0;
2229  float homeostasisScale = 1.0;
2230 
2231  if(grp_Info[g].WithHomeostasis) {
2232  carlsim_assert(baseFiring[i]>0);
2233  diff_firing = 1-avgFiring[i]/baseFiring[i];
2234  homeostasisScale = grp_Info[g].homeostasisScale;
2235  }
2236 
2237  if ((showLogMode >= 1) && (i==grp_Info[g].StartN))
2238  fprintf(fpProgLog,"Weights, Change at %lu (diff_firing:%f) \n", simTimeSec, diff_firing);
2239 
2240  for(int j=0; j < Npre_plastic[i]; j++) {
2241 
2242  if ((showLogMode >= 1) && (i==grp_Info[g].StartN))
2243  fprintf(fpProgLog,"%1.2f %1.2f \t", wt[offset+j]*10, wtChange[offset+j]*10);
2244  // homeostatic weight update
2245  if(grp_Info[g].WithHomeostasis) {
2246  if ((showLogMode >= 3) && (i==grp_Info[g].StartN))
2247  fprintf(fpProgLog,"%f\t",(diff_firing*(0.0+wt[offset+j]) + wtChange[offset+j])/10/(Npre_plastic[i]+10)/(grp_Info[g].avgTimeScale*2/1000.0)*baseFiring[i]/(1+fabs(diff_firing)*50));
2248  //need to figure out exactly why we change the weight to this value. Specifically, what is with the second term? -- KDC
2249  wt[offset+j] += (diff_firing*wt[offset+j]*homeostasisScale + wtChange[offset+j])*baseFiring[i]/grp_Info[g].avgTimeScale/(1+fabs(diff_firing)*50);
2250  } else{
2251  // just STDP weight update
2252  wt[offset+j] += wtChange[offset+j];
2253  // STDP weight update that is biased towards learning
2254  //wt[offset+j] += (wtChange[offset+j]+0.1f);
2255  }
2256 
2257  //MDR - don't decay weights, just set to 0
2258  //wtChange[offset+j]*=0.99f;
2259  wtChange[offset+j] = 0;
2260 
2261  // if this is an excitatory or inhibitory synapse
2262  if (maxSynWt[offset+j] >= 0) {
2263  if (wt[offset+j]>=maxSynWt[offset+j])
2264  wt[offset+j] = maxSynWt[offset+j];
2265  if (wt[offset+j]<0)
2266  wt[offset+j] = 0.0;
2267  } else {
2268  if (wt[offset+j]<=maxSynWt[offset+j])
2269  wt[offset+j] = maxSynWt[offset+j];
2270  if (wt[offset+j]>0)
2271  wt[offset+j] = 0.0;
2272  }
2273  }
2274 
2275  if ((showLogMode >= 1) && (i==grp_Info[g].StartN))
2276  fprintf(fpProgLog,"\n");
2277  }
2278  }
2279 
2280  spikeCountAll += spikeCountAll1sec;
2281  spikeCountD2Host += (secD2fireCntHost-timeTableD2[D]);
2282  spikeCountD1Host += secD1fireCntHost;
2283 
2284  secD1fireCntHost = 0;
2285  spikeCountAll1sec = 0;
2286  secD2fireCntHost = timeTableD2[D];
2287 
2288  for(int i=0; i < numGrp; i++) {
2289  grp_Info[i].FiringCount1sec=0;
2290  }
2291 
2292 }
2293 
2294 // This method loops through all spikes that are generated by neurons with a delay of 2+ms
2295 // and delivers the spikes to the appropriate post-synaptic neuron
2296 void CpuSNN::doD2CurrentUpdate()
2297 {
2298  int k = secD2fireCntHost-1;
2299  int k_end = timeTableD2[simTimeMs+1];
2300  int t_pos = simTimeMs;
2301 
2302  while((k>=k_end)&& (k >=0)) {
2303 
2304  // get the neuron id from the index k
2305  int i = firingTableD2[k];
2306 
2307  // find the time of firing from the timeTable using index k
2308  while (!((k >= timeTableD2[t_pos+D])&&(k < timeTableD2[t_pos+D+1]))) {
2309  t_pos = t_pos - 1;
2310  carlsim_assert((t_pos+D-1)>=0);
2311  }
2312 
2313  // TODO: Instead of using the complex timeTable, can neuronFiringTime value...???
2314  // Calculate the time difference between time of firing of neuron and the current time...
2315  int tD = simTimeMs - t_pos;
2316 
2317  carlsim_assert((tD<D)&&(tD>=0));
2318  carlsim_assert(i<numN);
2319 
2320  delay_info_t dPar = postDelayInfo[i*(D+1)+tD];
2321 
2322  unsigned int offset = cumulativePost[i];
2323 
2324  // for each delay variables
2325  for(int idx_d = dPar.delay_index_start;
2326  idx_d < (dPar.delay_index_start + dPar.delay_length);
2327  idx_d = idx_d+1) {
2328  generatePostSpike( i, idx_d, offset, tD);
2329  }
2330 
2331  k=k-1;
2332  }
2333 }
2334 
2335 // This method loops through all spikes that are generated by neurons with a delay of 1ms
2336 // and delivers the spikes to the appropriate post-synaptic neuron
2337 void CpuSNN::doD1CurrentUpdate()
2338 {
2339  int k = secD1fireCntHost-1;
2340  int k_end = timeTableD1[simTimeMs+D];
2341 
2342  while((k>=k_end) && (k>=0)) {
2343 
2344  int neuron_id = firingTableD1[k];
2345  carlsim_assert(neuron_id<numN);
2346 
2347  delay_info_t dPar = postDelayInfo[neuron_id*(D+1)];
2348 
2349  unsigned int offset = cumulativePost[neuron_id];
2350 
2351  for(int idx_d = dPar.delay_index_start;
2352  idx_d < (dPar.delay_index_start + dPar.delay_length);
2353  idx_d = idx_d+1) {
2354  generatePostSpike( neuron_id, idx_d, offset, 0);
2355  }
2356  k=k-1;
2357  }
2358 }
2359 
2360 void CpuSNN::generatePostSpike(unsigned int pre_i, unsigned int idx_d, unsigned int offset, unsigned int tD)
2361 {
2362  // get synaptic info...
2363  post_info_t post_info = postSynapticIds[offset + idx_d];
2364 
2365  // get neuron id
2366  unsigned int p_i = GET_CONN_NEURON_ID(post_info);
2367  carlsim_assert(p_i<numN);
2368 
2369  // get syn id
2370  int s_i = GET_CONN_SYN_ID(post_info);
2371  carlsim_assert(s_i<(Npre[p_i]));
2372 
2373  // get the cumulative position for quick access...
2374  unsigned int pos_i = cumulativePre[p_i] + s_i;
2375 
2376  carlsim_assert(p_i < numNReg);
2377 
2378  float change;
2379 
2380  int pre_grpId = findGrpId(pre_i);
2381  char type = grp_Info[pre_grpId].Type;
2382 
2383  // TODO: MNJ TEST THESE CONDITIONS FOR CORRECTNESS...
2384  int ind = STP_BUF_POS(pre_i,(simTime-tD-1));
2385 
2386  // if the source group STP is disabled. we need to skip it..
2387  if (grp_Info[pre_grpId].WithSTP) {
2388  change = wt[pos_i]*stpx[ind]*stpu[ind];
2389  } else
2390  change = wt[pos_i];
2391 
2392  if (grp_Info[pre_grpId].WithConductances) {
2393  if (type & TARGET_AMPA) gAMPA [p_i] += change;
2394  if (type & TARGET_NMDA) gNMDA [p_i] += change;
2395  if (type & TARGET_GABAa) gGABAa[p_i] -= change; // wt should be negative for GABAa and GABAb
2396  if (type & TARGET_GABAb) gGABAb[p_i] -= change;
2397  } else
2398  current[p_i] += change;
2399 
2400  int post_grpId = findGrpId(p_i);
2401  if ((showLogMode >= 3) && (p_i==grp_Info[post_grpId].StartN))
2402  printf("%d => %d (%d) am=%f ga=%f wt=%f stpu=%f stpx=%f td=%d\n",
2403  pre_i, p_i, findGrpId(p_i), gAMPA[p_i], gGABAa[p_i],
2404  wt[pos_i],(grp_Info[post_grpId].WithSTP?stpx[ind]:1.0),(grp_Info[post_grpId].WithSTP?stpu[ind]:1.0),tD);
2405 
2406  // STDP calculation....
2407  if (grp_Info[post_grpId].WithSTDP) {
2408  //stdpChanged[pos_i]=false;
2409  //carlsim_assert(simTime-lastSpikeTime[p_i])>=0);
2410  int stdp_tDiff = (simTime-lastSpikeTime[p_i]);
2411 
2412  if (stdp_tDiff >= 0) {
2413 #ifdef INHIBITORY_STDP
2414  if ((type & TARGET_GABAa) || (type & TARGET_GABAb))
2415  {
2416  //printf("I");
2417  if ((stdp_tDiff*grp_Info[post_grpId].TAU_LTD_INV)<25)
2418  wtChange[pos_i] -= (STDP(stdp_tDiff, grp_Info[post_grpId].ALPHA_LTP, grp_Info[post_grpId].TAU_LTP_INV) - STDP(stdp_tDiff, grp_Info[post_grpId].ALPHA_LTD*1.5, grp_Info[post_grpId].TAU_LTD_INV));
2419  }
2420  else
2421 #endif
2422  {
2423  //printf("E");
2424  if ((stdp_tDiff*grp_Info[post_grpId].TAU_LTD_INV)<25)
2425  wtChange[pos_i] -= STDP(stdp_tDiff, grp_Info[post_grpId].ALPHA_LTD, grp_Info[post_grpId].TAU_LTD_INV);
2426  }
2427 
2428  }
2429  carlsim_assert(!((stdp_tDiff < 0) && (lastSpikeTime[p_i] != MAX_SIMULATION_TIME)));
2430  }
2431 
2432  synSpikeTime[pos_i] = simTime;
2433 }
2434 
2435 void CpuSNN::globalStateUpdate()
2436 {
2437 #define CUR_DEBUG 1
2438  //fprintf(stdout, "---%d ----\n", simTime);
2439  // now we update the state of all the neurons
2440  for(int g=0; g < numGrp; g++) {
2441  if (grp_Info[g].Type&POISSON_NEURON){
2442  for(int i=grp_Info[g].StartN; i <= grp_Info[g].EndN; i++)
2443  avgFiring[i] *= grp_Info[g].avgTimeScale_decay;
2444  continue;
2445  }
2446 
2447  for(int i=grp_Info[g].StartN; i <= grp_Info[g].EndN; i++) {
2448  carlsim_assert(i < numNReg);
2449  avgFiring[i] *= grp_Info[g].avgTimeScale_decay;
2450 
2451  if (grp_Info[g].WithConductances) {
2452  // all the tmpIs will be summed into current[i] in the following loop
2453  current[i] = 0.0f;
2454 
2455  for (int j=0; j<COND_INTEGRATION_SCALE; j++) {
2456  float NMDAtmp = (voltage[i]+80)*(voltage[i]+80)/60/60;
2457  // There is an instability issue when dealing with large conductances, which causes the membr.
2458  // pot. to plateau just below the spike threshold... We cap the "slow" conductances to prevent
2459  // this issue. Note: 8.0 and 2.0 seemed to work in some experiments, but it might not be the
2460  // best choice in general... compare updateNeuronState() in snn_gpu.cu
2461  float tmpI = - ( gAMPA[i]*(voltage[i]-0)
2462  + MIN(8.0f,gNMDA[i])*NMDAtmp/(1+NMDAtmp)*(voltage[i]-0) // cap gNMDA at 8.0
2463  + gGABAa[i]*(voltage[i]+70)
2464  + MIN(2.0f,gGABAb[i])*(voltage[i]+90)); // cap gGABAb at 2.0
2465 
2466  current[i] += tmpI;
2467 
2468 #ifdef NEURON_NOISE
2469  float noiseI = -intrinsicWeight[i]*log(getRand());
2470  if (isnan(noiseI) || isinf(noiseI)) noiseI = 0;
2471  tmpI += noiseI;
2472 #endif
2473 
2474  voltage[i]+=((0.04f*voltage[i]+5)*voltage[i]+140-recovery[i]+tmpI)/COND_INTEGRATION_SCALE;
2475  carlsim_assert(!isnan(voltage[i]) && !isinf(voltage[i]));
2476 
2477  if (voltage[i] > 30) {
2478  voltage[i] = 30;
2479  j=COND_INTEGRATION_SCALE; // break the loop but evaluate u[i]
2480  }
2481  if (voltage[i] < -90) voltage[i] = -90;
2482  recovery[i]+=Izh_a[i]*(Izh_b[i]*voltage[i]-recovery[i])/COND_INTEGRATION_SCALE;
2483  }
2484  //if (i==grp_Info[6].StartN) printf("voltage: %f AMPA: %f NMDA: %f GABAa: %f GABAb: %f\n",voltage[i],gAMPA[i],gNMDA[i],gGABAa[i],gGABAb[i]);
2485  } else {
2486  voltage[i]+=0.5f*((0.04f*voltage[i]+5)*voltage[i]+140-recovery[i]+current[i]); // for numerical stability
2487  voltage[i]+=0.5f*((0.04f*voltage[i]+5)*voltage[i]+140-recovery[i]+current[i]); // time step is 0.5 ms
2488  if (voltage[i] > 30) voltage[i] = 30;
2489  if (voltage[i] < -90) voltage[i] = -90;
2490  recovery[i]+=Izh_a[i]*(Izh_b[i]*voltage[i]-recovery[i]);
2491  }
2492 
2493  if ((showLogMode >= 2) && (i==grp_Info[g].StartN))
2494  fprintf(stdout, "%d: voltage=%0.3f, recovery=%0.5f, AMPA=%0.5f, NMDA=%0.5f\n",
2495  i, voltage[i], recovery[i], gAMPA[i], gNMDA[i]);
2496  }
2497  }
2498 }
2499 
2500 void CpuSNN::printWeight(int grpId, const char *str)
2501 {
2502  int stg, endg;
2503  if(grpId == -1) {
2504  stg = 0;
2505  endg = numGrp;
2506  }
2507  else {
2508  stg = grpId;
2509  endg = grpId+1;
2510  }
2511 
2512  for(int g=stg; (g < endg) ; g++) {
2513  fprintf(stderr, "%s", str);
2514  if (!grp_Info[g].FixedInputWts) {
2515  //fprintf(stderr, "w=\t");
2516  if (currentMode == GPU_MODE) {
2517  copyWeightState (&cpuNetPtrs, &cpu_gpuNetPtrs, cudaMemcpyDeviceToHost, false, g);
2518  }
2519  int i=grp_Info[g].StartN;
2520  unsigned int offset = cumulativePre[i];
2521  //fprintf(stderr, "time=%d, Neuron synaptic weights %d:\n", simTime, i);
2522  for(int j=0; j < Npre[i]; j++) {
2523  //fprintf(stderr, "w=%f c=%f spt=%d\t", wt[offset+j], wtChange[offset+j], synSpikeTime[offset+j]);
2524  fprintf(stdout, "%1.3f,%1.3f\t", cpuNetPtrs.wt[offset+j], cpuNetPtrs.wtChange[offset+j]);
2525  }
2526  fprintf(stdout, "\n");
2527  }
2528  }
2529 }
2530 
2531 // show the status of the simulator...
2532 // when onlyCnt is set, we print the actual count instead of frequency of firing
2533 void CpuSNN::showStatus(int simType)
2534 {
2535  DBG(2, fpLog, AT, "showStatus() called");
2536 
2537  printState("showStatus\n");
2538 
2539  if(simType == GPU_MODE) {
2540  showStatus_GPU();
2541  return;
2542  }
2543 
2544  FILE* fpVal[2];
2545  fpVal[0] = fpLog;
2546  fpVal[1] = fpProgLog;
2547 
2548  for(int k=0; k < 2; k++) {
2549 
2550  if(k==0)
2551  printWeight(-1);
2552 
2553  fprintf(fpVal[k], "(time=%lld) =========\n\n", (unsigned long long) simTimeSec);
2554 
2555 
2556 #if REG_TESTING
2557  // if the overall firing rate is very low... then report error...
2558  if((spikeCountAll1sec*1.0f/numN) < 1.0) {
2559  fprintf(fpVal[k], " SIMULATION WARNING !!! Very Low Firing happened...\n");
2560  fflush(fpVal[k]);
2561  }
2562 #endif
2563 
2564  fflush(fpVal[k]);
2565  }
2566 
2567 #if REG_TESTING
2568  if(spikeCountAll1sec == 0) {
2569  fprintf(stderr, " SIMULATION ERROR !!! Very Low or no firing happened...\n");
2570  //exit(-1);
2571  }
2572 #endif
2573 }
2574 
2575 void CpuSNN::startCPUTiming()
2576 {
2577  prevCpuExecutionTime = cumExecutionTime;
2578 }
2579 
2580 void CpuSNN::resetCPUTiming()
2581 {
2582  prevCpuExecutionTime = cumExecutionTime;
2583  cpuExecutionTime = 0.0;
2584 }
2585 
2586 void CpuSNN::stopCPUTiming()
2587 {
2588  cpuExecutionTime += (cumExecutionTime - prevCpuExecutionTime);
2589  prevCpuExecutionTime = cumExecutionTime;
2590 }
2591 
2592 void CpuSNN::startGPUTiming()
2593 {
2594  prevGpuExecutionTime = cumExecutionTime;
2595 }
2596 
2597 void CpuSNN::resetGPUTiming()
2598 {
2599  prevGpuExecutionTime = cumExecutionTime;
2600  gpuExecutionTime = 0.0;
2601 }
2602 
2603 void CpuSNN::stopGPUTiming()
2604 {
2605  gpuExecutionTime += (cumExecutionTime - prevGpuExecutionTime);
2606  prevGpuExecutionTime = cumExecutionTime;
2607 }
2608 
2609 // reorganize the network and do the necessary allocation
2610 // of all variable for carrying out the simulation..
2611 // this code is run only one time during network initialization
2612 void CpuSNN::setupNetwork(int simType, int ithGPU, bool removeTempMem)
2613 {
2614  if(!doneReorganization)
2615  reorganizeNetwork(removeTempMem, simType);
2616 
2617  if((simType == GPU_MODE) && (cpu_gpuNetPtrs.allocated == false))
2618  allocateSNN_GPU(ithGPU);
2619 }
2620 
2621 //DWC: Used to determine when to call the spike monitors
2623 {
2624  bool finishedOneSec = false;
2625 
2626  // done one second worth of simulation
2627  // update relevant parameters...now
2628  if(++simTimeMs == CARLSIM_STEP_SIZE) {
2629  simTimeMs = 0;
2630  simTimeSec++;
2631  finishedOneSec = true;
2632  }
2633 
2634  simTime++;
2635  if(simTime >= MAX_SIMULATION_TIME){
2636  // reached the maximum limit of the simulation time using 32 bit value...
2637  updateAfterMaxTime();
2638  }
2639 
2640  return finishedOneSec;
2641 }
2642 
2643 // Run the simulation for n sec
2644 int CpuSNN::runNetwork(int _nsec, int _nmsec, int simType, int ithGPU, bool enablePrint, int copyState)
2645 {
2646  DBG(2, fpLog, AT, "runNetwork() called");
2647 
2648  carlsim_assert(_nmsec >= 0);
2649  carlsim_assert(_nsec >= 0);
2650 
2651  carlsim_assert(simType == CPU_MODE || simType == GPU_MODE);
2652 
2653  int runDuration = _nsec*1000 + _nmsec;
2654 
2655  setGrpTimeSlice(ALL, MAX(1,MIN(runDuration,PROPAGATED_BUFFER_SIZE-1))); // set the Poisson generation time slice to be at the run duration up to PROPOGATED_BUFFER_SIZE ms.
2656 
2657  // First time when the network is run we do various kind of space compression,
2658  // and data structure optimization to improve performance and save memory.
2659 
2660  setupNetwork(simType,ithGPU);
2661 
2662  currentMode = simType;
2663 
2664  CUDA_RESET_TIMER(timer);
2665 
2666  CUDA_START_TIMER(timer);
2667 
2668  bool end_stepping = false;
2669  // if nsec=0, simTimeMs=10, we need to run the simulator for 10 timeStep;
2670  // if nsec=1, simTimeMs=10, we need to run the simulator for 1*1000+10, time Step;
2671  for(int i=0; i < runDuration && !end_stepping; i++) {
2672 
2673  // initThalInput();
2674 
2675  if(simType == CPU_MODE)
2676  doSnnSim();
2677  else
2678  doGPUSim();
2679 
2680  if (enablePrint) {
2681  printState();
2682  }
2683 
2684  if (updateTime()) {
2685 
2686  // finished one sec of simulation...
2687  if(showLog)
2688  if(showLogCycle==showLog++) {
2689  showStatus(currentMode);
2690  showLog=1;
2691  }
2692 
2693  updateSpikeMonitor();
2694 
2695  if(simType == CPU_MODE)
2696  updateStateAndFiringTable();
2697  else
2698  updateStateAndFiringTable_GPU();
2699 
2700  if(stepFeedback)
2701  stepFeedback->updateMonitors(this, i);
2702  }
2703 
2704  if(enableGPUSpikeCntPtr==true && simType == CPU_MODE){
2705  fprintf(stderr,"Error: the enableGPUSpikeCntPtr flag cannot be set in CPU_MODE\n");
2706  carlsim_assert(currentMode==GPU_MODE);
2707  }
2708  if(enableGPUSpikeCntPtr==true && simType == GPU_MODE){
2709  copyFiringStateFromGPU();
2710  }
2711 
2712  if(stepFeedback)
2713  end_stepping = stepFeedback->stepUpdate(this, i);
2714  }
2715  if(copyState) {
2716  // copy the state from GPU to GPU
2717  for(int g=0; g < numGrp; g++) {
2718  if ((!grp_Info[g].isSpikeGenerator) && (currentMode==GPU_MODE)) {
2719  copyNeuronState(&cpuNetPtrs, &cpu_gpuNetPtrs, cudaMemcpyDeviceToHost, false, g);
2720  }
2721  }
2722  }
2723 
2724  // keep track of simulation time...
2725  CUDA_STOP_TIMER(timer);
2726  lastExecutionTime = CUDA_GET_TIMER_VALUE(timer);
2727  if(0) {
2728  fprintf(fpLog, "(t%s = %2.2f sec)\n", (currentMode == GPU_MODE)?"GPU":"CPU", lastExecutionTime/1000);
2729  fprintf(stdout, "(t%s = %2.2f sec)\n", (currentMode == GPU_MODE)?"GPU":"CPU", lastExecutionTime/1000);
2730  }
2731  cumExecutionTime += lastExecutionTime;
2732  return 0;
2733 }
2734 
2735 void CpuSNN::updateAfterMaxTime()
2736 {
2737  fprintf(stderr, "Maximum Simulation Time Reached...Resetting simulation time\n");
2738 
2739  // This will be our cut of time. All other time values
2740  // that are less than cutOffTime will be set to zero
2741  unsigned int cutOffTime = (MAX_SIMULATION_TIME - 10*1000);
2742 
2743  for(int g=0; g < numGrp; g++) {
2744 
2745  if (grp_Info[g].isSpikeGenerator) {
2746  int diffTime = (grp_Info[g].SliceUpdateTime - cutOffTime);
2747  grp_Info[g].SliceUpdateTime = (diffTime < 0) ? 0 : diffTime;
2748  }
2749 
2750  // no STDP then continue...
2751  if(!grp_Info[g].FixedInputWts) {
2752  continue;
2753  }
2754 
2755  for(int k=0, nid = grp_Info[g].StartN; nid <= grp_Info[g].EndN; nid++,k++) {
2756  carlsim_assert(nid < numNReg);
2757  // calculate the difference in time
2758  signed diffTime = (lastSpikeTime[nid] - cutOffTime);
2759  lastSpikeTime[nid] = (diffTime < 0) ? 0 : diffTime;
2760 
2761  // do the same thing with all synaptic connections..
2762  unsigned* synTime = &synSpikeTime[cumulativePre[nid]];
2763  for(int i=0; i < Npre[nid]; i++, synTime++) {
2764  // calculate the difference in time
2765  signed diffTime = (synTime[0] - cutOffTime);
2766  synTime[0] = (diffTime < 0) ? 0 : diffTime;
2767  }
2768  }
2769  }
2770 
2771  simTime = MAX_SIMULATION_TIME - cutOffTime;
2772  resetPropogationBuffer();
2773 }
2774 
2775 void CpuSNN::resetPropogationBuffer()
2776 {
2777  pbuf->reset(0, 1023);
2778 }
2779 
2780 unsigned int poissonSpike(unsigned int currTime, float frate, int refractPeriod)
2781 {
2782  bool done = false;
2783  unsigned int nextTime = 0;
2784  carlsim_assert(refractPeriod>0); // refractory period must be 1 or greater, 0 means could have multiple spikes specified at the same time.
2785  static int cnt = 0;
2786  while(!done)
2787  {
2788  float randVal = drand48();
2789  unsigned int tmpVal = -log(randVal)/frate;
2790  nextTime = currTime + tmpVal;
2791  //fprintf(stderr, "%d: next random = %f, frate = %f, currTime = %d, nextTime = %d tmpVal = %d\n", cnt++, randVal, frate, currTime, nextTime, tmpVal);
2792  if ((nextTime - currTime) >= (unsigned) refractPeriod)
2793  done = true;
2794  }
2795 
2796  carlsim_assert(nextTime != 0);
2797  return nextTime;
2798 }
2799 
2800 //
2801 void CpuSNN::updateSpikeGeneratorsInit()
2802 {
2803  int cnt=0;
2804  for(int g=0; (g < numGrp); g++) {
2805  if (grp_Info[g].isSpikeGenerator) {
2806 
2807  // This is done only during initialization
2808  grp_Info[g].CurrTimeSlice = grp_Info[g].NewTimeSlice;
2809 
2810  // we only need NgenFunc for spike generator callbacks that need to transfer their spikes to the GPU
2811  if (grp_Info[g].spikeGen) {
2812  grp_Info[g].Noffset = NgenFunc;
2813  NgenFunc += grp_Info[g].SizeN;
2814  }
2815 
2816  updateSpikesFromGrp(g);
2817  cnt++;
2818  carlsim_assert(cnt <= numSpikeGenGrps);
2819  }
2820  }
2821 
2822  // spikeGenBits can be set only once..
2823  carlsim_assert(spikeGenBits == NULL);
2824 
2825  if (NgenFunc) {
2826  spikeGenBits = new uint32_t[NgenFunc/32+1];
2827  cpuNetPtrs.spikeGenBits = spikeGenBits;
2828  // increase the total memory size used by the routine...
2829  cpuSnnSz.addInfoSize += sizeof(spikeGenBits[0])*(NgenFunc/32+1);
2830  }
2831 }
2832 
2833 void CpuSNN::updateSpikeGenerators()
2834 {
2835  for(int g=0; (g < numGrp); g++) {
2836  if (grp_Info[g].isSpikeGenerator) {
2837  // This evaluation is done to check if its time to get new set of spikes..
2838  // fprintf(stderr, "[MODE=%s] simtime = %d, NumTimeSlice = %d, SliceUpdate = %d, currTime = %d\n",
2839  // (currentMode==GPU_MODE)?"GPU_MODE":"CPU_MODE", simTime, grp_Info[g].NumTimeSlice,
2840  // grp_Info[g].SliceUpdateTime, grp_Info[g].CurrTimeSlice);
2841  if(((simTime-grp_Info[g].SliceUpdateTime) >= (unsigned) grp_Info[g].CurrTimeSlice))
2842  updateSpikesFromGrp(g);
2843  }
2844  }
2845 }
2846 
2847 void CpuSNN::generateSpikesFromFuncPtr(int grpId)
2848 {
2849  bool done;
2850  SpikeGenerator* spikeGen = grp_Info[grpId].spikeGen;
2851  int timeSlice = grp_Info[grpId].CurrTimeSlice;
2852  unsigned int currTime = simTime;
2853  int spikeCnt=0;
2854  for(int i=grp_Info[grpId].StartN;i<=grp_Info[grpId].EndN;i++) {
2855  // start the time from the last time it spiked, that way we can ensure that the refractory period is maintained
2856  unsigned int nextTime = lastSpikeTime[i];
2857  if (nextTime == MAX_SIMULATION_TIME)
2858  nextTime = 0;
2859 
2860  done = false;
2861  while (!done) {
2862 
2863  nextTime = spikeGen->nextSpikeTime(this, grpId, i-grp_Info[grpId].StartN, nextTime);
2864 
2865  // found a valid time window
2866  if (nextTime < (currTime+timeSlice)) {
2867  if (nextTime >= currTime) {
2868  // scheduled spike...
2869  //fprintf(stderr, "scheduled time = %d, nid = %d\n", nextTime, i);
2870  pbuf->scheduleSpikeTargetGroup(i, nextTime-currTime);
2871  spikeCnt++;
2872  }
2873  }
2874  else {
2875  done=true;
2876  }
2877  }
2878  }
2879 }
2880 
2881 void CpuSNN::generateSpikesFromRate(int grpId)
2882 {
2883  bool done;
2884  PoissonRate* rate = grp_Info[grpId].RatePtr;
2885  float refPeriod = grp_Info[grpId].RefractPeriod;
2886  int timeSlice = grp_Info[grpId].CurrTimeSlice;
2887  unsigned int currTime = simTime;
2888  int spikeCnt = 0;
2889 
2890  if (rate == NULL) return;
2891 
2892  if (rate->onGPU) {
2893  printf("specifying rates on the GPU but using the CPU SNN is not supported.\n");
2894  return;
2895  }
2896 
2897  const float* ptr = rate->rates;
2898  for (int cnt=0;cnt<rate->len;cnt++,ptr++) {
2899  float frate = *ptr;
2900 
2901  unsigned int nextTime = lastSpikeTime[grp_Info[grpId].StartN+cnt]; // start the time from the last time it spiked, that way we can ensure that the refractory period is maintained
2902  if (nextTime == MAX_SIMULATION_TIME)
2903  nextTime = 0;
2904 
2905  done = false;
2906  while (!done && frate>0) {
2907  nextTime = poissonSpike (nextTime, frate/1000.0, refPeriod);
2908  // found a valid timeSlice
2909  if (nextTime < (currTime+timeSlice)) {
2910  if (nextTime >= currTime) {
2911  int nid = grp_Info[grpId].StartN+cnt;
2912  pbuf->scheduleSpikeTargetGroup(nid, nextTime-currTime);
2913  spikeCnt++;
2914  }
2915  }
2916  else {
2917  done=true;
2918  }
2919  }
2920  }
2921 }
2922 
2923 void CpuSNN::updateSpikesFromGrp(int grpId)
2924 {
2925  carlsim_assert(grp_Info[grpId].isSpikeGenerator==true);
2926 
2927  bool done;
2928  //static FILE* fp = fopen("spikes.txt", "w");
2929  unsigned int currTime = simTime;
2930 
2931  int timeSlice = grp_Info[grpId].CurrTimeSlice;
2932  grp_Info[grpId].SliceUpdateTime = simTime;
2933 
2934  // we dont generate any poisson spike if during the
2935  // current call we might exceed the maximum 32 bit integer value
2936  if (((uint64_t) currTime + timeSlice) >= MAX_SIMULATION_TIME)
2937  return;
2938 
2939  if (grp_Info[grpId].spikeGen) {
2940  generateSpikesFromFuncPtr(grpId);
2941  } else {
2942  // current mode is GPU, and GPU would take care of poisson generators
2943  // and other information about refractor period etc. So no need to continue further...
2944 #if !TESTING_CPU_GPU_POISSON
2945  if(currentMode == GPU_MODE)
2946  return;
2947 #endif
2948 
2949  generateSpikesFromRate(grpId);
2950  }
2951 }
2952 
2953 inline int CpuSNN::getPoissNeuronPos(int nid)
2954 {
2955  int nPos = nid-numNReg;
2956  carlsim_assert(nid >= numNReg);
2957  carlsim_assert(nid < numN);
2958  carlsim_assert((nid-numNReg) < numNPois);
2959  return nPos;
2960 }
2961 
2962 void CpuSNN::setSpikeRate(int grpId, PoissonRate* ratePtr, int refPeriod, int configId)
2963 {
2964  if (configId == ALL) {
2965  for(int c=0; c < numConfig; c++)
2966  setSpikeRate(grpId, ratePtr, refPeriod,c);
2967  } else {
2968  int cGrpId = getGroupId(grpId, configId);
2969  if(grp_Info[cGrpId].RatePtr==NULL) {
2970  fprintf(fpParam, " // refPeriod = %d\n", refPeriod);
2971  }
2972 
2973  carlsim_assert(ratePtr);
2974  if (ratePtr->len != grp_Info[cGrpId].SizeN) {
2975  fprintf(stderr,"The PoissonRate length did not match the number of neurons in group %s(%d).\n", grp_Info2[cGrpId].Name.c_str(),grpId);
2976  carlsim_assert(0);
2977  }
2978 
2979  assert (grp_Info[cGrpId].isSpikeGenerator);
2980  grp_Info[cGrpId].RatePtr = ratePtr;
2981  grp_Info[cGrpId].RefractPeriod = refPeriod;
2982  spikeRateUpdated = true;
2983 
2984  }
2985 }
2986 
2987 void CpuSNN::setSpikeGenerator(int grpId, SpikeGenerator* spikeGen, int configId)
2988 {
2989  if (configId == ALL) {
2990  for(int c=0; c < numConfig; c++)
2991  setSpikeGenerator(grpId, spikeGen,c);
2992  } else {
2993  int cGrpId = getGroupId(grpId, configId);
2994 
2995  carlsim_assert(spikeGen);
2996 
2997  assert (grp_Info[cGrpId].isSpikeGenerator);
2998  grp_Info[cGrpId].spikeGen = spikeGen;
2999  }
3000 }
3001 
3002 void CpuSNN::generateSpikes()
3003 {
3006 
3007  for( srg_iter = pbuf->beginSpikeTargetGroups(); srg_iter != srg_iter_end; ++srg_iter ) {
3008  // Get the target neurons for the given groupId
3009  int nid = srg_iter->stg;
3010  //delaystep_t del = srg_iter->delay;
3011  //generate a spike to all the target neurons from source neuron nid with a delay of del
3012  int g = findGrpId(nid);
3013 
3014  addSpikeToTable (nid, g);
3015  //fprintf(stderr, "nid = %d\t", nid);
3016  spikeCountAll1sec++;
3017  nPoissonSpikes++;
3018  }
3019 
3020  //fprintf(stderr, "\n");
3021 
3022  // advance the time step to the next phase...
3023  pbuf->nextTimeStep();
3024 
3025 }
3026 
3027 void CpuSNN::setGrpTimeSlice(int grpId, int timeSlice)
3028 {
3029  if (grpId == ALL) {
3030  for(int g=0; (g < numGrp); g++) {
3031  if (grp_Info[g].isSpikeGenerator)
3032  setGrpTimeSlice(g, timeSlice);
3033  }
3034  } else {
3035  carlsim_assert((timeSlice > 0 ) && (timeSlice < PROPAGATED_BUFFER_SIZE));
3036  // the group should be poisson spike generator group
3037  grp_Info[grpId].NewTimeSlice = timeSlice;
3038  grp_Info[grpId].CurrTimeSlice = timeSlice;
3039  }
3040 }
3041 
3042 int CpuSNN::addSpikeToTable(int nid, int g)
3043 {
3044  int spikeBufferFull = 0;
3045  lastSpikeTime[nid] = simTime;
3046  curSpike[nid] = true;
3047  nSpikeCnt[nid]++;
3048  avgFiring[nid] += 1000/(grp_Info[g].avgTimeScale*1000);
3049 
3050  if(showLogMode >= 3)
3051  if (nid<128) printf("spiked: %d\n",nid);
3052 
3053  if (currentMode == GPU_MODE) {
3054  carlsim_assert(grp_Info[g].isSpikeGenerator == true);
3055  setSpikeGenBit_GPU(nid, g);
3056  return 0;
3057  }
3058 
3059  if (grp_Info[g].WithSTP) {
3060  // implements Mongillo, Barak and Tsodyks model of Short term plasticity
3061  int ind = STP_BUF_POS(nid,simTime);
3062  int ind_1 = STP_BUF_POS(nid,(simTime-1)); // MDR -1 is correct, we use the value before the decay has been applied for the current time step.
3063  stpx[ind] = stpx[ind] - stpu[ind_1]*stpx[ind_1];
3064  stpu[ind] = stpu[ind] + grp_Info[g].STP_U*(1-stpu[ind_1]);
3065  }
3066 
3067  if (grp_Info[g].MaxDelay == 1) {
3068  carlsim_assert(nid < numN);
3069  firingTableD1[secD1fireCntHost] = nid;
3070  secD1fireCntHost++;
3071  grp_Info[g].FiringCount1sec++;
3072  if (secD1fireCntHost >= maxSpikesD1) {
3073  spikeBufferFull = 2;
3074  secD1fireCntHost = maxSpikesD1-1;
3075  }
3076  }
3077  else {
3078  carlsim_assert(nid < numN);
3079  firingTableD2[secD2fireCntHost] = nid;
3080  grp_Info[g].FiringCount1sec++;
3081  secD2fireCntHost++;
3082  if (secD2fireCntHost >= maxSpikesD2) {
3083  spikeBufferFull = 1;
3084  secD2fireCntHost = maxSpikesD2-1;
3085  }
3086  }
3087  return spikeBufferFull;
3088 }
3089 
3090 void CpuSNN::findFiring()
3091 {
3092  int spikeBufferFull = 0;
3093 
3094  for(int g=0; (g < numGrp) & !spikeBufferFull; g++) {
3095  // given group of neurons belong to the poisson group....
3096  if (grp_Info[g].Type&POISSON_NEURON)
3097  continue;
3098 
3099  // his flag is set if with_stdp is set and also grpType is set to have GROUP_SYN_FIXED
3100  for(int i=grp_Info[g].StartN; i <= grp_Info[g].EndN; i++) {
3101 
3102  carlsim_assert(i < numNReg);
3103 
3104  if (grp_Info[g].WithConductances) {
3105  gAMPA[i] *= grp_Info[g].dAMPA;
3106  gNMDA[i] *= grp_Info[g].dNMDA;
3107  gGABAa[i] *= grp_Info[g].dGABAa;
3108  gGABAb[i] *= grp_Info[g].dGABAb;
3109  }
3110  else
3111  current[i] = 0.0f; // in CUBA mode, reset current to 0 at each time step and sum up all wts
3112 
3113  if (voltage[i] >= 30.0) {
3114  voltage[i] = Izh_c[i];
3115  recovery[i] += Izh_d[i];
3116 
3117  spikeBufferFull = addSpikeToTable(i, g);
3118 
3119  if (spikeBufferFull) break;
3120 
3121  if (grp_Info[g].WithSTDP) {
3122  unsigned int pos_ij = cumulativePre[i];
3123  for(int j=0; j < Npre_plastic[i]; pos_ij++, j++) {
3124  //stdpChanged[pos_ij] = true;
3125  int stdp_tDiff = (simTime-synSpikeTime[pos_ij]);
3126  carlsim_assert(!((stdp_tDiff < 0) && (synSpikeTime[pos_ij] != MAX_SIMULATION_TIME)));
3127  // don't do LTP if time difference is a lot..
3128 
3129  if (stdp_tDiff > 0)
3130 #ifdef INHIBITORY_STDP
3131  // if this is an excitatory or inhibitory synapse
3132  if (maxSynWt[pos_ij] >= 0)
3133 #endif
3134  if ((stdp_tDiff*grp_Info[g].TAU_LTP_INV)<25)
3135  wtChange[pos_ij] += STDP(stdp_tDiff, grp_Info[g].ALPHA_LTP, grp_Info[g].TAU_LTP_INV);
3136 
3137 #ifdef INHIBITORY_STDP
3138  else
3139  if ((stdp_tDiff > 0) && ((stdp_tDiff*grp_Info[g].TAU_LTD_INV)<25))
3140  wtChange[pos_ij] -= (STDP(stdp_tDiff, grp_Info[g].ALPHA_LTP, grp_Info[g].TAU_LTP_INV) - STDP(stdp_tDiff, grp_Info[g].ALPHA_LTD*1.5, grp_Info[g].TAU_LTD_INV));
3141 #endif
3142  }
3143  }
3144  spikeCountAll1sec++;
3145  }
3146  }
3147  }
3148 }
3149 
3150 void CpuSNN::doSTPUpdates()
3151 {
3152  int spikeBufferFull = 0;
3153 
3154  //decay the STP variables before adding new spikes.
3155  for(int g=0; (g < numGrp) & !spikeBufferFull; g++) {
3156  if (grp_Info[g].WithSTP) {
3157  for(int i=grp_Info[g].StartN; i <= grp_Info[g].EndN; i++) {
3158  int ind = 0, ind_1 = 0;
3159  ind = STP_BUF_POS(i,simTime);
3160  ind_1 = STP_BUF_POS(i,(simTime-1));
3161  stpx[ind] = stpx[ind_1] + (1-stpx[ind_1])/grp_Info[g].STP_tD;
3162  stpu[ind] = stpu[ind_1] + (grp_Info[g].STP_U - stpu[ind_1])/grp_Info[g].STP_tF;
3163  }
3164  }
3165  }
3166 }
3167 
3168 void CpuSNN::doSnnSim()
3169 {
3170  doSTPUpdates();
3171 
3172  //return;
3173 
3174  updateSpikeGenerators();
3175 
3176  //generate all the scheduled spikes from the spikeBuffer..
3177  generateSpikes();
3178 
3179  if(0) fprintf(fpProgLog, "\nLTP time=%d, \n", simTime);
3180 
3181  // find the neurons that has fired..
3182  findFiring();
3183 
3184  timeTableD2[simTimeMs+D+1] = secD2fireCntHost;
3185  timeTableD1[simTimeMs+D+1] = secD1fireCntHost;
3186 
3187  if(0) fprintf(fpProgLog, "\nLTD time=%d,\n", simTime);
3188 
3189  doD2CurrentUpdate();
3190 
3191  doD1CurrentUpdate();
3192 
3193  globalStateUpdate();
3194 
3195  updateMonitors();
3196 
3197  return;
3198 
3199 }
3200 
3201 void CpuSNN::swapConnections(int nid, int oldPos, int newPos)
3202 {
3203  unsigned int cumN=cumulativePost[nid];
3204 
3205  // Put the node oldPos to the top of the delay queue
3206  post_info_t tmp = postSynapticIds[cumN+oldPos];
3207  postSynapticIds[cumN+oldPos]= postSynapticIds[cumN+newPos];
3208  postSynapticIds[cumN+newPos]= tmp;
3209 
3210  // Ensure that you have shifted the delay accordingly....
3211  uint8_t tmp_delay = tmp_SynapticDelay[cumN+oldPos];
3212  tmp_SynapticDelay[cumN+oldPos] = tmp_SynapticDelay[cumN+newPos];
3213  tmp_SynapticDelay[cumN+newPos] = tmp_delay;
3214 
3215  // update the pre-information for the postsynaptic neuron at the position oldPos.
3216  post_info_t postInfo = postSynapticIds[cumN+oldPos];
3217  int post_nid = GET_CONN_NEURON_ID(postInfo);
3218  int post_sid = GET_CONN_SYN_ID(postInfo);
3219 
3220  post_info_t* preId = &preSynapticIds[cumulativePre[post_nid]+post_sid];
3221  int pre_nid = GET_CONN_NEURON_ID((*preId));
3222  int pre_sid = GET_CONN_SYN_ID((*preId));
3223  int pre_gid = GET_CONN_GRP_ID((*preId));
3224  assert (pre_nid == nid);
3225  assert (pre_sid == newPos);
3226  *preId = SET_CONN_ID( pre_nid, oldPos, pre_gid);
3227 
3228  // update the pre-information for the postsynaptic neuron at the position newPos
3229  postInfo = postSynapticIds[cumN+newPos];
3230  post_nid = GET_CONN_NEURON_ID(postInfo);
3231  post_sid = GET_CONN_SYN_ID(postInfo);
3232 
3233  preId = &preSynapticIds[cumulativePre[post_nid]+post_sid];
3234  pre_nid = GET_CONN_NEURON_ID((*preId));
3235  pre_sid = GET_CONN_SYN_ID((*preId));
3236  pre_gid = GET_CONN_GRP_ID((*preId));
3237  assert (pre_nid == nid);
3238  assert (pre_sid == oldPos);
3239  *preId = SET_CONN_ID( pre_nid, newPos, pre_gid);
3240 }
3241 
3242 // The post synaptic connections are sorted based on delay here so that we can reduce storage requirement
3243 // and generation of spike at the post-synaptic side.
3244 // We also create the delay_info array has the delay_start and delay_length parameter
3245 void CpuSNN::reorganizeDelay()
3246 {
3247  for(int grpId=0; grpId < numGrp; grpId++) {
3248  for(int nid=grp_Info[grpId].StartN; nid <= grp_Info[grpId].EndN; nid++) {
3249  unsigned int jPos=0; // this points to the top of the delay queue
3250  unsigned int cumN=cumulativePost[nid]; // cumulativePost[] is unsigned int
3251  unsigned int cumDelayStart=0; // Npost[] is unsigned short
3252  for(int td = 0; td < D; td++) {
3253  unsigned int j=jPos; // start searching from top of the queue until the end
3254  unsigned int cnt=0; // store the number of nodes with a delay of td;
3255  while(j < Npost[nid]) {
3256  // found a node j with delay=td and we put
3257  // the delay value = 1 at array location td=0;
3258  if(td==(tmp_SynapticDelay[cumN+j]-1)) {
3259  carlsim_assert(jPos<Npost[nid]);
3260  swapConnections(nid, j, jPos);
3261 
3262  jPos=jPos+1;
3263  cnt=cnt+1;
3264  }
3265  j=j+1;
3266  }
3267 
3268  // update the delay_length and start values...
3269  postDelayInfo[nid*(D+1)+td].delay_length = cnt;
3270  postDelayInfo[nid*(D+1)+td].delay_index_start = cumDelayStart;
3271  cumDelayStart += cnt;
3272 
3273  carlsim_assert(cumDelayStart <= Npost[nid]);
3274  }
3275 
3276  // total cumulative delay should be equal to number of post-synaptic connections at the end of the loop
3277  carlsim_assert(cumDelayStart == Npost[nid]);
3278  for(unsigned int j=1; j < Npost[nid]; j++) {
3279  unsigned int cumN=cumulativePost[nid]; // cumulativePost[] is unsigned int
3280  if( tmp_SynapticDelay[cumN+j] < tmp_SynapticDelay[cumN+j-1]) {
3281  fprintf(stderr, "Post-synaptic delays not sorted correctly...\n");
3282  fprintf(stderr, "id=%d, delay[%d]=%d, delay[%d]=%d\n",
3283  nid, j, tmp_SynapticDelay[cumN+j], j-1, tmp_SynapticDelay[cumN+j-1]);
3284  carlsim_assert( tmp_SynapticDelay[cumN+j] >= tmp_SynapticDelay[cumN+j-1]);
3285  }
3286  }
3287  }
3288  }
3289 }
3290 
3291 
3292 char* extractFileName(char *fname)
3293 {
3294  char* varname = strrchr(fname, '\\');
3295  size_t len1 = strlen(varname+1);
3296  char* extname = strchr(varname, '.');
3297  size_t len2 = strlen(extname);
3298  varname[len1-len2]='\0';
3299  return (varname+1);
3300 }
3301 
3302 #define COMPACTION_ALIGNMENT_PRE 16
3303 #define COMPACTION_ALIGNMENT_POST 0
3304 
3305 #define SETPOST_INFO(name, nid, sid, val) name[cumulativePost[nid]+sid]=val;
3306 
3307 #define SETPRE_INFO(name, nid, sid, val) name[cumulativePre[nid]+sid]=val;
3308 
3309 
3310 // initialize all the synaptic weights to appropriate values..
3311 // total size of the synaptic connection is 'length' ...
3312 void CpuSNN::initSynapticWeights()
3313 {
3314  // Initialize the network wtChange, wt, synaptic firing time
3315  wtChange = new float[preSynCnt];
3316  synSpikeTime = new uint32_t[preSynCnt];
3317  // memset(synSpikeTime,0,sizeof(uint32_t)*preSynCnt);
3318  cpuSnnSz.synapticInfoSize = sizeof(float)*(preSynCnt*2);
3319 
3320  resetSynapticConnections(false);
3321 }
3322 
3323 // We parallelly cleanup the postSynapticIds array to minimize any other wastage in that array by compacting the store
3324 // Appropriate alignment specified by ALIGN_COMPACTION macro is used to ensure some level of alignment (if necessary)
3325 void CpuSNN::compactConnections()
3326 {
3327  unsigned int* tmp_cumulativePost = new unsigned int[numN];
3328  unsigned int* tmp_cumulativePre = new unsigned int[numN];
3329  unsigned int lastCnt_pre = 0;
3330  unsigned int lastCnt_post = 0;
3331 
3332  tmp_cumulativePost[0] = 0;
3333  tmp_cumulativePre[0] = 0;
3334 
3335  for(int i=1; i < numN; i++) {
3336  lastCnt_post = tmp_cumulativePost[i-1]+Npost[i-1]; //position of last pointer
3337  lastCnt_pre = tmp_cumulativePre[i-1]+Npre[i-1]; //position of last pointer
3338 #if COMPACTION_ALIGNMENT_POST
3339  lastCnt_post= lastCnt_post + COMPACTION_ALIGNMENT_POST-lastCnt_post%COMPACTION_ALIGNMENT_POST;
3340  lastCnt_pre = lastCnt_pre + COMPACTION_ALIGNMENT_PRE- lastCnt_pre%COMPACTION_ALIGNMENT_PRE;
3341 #endif
3342  tmp_cumulativePost[i] = lastCnt_post;
3343  tmp_cumulativePre[i] = lastCnt_pre;
3344  carlsim_assert(tmp_cumulativePost[i] <= cumulativePost[i]);
3345  carlsim_assert(tmp_cumulativePre[i] <= cumulativePre[i]);
3346  }
3347 
3348  // compress the post_synaptic array according to the new values of the tmp_cumulative counts....
3349  unsigned int tmp_postSynCnt = tmp_cumulativePost[numN-1]+Npost[numN-1];
3350  unsigned int tmp_preSynCnt = tmp_cumulativePre[numN-1]+Npre[numN-1];
3351  carlsim_assert(tmp_postSynCnt <= allocatedPost);
3352  carlsim_assert(tmp_preSynCnt <= allocatedPre);
3353  carlsim_assert(tmp_postSynCnt <= postSynCnt);
3354  carlsim_assert(tmp_preSynCnt <= preSynCnt);
3355  fprintf(fpLog, "******************\n");
3356  fprintf(fpLog, "CompactConnection: \n");
3357  fprintf(fpLog, "******************\n");
3358  fprintf(fpLog, "old_postCnt = %d, new_postCnt = %d\n", postSynCnt, tmp_postSynCnt);
3359  fprintf(fpLog, "old_preCnt = %d, new_postCnt = %d\n", preSynCnt, tmp_preSynCnt);
3360 
3361  // new buffer with required size + 100 bytes of additional space just to provide limited overflow
3362  post_info_t* tmp_postSynapticIds = new post_info_t[tmp_postSynCnt+100];
3363 
3364  // new buffer with required size + 100 bytes of additional space just to provide limited overflow
3365  post_info_t* tmp_preSynapticIds = new post_info_t[tmp_preSynCnt+100];
3366  float* tmp_wt = new float[tmp_preSynCnt+100];
3367  float* tmp_maxSynWt = new float[tmp_preSynCnt+100];
3368 
3369  for(int i=0; i < numN; i++) {
3370  carlsim_assert(tmp_cumulativePost[i] <= cumulativePost[i]);
3371  carlsim_assert(tmp_cumulativePre[i] <= cumulativePre[i]);
3372  for( int j=0; j < Npost[i]; j++) {
3373  unsigned int tmpPos = tmp_cumulativePost[i]+j;
3374  unsigned int oldPos = cumulativePost[i]+j;
3375  tmp_postSynapticIds[tmpPos] = postSynapticIds[oldPos];
3376  tmp_SynapticDelay[tmpPos] = tmp_SynapticDelay[oldPos];
3377  }
3378  for( int j=0; j < Npre[i]; j++) {
3379  unsigned int tmpPos = tmp_cumulativePre[i]+j;
3380  unsigned int oldPos = cumulativePre[i]+j;
3381  tmp_preSynapticIds[tmpPos] = preSynapticIds[oldPos];
3382  tmp_maxSynWt[tmpPos] = maxSynWt[oldPos];
3383  tmp_wt[tmpPos] = wt[oldPos];
3384  }
3385  }
3386 
3387  // delete old buffer space
3388  delete[] postSynapticIds;
3389  postSynapticIds = tmp_postSynapticIds;
3390  cpuSnnSz.networkInfoSize -= (sizeof(post_info_t)*postSynCnt);
3391  cpuSnnSz.networkInfoSize += (sizeof(post_info_t)*(tmp_postSynCnt+100));
3392 
3393  delete[] cumulativePost;
3394  cumulativePost = tmp_cumulativePost;
3395 
3396  delete[] cumulativePre;
3397  cumulativePre = tmp_cumulativePre;
3398 
3399  delete[] maxSynWt;
3400  maxSynWt = tmp_maxSynWt;
3401  cpuSnnSz.synapticInfoSize -= (sizeof(float)*preSynCnt);
3402  cpuSnnSz.synapticInfoSize += (sizeof(int)*(tmp_preSynCnt+100));
3403 
3404  delete[] wt;
3405  wt = tmp_wt;
3406  cpuSnnSz.synapticInfoSize -= (sizeof(float)*preSynCnt);
3407  cpuSnnSz.synapticInfoSize += (sizeof(int)*(tmp_preSynCnt+100));
3408 
3409  delete[] preSynapticIds;
3410  preSynapticIds = tmp_preSynapticIds;
3411  cpuSnnSz.synapticInfoSize -= (sizeof(post_info_t)*preSynCnt);
3412  cpuSnnSz.synapticInfoSize += (sizeof(post_info_t)*(tmp_preSynCnt+100));
3413 
3414  preSynCnt = tmp_preSynCnt;
3415  postSynCnt = tmp_postSynCnt;
3416 }
3417 
3418 void CpuSNN::updateParameters(int* curN, int* numPostSynapses, int* numPreSynapses, int nConfig)
3419 {
3420  carlsim_assert(nConfig > 0);
3421  numNExcPois = 0; numNInhPois = 0; numNExcReg = 0; numNInhReg = 0;
3422  *numPostSynapses = 0; *numPreSynapses = 0;
3423 
3424  // scan all the groups and find the required information
3425  // about the group (numN, numPostSynapses, numPreSynapses and others).
3426  for(int g=0; g < numGrp; g++) {
3427  if (grp_Info[g].Type==UNKNOWN_NEURON) {
3428  std::ostringstream stringStream;
3429  stringStream << "Unknown group for " << g << "(" << grp_Info2[g].Name << ")\n";
3430  exitSimulation(1, stringStream.str().c_str());
3431  }
3432 
3433  if (IS_INHIBITORY_TYPE(grp_Info[g].Type) && !(grp_Info[g].Type&POISSON_NEURON))
3434  numNInhReg += grp_Info[g].SizeN;
3435  else if (IS_EXCITATORY_TYPE(grp_Info[g].Type) && !(grp_Info[g].Type&POISSON_NEURON))
3436  numNExcReg += grp_Info[g].SizeN;
3437  else if (IS_EXCITATORY_TYPE(grp_Info[g].Type) && (grp_Info[g].Type&POISSON_NEURON))
3438  numNExcPois += grp_Info[g].SizeN;
3439  else if (IS_INHIBITORY_TYPE(grp_Info[g].Type) && (grp_Info[g].Type&POISSON_NEURON))
3440  numNInhPois += grp_Info[g].SizeN;
3441 
3442  // find the values for maximum postsynaptic length
3443  // and maximum pre-synaptic length
3444  if (grp_Info[g].numPostSynapses >= *numPostSynapses)
3445  *numPostSynapses = grp_Info[g].numPostSynapses;
3446  if (grp_Info[g].numPreSynapses >= *numPreSynapses)
3447  *numPreSynapses = grp_Info[g].numPreSynapses;
3448  }
3449 
3450  *curN = numNExcReg + numNInhReg + numNExcPois + numNInhPois;
3451  numNPois = numNExcPois + numNInhPois;
3452  numNReg = numNExcReg +numNInhReg;
3453 }
3454 
3455 //Reset wt, wtChange, pre-firing time values to default values, rewritten to
3456 //integrate changes between JMN and MDR -- KDC
3457 //if changeWeights is false, we should keep the values of the weights as they currently
3458 //are but we should be able to change them to plastic or fixed synapses. -- KDC
3459 void CpuSNN::resetSynapticConnections(bool changeWeights)
3460 {
3461  int j;
3462  // Reset wt,wtChange,pre-firingtime values to default values...
3463  for(int destGrp=0; destGrp < numGrp; destGrp++) {
3464  const char* updateStr = (grp_Info[destGrp].newUpdates == true)?"(**)":"";
3465  fprintf(stdout, "Grp: %d:%s s=%d e=%d %s\n", destGrp, grp_Info2[destGrp].Name.c_str(), grp_Info[destGrp].StartN, grp_Info[destGrp].EndN, updateStr);
3466  fprintf(fpLog, "Grp: %d:%s s=%d e=%d %s\n", destGrp, grp_Info2[destGrp].Name.c_str(), grp_Info[destGrp].StartN, grp_Info[destGrp].EndN, updateStr);
3467 
3468  for(int nid=grp_Info[destGrp].StartN; nid <= grp_Info[destGrp].EndN; nid++) {
3469  unsigned int offset = cumulativePre[nid];
3470  for (j=0;j<Npre[nid]; j++) wtChange[offset+j] = 0.0; // synaptic derivatives is reset
3471  for (j=0;j<Npre[nid]; j++) synSpikeTime[offset+j] = MAX_SIMULATION_TIME; // some large negative value..
3472  post_info_t *preIdPtr = &preSynapticIds[cumulativePre[nid]];
3473  float* synWtPtr = &wt[cumulativePre[nid]];
3474  float* maxWtPtr = &maxSynWt[cumulativePre[nid]];
3475  int prevPreGrp = -1;
3476 
3477 
3478  for (j=0; j < Npre[nid]; j++,preIdPtr++, synWtPtr++, maxWtPtr++) {
3479  int preId = GET_CONN_NEURON_ID((*preIdPtr));
3480  carlsim_assert(preId < numN);
3481  int srcGrp = findGrpId(preId);
3482  grpConnectInfo_t* connInfo;
3483  grpConnectInfo_t* connIterator = connectBegin;
3484  while(connIterator){
3485  if(connIterator->grpSrc == srcGrp && connIterator->grpDest == destGrp){
3486  //we found the corresponding connection
3487  connInfo=connIterator;
3488  break;
3489  }
3490  //move to the next grpConnectInfo_t
3491  connIterator=connIterator->next;
3492  }
3493  carlsim_assert(connInfo != NULL);
3494  int connProp = connInfo->connProp;
3495  bool synWtType = GET_FIXED_PLASTIC(connProp);
3496  // print debug information...
3497  if( prevPreGrp != srcGrp) {
3498  if(nid==grp_Info[destGrp].StartN) {
3499  const char* updateStr = (connInfo->newUpdates==true)? "(**)":"";
3500  fprintf(stdout, "\t%d (%s) start=%d, type=%s maxWts = %f %s\n", srcGrp,
3501  grp_Info2[srcGrp].Name.c_str(), j, (j<Npre_plastic[nid]?"P":"F"), connInfo->maxWt, updateStr);
3502  fprintf(fpLog, "\t%d (%s) start=%d, type=%s maxWts = %f %s\n", srcGrp,
3503  grp_Info2[srcGrp].Name.c_str(), j, (j<Npre_plastic[nid]?"P":"F"), connInfo->maxWt, updateStr);
3504  }
3505  prevPreGrp = srcGrp;
3506  }
3507 
3508  if(!changeWeights)
3509  continue;
3510 
3511  // if connection was of plastic type or if the connection weights were updated we need to reset the weights..
3512  // TODO: How to account for user-defined connection reset...
3513  if ((synWtType == SYN_PLASTIC) || connInfo->newUpdates) {
3514  *synWtPtr = getWeights(connInfo->connProp, connInfo->initWt, connInfo->maxWt, nid, srcGrp);
3515  *maxWtPtr = connInfo->maxWt;
3516  }
3517  }
3518 
3519  }
3520  grp_Info[destGrp].newUpdates = false;
3521  }
3522 
3523  grpConnectInfo_t* connInfo = connectBegin;
3524  // clear all existing connection info...
3525  while (connInfo) {
3526  connInfo->newUpdates = false;
3527  connInfo = connInfo->next;
3528  }
3529 }
3530 
3531 void CpuSNN::resetGroups()
3532 {
3533  for(int g=0; (g < numGrp); g++) {
3534  // reset spike generator group...
3535  if (grp_Info[g].isSpikeGenerator) {
3536  grp_Info[g].CurrTimeSlice = grp_Info[g].NewTimeSlice;
3537  grp_Info[g].SliceUpdateTime = 0;
3538  for(int nid=grp_Info[g].StartN; nid <= grp_Info[g].EndN; nid++)
3539  resetPoissonNeuron(nid, g);
3540  }
3541  // reset regular neuron group...
3542  else {
3543  for(int nid=grp_Info[g].StartN; nid <= grp_Info[g].EndN; nid++)
3544  resetNeuron(nid, g);
3545  }
3546  }
3547 
3548  // reset the currents for each neuron
3549  resetCurrent();
3550 
3551  // reset the conductances...
3552  resetConductances();
3553 
3554  // reset various counters in the group...
3555  resetCounters();
3556 }
3557 
3558 void CpuSNN::resetFiringInformation()
3559 {
3560  // Reset firing tables and time tables to default values..
3561 
3562  // reset Various Times..
3563  spikeCountAll = 0;
3564  spikeCountAll1sec = 0;
3565  spikeCountD2Host = 0;
3566  spikeCountD1Host = 0;
3567 
3568  secD1fireCntHost = 0;
3569  secD2fireCntHost = 0;
3570 
3571  for(int i=0; i < numGrp; i++) {
3572  grp_Info[i].FiringCount1sec = 0;
3573  }
3574 
3575  // reset various times...
3576  simTimeMs = 0;
3577  simTimeSec = 0;
3578  simTime = 0;
3579 
3580  // reset the propogation Buffer.
3581  resetPropogationBuffer();
3582 
3583  // reset Timing Table..
3584  resetTimingTable();
3585 }
3586 
3587 // function used for parameter tuning interface
3589 {
3590  if(!doneReorganization)
3591  return;
3592 
3593  // change weights back to the default level for all the connections...
3594  resetSynapticConnections(true);
3595 
3596  // Reset v,u,firing time values to default values...
3597  resetGroups();
3598 
3599  // reset all firing information..
3600  resetFiringInformation();
3601 
3602  printTuningLog();
3603 }
3604 
3605 // function used for parameter tuning interface
3606 void CpuSNN::updateNetwork(bool resetFiringInfo, bool resetWeights)
3607 {
3608  if(!doneReorganization){
3609  fprintf(stderr,"UpdateNetwork function was called but nothing was done because reorganizeNetwork must be called first.\n");
3610  return;
3611  }
3612  //change weights back to the default level for all the connections...
3613  if(resetWeights)
3614  resetSynapticConnections(true);
3615  else
3616  resetSynapticConnections(false);
3617 
3618  // Reset v,u,firing time values to default values...
3619  resetGroups();
3620 
3621  if(resetFiringInfo)
3622  resetFiringInformation();
3623 
3624  if(currentMode==GPU_MODE){
3625  //copyGrpInfo_GPU();
3626  //do a call to updateNetwork_GPU()
3627  updateNetwork_GPU(resetFiringInfo);
3628  }
3629 
3630  printTuningLog();
3631 }
3632 
3633 void CpuSNN::printTuningLog()
3634 {
3635  if (fpTuningLog) {
3636  fprintf(fpTuningLog, "Generating Tuning log %d\n", cntTuning);
3637  printParameters(fpTuningLog);
3638  cntTuning++;
3639  }
3640 }
3641 
3642 // after all the initalization. Its time to create the synaptic weights, weight change and also
3643 // time of firing these are the mostly costly arrays so dense packing is essential to minimize wastage of space
3644 void CpuSNN::reorganizeNetwork(bool removeTempMemory, int simType)
3645 {
3646  //Double check...sometimes by mistake we might call reorganize network again...
3647  if(doneReorganization)
3648  return;
3649 
3650  fprintf(stdout, "Beginning reorganization of network....\n");
3651 
3652  // time to build the complete network with relevant parameters..
3653  buildNetwork();
3654 
3655  //..minimize any other wastage in that array by compacting the store
3656  compactConnections();
3657 
3658  // The post synaptic connections are sorted based on delay here
3659  reorganizeDelay();
3660 
3661  // Print statistics of the memory used to stdout...
3662  printMemoryInfo();
3663 
3664  // Print the statistics again but dump the results to a file
3665  printMemoryInfo(fpLog);
3666 
3667  // initialize the synaptic weights accordingly..
3668  initSynapticWeights();
3669 
3670  //not of much use currently
3671  // updateRandomProperty();
3672 
3673  updateSpikeGeneratorsInit();
3674 
3675  //ensure that we dont do all the above optimizations again
3676  doneReorganization = true;
3677 
3678  //printParameters(fpParam);
3679  printParameters(fpLog);
3680 
3681  printTuningLog();
3682 
3683  makePtrInfo();
3684 
3685  // if our initial operating mode is GPU_MODE, then it is time to
3686  // allocate necessary data within the GPU
3687 
3688  // carlsim_assert(simType != GPU_MODE || cpu_gpuNetPtrs.allocated);
3689  // if(netInitMode==GPU_MODE)
3690  // allocateSNN_GPU();
3691 
3692  if(simType==GPU_MODE)
3693  fprintf(stdout, "Starting GPU-SNN Simulations ....\n");
3694  else
3695  fprintf(stdout, "Starting CPU-SNN Simulations ....\n");
3696 
3697  FILE* fconn = NULL;
3698 
3699 #if TESTING
3700  if (simType == GPU_MODE)
3701  fconn = fopen("gpu_conn.txt", "w");
3702  else
3703  fconn = fopen("conn.txt", "w");
3704  //printCheckDetailedInfo(fconn);
3705 #endif
3706 
3707 #if 0
3708  printPostConnection(fconn);
3709  printPreConnection(fconn);
3710 #endif
3711 
3712  //printNetworkInfo();
3713 
3714  printDotty();
3715 
3716 #if TESTING
3717  fclose(fconn);
3718 #endif
3719 
3720  if(removeTempMemory) {
3721  memoryOptimized = true;
3722  delete[] tmp_SynapticDelay;
3723  tmp_SynapticDelay = NULL;
3724  }
3725 }
3726 
3727 void CpuSNN::setDefaultParameters(float alpha_ltp, float tau_ltp, float alpha_ltd, float tau_ltd)
3728 {
3729  printf("Warning: setDefaultParameters() is deprecated and may be removed in the future.\nIt is recommended that you set the desired parameters explicitly.\n");
3730 #define DEFAULT_COND_tAMPA 5.0
3731 #define DEFAULT_COND_tNMDA 150.0
3732 #define DEFAULT_COND_tGABAa 6.0
3733 #define DEFAULT_COND_tGABAb 150.0
3734 
3735 #define DEFAULT_STP_U_Inh 0.5
3736 #define DEFAULT_STP_tD_Inh 800
3737 #define DEFAULT_STP_tF_Inh 1000
3738 #define DEFAULT_STP_U_Exc 0.2
3739 #define DEFAULT_STP_tD_Exc 700
3740 #define DEFAULT_STP_tF_Exc 20
3741 #define DEFAULT_HOMEO_SCALE 0.1
3742 #define DEFAULT_AVG_TIME_SCALE 10
3743 
3744  // setup the conductance parameter for the given network
3745  setConductances(ALL, true, DEFAULT_COND_tAMPA, DEFAULT_COND_tNMDA, DEFAULT_COND_tGABAa, DEFAULT_COND_tGABAb);
3746 
3747  // setting the STP values for different groups...
3748  for(int g=0; g < getNumGroups(); g++) {
3749 
3750  // default STDP is set to false for all groups..
3751  setSTDP(g, false);
3752 
3753  if(!isPoissonGroup(g))
3754  setHomeostasis(g, true, DEFAULT_HOMEO_SCALE, DEFAULT_AVG_TIME_SCALE);
3755  else
3756  setHomeostasis(g, false, DEFAULT_HOMEO_SCALE, DEFAULT_AVG_TIME_SCALE);
3757  // setup the excitatory group properties here..
3758  if(isExcitatoryGroup(g)) {
3759  setSTP(g, true, DEFAULT_STP_U_Exc, DEFAULT_STP_tD_Exc, DEFAULT_STP_tF_Exc);
3760  if ((alpha_ltp!=0.0) && (!isPoissonGroup(g)))
3761  setSTDP(g, true, alpha_ltp, tau_ltp, alpha_ltd, tau_ltd);
3762  }
3763  else {
3764  setSTP(g, true, DEFAULT_STP_U_Inh, DEFAULT_STP_tD_Inh, DEFAULT_STP_tF_Inh);
3765  }
3766  }
3767 }
3768 
3769 #if ! (_WIN32 || _WIN64)
3770 #include <string.h>
3771 #define strcmpi(s1,s2) strcasecmp(s1,s2)
3772 #endif
3773 
3774 #define PROBE_CURRENT (1 << 1)
3775 #define PROBE_VOLTAGE (1 << 2)
3776 #define PROBE_FIRING_RATE (1 << 3)
3777 
3778 void CpuSNN::setProbe(int g, const string& type, int startId, int cnt, uint32_t _printProbe)
3779 {
3780  int endId;
3781  carlsim_assert(startId >= 0);
3782  carlsim_assert(startId <= grp_Info[g].SizeN);
3783  //carlsim_assert(cnt!=0);
3784 
3785  int i=grp_Info[g].StartN+startId;
3786  if (cnt<=0)
3787  endId = grp_Info[g].EndN;
3788  else
3789  endId = i + cnt - 1;
3790 
3791  if(endId > grp_Info[g].EndN)
3792  endId = grp_Info[g].EndN;
3793 
3794  for(; i <= endId; i++) {
3795 
3796  probeParam_t* n = new probeParam_t;
3797  memset(n, 0, sizeof(probeParam_t));
3798  n->next = neuronProbe;
3799 
3800  if(type.find("current") != string::npos) {
3801  n->type |= PROBE_CURRENT;
3802  n->bufferI = new float[CARLSIM_STEP_SIZE];
3803  cpuSnnSz.probeInfoSize += sizeof(float)*CARLSIM_STEP_SIZE;
3804  }
3805 
3806  if(type.find("voltage") != string::npos) {
3807  n->type |= PROBE_VOLTAGE;
3808  n->bufferV = new float[CARLSIM_STEP_SIZE];
3809  cpuSnnSz.probeInfoSize += sizeof(float)*CARLSIM_STEP_SIZE;
3810  }
3811 
3812  if(type.find("firing-rate") != string::npos) {
3813  n->type |= PROBE_FIRING_RATE;
3814  n->spikeBins = new bool[CARLSIM_STEP_SIZE];
3815  n->bufferFRate = new float[CARLSIM_STEP_SIZE];
3816  cpuSnnSz.probeInfoSize += (sizeof(float)+sizeof(bool))*CARLSIM_STEP_SIZE;
3817  n->cumCount = 0;
3818  }
3819 
3820  n->vmax = 40.0; n->vmin = -80.0;
3821  n->imax = 50.0; n->imin = -50.0;
3822  n->debugCnt = 0;
3823  n->printProbe = _printProbe;
3824  n->nid = i;
3825  neuronProbe = n;
3826  numProbe++;
3827  }
3828 }
3829 
3830 void CpuSNN::updateMonitors()
3831 {
3832  int cnt=0;
3833  probeParam_t* n = neuronProbe;
3834 
3835  while(n) {
3836  int nid = n->nid;
3837  if(n->printProbe) {
3838 
3839  // if there is an input inhspike or excSpike or curSpike then display values..
3840  //if( I[nid] != 0 ) {
3841 
3842  /* FIXME
3843  MDR I broke this because I removed inhSpikes and excSpikes because they are incorrectly named...
3844 
3845  if (inhSpikes[nid] || excSpikes[nid] || curSpike[nid] || (n->debugCnt++ > n->printProbe)) {
3846  fprintf(stderr, "[t=%d, n=%d] voltage=%3.3f current=%3.3f ", simTime, nid, voltage[nid], current[nid]);
3847  //FIXME should check to see if conductances are enabled for this group
3848  if (true) {
3849  fprintf(stderr, " ampa=%3.4f nmda=%3.4f gabaA=%3.4f gabaB=%3.4f ",
3850  gAMPA[nid], gNMDA[nid], gGABAa[nid], gGABAb[nid]);
3851  }
3852 
3853  fprintf(stderr, " +Spike=%d ", excSpikes[nid]);
3854 
3855  if (inhSpikes[nid])
3856  fprintf(stderr, " -Spike=%d ", inhSpikes[nid]);
3857 
3858  if (curSpike[nid])
3859  fprintf(stderr, " | ");
3860 
3861  fprintf(stderr, "\n");
3862 
3863  if(n->debugCnt > n->printProbe) {
3864  n->debugCnt = 0;
3865  }
3866  }
3867  */
3868  }
3869 
3870  if (n->type & PROBE_CURRENT)
3871  n->bufferI[simTimeMs] = current[nid];
3872 
3873  if (n->type & PROBE_VOLTAGE)
3874  n->bufferV[simTimeMs] = voltage[nid];
3875 
3876 #define NUM_BIN 256
3877 #define BIN_SIZE 0.001 /* 1ms bin size */
3878 
3879  if (n->type & PROBE_FIRING_RATE) {
3880  int oldSpike = 0;
3881  if (simTime >= NUM_BIN)
3882  oldSpike = n->spikeBins[simTimeMs%NUM_BIN];
3883  int newSpike = (voltage[nid] >= 30.0 ) ? 1 : 0;
3884  n->cumCount = n->cumCount - oldSpike + newSpike;
3885  float frate = n->cumCount/(NUM_BIN*BIN_SIZE);
3886  n->spikeBins[simTimeMs % NUM_BIN] = newSpike;
3887  if (simTime >= NUM_BIN)
3888  n->bufferFRate[(simTime-NUM_BIN)%CARLSIM_STEP_SIZE] = frate;
3889  }
3890 
3891  n=n->next;
3892  cnt++;
3893  }
3894 
3895  //fclose(fp);
3896  // ensure that we checked all the nodes in the list
3897  carlsim_assert(cnt==numProbe);
3898 }
3899 
3901 public:
3902  WriteSpikeToFile(FILE* _fid) {
3903  fid = _fid;
3904  }
3905 
3906  void update(CpuSNN* s, int grpId, unsigned int* Nids, unsigned int* timeCnts, unsigned int total_spikes, float firing_Rate)
3907  {
3908  int pos = 0;
3909 
3910  for (int t=0; t < CARLSIM_STEP_SIZE; t++) {
3911  for(int i=0; i<timeCnts[t];i++,pos++) {
3912  int time = t + s->getSimTime() - CARLSIM_STEP_SIZE;
3913  int id = Nids[pos];
3914  int cnt = fwrite(&time,sizeof(int),1,fid);
3915  carlsim_assert(cnt != 0);
3916  cnt = fwrite(&id,sizeof(int),1,fid);
3917  carlsim_assert(cnt != 0);
3918  }
3919  }
3920 
3921  fflush(fid);
3922  }
3923 
3924  FILE* fid;
3925 };
3926 
3927 void CpuSNN::setSpikeMonitor(int gid, const string& fname, int configId) {
3928  FILE* fid = fopen(fname.c_str(),"wb");
3929  if (fid==NULL) {
3930  // file could not be opened
3931 
3932 #if defined(CREATE_SPIKEDIR_IF_NOT_EXISTS)
3933  // if option set, attempt to create directory
3934  int status;
3935 
3936  // this is annoying...for dirname we need to convert from const string to char*
3937  char fchar[200];
3938  strcpy(fchar,fname.c_str());
3939 
3940 #if defined(_WIN32) || defined(_WIN64) // TODO: test it
3941  status = _mkdir(fname.c_str()); // Windows platform
3942 #else
3943  status = mkdir(dirname(fchar), 0777); // Unix
3944 #endif
3945  if (status==-1 && errno!=EEXIST) {
3946  fprintf(stderr,"ERROR %d: could not create spike file '%s', directory '%%CARLSIM_ROOT%%/results/' does not exist\n",errno,fname.c_str());
3947 #ifdef USE_EXCEPTIONS
3948  std::ostringstream stringStream;
3949  stringStream << "ERROR " << errno << ": could not create spike file '" << fname << "', directory '%%CARLSIM_ROOT%%/results/' does not exist\n";
3950  throw std::runtime_error(stringStream.str().c_str());
3951 #else
3952  exit(1);
3953 #endif
3954  return;
3955  }
3956 
3957  // now that the directory is created, fopen file
3958  fid = fopen(fname.c_str(),"wb");
3959 #else
3960  // default case: print error and exit
3961  fprintf(stderr,"ERROR: File \"%s\" could not be opened, please check if it exists.\n",fname.c_str());
3962  fprintf(stderr," Enable option CREATE_SPIKEDIR_IF_NOT_EXISTS in config.h to attempt creating the "
3963  "specified subdirectory automatically.\n");
3964 
3965 #ifdef USE_EXCEPTIONS
3966  std::ostringstream stringStream;
3967  stringStream << "ERROR " << errno << " File \"" << fname << "\" could not be opened, please check if it exists.\n Enable option CREATE_SPIKEDIR_IF_NOT_EXISTS in config.h to attempt creating thespecified subdirectory automatically.\n";
3968  throw std::runtime_error(stringStream.str().c_str());
3969 #else
3970  exit(1);
3971 #endif
3972  return;
3973 #endif
3974  }
3975 
3976  carlsim_assert(configId != ALL);
3977 
3978  setSpikeMonitor(gid, new WriteSpikeToFile(fid), configId);
3979  }
3980 
3981 void CpuSNN::setSpikeMonitor(int grpId, SpikeMonitor* spikeMon, int configId)
3982 {
3983  if (configId == ALL) {
3984  for(int c=0; c < numConfig; c++)
3985  setSpikeMonitor(grpId, spikeMon,c);
3986  } else {
3987  int cGrpId = getGroupId(grpId, configId);
3988  DBG(2, fpLog, AT, "spikeMonitor Added");
3989 
3990  // store the gid for further reference
3991  monGrpId[numSpikeMonitor] = cGrpId;
3992 
3993  // also inform the grp that it is being monitored...
3994  grp_Info[cGrpId].MonitorId = numSpikeMonitor;
3995 
3996  float maxRate = grp_Info[cGrpId].MaxFiringRate;
3997 
3998  // count the size of the buffer for storing 1 sec worth of info..
3999  // only the last second is stored in this buffer...
4000  int buffSize = (int)(maxRate*grp_Info[cGrpId].SizeN);
4001 
4002  // store the size for future comparison etc.
4003  monBufferSize[numSpikeMonitor] = buffSize;
4004 
4005  // reset the position of the buffer pointer..
4006  monBufferPos[numSpikeMonitor] = 0;
4007 
4008  monBufferCallback[numSpikeMonitor] = spikeMon;
4009 
4010  // create the new buffer for keeping track of all the spikes in the system
4011  monBufferFiring[numSpikeMonitor] = new unsigned int[buffSize];
4012  monBufferTimeCnt[numSpikeMonitor]= new unsigned int[CARLSIM_STEP_SIZE];
4013  memset(monBufferTimeCnt[numSpikeMonitor],0,sizeof(int)*(CARLSIM_STEP_SIZE));
4014 
4015  numSpikeMonitor++;
4016 
4017  // oh. finally update the size info that will be useful to see
4018  // how much memory are we eating...
4019  cpuSnnSz.monitorInfoSize += sizeof(int)*buffSize;
4020  cpuSnnSz.monitorInfoSize += sizeof(int)*(CARLSIM_STEP_SIZE);
4021  }
4022 }
4023 
4024 void CpuSNN::updateSpikeMonitor()
4025 {
4026  // don't continue if numSpikeMonitor is zero
4027  if(numSpikeMonitor==0)
4028  return;
4029 
4030  bool bufferOverFlow[MAX_GRP_PER_SNN];
4031  memset(bufferOverFlow,0,sizeof(bufferOverFlow));
4032 
4033  /* Reset buffer time counter */
4034  for(int i=0; i < numSpikeMonitor; i++)
4035  memset(monBufferTimeCnt[i],0,sizeof(int)*(CARLSIM_STEP_SIZE));
4036 
4037  /* Reset buffer position */
4038  memset(monBufferPos,0,sizeof(int)*numSpikeMonitor);
4039 
4040  if(currentMode == GPU_MODE) {
4041  updateSpikeMonitor_GPU();
4042  }
4043 
4044  /* Read one spike at a time from the buffer and
4045  put the spikes to an appopriate monitor buffer.
4046  Later the user may need need to dump these spikes
4047  to an output file */
4048  for(int k=0; k < 2; k++) {
4049  unsigned int* timeTablePtr = (k==0)?timeTableD2:timeTableD1;
4050  unsigned int* fireTablePtr = (k==0)?firingTableD2:firingTableD1;
4051  for(int t=0; t < CARLSIM_STEP_SIZE; t++) {
4052  for(int i=timeTablePtr[t+D]; i<timeTablePtr[t+D+1];i++) {
4053  /* retrieve the neuron id */
4054  int nid = fireTablePtr[i];
4055  if (currentMode == GPU_MODE)
4056  nid = GET_FIRING_TABLE_NID(nid);
4057  //fprintf(fpLog, "%d %d \n", t, nid);
4058  carlsim_assert(nid < numN);
4059 
4060  int grpId = findGrpId(nid);
4061  int monitorId = grp_Info[grpId].MonitorId;
4062  if(monitorId!= -1) {
4063  carlsim_assert(nid >= grp_Info[grpId].StartN);
4064  carlsim_assert(nid <= grp_Info[grpId].EndN);
4065  int pos = monBufferPos[monitorId];
4066  if((pos >= monBufferSize[monitorId]))
4067  {
4068  if(!bufferOverFlow[monitorId])
4069  fprintf(stderr, "Buffer Monitor size (%d) is small. Increase buffer firing rate for %s\n", monBufferSize[monitorId], grp_Info2[grpId].Name.c_str());
4070  bufferOverFlow[monitorId] = true;
4071  }
4072  else {
4073  monBufferPos[monitorId]++;
4074  monBufferFiring[monitorId][pos] = nid-grp_Info[grpId].StartN; // store the Neuron ID relative to the start of the group
4075  // we store the total firing at time t...
4076  monBufferTimeCnt[monitorId][t]++;
4077  }
4078  } /* if monitoring is enabled for this spike */
4079  } /* for all spikes happening at time t */
4080  } /* for all time t */
4081  }
4082 
4083  for (int grpId=0;grpId<numGrp;grpId++) {
4084  int monitorId = grp_Info[grpId].MonitorId;
4085  if(monitorId!= -1) {
4086  unsigned int total_spikes = monBufferPos[monitorId];
4087  float firing_rate = (((float)monBufferPos[monitorId])/(grp_Info[grpId].SizeN)/((float) (CARLSIM_STEP_SIZE*CARLSIM_STEP_INCREMENT)));
4088  fprintf(stderr, "Spike Monitor for Group %s has %d spikes (%f Hz)\n",grp_Info2[grpId].Name.c_str(),total_spikes,firing_rate);
4089 
4090  // call the callback function
4091  if (monBufferCallback[monitorId])
4092  monBufferCallback[monitorId]->update(this,grpId,monBufferFiring[monitorId],monBufferTimeCnt[monitorId], total_spikes, firing_rate);
4093  }
4094  }
4095 }
4096 
4097 // reassigns weights from the input weightMatrix to the weights between two
4098 // specified neuron groups.
4099 void CpuSNN::reassignFixedWeights(int connectId, float weightMatrix[], int sizeMatrix, int configId)
4100 {
4101  // handle the config == ALL recursive call contigency.
4102  if (configId == ALL) {
4103  for(int c=0; c < numConfig; c++)
4104  reassignFixedWeights(connectId, weightMatrix, sizeMatrix, c);
4105  } else {
4106  int j;
4107  //first find the correct connection
4108  grpConnectInfo_t* connInfo; //connInfo = current connection information.
4109  connInfo = getConnectInfo(connectId,configId);
4110  //make sure that it is for fixed connections.
4111  bool synWtType = GET_FIXED_PLASTIC(connInfo->connProp);
4112  if(synWtType == SYN_PLASTIC){
4113  printf("The synapses in this connection must be SYN_FIXED in order to use this function.\n");
4114  carlsim_assert(false);
4115  }
4116  //make sure that the user passes the correctly sized matrix
4117  if(connInfo->numberOfConnections != sizeMatrix){
4118  printf("The size of the input weight matrix and the number of synaptic connections in this connection do not match.\n");
4119  carlsim_assert(false);
4120  }
4121  //We have to iterate over all the presynaptic connections of each postsynaptic neuron
4122  //and see if they are part of our srcGrp. If they are,
4123  int destGrp = connInfo->grpDest;
4124  int srcGrp = connInfo->grpSrc;
4125  //iterate over all neurons in the destination group.
4126  for(int postId=grp_Info[destGrp].StartN; postId <= grp_Info[destGrp].EndN; postId++) {
4127  int offset = cumulativePre[postId];
4128  float* synWtPtr = &wt[cumulativePre[postId]];
4129  post_info_t *preIdPtr = &preSynapticIds[offset];
4130  //iterate over all presynaptic connections in current postsynaptic neuron.
4131  for (j=0; j < Npre[postId]; j++,preIdPtr++, synWtPtr++) {
4132  int preId = GET_CONN_NEURON_ID((*preIdPtr));
4133  carlsim_assert(preId < numN);
4134  int currentSrcId = findGrpId(preId);
4135  //if the neuron is part of the source group, assign it a value
4136  //from the reassignment matrix.
4137  if(currentSrcId == srcGrp){
4138  //assign wt to reassignment matrix value
4139  *synWtPtr = (*weightMatrix);
4140  //iterate reassignment matrix
4141  weightMatrix++;
4142  }
4143  }
4144  }
4145  }
4146  //after all configurations and weights have been set, copy them back to the GPU if
4147  //necessary:
4148  if(currentMode == GPU_MODE)
4150 }
4151 
4152 // returns the number of synaptic connections associated with this connection.
4153 int CpuSNN::getNumConnections(int connectionId)
4154 {
4155  grpConnectInfo_t* connInfo;
4156  grpConnectInfo_t* connIterator = connectBegin;
4157  while(connIterator){
4158  if(connIterator->connId == connectionId){
4159  //found the corresponding connection
4160  return connIterator->numberOfConnections;
4161  }
4162  //move to the next grpConnectInfo_t
4163  connIterator=connIterator->next;
4164  }
4165  //we didn't find the connection.
4166  printf("Connection ID was not found. Quitting.\n");
4167  carlsim_assert(false);
4168 }
4169 
4170 
unsigned int * delay_opts
first 8 bits are delay, higher are for Fixed/Plastic and any other future options ...
Definition: snn.h:609
static const unsigned int MAJOR_VERSION
major release version, as in CARLsim X
Definition: snn.h:623
void nextTimeStep()
Must be called to tell the buffer that it should move on to the next time step.
virtual void update(CpuSNN *s, int grpId, unsigned int *Nids, unsigned int *timeCnts, unsigned int total_spikes, float firing_Rate)
Controls actions that are performed when certain neurons fire (user-defined).
Definition: snn.h:271
int createGroup(const string &_name, unsigned int _numN, int _nType, int configId=ALL)
creates a group of Izhikevich spiking neurons
Definition: snn_cpu.cpp:787
float dGABAb
homeostatic plasticity variables
Definition: snn.h:466
int getNumConnections(int connectionId)
Input: connectionID. Output: the number of connections associated with that connection ID...
Definition: snn_cpu.cpp:4153
int connect(int gIDpre, int gIDpost, const string &_type, float initWt, float maxWt, float _C, uint8_t minDelay, uint8_t maxDelay, bool synWtType=SYN_FIXED, const string &wtType=" ")
make from each neuron in grpId1 to 'numPostSynapses' neurons in grpId2
Definition: snn_cpu.cpp:1600
void reset(int minDelay, int maxDelay)
Must be called at the begin (reset) of a simulation.
void setSpikeMonitor(int gid, SpikeMonitor *spikeMon=NULL, int configId=ALL)
Definition: snn_cpu.cpp:3981
float * wt
stores the synaptic weight and weight change of a synaptic connection
Definition: snn.h:375
virtual void connect(CpuSNN *s, int srcGrpId, int i, int destGrpId, int j, float &weight, float &maxWt, float &delay, bool &connected)
specifies which synaptic connections (per group, per neuron, per synapse) should be made ...
Definition: snn.h:250
void resetSpikeCnt(int grpId=-1)
Resets the spike count for a particular group.
Definition: snn_cpu.cpp:293
unsigned int * nSpikeCnt
homeostatic plasticity variables
Definition: snn.h:413
used for fine-grained control over spike generation, using a callback mechanism
Definition: snn.h:226
bool updateTime()
returns true when a new second is started
Definition: snn_cpu.cpp:2622
used for fine-grained control over spike generation, using a callback mechanism
Definition: snn.h:244
int allocated
true if all data has been allocated..
Definition: snn.h:367
int runNetwork(int _nsec, int _tstep=0, int simType=CPU_MODE, int ithGPU=0, bool enablePrint=false, int copyState=false)
run the simulation for n sec simType can either be CPU_MODE or GPU_MODE ithGPU: specify on which CUDA...
Definition: snn_cpu.cpp:2644
int createSpikeGeneratorGroup(const string &_name, int unsigned size_n, int stype, int configId=ALL)
creates a spike generator group (dummy-neurons, not Izhikevich spiking neurons).
Definition: snn_cpu.cpp:838
Schedule/Store spikes to be delivered at a later point in the simulation.
void CpuSNNInit(unsigned int _numN, unsigned int _numPostSynapses, unsigned int _numPreSynapses, unsigned int _D)
Definition: snn_cpu.cpp:159
void setNeuronParameters(int groupId, float _a, float a_sd, float _b, float b_sd, float _c, float c_sd, float _d, float d_sd, int configId=ALL)
Sets the Izhikevich parameters a, b, c, and d of a neuron group.
Definition: snn_cpu.cpp:923
unsigned short * Npost
stores the number of output connections from a neuron.
Definition: snn.h:373
void printMemoryInfo(FILE *fp=stdout)
prints memory info to file
unsigned short * Npre
stores the number of input connections to the neuron
Definition: snn.h:370
virtual unsigned int nextSpikeTime(CpuSNN *s, int grpId, int i, unsigned int currentTime)
controls spike generation using a callback
Definition: snn.h:232
Definition: mtrand.h:97
bool enablePrint
when we call print state, should the group properties be printed. default is false and we do not want...
Definition: snn.h:505
virtual bool stepUpdate(CpuSNN *s, int step)
Definition: snn.h:211
void resetSpikeCnt_GPU(int _startGrp, int _endGrp)
Utility function to clear spike counts in the GPU code.
bool newUpdates
FIXME this flag has mixed meaning and is not rechecked after the simulation is started.
Definition: snn.h:475
void printPostConnection(FILE *fp=stdout)
print all the connections...
void readNetwork(FILE *fid)
reads the network state from file
Definition: snn_cpu.cpp:1952
void updateNetwork()
Original updateNetwork() function used by JMN.
Definition: snn_cpu.cpp:3588
short int MaxFiringRate
this is for the monitoring mechanism, it needs to know what is the maximum firing rate in order to al...
Definition: snn.h:437
Iterator to loop over the scheduled spikes at a certain delay.
static const unsigned int MINOR_VERSION
minor release version, as in CARLsim 2.X
Definition: snn.h:624
void writeNetwork(FILE *fid)
stores the pre and post synaptic neuron ids with the weight and delay
Definition: snn_cpu.cpp:1886
void updateNetwork_GPU(bool resetFiringInfo)
const_iterator beginSpikeTargetGroups(int stepOffset=0)
Returns an iterator to loop over all scheduled spike target groups.
void getPopWeights(int gIDpre, int gIDpost, float *&weights, int &size, int configId=0)
Writes weights from synaptic connections from gIDpre to gIDpost. Returns a pointer to the weights and...
Definition: snn_cpu.cpp:1166
void update(CpuSNN *s, int grpId, unsigned int *Nids, unsigned int *timeCnts, unsigned int total_spikes, float firing_Rate)
Controls actions that are performed when certain neurons fire (user-defined).
Definition: snn_cpu.cpp:3906
void printDotty()
prints a network graph using Dotty (GraphViz)
Definition: snn_cpu.cpp:1464
void setHomeostasis(int g, bool enable, int configId=0)
Sets the homeostasis parameters. g is the grpID, enable=true(false) enables(disables) homeostasis...
Definition: snn_cpu.cpp:746
connection infos...
Definition: snn.h:517
void scheduleSpikeTargetGroup(spikegroupid_t stg, delaystep_t delay)
Schedule a group of spike targets to get a spike at time t + delay.
void resetSpikeCntUtil(int grpId=-1)
Resets the spike count for a particular neuron group. Input: group ID variable named grpID...
Definition: snn_cpu.cpp:318
void printSimSummary(FILE *fp=stdout)
prints a simulation summary to file
void writePopWeights(string fname, int gIDpre, int gIDpost, int configId=0)
function writes population weights from gIDpre to gIDpost to file fname in binary.
Definition: snn_cpu.cpp:1228
const_iterator endSpikeTargetGroups()
End iterator corresponding to beginSynapseGroups.
can be used to create a custom spike monitor
Definition: snn.h:265
void setBaseFiring(int groupId, int configId, float _baseFiring, float _baseFiringSD)
Sets the homeostatic target firing rate. Neurons will try to attain this firing rate using homeostati...
Definition: snn_cpu.cpp:779
void copyUpdateVariables_GPU()
int CurrTimeSlice
timeSlice is used by the Poisson generators in order to note generate too many or too few spikes with...
Definition: snn.h:440
Contains all of CARLsim's core functionality.
Definition: snn.h:619
void reassignFixedWeights(int connectId, float weightMatrix[], int matrixSize, int configId=ALL)
Reassigns fixed weights to values passed into the function in a single 1D float matrix called weightM...
Definition: snn_cpu.cpp:4099