summaryrefslogtreecommitdiff
path: root/core/sim_loop.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/sim_loop.hpp')
-rw-r--r--core/sim_loop.hpp218
1 files changed, 218 insertions, 0 deletions
diff --git a/core/sim_loop.hpp b/core/sim_loop.hpp
new file mode 100644
index 0000000..0ef748d
--- /dev/null
+++ b/core/sim_loop.hpp
@@ -0,0 +1,218 @@
+#ifndef Lh5wJREkwqXIDpptCEqbkLO3ed4
+#define Lh5wJREkwqXIDpptCEqbkLO3ed4
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/mpl/joint_view.hpp>
+
+#include "context.hpp"
+#include "event.hpp"
+#include "evolve.hpp"
+#include "index.hpp"
+#include "index_global.hpp"
+#include "index_randomspike.hpp"
+#include "index_spike.hpp"
+#include "index_spike_arrival.hpp"
+#include "multi_queue.hpp"
+#include "pla_apply.hpp"
+#include "pla_evolve.hpp"
+#include "pla_generate.hpp"
+#include "pla_sync.hpp"
+#include "time.hpp"
+#include "topology.hpp"
+#include "type_set.hpp"
+
+namespace SimLoopImpl {
+
+using namespace boost;
+using namespace boost::mpl;
+
+template<typename PropList>
+struct SimLoop {
+ typedef PropertyComposition<PropList> pc_t;
+
+ SimLoop()
+ : indices(),
+ queues()
+ {}
+
+ bool run(const Time until, uint64_t maxEvents) __attribute__((noinline)) {
+ Time old(queues.min());
+ while (queues.min() <= until && maxEvents) {
+ assert(old <= queues.min());
+ old = queues.min();
+ switch (queues.minType()) {
+#define HT(T) case RuntimeID<T>::value: handleEvent<T>(); break;
+ HT(SpikeArrival);
+ HT(Spike);
+ HT(RandomSpike);
+ HT(GlobalMsg);
+#undef HT
+ default: assert(false);
+ }
+ maxEvents--;
+ }
+ return maxEvents;
+ }
+
+ template<typename Quant>
+ inline void handleEvent() {
+ typedef typename QuantDestinationQuant<Quant>::type DstQuant;
+ Time ct(queues.min());
+ Event<Quant> &event = queues.get<Quant>()(ct).minPayload();
+ Ptr<DstQuant> dst(event.dst(topology));
+
+ // deliever the event and check if to create new events
+ DelieverContext<Quant, DstQuant> delieverContext(event.instance(), dst);
+ PLA_Apply<Quant, DstQuant, pc_t> apply(ct, delieverContext);
+ pc.call(apply);
+
+ // if we create any events
+ if (apply.generateAny()) {
+ // evolve all entities which depend on our pre-event values
+ Evolve<DstQuant>()(pc, ct, dst);
+
+ // compute delay values (they require access to the pre- and
+ // post-event values and can thus only be computed here)
+ apply.computeDelay(pc);
+ }
+
+ // commit data calculated during apply
+ // this is necessary because childs are only eventually evolved,
+ // but require the pre-event values of the instance we are
+ // committing to now
+ apply.commit(pc);
+
+ // generate events and compute discrete properties
+#define MGE(DQ) \
+ if (apply.template generate<DQ>()) \
+ generateEvent<DstQuant, DQ, Quant> (ct, dst, apply);
+
+ MGE(GlobalMsg);
+ MGE(Spike);
+ MGE(RandomSpike);
+#undef MGE
+ if (apply.template generate<SpikeArrival>())
+ generateSAEvent(ct, event, apply);
+
+ if (boost::is_same<Quant, Spike>::value) {
+ // reinsert spike to get to the next neuron; also handles
+ // removing current min element from the queue (because of a
+ // race condition)
+ reinsertSpike(ct, FORCE_CONV(Event<Spike>, event));
+ }else{
+ queues.removeLocalMin<Quant>(ct);
+ }
+ }
+
+ template<typename ContQuant, typename EventQuant, typename SrcEvQuant>
+ inline void generateEvent(Time ct,
+ typename ContQuant::instance_ptr_t src,
+ PLA_Apply<SrcEvQuant, ContQuant, pc_t> &apply) {
+ // generate new discrete quant instance
+ Time eventTime = ct + apply.template getDelay<EventQuant>();
+ Ptr<EventQuant> ptrNE(indices.get<Index<EventQuant>>().add(ct, eventTime, src));
+ EmitContext<ContQuant, EventQuant> emitContext(src, ptrNE);
+ PLA_Generate<ContQuant, EventQuant, indices_t, queues_t>
+ pla_gen(ct, emitContext, indices, queues);
+ pc.call(pla_gen);
+
+ // generate new event
+ if (likely((not TopologicalEventDiscard<ContQuant, EventQuant>()(topology, src))))
+ queues.insert
+ (ct,
+ eventTime + TopologicalTimeOffset<ContQuant, EventQuant>()(topology, src),
+ Event<EventQuant>(eventTime, src, ptrNE));
+ }
+
+ template<typename EventT, typename ContQuant, typename SrcEvQuant>
+ inline void generateSAEvent(Time ct,
+ EventT &rawEvent,
+ PLA_Apply<SrcEvQuant, ContQuant, pc_t> &apply) {
+ // garantuee that we are called by spike event and cast alike
+ assert((boost::is_same<EventT, Event<Spike>>::value));
+ assert((boost::is_same<ContQuant, Synapse>::value));
+ Event<Spike> &event(FORCE_CONV(Event<Spike>, rawEvent));
+ Ptr<Synapse> src(event.dst(topology));
+
+ // calculate the SA-ptr
+ Ptr<SpikeArrival> ptrNE(event.instance(), event.offset);
+
+ // generate all SA properties (except voltage difference)
+ EmitContext<Synapse, SpikeArrival> emitContext(src, ptrNE);
+ PLA_Generate<Synapse, SpikeArrival, indices_t, queues_t>
+ pla_gen(ct, emitContext, indices, queues);
+ pc.call(pla_gen);
+
+ // generate event and add to queues
+ queues.insert(ct, ct, Event<SpikeArrival>(src, ptrNE));
+ }
+
+ inline void reinsertSpike(Time ct, Event<Spike> &event) {
+ // TODO (optimize): reuse the current event
+ Event<Spike>::offset_t offset(event.offset + 1);
+
+ if (unlikely((topology.synapse(event.src, offset)() == Topology::nil()()))) {
+ queues.removeLocalMin<Spike>(ct);
+ }else{
+ // create new event (depends on old)
+ Event<Spike> newEvent
+ (event.baseTime,
+ event.src,
+ event.spike,
+ offset);
+
+ // delete old event; this must happen before insertion of the
+ // new event to avoid race in case of equal times
+ queues.removeLocalMin<Spike>(ct);
+
+ // insert new event
+ queues.insert
+ (ct,
+ newEvent.baseTime + topology.time(newEvent.src, offset),
+ newEvent);
+ }
+ }
+
+ void sync() {
+ // TODO: sync all or remove method
+ pc.cast(PLA_Sync{});
+ indices.get<Index<GlobalMsg>>().sync();
+ queues.get<GlobalMsg>().sync();
+ }
+
+ Time currentTime() {
+ return queues.min();
+ }
+
+ /// persistant data storage (holds every mmap'ed data structure)
+
+ // properties
+ pc_t pc;
+ Topology topology;
+
+ // indices
+ template<typename T> struct index_from_type {
+ typedef Index<T> type;
+ };
+ typedef typename boost::mpl::transform<
+ DiscreteQuantorList,
+ index_from_type<boost::mpl::_>
+ >::type indices_list_t;
+ typedef typename UnpackTypeList<TypeSet, indices_list_t>::type indices_t;
+ indices_t indices;
+
+ // event queues
+ typedef MultiQueue<
+ Time, Event, DiscreteQuantorList
+ > queues_t;
+ queues_t queues;
+
+ // TODO (beauty): add checks for proper r/w status in pc_t (all
+ // writable)
+};
+
+} // Namespace SimLoopImpl
+
+using SimLoopImpl::SimLoop;
+
+#endif // Lh5wJREkwqXIDpptCEqbkLO3ed4
contact: Jan Huwald // Impressum