summaryrefslogtreecommitdiff
path: root/core/sim_replay.hpp
diff options
context:
space:
mode:
authorJan Huwald <jh@sotun.de>2012-05-07 20:01:51 (GMT)
committerJan Huwald <jh@sotun.de>2012-05-07 20:01:51 (GMT)
commit420d2ef464d4a741028e132e662d5626806a41f5 (patch)
tree1aca6eb512e4ed0fb5f3c10c528cb998b6ffd695 /core/sim_replay.hpp
Initial commitHEADmaster
Diffstat (limited to 'core/sim_replay.hpp')
-rw-r--r--core/sim_replay.hpp268
1 files changed, 268 insertions, 0 deletions
diff --git a/core/sim_replay.hpp b/core/sim_replay.hpp
new file mode 100644
index 0000000..c34e216
--- /dev/null
+++ b/core/sim_replay.hpp
@@ -0,0 +1,268 @@
+#ifndef BjxF7IwCJEpR8eQGIzMk04pwFg
+#define BjxF7IwCJEpR8eQGIzMk04pwFg
+
+#include <algorithm>
+#include <boost/tuple/tuple.hpp>
+#include <boost/mpl/set.hpp>
+#include <boost/mpl/contains.hpp>
+
+#include "context.hpp"
+#include "event.hpp"
+#include "evolve.hpp"
+#include "index.hpp"
+#include "index_global.hpp"
+#include "index_spike.hpp"
+#include "index_spike_arrival.hpp"
+#include "filter.hpp"
+#include "multi_queue.hpp"
+#include "pla_apply.hpp"
+#include "pla_evolve.hpp"
+#include "pla_generate.hpp"
+#include "pla_initbycopy.hpp"
+#include "pla_sync.hpp"
+#include "time.hpp"
+#include "topology.hpp"
+#include "type_set.hpp"
+
+#include "model.hpp"
+
+namespace SimReplayImpl {
+
+using namespace boost;
+using namespace boost::mpl;
+
+// TODO: remove (is redundant code)
+template <typename Quant> struct CalcDPtr {
+ typedef Ptr<Quant> type;
+};
+template <> struct CalcDPtr<SpikeArrival> {
+ typedef boost::tuple<Ptr<SpikeArrival>, Ptr<Synapse>> type;
+};
+
+/// factory defining which discrete quants we have to consider
+
+template<typename ReplayQuant>
+struct MultiQueueFactory;
+
+template<>
+struct MultiQueueFactory<Global> {
+ typedef list<GlobalMsg> dependencies;
+ typedef MultiQueue<Time, FilterPayload, dependencies, FilterContainer> type;
+ typedef IdList<Ptr<Global>::ptr_t> id_list_t;
+ static type instance(id_list_t &, const Time time) {
+ return type(time);
+ }
+};
+
+template<>
+struct MultiQueueFactory<Neuron> {
+ typedef list<GlobalMsg, Spike, RandomSpike, SpikeArrival> dependencies;
+ typedef MultiQueue<Time, FilterPayload, dependencies, FilterContainer> type;
+ typedef IdList<Ptr<Neuron>::ptr_t> id_list_t;
+ static type instance(id_list_t ids, const Time time) {
+ return type(Filter<GlobalMsg> (time),
+ Filter<Spike> (ids, time),
+ Filter<RandomSpike> (ids, time),
+ Filter<SpikeArrival>(ids, time));
+ }
+};
+
+template<>
+struct MultiQueueFactory<Synapse> : MultiQueueFactory<Neuron> {
+ typedef IdList<Ptr<Synapse>::ptr_t> id_list_t;
+ static type instance(id_list_t ids_synapse, Time time) {
+ MultiQueueFactory<Neuron>::id_list_t ids_neuron;
+ for (auto syn : ids_synapse)
+ ids_neuron.insert(Ptr<Synapse>(syn).extractNeuron()());
+ return MultiQueueFactory<Neuron>::instance(ids_neuron, time);
+ }
+};
+
+/// template brainfuck to prevent instancing unnecessary handleEvents<>()
+
+template<typename ReplayQuant, typename Quant>
+struct MaybeHandleEvent {
+ template<typename Q> struct HandleEvent {
+ template<typename Sim> void operator() (Sim &sim) {
+ sim.template handleEvent<Q>();
+ }
+ };
+
+ struct IgnoreEvent {
+ template<typename Sim> void operator() (Sim &sim) {}
+ };
+
+ typedef typename contains<
+ typename MultiQueueFactory<ReplayQuant>::dependencies,
+ Quant>::type isRelevant;
+ typedef typename if_<isRelevant,
+ HandleEvent<Quant>,
+ IgnoreEvent
+ >::type impl;
+};
+
+
+/// extract neurons from arbitrary id list
+template<typename Quant> struct ExtractNeuronIDs;
+
+template<>
+struct ExtractNeuronIDs<Global> {
+ IdList<Ptr<Neuron>::ptr_t> operator() (IdList<Ptr<Global>::ptr_t> &) {
+ return IdList<Ptr<Neuron>::ptr_t>();
+ }
+};
+
+template<>
+struct ExtractNeuronIDs<Neuron> {
+ IdList<Ptr<Neuron>::ptr_t> operator() (IdList<Ptr<Neuron>::ptr_t> &src) {
+ return src;
+ }
+};
+
+template<>
+struct ExtractNeuronIDs<Synapse> {
+ IdList<Ptr<Neuron>::ptr_t> operator() (IdList<Ptr<Synapse>::ptr_t> &src) {
+ IdList<Ptr<Neuron>::ptr_t> res;
+ for (auto id : src)
+ res.insert(Ptr<Synapse>(id).extractNeuron()());
+ return res;
+ }
+};
+
+/// the precious replay
+
+template<typename PropList, typename ReplayQuant,
+ template<class, class> class EventHandler = MaybeHandleEvent>
+struct SimReplay {
+ typedef PropertyComposition<PropList> PropComp;
+ typedef Checkpoint<Void, 1> Cp;
+ typedef IdList<typename Ptr<ReplayQuant>::ptr_t> id_list_t;
+ typedef IdList<typename Ptr<Neuron>::ptr_t> neuron_list_t;
+
+ SimReplay(id_list_t ids, Time start)
+ // we need the previous checkpoint interval
+ : ct(Cp::interval() * (std::max((const uint32_t) 1, Cp::binTime(start)) - 1)),
+ ids(ids),
+ neurons(ExtractNeuronIDs<ReplayQuant>()(ids)),
+ queues(std::move(MultiQueueFactory<ReplayQuant>::instance(ids, ct)))
+ {
+ // init values of our quant
+ pc.cast(PLA_InitByCopy{ct});
+
+ // forward precisely to the request time
+ run(start, -1);
+ }
+
+ template<typename Prop>
+ typename Prop::type get(Ptr<ReplayQuant> id, Time t) {
+ // TODO (maybe): allow to read all calculated values, not just
+ // those of the ReplayQuant (e.g. the synapses properties of a
+ // simulated neuron)
+ assert(t >= ct);
+ assert(ids.count(id()));
+ run(t, -1);
+ typedef ContinuousContext<ReplayQuant> Ctx;
+ PLA_Get<Prop, Ctx> pla_get(t, Ctx(id));
+ return pc.call(pla_get);
+ }
+
+ bool run(const Time until, uint64_t maxEvents) {
+ assert(until != Time::never());
+ while (queues.min() <= until && maxEvents) {
+ ct = queues.min();
+ switch (queues.minType()) {
+#define HT(T) case RuntimeID<T>::value: typename EventHandler<ReplayQuant, T>::impl()(*this); break;
+ HT(SpikeArrival);
+ HT(Spike);
+ HT(RandomSpike);
+ HT(GlobalMsg);
+#undef HT
+ default: assert(false);
+ }
+ --maxEvents;
+ }
+ return maxEvents;
+ }
+
+ template<typename Quant>
+ inline bool handleEvent() {
+ typedef typename QuantDestinationQuant<Quant>::type DstQuant;
+ typename CalcDPtr<Quant>::type src(queues.get<Quant>().minPayload().src);
+ Ptr<DstQuant> dst(queues.get<Quant>().minPayload().dst);
+
+ // deliever the event and check if to create new events
+ DelieverContext<Quant, DstQuant> delieverContext{src, dst};
+ PLA_Apply<Quant, DstQuant, PropComp> apply(ct, delieverContext);
+ pc.call(apply);
+
+ // create events
+ if (apply.generateAny()) {
+ // determine how much we have to simulate:
+ if (is_same<ReplayQuant, Global>::value) {
+ // - global replay don't needs any childs
+ pc.cast(PLA_Evolve<Global>{ContinuousContext<Global>{Ptr<Global>{}}, ct});
+ }else{
+ if (is_same<DstQuant, Global>::value) {
+ // - neuron/synapse replay needs global and selected neurons
+ for (auto id : neurons)
+ Evolve<Neuron>()(pc, ct, Ptr<Neuron>{id});
+ pc.cast(PLA_Evolve<Global>{ContinuousContext<Global>{Ptr<Global>{}}, ct});
+ }else{
+ // - neuron/synapse evolve happens as usual
+ Evolve<DstQuant>()(pc, ct, dst);
+ }
+ }
+ }
+ // 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);
+
+ // call the continuous property related post-event triggers to
+ // update state
+#define HGE(Q) \
+ if (apply.template generate<Q>()) \
+ handleEventGeneration<DstQuant, Q, Quant>(ct, dst, apply);
+
+ HGE(GlobalMsg);
+ HGE(Spike);
+ HGE(RandomSpike);
+ HGE(SpikeArrival);
+#undef HGE
+
+ queues.template removeMin<Quant>(ct);
+
+ return apply.template generate<Spike>();
+ }
+
+ template<typename ContQuant, typename EventQuant, typename SrcEvQuant>
+ inline void handleEventGeneration(Time ct, Ptr<ContQuant> src,
+ PLA_Apply<SrcEvQuant, ContQuant, PropComp> &)
+ {
+ Void nix;
+ pc.cast(PLA_Generate<ContQuant, EventQuant, Void, Void>
+ (ct, EmitContext<ContQuant, EventQuant>(src, Ptr<EventQuant>(-1)),
+ nix, nix));
+ }
+
+ Time currentTime() {
+ return ct;
+ }
+
+ /// ephermal state
+ Time ct;
+ id_list_t ids;
+ neuron_list_t neurons;
+ typename MultiQueueFactory<ReplayQuant>::type queues;
+ PropComp pc;
+
+ /// persistant data storage (holds every mmap'ed data structure)
+ //Topology topology;
+};
+
+} // Namespace ReplayImpl
+
+using SimReplayImpl::SimReplay;
+
+#endif // BjxF7IwCJEpR8eQGIzMk04pwFg
contact: Jan Huwald // Impressum