#ifndef GyWue2EL4TyiAsNv0XegfFL4jk #define GyWue2EL4TyiAsNv0XegfFL4jk #include #include "sim_replay.hpp" // discrete property Egal struct Egal { typedef uint8_t type; typedef SpikeArrival quant; typedef SpikeArrival::instance_ptr_t instance_ptr_t; static const uint32_t size = 2; static const char* const name; }; const char* const Egal::name = "Egal"; namespace SimCausalityImpl { using namespace boost::mpl; using namespace boost; namespace MC = ModelConsts; template struct SimCausality; template struct MaybeTrackEvent { template void operator() (Sim &sim) { // we handle every event but only track those affecting neurons auto &sg = static_cast&>(sim); if (is_same::value) { sg.handleSA(); }else if (is_same::value) { sg.handleRand(); }else{ sim.template handleEvent(); } } typedef MaybeTrackEvent impl; }; template struct SimCausality : public SimReplay { typedef SimReplay Super; using Super::queues; using Super::pc; using Super::ct; using Super::handleEvent; SimCausality(Time start) : Super(IdList((char*) "0-999"), start), totalMarks{}, trueMarks{}, inactiveNeurons(1000), hasFired{} { if (start == Time(0)) { // special case: at t=0 all neurons are have zero membrane // voltage and can be used for analysis before firing the first // time inactiveNeurons = 0; for (int i=0; i<1000; i++) hasFired[i] = true; } } bool run(const Time until, uint64_t maxEvents) __attribute__((noinline)) { return Super::run(until, maxEvents); } void handleRand() { Ptr neuron(queues.get().minPayload().dst); Ptr fakeSA(Index::nil()); handleDiff(neuron, fakeSA, MC::RandomSpikeWeight, &SimCausality::template handleEvent); } void handleSA() { auto &event(queues.get().minPayload()); Ptr sa (event.src.get<0>()); Ptr syn (event.src.get<1>()); Ptr neuron(event.dst); PLA_Get getWeight (ct, syn); Weight::type weight(pc.call(getWeight)); handleDiff(neuron, sa, weight, &SimCausality::template handleEvent); } void handleDiff(Ptr neuron, Ptr sa, Voltage::type diff, bool (SimCausality::*handleEvent)()) { PLA_Get getVoltage (ct, neuron); PLA_Get getIPCoeff1(ct, neuron); Voltage::type preEventVoltage(pc.call(getVoltage)); IPCoeff1::type ipCoeff1 (pc.call(getIPCoeff1)); bool evokedSpike = (this->*handleEvent)(); auto &openExc(this->openExc[neuron()]); auto &openInh(this->openInh[neuron()]); if (!hasFired[neuron()]) { if (evokedSpike) { hasFired[neuron()] = true; inactiveNeurons--; if (!inactiveNeurons) lastNeuronActivation = ct; } return; } if (evokedSpike) { // check exc. list against voltage diff Time wntGap = ct + wntNorm(diff + preEventVoltage - MC::FireThreshold - ipCoeff1); for (auto i = openExc.lower_bound(wntGap); i != openExc.end();) { mark(i->second, 0); openExc.erase(i++); } // mark own spike mark(sa, 0); // mark remainig inh/exc spikes as q>0, clear buffers for (auto i : openExc) mark(i.second, 1); openExc.clear(); for (auto i : openInh) mark(i.second, 1); openInh.clear(); }else{ if (diff < 0) { // add to inh. list Time wnt = ct + wntNorm(- diff); openInh.insert(std::make_pair(wnt, sa)); }else{ // add to exc. list Time wntSelf = ct + wntNorm(diff); openExc.insert(std::make_pair(wntSelf, sa)); // check inh. list against voltage gap PLA_Get pla_get(ct, neuron); Voltage::type voltage = pc.call(pla_get); Time wntGap = ct + wntNorm(MC::FireThreshold + ipCoeff1 - voltage); for (auto i = openInh.lower_bound(wntGap); i != openInh.end();) { mark(i->second, 0); openInh.erase(i++); } } } } void mark(Ptr ptr, bool m) { bool isSA = ptr() != Index::nil(); totalMarks[isSA]++; trueMarks[isSA] += !m; if (isSA) egalPC.cast(PLA_Set(ptr, 1+m)); // unset values are encoded as zero } Time wntNorm(Voltage::type diff) { return MC::Tau_Voltage * log(diff); } PropertyComposition> >> egalPC; uint64_t totalMarks[2], trueMarks[2]; uint16_t inactiveNeurons; Time lastNeuronActivation; bool hasFired[maxNeurons]; std::multimap> openInh[maxNeurons], openExc[maxNeurons]; }; } // NS using SimCausalityImpl::SimCausality; #endif // GyWue2EL4TyiAsNv0XegfFL4jk