summaryrefslogtreecommitdiff
path: root/code/core/simulate.cpp
blob: 69252bb0ee0ba8e8af46ef1ccc4aabc3451ee16d (plain)
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;
}
contact: Jan Huwald // Impressum