00001
00002 #include "SingleThreadNetwork.h"
00003 #include "SpikeSender.h"
00004 #include "PCSIMException.h"
00005 #include "RandomDistribution.h"
00006
00007 #include <boost/format.hpp>
00008
00009 #include <string>
00010 using std::string;
00011
00012 #include <iostream>
00013 using std::cerr;
00014 using std::endl;
00015
00016
00017
00018 SingleThreadNetwork::SingleThreadNetwork( SimParameter sp ) :
00019 SimNetwork(MPI::COMM_WORLD, sp, &localRoundRobin)
00020 {
00021 init();
00022 }
00023
00024 SingleThreadNetwork::SingleThreadNetwork(MPI::Intracomm &comm, SimParameter sp ) :
00025 SimNetwork(comm, sp, &localRoundRobin)
00026 {
00027 init();
00028 }
00029
00030 void SingleThreadNetwork::init()
00031 {
00032 spikeBuffer = new PropagatedSpikeBuffer(simParam.minDelay.in_steps( get_dt() ), simParam.maxDelay.in_steps( get_dt() ) );
00033 delayMap = new LocalDelayMap;
00034 stgPool = new SpikeTargetGroupPool;
00035 spikeScheduler = new SingleThreadSpikeScheduler(*delayMap, *stgPool, *spikeBuffer, simParam ) ;
00036 analogMsgDispatcher = new SingleThreadAnalogMsgDispatcher;
00037 simEngine = new SingleThreadSimEngine(0, *spikeScheduler, *analogMsgDispatcher, *this );
00038 analogDelayObjectsMap = new AnalogDelayObjectMap;
00039
00040 analogMsgCreator = new STAnalogMessageCreator(*analogMsgDispatcher,
00041 *simEngine,
00042 *analogDelayObjectsMap,
00043 (delay_t)simParam.minDelay.in_steps( get_dt() ) );
00044
00045
00046 setupConstructRNGEngines();
00047 SingleThreadNetwork::seed_noise_rng( makeSeed( simParam.simulationRNGSeed ) );
00048
00049 }
00050
00051 SingleThreadNetwork::~SingleThreadNetwork()
00052 {
00053 delete spikeBuffer;
00054 delete delayMap;
00055 delete spikeScheduler;
00056 delete simEngine;
00057 delete stgPool;
00058 delete analogMsgDispatcher;
00059 delete analogMsgCreator;
00060 if (!initialized) {
00061 delete analogDelayObjectsMap;
00062 }
00063 }
00064
00065 void SingleThreadNetwork::seed_noise_rng( uint32 noiseRNGseed )
00066 {
00067 simEngine->seed( noiseRNGseed );
00068 objectVariationRNDEngine->seed( makeSeed( simParam.constructionRNGSeed ) ) ;
00069 }
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 void SingleThreadNetwork::_addObject_( const SimObjectFactory &objFactory, const SimEngine::ID &loc, SimObject::ID &oid )
00092 {
00093 if( loc.node == _mpi_rank && loc.engine == 0 ) {
00094 addObject( objFactory, oid );
00095 } else {
00096
00097 oid = SimObject::ID::Invalid;
00098 if( loc.node != _mpi_rank )
00099 throw( PCSIM::ConstructionException( "SingleThreadNetwork::addObject", str( boost::format("Specified node (%1%) does not mach mpi rank (%2%)") % loc.node % _mpi_rank ) ) );
00100 else
00101 throw( PCSIM::ConstructionException( "SingleThreadNetwork::addObject", str( boost::format("Specified engine (%1%) not zero") % loc.engine ) ) );
00102 }
00103 }
00104
00105 void SingleThreadNetwork::_addObject_( const SimObjectFactory &objFactory, SimObject::ID &gid )
00106 {
00107 simEngine->addObject( objFactory, gid );
00108 gid.node = _mpi_rank;
00109 gid.eng = 0;
00110 }
00111
00112 void SingleThreadNetwork::_mount_( const SimObjectFactory &objFactory, const SimObject::ID &mountpoint, SimObject::ID &gid )
00113 {
00114 simEngine->mount( objFactory, mountpoint, gid );
00115 gid.node = _mpi_rank;
00116 gid.eng = 0;
00117 }
00118
00119 void SingleThreadNetwork::_insert_( const SimObjectFactory &objFactory, const SimObject::ID &container, SimObject::ID &gid )
00120 {
00121 simEngine->insert( objFactory, container, gid );
00122 gid.node = _mpi_rank;
00123 gid.eng = 0;
00124 }
00125
00126 SimObject * SingleThreadNetwork::_getObject_(const SimObject::ID &id)
00127 {
00128 return simEngine->getObject(id);
00129 }
00130
00131
00132
00133
00134 void SingleThreadNetwork::_connect_( SimObject::ID const& src, port_t out, const SimObject::ID &dst, port_t in, int delay )
00135 {
00136 SimObject *src_obj = simEngine->getObject(src);
00137 SimObject *dst_obj = simEngine->getObject(dst);
00138
00139
00140
00141 Time delay_to_use;
00142 if( delay < 0 ) {
00143 delay_to_use = Time::sec( dst_obj->getManagedDelay() );
00144 } else {
00145 delay_to_use = Time::steps( delay, get_dt() );
00146 }
00147
00148 if( src_obj->outputPortType(out) == SimObject::spiking && dst_obj->inputPortType( in ) == SimObject::spiking ) {
00149 addSpikeMessage( src, out, dst, in, delay_to_use );
00150 } else if ( src_obj->outputPortType(out) == SimObject::analog && dst_obj->inputPortType( in ) == SimObject::analog ) {
00151 addAnalogMessage( src, out, dst, in, delay_to_use );
00152 } else {
00153 cerr << " output port = " << int(src_obj->outputPortType(out)) << " input port " << in << " = " << int(dst_obj->inputPortType( in )) << " spiking constant = " << int(SimObject::spiking) << endl;
00154 throw( PCSIM::ConstructionException(
00155 "SingleThreadNetwork::_connect_",
00156 str( boost::format("Can not connect specified source (%1%) and destination object (%2%): no matching in (%3%) and out (%4%) ports.") % src.toString() % dst.toString() % in % out )
00157 ) );
00158 }
00159 }
00160
00161
00162
00163 void SingleThreadNetwork::_addSpikeMessage_(const SimObject::ID &sender, const port_t out, const SimObject::ID &receiver, const port_t in_port, const Time &delay)
00164 {
00165 if( delay > simParam.maxDelay ) {
00166 throw( PCSIM::ConstructionException( "SingleThreadNetwork::addSpikeMessage", str( boost::format("Specified delay (%1% ms) larger then maximum delay (%2% ms)") % delay.in_ms() % simParam.maxDelay.in_ms() ) ) );
00167 }
00168
00169 SimObject *src_obj = simEngine->getObject(sender);
00170 SpikeSender *ss = dynamic_cast<SpikeSender*>( src_obj );
00171
00172 if( ss == NULL ) {
00173 throw( PCSIM::ConstructionException( "SingleThreadNetwork::addSpikeMessage", str( boost::format("Specified simulation object (%1%,%2%) is not a spike sender.") % sender.toString() % typeid(*src_obj).name() ) ) );
00174 }
00175
00176 if( ss->getSpikePort( out ) != NULL ) {
00177 addLocalSpikeMessage( delayMap, stgPool, simEngine, ss->getSpikePort( out )->ID(), receiver, in_port, delay.in_steps( get_dt() ) );
00178 _nSpikeMessages++;
00179 } else {
00180 throw(
00181 PCSIM::ConstructionException (
00182 "SingleThreadNetwork::addSpikeMessage",
00183 str( boost::format("Specified spike output port (%1%) of %s with ID=%2% does not exist") % out % typeid(*src_obj).name() % sender.toString() )
00184 )
00185 );
00186 }
00187 }
00188
00189 void SingleThreadNetwork::addLocalSpikeMessage(
00190 LocalDelayMap *arg_delayMap, SpikeTargetGroupPool *arg_stgPool, SimEngine *arg_simEng,
00191 const spike_port_id_t sender_port, const SimObject::ID &receiver, port_t in_port, step_t delay )
00192 {
00193 SimObject *rec_obj = arg_simEng->getObject(receiver);
00194 spikegroupid_t tg = arg_delayMap->find(sender_port, (delaystep_t)delay);
00195 if( tg == no_spikegroup ) {
00196 tg = arg_stgPool->addSpikeTarget( rec_obj, in_port );
00197 arg_delayMap->insert( sender_port, (delaystep_t)delay, tg );
00198 } else {
00199 arg_stgPool->addSpikeTarget( tg, rec_obj, in_port);
00200 }
00201 }
00202
00203
00204
00205 void SingleThreadNetwork::_addAnalogMessage_(const SimObject::ID &sender, int sender_port, const SimObject::ID &receiver, int recv_port, const Time &delay)
00206 {
00207 _nAnalogMessages++;
00208 analogMsgCreator->addAnalogMessage(sender, sender_port, receiver, recv_port, (delay_t)delay.in_steps( get_dt() ) );
00209 }
00210
00211 void SingleThreadNetwork::_addAnalogMessage_(const SimObject::ID &sender, int sender_port, const SimObject::ID &receiver, string destfield, const Time &delay)
00212 {
00213 _nAnalogMessages++;
00214 analogMsgCreator->addAnalogMessage(sender, sender_port, receiver, destfield, (delay_t)delay.in_steps( get_dt() ) );
00215 }
00216
00217 void SingleThreadNetwork::_addAnalogMessage_(const SimObject::ID &sender, string srcfield, const SimObject::ID &receiver, int recv_port, const Time &delay)
00218 {
00219 _nAnalogMessages++;
00220 analogMsgCreator->addAnalogMessage(sender, srcfield, receiver, recv_port, (delay_t)delay.in_steps( get_dt() ) );
00221 }
00222
00223 void SingleThreadNetwork::_addAnalogMessage_(const SimObject::ID &sender, string srcfield, const SimObject::ID &receiver, string destfield, const Time &delay)
00224 {
00225 _nAnalogMessages++;
00226 analogMsgCreator->addAnalogMessage(sender, srcfield, receiver, destfield, (delay_t)delay.in_steps( get_dt() ) );
00227 }
00228
00229
00230
00231 void SingleThreadNetwork::_initialize_()
00232 {
00233 if (!initialized) {
00234 simEngine->initialize();
00235 delete analogDelayObjectsMap;
00236 initialized = true;
00237 }
00238 }
00239
00240 void SingleThreadNetwork::_reset_()
00241 {
00242 if( ! initialized ) initialize();
00243 spikeScheduler->reset();
00244 simEngine->reset();
00245 reseted = true;
00246 }
00247
00248 void SingleThreadNetwork::_advance_( int nSteps )
00249 {
00250 if( ! reseted ) reset();
00251 simEngine->advance( nSteps );
00252 }