SingleThreadSimEngine.cpp

Go to the documentation of this file.
00001 #include "SingleThreadSimEngine.h"
00002 
00003 #include "SpikeSender.h"
00004 #include "SimNetwork.h"
00005 #include "SimObjectRegistry.h"
00006 
00007 #include <algorithm>
00008 using std::make_heap;
00009 using std::sort_heap;
00010 
00011 #include <iostream>
00012 using std::cout;
00013 using std::endl;
00014 using std::cerr;
00015 
00016 SingleThreadSimEngine::SingleThreadSimEngine(int ID, SpikeScheduler &scheduler, AnalogMessageDispatcher &analogMsgDispatcher, SimNetwork &net):
00017         SimEngine(ID,scheduler, net),
00018         activeSpikeReceiver(0), t( Time::ms(0) ), step(0),  dtHasChanged(false),
00019         initialized(false),
00020         isReset(false),
00021         objectListsDirty(true),
00022         analog_msg_dispatcher(analogMsgDispatcher),
00023         objPool(20),
00024         nSpikeOutputPorts(0)
00025 {
00026     // srng = new SimpleRandomNumberGenerator;
00027     noiseRNDEngine = new ThreadSpecificRandomEngineType;
00028     noiseRNDEngine->seed( net.simParameter().simulationRNGSeed );
00029     //SimObject::setSimEngine( this );
00030 }
00031 
00032 SingleThreadSimEngine::~SingleThreadSimEngine()
00033 {
00034         theThreadSpecificRandomEngine.unset( noiseRNDEngine );
00035     delete noiseRNDEngine;
00036 }
00037 
00038 void SingleThreadSimEngine::seed( vector<uint32> const& noiseSeed )
00039 {
00040     noiseRNDEngine->seed( noiseSeed[0] );
00041 }
00042 
00043 void SingleThreadSimEngine::seed( uint32 noiseSeed )
00044 {
00045     noiseRNDEngine->seed( noiseSeed );
00046 }
00047 
00048 void SingleThreadSimEngine::addObject( SimObjectFactory const& objFactory, SimObject::ID &id )
00049 {
00050     objectListsDirty = true;
00051     id.type = objFactory.getObjectTypeID();
00052     id.localid = objPool.addObject( objFactory, network.getObjectVariationRNDEngine() );
00053     addSpikePorts( objPool.getObject( id.type, id.localid ), id );    
00054 }
00055 
00056 void SingleThreadSimEngine::addSpikePorts( SimObject *obj, SimObject::ID &id )
00057 {
00058     SingleOutputSpikeSender *single_out = dynamic_cast< SingleOutputSpikeSender *>( obj );
00059     if( single_out != NULL ) {
00060         single_out->getSpikePort()->setID( (spike_port_id_t)nSpikeOutputPorts );
00061         nSpikeOutputPorts++;
00062     } else {
00063         MultipleOutputSpikeSender *multi_out = dynamic_cast< MultipleOutputSpikeSender *>( obj );
00064         if( multi_out != NULL ) {
00065             for( int p = 0; p < ( obj->nSpikeOutputPorts() + obj->nAnalogOutputPorts() ); p++ ) {
00066                 if( obj->outputPortType( p ) == SimObject::spiking ) {
00067                     multi_out->getSpikePort(p)->setID( nSpikeOutputPorts );
00068                     nSpikeOutputPorts++;
00069                 }
00070             }
00071         }
00072     }
00073 }
00074 
00075 void SingleThreadSimEngine::mount( const SimObjectFactory &objFactory, const SimObject::ID &mountpoint, SimObject::ID &gid )
00076 {
00077     addObject( objFactory, gid );
00078     one_way_link( gid, mountpoint );
00079 }
00080 
00081 void SingleThreadSimEngine::insert( const SimObjectFactory &objFactory, const SimObject::ID &mountpoint, SimObject::ID &gid )
00082 {
00083     addObject( objFactory, gid );
00084     two_way_link( gid, mountpoint );
00085 }
00086 
00087 void SingleThreadSimEngine::two_way_link( const SimObject::ID &id1, const SimObject::ID &id2 )
00088 {
00089 
00090     SimObject *obj1 = objPool.getObject( id1.type, id1.localid );
00091     SimObject *obj2 = objPool.getObject( id2.type, id2.localid );
00092 
00093     obj1->incoming( obj2, id2, id1, network );
00094     obj2->outgoing( obj1, id1, id2, network );
00095 
00096     obj2->incoming( obj1, id1, id2, network );
00097     obj1->outgoing( obj2, id2, id1, network );
00098 }
00099 
00100 void SingleThreadSimEngine::one_way_link( const SimObject::ID &src, const SimObject::ID &dst )
00101 {
00102     SimObject *s = objPool.getObject( src.type, src.localid );
00103     SimObject *d = objPool.getObject( dst.type, dst.localid );
00104 
00105     d->incoming( s, src, dst, network );
00106     s->outgoing( d, dst, src, network );
00107 }
00108 
00109 void SingleThreadSimEngine::reset()
00110 {
00111     if (!initialized)
00112         initialize();
00113     // register ourselfs at the executing thread
00114     //SimObject::setSimEngine( this );
00115     theThreadSpecificRandomEngine.set( noiseRNDEngine );
00116 
00117     // make sure that all objects have consistent internal states
00118     double dt = network.get_dt().in_sec();
00119     objPool.updateObjects( dtHasChanged, dt );
00120 
00121     // reset to t=0
00122     t = Time::ms(0);
00123     step = 0;
00124 
00125     // empty list of active synapses
00126     activeSpikeReceiver.resize(0);
00127 
00128     SimObjectPool::SimObjectIterator oit;
00129     // reset all elements
00130     int nTypes = objPool.numOfTypes();
00131     for( int t = 0; t < nTypes; t++ ) {
00132         for( oit = objPool.beginObject(t); oit != objPool.endObject(t); ++oit ) {
00133             if( (*oit)->reset( dt ) & RESETFLAG_ACTIVATE ) {
00134                 activeSpikeReceiver.push_back( *oit );
00135             };
00136         }
00137     }
00138 
00139     // finally say that we did a reset
00140     isReset = 1;
00141 }
00142 
00143 void SingleThreadSimEngine::initialize()
00144 {
00145 
00146     // register ourselfs at the executing thread
00147     if (!initialized) {
00148         //SimObject::setSimEngine( this );
00149         theThreadSpecificRandomEngine.set( noiseRNDEngine );
00150 
00151         SimObjectPool::SimObjectIterator oit;        
00152         InitializeInfo ii( &network, this );        
00153         int nTypes = objPool.numOfTypes();
00154         for( int t = 0; t < nTypes; t++ ) {
00155             for( oit = objPool.beginObject(t); oit != objPool.endObject(t); ++oit ) {
00156                 (*oit)->init(&ii);
00157             }
00158         }
00159         initialized = true;
00160     }
00161 }
00162 
00163 
00164 
00165 void SingleThreadSimEngine::advance(int nSteps)
00166 {
00167     // there must be at least one call to reset!
00168     if( !isReset ) {
00169         reset();
00170     }
00171 
00172     // register ourselfs at the executing thread
00173     //SimObject::setSimEngine( this );
00174     theThreadSpecificRandomEngine.set( noiseRNDEngine );
00175 
00176     SimObjectPool::SimObjectIterator oit;
00177 
00178     int type;
00179 
00180     AdvanceInfo adv_inf( &network, this );
00181 
00182     for( int s=0; s<nSteps; s++ ) {
00183 
00184         adv_inf.t = this->t;
00185 
00186         // A) Do analog messages dispatching first
00187         analog_msg_dispatcher.dispatchAnalogMsgs();
00188 
00189         // B) ADVANCE_PHASE_1: Advance all objects scheduled before potential event driven objects
00190         for( type = 0; type < SimObjectRegistry::FirstIndexOf::SpikeDriven ; type++ ) {
00191             for( oit = objPool.beginObject(type); oit != objPool.endObject(type); ++oit ) {
00192                 (*oit)->advance(adv_inf);
00193             }
00194         }
00195         
00196         // C) Deliver the spikes to their targets
00197         spikeScheduler.deliverSpikes( activeSpikeReceiver, this->eid, t.in_sec() );
00198 
00199         // D) SPIKE DRIVEN: advance the vector of active sim objects
00200         size_t i=0;
00201         while( i < activeSpikeReceiver.size() ) {
00202             // if advance() & ADVANCEFLAG_DEACTIVATE > 0
00203             if( activeSpikeReceiver[i]->advance(adv_inf) & ADVANCEFLAG_DEACTIVATE ) {
00204                 activeSpikeReceiver[i] = activeSpikeReceiver.back();
00205                 activeSpikeReceiver.resize( activeSpikeReceiver.size() - 1);
00206             } else {
00207                 i++;
00208             }
00209         }
00210 
00211         // E) ADVANCE_PHASE_2: advance all objects scheduled after potential event driven objects except objetcs with type >= SimObject::TypeID::NoAdvance
00212         for( type = SimObjectRegistry::FirstIndexOf::AdvancePhase2; type < SimObjectRegistry::FirstIndexOf::NoAdvance; type++ ) {
00213             for( oit = objPool.beginObject(type); oit != objPool.endObject(type); ++oit ) {
00214                 (*oit)->advance(adv_inf);
00215             }
00216         }
00217 
00218         // also the spike scheduler wants to know the clock
00219         spikeScheduler.advance(eid);
00220 
00221         // increment simulation time from t -> t + dt
00222         t += network.get_dt();
00223         step++;
00224 
00225     }
00226 
00227 }
00228 
00229 void SingleThreadSimEngine::advanceOneFullCycle()
00230 {
00231     advance(default_steps_per_cycle);
00232     spikeScheduler.nextCycle();
00233 }
00234 
00235 void SingleThreadSimEngine::advanceSeveralStepsWithinACycle(int nsteps)
00236 {
00237     advance(nsteps);
00238 }
00239 
00240 void SingleThreadSimEngine::finalizeCycle() {}

Generated on Wed Jul 9 16:34:38 2008 for PCSIM by  doxygen 1.5.5