AnimatLab  2
Test
PropagatedSpikeBuffer.cpp
1 // IMPORTED FROM PCSIM SOURCE CODE
3 // http://www.lsm.tugraz.at/pcsim/
5 
6 #include "PropagatedSpikeBuffer.h"
7 
8 #include <iostream>
9 
10 using std::cout;
11 using std::endl;
12 
13 PropagatedSpikeBuffer::PropagatedSpikeBuffer(int minDelay, int maxDelay, int chunkSize ):
14  currIdx(0),
15  ringBufferFront(maxDelay+1),
16  ringBufferBack(maxDelay+1),
17  chunkBuffer(0),
18  currentFreeChunk(NULL),
19  nextFreeSrgNodeIdx(0),
20  nextFreeChunkIdx(0),
21  recycledNodes(NULL),
22  chunkSize(chunkSize)
23 {
24  // Check arguments
25  //assert( minDelay <= maxDelay );
26  //assert( minDelay >= 0 );
27  //assert( maxDelay >= 0 );
28 
29  cout << "Ringbuffer size is: " << ringBufferFront.size() << endl;
30 
31  reset( minDelay, maxDelay );
32 
33  currT = 0;
34 }
35 
36 
37 /* PropagatedSpikeBuffer & PropagatedSpikeBuffer::operator=(const PropagatedSpikeBuffer &src)
38 {
39  *this = src;
40  currentFreeChunk = chunkBuffer[0];
41  return *this;
42 } */
43 
45 {
46  for(size_t i=0; i<chunkBuffer.size(); i++) {
47  delete[] chunkBuffer[i];
48  }
49 }
50 
51 void PropagatedSpikeBuffer::init(size_t maxDelaySteps)
52 {
54  //assert( maxDelaySteps > 0 );
55 
56  if( ringBufferFront.size() != maxDelaySteps + 1 ) {
57  ringBufferFront.resize( maxDelaySteps + 1 );
58  ringBufferBack.resize( maxDelaySteps + 1 );
59  }
60  if( chunkBuffer.size() < 1 ) {
61  chunkBuffer.reserve( 10 );
62  chunkBuffer.resize( 0 );
63  chunkBuffer.push_back( new StgNode[ chunkSize ] );
64  }
65 }
66 
67 void PropagatedSpikeBuffer::reset(int minDelay, int maxDelay)
68 {
69  //assert( minDelay <= maxDelay );
70  //assert( minDelay >= 0 );
71  //assert( maxDelay >= 0 );
72 
73  init( maxDelay + minDelay );
74 
75  for(size_t i=0; i<ringBufferFront.size(); i++) {
76  ringBufferFront[i] = ringBufferBack[i] = NULL;
77  }
78 
79  currentFreeChunk = chunkBuffer[0];
80  nextFreeChunkIdx = 1;
81 
82  nextFreeSrgNodeIdx = 0;
83 
84  recycledNodes = NULL;
85 
86  currIdx = 0;
87 }
88 
89 PropagatedSpikeBuffer::StgNode *PropagatedSpikeBuffer::getFreeNode(void)
90 {
91  StgNode *n;
92  if (recycledNodes != NULL) {
93  // get a recycled node
94  n = recycledNodes;
95  recycledNodes = recycledNodes->next;
96  } else if ( nextFreeSrgNodeIdx < chunkSize ) {
97  // get slot from the current (allocIdx) pre-allocated memory chunk
98  n = &(currentFreeChunk[nextFreeSrgNodeIdx++]);
99  } else if (nextFreeChunkIdx < chunkBuffer.size() ) {
100  // current (currentFreeChunk) pre-allocated memory chunk used up: go to next chunk
101  currentFreeChunk = chunkBuffer[nextFreeChunkIdx++];
102  n = &(currentFreeChunk[0]);
103  nextFreeSrgNodeIdx = 1;
104  } else {
105  // no more chunks available: alloc a new one
106  currentFreeChunk = new StgNode[chunkSize];
107  chunkBuffer.push_back( currentFreeChunk );
108  nextFreeChunkIdx++;
109  n = &(currentFreeChunk[0]);
110  nextFreeSrgNodeIdx = 1;
111  }
112  return n;
113 }
114 
115 void PropagatedSpikeBuffer::scheduleSpikeTargetGroup(spikegroupid_t stg, delaystep_t delay)
116 {
117  //cout << "in buffer timestep = " << currT << " delay=" << delay << endl;
118  StgNode *n = getFreeNode();
119 
120  //assert( n != NULL );
121 
122  int writeIdx = ( currIdx + delay ) % ringBufferFront.size();
123 
124  n->stg = stg;
125  n->delay = delay;
126  n->next = NULL;
127  if( ringBufferFront[writeIdx] == NULL ) {
128  ringBufferBack[writeIdx] = ringBufferFront[writeIdx] = n;
129  } else {
130  ringBufferBack[writeIdx]->next = n;
131  ringBufferBack[writeIdx] = n;
132  }
133 }
134 
136 {
137  // move the solts of currIdx to recycled slots
138  // cout << ">>> curIDx=" << currIdx << ", bksz=" << ringBufferBack.size() << ", frsz=" << ringBufferFront.size() << endl;
139  if( ringBufferFront[ currIdx ] != NULL ) {
140  ringBufferBack[ currIdx ]->next = recycledNodes;
141  recycledNodes = ringBufferFront[ currIdx ];
142  }
143  // mark current index as processed
144  // cout << ">>> curIDx=" << currIdx << ", bksz=" << ringBufferBack.size() << ", frsz=" << ringBufferFront.size() << endl;
145  ringBufferBack[ currIdx ] = ringBufferFront[ currIdx ] = NULL;
146  currIdx = ( currIdx + 1 ) % ringBufferFront.size();
147  currT ++;
148 }
149 
150 
void nextTimeStep()
Must be called to tell the buffer that it should move on to the next time step.
void reset(int minDelay, int maxDelay)
Must be called at the begin (reset) of a simulation.
Structure which stores the index of the spike target group and a pointer to the next element in vario...
void scheduleSpikeTargetGroup(spikegroupid_t stg, delaystep_t delay)
Schedule a group of spike targets to get a spike at time t + delay.
PropagatedSpikeBuffer(int minDelay, int maxDelay, int chunkSize=PROPAGATED_SPIKE_BUFFER_CHUNK_SIZE)
New spike buffer.
virtual ~PropagatedSpikeBuffer()
Destructor: Deletes all scheduled spikes.