/******************************************************************* * * DESCRIPTION: class Root * * AUTHOR: Amir Barylko & Jorge Beyoglonian * Version 2: Daniel Rodriguez * * EMAIL: mailto://amir@dc.uba.ar * mailto://jbeyoglo@dc.uba.ar * mailto://drodrigu@dc.uba.ar * * DATE: 27/06/1998 * DATE: 02/03/1999 (v2) * *******************************************************************/ /** include files **/ #include "evaldeb.h" // ShowVirtualTimeWhenFinish #include "root.h" // base #include "msgadm.h" // class MessageAdm #include "message.h" // class Message #include "modeladm.h" // class SingleModelAdm #include "coupled.h" // class Coupled #include "mainsimu.h" // class Simulator #include /** public **/ /******************************************************************* * Function Name: Instance * Description: ********************************************************************/ Root &Root::Instance() { static bool instance( false ); if( !instance ) { SingleProcessorAdmin::Instance().generateRoot() ; instance = true ; } return static_cast( SingleProcessorAdmin::Instance().processor( ProcessorAdmin::rootId ) ) ; } /******************************************************************* * Function Name: Root * Description: constructor Default ********************************************************************/ Root::Root( const ProcId &id ) //: child( NULL ) { this->id( id ) ; Coupled &top = static_cast( SingleModelAdm::Instance().model("top") ); topMasterId = top.masterId(); } /******************************************************************* * Function Name: initialize * Description: clean event List and output device ********************************************************************/ Root &Root::initialize() { lastChange( Time::Zero ); nextChange( Time::Zero ); externalEvents.erase( externalEvents.begin(), externalEvents.end() ) ; stopTime( Time::Inf ) ; maximumTimeStop = Time("99:99:99:999"); sendMsgType(Root::collectMsg); return *this; } /******************************************************************* * Function Name: start * Description: begin the simulation ********************************************************************/ Root &Root::simulate() { // gettimeofday( MainSimulator::Instance().getSimStartTime(), (struct timezone*) 0); // gettimeofday( &start_time, (struct timezone *) 0) ; // end_time = start_time; externalEvents.sort(); InitMessage initMsg( Time::Zero, this->Processor::id() ) ; //Rami // SingleMsgAdm::Instance().send( initMsg, top().id() ) ; SingleMsgAdm::Instance().send( initMsg , topMasterId ); SingleMsgAdm::Instance().run() ; return *this; } /******************************************************************* * Function Name: stop * Description: stop the simulation ********************************************************************/ Root &Root::stop(bool calledByWrapper) { cout << " IN Root::stop() " << endl; if (ShowVirtualTimeWhenFinish().Active()) cerr << "\n" << lastChg << "\n"; if ( SingleCPPWrapper::Instance().getMachineID() == 0 && SingleModelAdm::Instance().totalMachineCount() > 1) SingleCPPWrapper::Instance().calSOAPMessageDelay(); else { cout << "*******************************************************************\n"; cout << "NO SOAP messages were sent in this session" << endl; cout << "*******************************************************************\n"; } SingleMsgAdm::Instance().stop() ; if( !calledByWrapper ) SingleCPPWrapper::Instance().stop(true); // gettimeofday( &end_time , (struct timezone*) 0 ); // gettimeofday( MainSimulator::Instance().getSimEndTime(), (struct timezone*) 0 ); long long total_time = 0; return *this; } /******************************************************************* * Function Name: receive * Description: send the time and value of the message to the output device ********************************************************************/ Processor &Root::receive( const OutputMessage &msg ) { MainSimulator::Instance().outputStream() << msg.time().asString() << " " << msg.port().name() << " " << Real(msg.value()) << endl ; return *this; } /******************************************************************* * Function Name: receive * Description: advance the time and go on with the simulation ********************************************************************/ Processor &Root::receive( const DoneMessage &msg ) { lastChange(msg.time()) ; nextChange( msg.nextChange() ); if (sendMsgType() == Root::internalMsg) { // Rami: The previous simulation cycle is not done yet. internal message is to be // sent so that the models can execue their internal/external/confluent functions InternalMessage intMsg(absoluteNext() , this->Processor::id()); SingleMsgAdm::Instance().send(intMsg , topMasterId ); sendMsgType(Root::collectMsg); } else { if (nextChange() == Time::Inf && externalEvents.empty() && stopTime() != maximumTimeStop) stop(); // Rami: no external events and no imninents --> stop the simulation else { Event ev(Time::Inf); Time nt = absoluteNext(); if( !externalEvents.empty() ) ev = externalEvents.front(); // Rami : if the external event time is less than the next scheduled // transition--> process the external event first if (ev.time < nt) nt = ev.time; // Rami: if the execution time is reached --> stop the simulation if ( stopTime() < nt) { stop(); } else { // Rami: send all the external events with the same time stamp (nt) // and stop if : // 1) The external events list is empty or... // 2) The remaining external events time stamp is lrger than nt while( !externalEvents.empty() && ev.time == nt) { ExternalMessage extMsg(ev.time, this->Processor::id(), *ev.port, ev.value.value()); extMsg.senderModelId(-1); externalEvents.pop_front(); SingleMsgAdm::Instance().send( extMsg, topMasterId ); if ( !externalEvents.empty()) ev = externalEvents.front(); } if (nt == absoluteNext()) { // Rami: if the nt has not been changed by an external event // time stamp and the nextSendMsg() == collectMsg // if the nextSendMsg() == intMsg--> this block won't be reached CollectMessage collectMsg( absoluteNext(), this->Processor::id()); sendMsgType( Root::internalMsg); SingleMsgAdm::Instance().send( collectMsg , topMasterId ); } else { // Rami: if external events with time stamp < absoluteNext() were // found --> send internal message to route the messages down and // activate the destination external transition functions lastChange(nt); nextChange(Time::Zero); InternalMessage intMsg( absoluteNext() , this->Processor::id()); sendMsgType( Root::collectMsg); SingleMsgAdm::Instance().send( intMsg , topMasterId ); } } } } } /******************************************************************* * Function Name: addExternalEvent * Description: add external event ********************************************************************/ Root &Root::addExternalEvent( const Time &t, const Port &p, const Real &r ) { externalEvents.push_back( Event(t, &p, r) ); return *this; }