/******************************************************************* * * DESCRIPTION: class TransportDelayCell * * 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: 03/07/1999 (v2) * *******************************************************************/ // ** include files **// #include "tdcell.h" // header class #include "message.h" // class InternalMessage #include "coupcell.h" // CoupledCell #include "realfunc.h" // calculateWithQuantum /******************************************************************* * Method: TransportDelayCell ********************************************************************/ TransportDelayCell::TransportDelayCell( const string &name, const LocalTransAdmin::Function &fn ) : AtomicCell( name , fn ) {} Model &TransportDelayCell::initFunction() { TransportDelayCell::QueueElement qe(Time::Zero, value()); queueVal.push_back(qe); holdIn(AtomicCell::active, Time::Zero); /* * ExternalMessage msg(Time::Zero , this->Processor::id() , this->neighborPort(), 0); this->Processor::externalMsgs.add(&msg); holdIn(AtomicCell::active, nextChange()); */ return *this; } /******************************************************************* * Method: externalFunction ********************************************************************/ //Model &TransportDelayCell::externalFunction( const ExternalMessage &msg ) Model &TransportDelayCell::externalFunction( const MessageBag &msgs ) { Time delay( static_cast( parent() ).defaultDelay() ) ; Time actualTime( msgs.time() ); localTransitionConfluent(msgs); bool executedLocal = false; Real tv ; // The time of the queue must be updated Time elapsed( msgs.time() - lastChange() ); updateRemainingTime( elapsed ); for (MessageBag::iterator cursor = msgs.begin(); cursor != msgs.end(); cursor++) { ExternalMessage msg = *(ExternalMessage*)(*cursor); if ( !executedLocal && ( inputPort().find( msg.port().id() ) != inputPort().end() ) ) { // cout << "ouch! executing portInTransition block " << endl; string functionName = inputPortFunction()[ msg.port().name() ]; // setPortValue( msg.port().name(), msg.value() ); if (functionName == DEFAULT_FUNCTION_InPort) tv = msg.value() ; else { VirtualPortList *vpl = new VirtualPortList; getOutPorts(vpl); tv = SingleLocalTransAdmin::Instance().evaluate( functionName, neighborhood(), &(inputPortValues()), delay, actualTime, vpl, this, msg.port().name() ) ; delete vpl; } executedLocal = true; } else if ( executedLocal && ( inputPort().find( msg.port().id() ) != inputPort().end() ) ) { cerr << "At : " << msg.time() << endl; cerr << "Warning: current implementation can Not handle multiple external messages !" ; } } if (!executedLocal) { VirtualPortList *vpl = new VirtualPortList; getOutPorts(vpl); tv = SingleLocalTransAdmin::Instance().evaluate( localFunction(), neighborhood(), NULL, delay, actualTime, vpl, this ) ; delete vpl; } /* ///////////////////////////////////////////////////////////////////// // if the message came from an external port we must set the value // If come from a neighbor if( msg.port() == neighborPort() ){ VirtualPortList *vpl = new VirtualPortList; getOutPorts(vpl); tv = SingleLocalTransAdmin::Instance().evaluate( localFunction(), neighborhood(), NULL, delay, actualTime, vpl, this ) ; delete vpl; } else // else the message come from an IN port { string functionName = inputPortFunction()[ msg.port().name() ]; // first we set the new port value in the list of PortValues setPortValue( msg.port().name(), msg.value() ); if (functionName == DEFAULT_FUNCTION_InPort) tv = msg.value() ; else { // sino es un PortInTransition valido VirtualPortList *vpl = new VirtualPortList; getOutPorts(vpl); tv = SingleLocalTransAdmin::Instance().evaluate( functionName, neighborhood(), &(inputPortValues()), delay, actualTime, vpl, this, msg.port().name() ) ; delete vpl; } } ///////////////////////////////////////////////////////////////////// */ ///////////////////////////////////////////////////////////////////// if (UseQuantum().Active()) tv = valueWithQuantum(tv, Real(UseQuantum().Value())); ///////////////////////////////////////////////////////////////////// Real ltb; Queue::iterator cursor; for( cursor = queueVal.begin() ; cursor != queueVal.end() && cursor->first < delay ; cursor++ ) ; //cursor--; if (cursor == queueVal.begin()) ltb = value(); else ltb = cursor->second; // cout << " in cell: " << this->description() << " tv: " << tv.value() << // " ltb: " << ltb.value() << endl; // cout << "neighborhood value of the cell: " << endl; // this->neighborhood().print(cout); if( ltb != tv ) { cursor++; // En CD++ se borraba hasta el ultimo elemento. //queueVal.erase( cursor, queueVal.end() ) ; ////////////////////////////////////////////////////////// // Ahora inserto en la cola pero ordenado por tiempo ////////////////////////////////////////////////////////// // Antes hacia: (insertaba sin tener en cuenta el orden) //queueVal.push_back( QueueElement( delay, tv ) ) ; // Ahora hace: (inserta teniendo en cuenta el orden) Queue::iterator cursorAux; for ( cursorAux = queueVal.begin(); cursorAux != queueVal.end() && cursorAux->first <= delay; cursorAux++ ) ; queueVal.insert( cursorAux, QueueElement(delay, tv) ); /////////////////////////////////////////////////////////////// holdIn( active, firstQueuedTime() ); } return *this ; } /******************************************************************* * Method: internalFunction ********************************************************************/ Model &TransportDelayCell::internalFunction( const InternalMessage &msg ) { Time elapsed( msg.time() - lastChange() ) ; updateRemainingTime( elapsed ); MASSERT( !queueVal.empty() && firstQueuedTime() == Time::Zero ) ; // Modificamos el valor de la celda value( firstQueuedValue() ); queueVal.erase( queueVal.begin() ); if( queueVal.empty() ) passivate() ; else holdIn( active, firstQueuedTime() ); return *this ; } /******************************************************************* * Method: outputFunction ********************************************************************/ //Model &TransportDelayCell::outputFunction( const InternalMessage &msg ) Model &TransportDelayCell::outputFunction( const CollectMessage &msg ) { // The cell value will be update when the coupled receives the output message sendOutput( msg.time(), outputPort(), firstQueuedValue().value() ) ; return *this ; } /******************************************************************* * Function Name: firstQueuedTime ********************************************************************/ const Time & TransportDelayCell::firstQueuedTime() const { return queueVal.begin()->first; } /******************************************************************* * Function Name: firstQueueValue ********************************************************************/ const Real &TransportDelayCell::firstQueuedValue() const { return queueVal.begin()->second ; } /******************************************************************* * Function Name: updateRemainingTime ********************************************************************/ TransportDelayCell & TransportDelayCell::updateRemainingTime( const Time &elapsed ) { for( Queue::iterator cursor = queueVal.begin() ; cursor != queueVal.end() ; cursor++ ) cursor->first -= elapsed ; return *this; }