1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
#include <utility>
#include <map>
#include <signal.h>
#include "model_switch.h"
#include "synapse.h"
#include "neuron.h"
#include "topology.h"
#include "reward.h"
#include "tracepoints.h"
#include "fileutils.h"
#include "log.h"
#include "simulate.h"
// include cpp files to allow all otpimizations to take place across all files
#include "synapse.cpp"
#include "neuron.cpp"
#include "topology.cpp"
#include "fileutils.cpp"
#include "event.cpp"
#include "reward.cpp"
#include "bin.cpp"
#include "tracepoints.cpp" // should be excluded to speed up compilation
Simulation::Simulation() :
// debug related stuff
#ifdef DEBUG_STATUSLINE
numSpikes(0),
charCount(0),
#endif
// init globals
currentTime(0.0),
{
// set the initial dopamin level
da_history.push_front(pair<double, double>(0.0, g.dopamin_level));
}
bool Simulation::Step() {
// check if there are pending events
if (pendingSpikes.empty())
return false;
// retrieve and check next event
Event *e = pendingSpikes.top();
pendingSpikes.pop();
// proceed to the new time
if (currentTime > e->time)
DIE("tried to execute event of the past");
currentTime = e->time;
#ifdef DEBUG_STATUSLINE
if (numSpikes % 16384 == 0) {
// remove old line
while (charCount-- > 0)
fprintf(stderr, " ");
fprintf(stderr, "\r");
// print new line
charCount += fprintf(stderr, "%f s, %d, %lld events (%d\tpending:", e->type, currentTime, numSpikes, pendingSpikes.size());
for (map<int, int>::iterator i = eventCount.begin(); i != eventCount.end(); i++) {
charCount += fprintf(stderr, "\t%d: %d", i->first, i->second);
charCount += 7; // tab
}
charCount += fprintf(stderr, ")\r");
charCount += 7; // tab
}
fflush(stderr);
numSpikes++;
eventCount[e->type]--;
#endif
// execute event
e->execute();
e->free();
return true;
}
bool Simulation::proceedTime(double targetTime) {
// insert an intrinsic event for each neuron to have it computed up to exactly targetTime
for (int i=0; i < numNeurons; i++) {
addEvent(new IntrinsicNeuron(targetTime, i));
}
// proceed until no event is left before the time-point to be reached
// then also currentTime == targetTime holds
while (!pendingSpikes.empty() && (pendingSpikes.top()-> time <= targetTime)) {
Step();
}
// check if there are events left ... with the new event system this should always be the case
// and does not anymore indicate that the network is alive
return !pendingSpikes.empty();
}
void Simulation::addEvent(Event *e) {
pendingSpikes.push(e);
#ifdef DEBUG_STATUSLINE
eventCount[e->type]++;
#endif
}
void initStaticVars() {
Synapse::numSynapses = 0;
}
int main(int argc, char **argv) {
// ignore broken pipe signals (they should be handled by stdio file handlers and our usual error functions)
signal(SIGPIPE, SIG_IGN);
initStaticVars();
// load the network
// tp_load(s.fd_isynapse);
// neuron_load(s.fd_ineuron);
// init services implemented via events by adding one of them to the event population
s.addEvent(new ExternalNoise(0.0));
s.addEvent(new Reward(0.0));
// check for autoexciting events (and init neurons btw)
s.proceedTime(0.0);
// pass control to the tracepoint parser
// this allows to run the simulation interactively
executeTracepoints(s.fd_trace, s.fd_ispike, s.fd_iglobal);
return 0;
}
|