/******************************************************************* * * DESCRIPTION: class TransportDelayCell * * AUTHOR: Amir Barylko & Jorge Beyoglonian * Version 2: Daniel Rodriguez * Version 3: Gabriel Wainer * Version 4: Alejandro Troccoli * Version 5: Qi (Jacky) Liu * * EMAIL: mailto://amir@dc.uba.ar * mailto://jbeyoglo@dc.uba.ar * mailto://drodrigu@dc.uba.ar * mailto://liuqi@sce.carleton.ca * * DATE: 27/06/1998 * DATE: 02/03/1999 (v2) * DATE: 06/02/2000 * DATE: 21/02/2001 * DATE: 11/01/2006 *******************************************************************/ #ifndef __TRANSPORT_DELAY_ATOMIC_CELL_H #define __TRANSPORT_DELAY_ATOMIC_CELL_H /** include files **/ #include #include #include "atomcell.h" // base class header #include "JackyDebugStream.h" //jacky-debug-mode & jacky-sync /** foward declarations **/ #define TRANSPORT_DELAY_CELL_NAME "TransportDelayCell" /** declarations **/ class TDCellState : public AtomicCellState { public: typedef pair< string, Real > QueueValue ; //Jacky: portName = value //Jacky: add a field to record the scheduleTime of the internal event. // "change further" and "change back" search the Queue for removal/replacement // based on this "scheduleTime" rather than the "output time" as we did before! typedef pair< QueueValue, VTime > QueueValueWithScheduleTime ; //QueueElement => pair< outputTime, pair< pair< outputPortName, outputValue >, scheduleTime > > typedef pair< VTime, QueueValueWithScheduleTime > QueueElement ; //this is for the TransientQueue. //Note: PortIn_First is now based on the flag in the TransientValue! [2006-01-11] //TransientValue => pair< pair< outputPortName, outputValue >, flag > typedef pair< QueueValue, bool > QueueValueWithFlag ; typedef list< QueueElement > Queue ; Queue queueVal ; //a list of (portName = value) pairs to record value changes on all output ports of the cell //these ports include: out, out_XXX // [Nov. 29, 2005] add a flag to identify value generated from external event (input) typedef list< QueueValueWithFlag > TransientQueue; //a list of (portName = value / flag) TransientQueue transientVal ; // [2006-01-06] // We need to record the simulation time to set the flag in the TransientValue // Flags in TQ are associated with a particular simulation time (RT). When ever the simulation time, // i.e. the time of the MessageBag in the externalFunction(), changes, we will update the flags in TQ // (reset the flag to FALSE for this new simulation time) // Whether the value of the cell will change depends on the flag in T for a given time: // 1. if flag = FALSE, state change/change further/change back are allowed // 2. if flag = TRUE, change further/change back are NOT allowed VTime recordTime; // RT for detecting a time change in externalFunction() // [2006-01-10] //add a StateVars here to record the values of the state variables at the beginning of Round 0 //[see macro JACKY_STATE_VAR in JackyDebugStream.h for more information] StateVars vars_round0; TDCellState(){}; virtual ~TDCellState(){}; TDCellState& operator=(TDCellState& thisState); //Assignment void copyState(BasicState *); int getSize() const; bool isAtomic(); bool isAtomic() const; #ifdef JACKY_DEBUG //Jacky: this function will be defined in all state classes for ParallelProcesses & Models // to show (print) the content of the state for debugging purpose virtual void showStateContent( ostream& ) const; void showQueue( ostream& ) const; void showTransientQueue( ostream& ) const; #endif }; #ifdef JACKY_DEBUG //======================================================================== inline void TDCellState::showQueue( ostream& out ) const{ TDCellState::Queue::const_iterator q_it = queueVal.begin(); out << "\t\t Queue -> " << flush; for ( ; q_it != queueVal.end(); q_it++){ out << "< OT = " << (q_it->first).asString() //VTime (outputTime) << " / " << (q_it->second).first.first << " = " //portName << (q_it->second).first.second.value() //value << flush; out << " / ST = " << (q_it->second).second.asString() //VTime (shceduleTime) << " > " << flush; } if( queueVal.size() == 0 ){ out << "EMPTY!" << flush; } out << endl << flush; } inline void TDCellState::showTransientQueue( ostream& out ) const{ TDCellState::TransientQueue::const_iterator tq_it = transientVal.begin(); out << "\t\t TransientQueue -> " << flush; for ( ; tq_it != transientVal.end(); tq_it++){ out << "<" << (tq_it->first).first //portName << " = " << (tq_it->first).second.value() //value << flush; if( (tq_it->second) == true ){ //flag for PORT_IN_FIRST out << " / flag = TRUE> " << flush; } else { out << " / flag = FALSE> " << flush; } } if( transientVal.size() == 0 ){ out << "EMPTY!" << flush; } out << endl << flush; } inline void TDCellState::showStateContent( ostream& out) const{ //1> first call the counterpart function in the base class AtomicCellState::showStateContent(out); //2> show content defined in this class out << "\t\tTDCellState : " << flush; out << "[RT = " << recordTime.asString() << "]" << flush; out << endl << flush; showQueue( out ); showTransientQueue( out ); //show the state variables in the AtomicCellState out << "\t[2006-01-10] State Variables in AtomicCellState = " << variables.asString() << endl << flush; //show the recorded values of these state variables out << "\t[2006-01-10] Recorded State Variables in TDCellState = " << vars_round0.asString() << endl << flush; } #endif //end JACKY_DEBUG =================================================================== class TransportDelayCell: public AtomicCell { public: TransportDelayCell( const CellPosition& cellPos, const string & = TRANSPORT_DELAY_CELL_NAME , const LocalTransAdmin::Function &fn = LocalTransAdmin::InvalidFn ) ; string className() const; protected: Model &initFunction(); Model &internalFunction( const InternalMessage & ) ; Model &externalFunction( const MessageBag & ) ; Model &outputFunction( const CollectMessage & ) ; ModelState* allocateState() { return new TDCellState;} void initializeCell(); private: //Real Quantum; // GW //AT: Quantum is now part of AtomicCellState //const Real & QuantumValue() const; // GW //AT: This is part of AtomicCell //function to get the Queue, a list of QueueValueWithScheduleTime TDCellState::Queue &queueVal() const; //function to get the TransientQueue, a list of QueueValueWithFlag TDCellState::TransientQueue &transientVal() const; //TransportDelayCell & updateTransientQueue(const list& ); //function to get T at a given output port const Real &getTransientValue(const string &portName) const; //function to set T, flag in it defaults to FALSE void setTransientValue(const string &portName, const Real &value, const bool &flag = false); //function to get the flag in T at a given output port const bool getTransientValueFlag(const string &portName) const; // [2006-01-06] //function to reset all flags in the transient queue to FALSE, values in the transient queue are not changed void resetTransientFlags( TDCellState::TransientQueue & ); //No need to use this function since PORT_IN_FIRST is based on the flag in the transient value //rather than the flag in the Queue element [2006-01-06] //function to get the flag in the Queue element for the same port & time //const bool getQueueElementFlag(const VTime &time, const string &portName); // [2006-01-06] // function to get/set the recordTime (RT) in the state const VTime &getRecordTime() const; void setRecordTime( const VTime& ); //get the StateVars in the AtomicCellState class StateVars &cellStateVariables(); //get the StateVars in the TDCellState class //this is a record of the StateVars in AtomicCellState at the beginning of Round 0 StateVars &recordStateVariables(); const VTime & firstQueuedTime() const; const Real & firstQueuedValue() const; const string & firstQueuedPort() const; TransportDelayCell & updateRemainingTime( const VTime & ); TransportDelayCell & insertByTime( const VTime &, const string &, const Real & ); #ifdef JACKY_DEBUG //this is the number to record the number of the Round //in the multiple-round message passing int roundNum; #endif //end JACKY_DEBUG } ; // TransportDelayCell /** inline **/ inline string TransportDelayCell::className() const { return TRANSPORT_DELAY_CELL_NAME; } inline TDCellState::Queue &TransportDelayCell::queueVal() const { return ((TDCellState *) getCurrentState())->queueVal; } inline TDCellState::TransientQueue &TransportDelayCell::transientVal() const{ return ((TDCellState *) getCurrentState())->transientVal; } inline const VTime &TransportDelayCell::getRecordTime() const{ return ((TDCellState*)getCurrentState())->recordTime; } inline void TransportDelayCell::setRecordTime( const VTime& newTime){ ((TDCellState*)getCurrentState())->recordTime = newTime; } //get the StateVars in the AtomicCellState class [2006-01-10] inline StateVars &TransportDelayCell::cellStateVariables(){ return ((TDCellState*)getCurrentState())->variables; } //get the StateVars in the TDCellState class, which is a record of the StateVars in AtomicCellState //at the beginning of Round 0 [2006-01-10] inline StateVars &TransportDelayCell::recordStateVariables(){ return ((TDCellState*)getCurrentState())->vars_round0; } #endif // __TRANSPORT_DELAY_ATOMIC_CELL_H